Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ATokenVault
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 10000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED // All Rights Reserved © AaveCo pragma solidity ^0.8.10; import {ERC4626Upgradeable} from "@openzeppelin-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol"; import {OwnableUpgradeable} from "@openzeppelin-upgradeable/access/OwnableUpgradeable.sol"; import {SafeERC20Upgradeable} from "@openzeppelin-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import {IERC20Upgradeable} from "@openzeppelin-upgradeable/interfaces/IERC20Upgradeable.sol"; import {EIP712Upgradeable} from "@openzeppelin-upgradeable/utils/cryptography/EIP712Upgradeable.sol"; import {MathUpgradeable} from "@openzeppelin-upgradeable/utils/math/MathUpgradeable.sol"; import {IncentivizedERC20} from "@aave-v3-core/protocol/tokenization/base/IncentivizedERC20.sol"; import {IPoolAddressesProvider} from "@aave-v3-core/interfaces/IPoolAddressesProvider.sol"; import {IPool} from "@aave-v3-core/interfaces/IPool.sol"; import {IAToken} from "@aave-v3-core/interfaces/IAToken.sol"; import {DataTypes as AaveDataTypes} from "@aave-v3-core/protocol/libraries/types/DataTypes.sol"; import {WadRayMath} from "@aave-v3-core/protocol/libraries/math/WadRayMath.sol"; import {IRewardsController} from "@aave-v3-periphery/rewards/interfaces/IRewardsController.sol"; import {IATokenVault} from "./interfaces/IATokenVault.sol"; import {MetaTxHelpers} from "./libraries/MetaTxHelpers.sol"; import "./libraries/Constants.sol"; import {ATokenVaultStorage} from "./ATokenVaultStorage.sol"; /** * @title ATokenVault * @author Aave Protocol * @notice An ERC-4626 vault for Aave V3, with support to add a fee on yield earned. */ contract ATokenVault is ERC4626Upgradeable, OwnableUpgradeable, EIP712Upgradeable, ATokenVaultStorage, IATokenVault { using SafeERC20Upgradeable for IERC20Upgradeable; using MathUpgradeable for uint256; /// @inheritdoc IATokenVault IPoolAddressesProvider public immutable POOL_ADDRESSES_PROVIDER; /// @inheritdoc IATokenVault IPool public immutable AAVE_POOL; /// @inheritdoc IATokenVault IAToken public immutable ATOKEN; /// @inheritdoc IATokenVault IERC20Upgradeable public immutable UNDERLYING; /// @inheritdoc IATokenVault uint16 public immutable REFERRAL_CODE; /** * @dev Constructor. * @param underlying The underlying ERC20 asset which can be supplied to Aave * @param referralCode The Aave referral code to use for deposits from this vault * @param poolAddressesProvider The address of the Aave v3 Pool Addresses Provider */ constructor(address underlying, uint16 referralCode, IPoolAddressesProvider poolAddressesProvider) { _disableInitializers(); POOL_ADDRESSES_PROVIDER = poolAddressesProvider; AAVE_POOL = IPool(poolAddressesProvider.getPool()); REFERRAL_CODE = referralCode; UNDERLYING = IERC20Upgradeable(underlying); address aTokenAddress = AAVE_POOL.getReserveData(address(underlying)).aTokenAddress; require(aTokenAddress != address(0), "ASSET_NOT_SUPPORTED"); ATOKEN = IAToken(aTokenAddress); } /** * @notice Initializes the vault, setting the initial parameters and initializing inherited contracts. * @dev It requires an initial non-zero deposit to prevent a frontrunning attack (in underlying tokens). Note * that care should be taken to provide a non-trivial amount, but this depends on the underlying asset's decimals. * @dev It does not initialize the OwnableUpgradeable contract to avoid setting the proxy admin as the owner. * @param owner The owner to set * @param initialFee The initial fee to set, expressed in wad, where 1e18 is 100% * @param shareName The name to set for this vault * @param shareSymbol The symbol to set for this vault * @param initialLockDeposit The initial amount of underlying assets to deposit */ function initialize( address owner, uint256 initialFee, string memory shareName, string memory shareSymbol, uint256 initialLockDeposit ) external initializer { require(owner != address(0), "ZERO_ADDRESS_NOT_VALID"); require(initialLockDeposit != 0, "ZERO_INITIAL_LOCK_DEPOSIT"); _transferOwnership(owner); __ERC4626_init(UNDERLYING); __ERC20_init(shareName, shareSymbol); __EIP712_init(shareName, "1"); _setFee(initialFee); UNDERLYING.safeApprove(address(AAVE_POOL), type(uint256).max); _handleDeposit(initialLockDeposit, address(this), msg.sender, false); } /*////////////////////////////////////////////////////////////// DEPOSIT/WITHDRAWAL LOGIC //////////////////////////////////////////////////////////////*/ /// @inheritdoc IATokenVault function deposit(uint256 assets, address receiver) public override(ERC4626Upgradeable, IATokenVault) returns (uint256) { return _handleDeposit(assets, receiver, msg.sender, false); } /// @inheritdoc IATokenVault function depositATokens(uint256 assets, address receiver) public override returns (uint256) { return _handleDeposit(assets, receiver, msg.sender, true); } /// @inheritdoc IATokenVault function depositWithSig( uint256 assets, address receiver, address depositor, EIP712Signature calldata sig ) public override returns (uint256) { unchecked { MetaTxHelpers._validateRecoveredAddress( MetaTxHelpers._calculateDigest( keccak256( abi.encode( DEPOSIT_WITH_SIG_TYPEHASH, assets, receiver, depositor, _sigNonces[depositor]++, sig.deadline ) ), _domainSeparatorV4() ), depositor, sig ); } return _handleDeposit(assets, receiver, depositor, false); } /// @inheritdoc IATokenVault function depositATokensWithSig( uint256 assets, address receiver, address depositor, EIP712Signature calldata sig ) public override returns (uint256) { unchecked { MetaTxHelpers._validateRecoveredAddress( MetaTxHelpers._calculateDigest( keccak256( abi.encode( DEPOSIT_ATOKENS_WITH_SIG_TYPEHASH, assets, receiver, depositor, _sigNonces[depositor]++, sig.deadline ) ), _domainSeparatorV4() ), depositor, sig ); } return _handleDeposit(assets, receiver, depositor, true); } /// @inheritdoc IATokenVault function mint(uint256 shares, address receiver) public override(ERC4626Upgradeable, IATokenVault) returns (uint256) { return _handleMint(shares, receiver, msg.sender, false); } /// @inheritdoc IATokenVault function mintWithATokens(uint256 shares, address receiver) public override returns (uint256) { return _handleMint(shares, receiver, msg.sender, true); } /// @inheritdoc IATokenVault function mintWithSig( uint256 shares, address receiver, address depositor, EIP712Signature calldata sig ) public override returns (uint256) { unchecked { MetaTxHelpers._validateRecoveredAddress( MetaTxHelpers._calculateDigest( keccak256( abi.encode(MINT_WITH_SIG_TYPEHASH, shares, receiver, depositor, _sigNonces[depositor]++, sig.deadline) ), _domainSeparatorV4() ), depositor, sig ); } return _handleMint(shares, receiver, depositor, false); } /// @inheritdoc IATokenVault function mintWithATokensWithSig( uint256 shares, address receiver, address depositor, EIP712Signature calldata sig ) public override returns (uint256) { unchecked { MetaTxHelpers._validateRecoveredAddress( MetaTxHelpers._calculateDigest( keccak256( abi.encode( MINT_WITH_ATOKENS_WITH_SIG_TYPEHASH, shares, receiver, depositor, _sigNonces[depositor]++, sig.deadline ) ), _domainSeparatorV4() ), depositor, sig ); } return _handleMint(shares, receiver, depositor, true); } /// @inheritdoc IATokenVault function withdraw( uint256 assets, address receiver, address owner ) public override(ERC4626Upgradeable, IATokenVault) returns (uint256) { return _handleWithdraw(assets, receiver, owner, msg.sender, false); } /// @inheritdoc IATokenVault function withdrawATokens(uint256 assets, address receiver, address owner) public override returns (uint256) { return _handleWithdraw(assets, receiver, owner, msg.sender, true); } /// @inheritdoc IATokenVault function withdrawWithSig( uint256 assets, address receiver, address owner, EIP712Signature calldata sig ) public override returns (uint256) { unchecked { MetaTxHelpers._validateRecoveredAddress( MetaTxHelpers._calculateDigest( keccak256( abi.encode(WITHDRAW_WITH_SIG_TYPEHASH, assets, receiver, owner, _sigNonces[owner]++, sig.deadline) ), _domainSeparatorV4() ), owner, sig ); } return _handleWithdraw(assets, receiver, owner, owner, false); } /// @inheritdoc IATokenVault function withdrawATokensWithSig( uint256 assets, address receiver, address owner, EIP712Signature calldata sig ) public override returns (uint256) { unchecked { MetaTxHelpers._validateRecoveredAddress( MetaTxHelpers._calculateDigest( keccak256( abi.encode( WITHDRAW_ATOKENS_WITH_SIG_TYPEHASH, assets, receiver, owner, _sigNonces[owner]++, sig.deadline ) ), _domainSeparatorV4() ), owner, sig ); } return _handleWithdraw(assets, receiver, owner, owner, true); } /// @inheritdoc IATokenVault function redeem( uint256 shares, address receiver, address owner ) public override(ERC4626Upgradeable, IATokenVault) returns (uint256) { return _handleRedeem(shares, receiver, owner, msg.sender, false); } /// @inheritdoc IATokenVault function redeemAsATokens(uint256 shares, address receiver, address owner) public override returns (uint256) { return _handleRedeem(shares, receiver, owner, msg.sender, true); } /// @inheritdoc IATokenVault function redeemWithSig( uint256 shares, address receiver, address owner, EIP712Signature calldata sig ) public override returns (uint256) { unchecked { MetaTxHelpers._validateRecoveredAddress( MetaTxHelpers._calculateDigest( keccak256(abi.encode(REDEEM_WITH_SIG_TYPEHASH, shares, receiver, owner, _sigNonces[owner]++, sig.deadline)), _domainSeparatorV4() ), owner, sig ); } return _handleRedeem(shares, receiver, owner, owner, false); } /// @inheritdoc IATokenVault function redeemWithATokensWithSig( uint256 shares, address receiver, address owner, EIP712Signature calldata sig ) public override returns (uint256) { unchecked { MetaTxHelpers._validateRecoveredAddress( MetaTxHelpers._calculateDigest( keccak256( abi.encode( REDEEM_WITH_ATOKENS_WITH_SIG_TYPEHASH, shares, receiver, owner, _sigNonces[owner]++, sig.deadline ) ), _domainSeparatorV4() ), owner, sig ); } return _handleRedeem(shares, receiver, owner, owner, true); } /// @inheritdoc IATokenVault function maxDeposit(address) public view override(ERC4626Upgradeable, IATokenVault) returns (uint256) { return _maxAssetsSuppliableToAave(); } /// @inheritdoc IATokenVault function maxMint(address) public view override(ERC4626Upgradeable, IATokenVault) returns (uint256) { return _convertToShares(_maxAssetsSuppliableToAave(), MathUpgradeable.Rounding.Down); } /// @inheritdoc IATokenVault function maxWithdraw(address owner) public view override(ERC4626Upgradeable, IATokenVault) returns (uint256) { uint256 maxWithdrawable = _maxAssetsWithdrawableFromAave(); return maxWithdrawable == 0 ? 0 : maxWithdrawable.min(_convertToAssets(balanceOf(owner), MathUpgradeable.Rounding.Down)); } /// @inheritdoc IATokenVault function maxRedeem(address owner) public view override(ERC4626Upgradeable, IATokenVault) returns (uint256) { uint256 maxWithdrawable = _maxAssetsWithdrawableFromAave(); return maxWithdrawable == 0 ? 0 : _convertToShares(maxWithdrawable, MathUpgradeable.Rounding.Down).min(balanceOf(owner)); } /// @inheritdoc IATokenVault function previewDeposit(uint256 assets) public view override(ERC4626Upgradeable, IATokenVault) returns (uint256) { return _convertToShares(_maxAssetsSuppliableToAave().min(assets), MathUpgradeable.Rounding.Down); } /// @inheritdoc IATokenVault function previewMint(uint256 shares) public view override(ERC4626Upgradeable, IATokenVault) returns (uint256) { return _convertToAssets(shares, MathUpgradeable.Rounding.Up).min(_maxAssetsSuppliableToAave()); } /// @inheritdoc IATokenVault function previewWithdraw(uint256 assets) public view override(ERC4626Upgradeable, IATokenVault) returns (uint256) { uint256 maxWithdrawable = _maxAssetsWithdrawableFromAave(); return maxWithdrawable == 0 ? 0 : _convertToShares(maxWithdrawable.min(assets), MathUpgradeable.Rounding.Up); } /// @inheritdoc IATokenVault function previewRedeem(uint256 shares) public view override(ERC4626Upgradeable, IATokenVault) returns (uint256) { uint256 maxWithdrawable = _maxAssetsWithdrawableFromAave(); return maxWithdrawable == 0 ? 0 : _convertToAssets(shares, MathUpgradeable.Rounding.Down).min(maxWithdrawable); } /// @inheritdoc IATokenVault function domainSeparator() public view override returns (bytes32) { return _domainSeparatorV4(); } /*////////////////////////////////////////////////////////////// ONLY OWNER FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @inheritdoc IATokenVault function setFee(uint256 newFee) public override onlyOwner { _accrueYield(); _setFee(newFee); } /// @inheritdoc IATokenVault function withdrawFees(address to, uint256 amount) public override onlyOwner { uint256 claimableFees = getClaimableFees(); require(amount <= claimableFees, "INSUFFICIENT_FEES"); // will underflow below anyway, error msg for clarity _s.accumulatedFees = uint128(claimableFees - amount); _s.lastVaultBalance = uint128(ATOKEN.balanceOf(address(this)) - amount); _s.lastUpdated = uint40(block.timestamp); ATOKEN.transfer(to, amount); emit FeesWithdrawn(to, amount, _s.lastVaultBalance, _s.accumulatedFees); } /// @inheritdoc IATokenVault function claimRewards(address to) public override onlyOwner { require(to != address(0), "CANNOT_CLAIM_TO_ZERO_ADDRESS"); address[] memory assets = new address[](1); assets[0] = address(ATOKEN); (address[] memory rewardsList, uint256[] memory claimedAmounts) = IRewardsController( address(IncentivizedERC20(address(ATOKEN)).getIncentivesController()) ).claimAllRewards(assets, to); emit RewardsClaimed(to, rewardsList, claimedAmounts); } /// @inheritdoc IATokenVault function emergencyRescue(address token, address to, uint256 amount) public override onlyOwner { require(token != address(ATOKEN), "CANNOT_RESCUE_ATOKEN"); IERC20Upgradeable(token).safeTransfer(to, amount); emit EmergencyRescue(token, to, amount); } /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @inheritdoc IATokenVault function totalAssets() public view override(ERC4626Upgradeable, IATokenVault) returns (uint256) { // Report only the total assets net of fees, for vault share logic return ATOKEN.balanceOf(address(this)) - getClaimableFees(); } /// @inheritdoc IATokenVault function getClaimableFees() public view override returns (uint256) { if (block.timestamp == _s.lastUpdated) { // Accumulated fees already up to date return _s.accumulatedFees; } else { // Calculate new fees since last accrueYield uint256 newVaultBalance = ATOKEN.balanceOf(address(this)); uint256 newYield = newVaultBalance - _s.lastVaultBalance; uint256 newFees = newYield.mulDiv(_s.fee, SCALE, MathUpgradeable.Rounding.Down); return _s.accumulatedFees + newFees; } } /// @inheritdoc IATokenVault function getSigNonce(address signer) public view override returns (uint256) { return _sigNonces[signer]; } /// @inheritdoc IATokenVault function getLastUpdated() public view override returns (uint256) { return _s.lastUpdated; } /// @inheritdoc IATokenVault function getLastVaultBalance() public view override returns (uint256) { return _s.lastVaultBalance; } /// @inheritdoc IATokenVault function getFee() public view override returns (uint256) { return _s.fee; } /*////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ function _setFee(uint256 newFee) internal { require(newFee <= SCALE, "FEE_TOO_HIGH"); uint256 oldFee = _s.fee; _s.fee = uint64(newFee); emit FeeUpdated(oldFee, newFee); } function _accrueYield() internal { if (block.timestamp != _s.lastUpdated) { uint256 newVaultBalance = ATOKEN.balanceOf(address(this)); uint256 newYield = newVaultBalance > _s.lastVaultBalance ? newVaultBalance - _s.lastVaultBalance : 0; uint256 newFeesEarned = newYield.mulDiv(_s.fee, SCALE, MathUpgradeable.Rounding.Down); _s.accumulatedFees += uint128(newFeesEarned); _s.lastVaultBalance = uint128(newVaultBalance); _s.lastUpdated = uint40(block.timestamp); emit YieldAccrued(newYield, newFeesEarned, newVaultBalance); } } function _handleDeposit(uint256 assets, address receiver, address depositor, bool asAToken) internal returns (uint256) { require(assets <= maxDeposit(receiver), "DEPOSIT_EXCEEDS_MAX"); _accrueYield(); uint256 shares = super.previewDeposit(assets); require(shares != 0, "ZERO_SHARES"); // Check for rounding error since we round down in previewDeposit. _baseDeposit(_convertToAssets(shares, MathUpgradeable.Rounding.Up), shares, depositor, receiver, asAToken); return shares; } function _handleMint(uint256 shares, address receiver, address depositor, bool asAToken) internal returns (uint256) { require(shares <= maxMint(receiver), "MINT_EXCEEDS_MAX"); _accrueYield(); uint256 assets = super.previewMint(shares); // No need to check for rounding error, previewMint rounds up. _baseDeposit(assets, shares, depositor, receiver, asAToken); return assets; } function _handleWithdraw( uint256 assets, address receiver, address owner, address allowanceTarget, bool asAToken ) internal returns (uint256) { _accrueYield(); require(assets <= maxWithdraw(owner), "WITHDRAW_EXCEEDS_MAX"); uint256 shares = super.previewWithdraw(assets); // No need to check for rounding error, previewWithdraw rounds up. _baseWithdraw(assets, shares, owner, receiver, allowanceTarget, asAToken); return shares; } function _handleRedeem( uint256 shares, address receiver, address owner, address allowanceTarget, bool asAToken ) internal returns (uint256) { _accrueYield(); require(shares <= maxRedeem(owner), "REDEEM_EXCEEDS_MAX"); uint256 assets = super.previewRedeem(shares); require(assets != 0, "ZERO_ASSETS"); // Check for rounding error since we round down in previewRedeem. _baseWithdraw(assets, shares, owner, receiver, allowanceTarget, asAToken); return assets; } function _maxAssetsSuppliableToAave() internal view returns (uint256) { // returns 0 if reserve is not active, frozen, or paused // returns max uint256 value if supply cap is 0 (not capped) // returns supply cap - current amount supplied as max suppliable if there is a supply cap for this reserve AaveDataTypes.ReserveData memory reserveData = AAVE_POOL.getReserveData(address(UNDERLYING)); uint256 reserveConfigMap = reserveData.configuration.data; uint256 supplyCap = (reserveConfigMap & ~AAVE_SUPPLY_CAP_MASK) >> AAVE_SUPPLY_CAP_BIT_POSITION; if ( (reserveConfigMap & ~AAVE_ACTIVE_MASK == 0) || (reserveConfigMap & ~AAVE_FROZEN_MASK != 0) || (reserveConfigMap & ~AAVE_PAUSED_MASK != 0) ) { return 0; } else if (supplyCap == 0) { return type(uint256).max; } else { // Reserve's supply cap - current amount supplied // See similar logic in Aave v3 ValidationLogic library, in the validateSupply function // https://github.com/aave/aave-v3-core/blob/a00f28e3ad7c0e4a369d8e06e0ac9fd0acabcab7/contracts/protocol/libraries/logic/ValidationLogic.sol#L71-L78 return (supplyCap * 10 ** decimals()) - WadRayMath.rayMul( (ATOKEN.scaledTotalSupply() + uint256(reserveData.accruedToTreasury)), reserveData.liquidityIndex ); } } function _maxAssetsWithdrawableFromAave() internal view returns (uint256) { // returns 0 if reserve is not active, or paused // otherwise, returns available liquidity AaveDataTypes.ReserveData memory reserveData = AAVE_POOL.getReserveData(address(UNDERLYING)); uint256 reserveConfigMap = reserveData.configuration.data; if ((reserveConfigMap & ~AAVE_ACTIVE_MASK == 0) || (reserveConfigMap & ~AAVE_PAUSED_MASK != 0)) { return 0; } else { return UNDERLYING.balanceOf(address(ATOKEN)); } } function _baseDeposit(uint256 assets, uint256 shares, address depositor, address receiver, bool asAToken) private { // Need to transfer before minting or ERC777s could reenter. if (asAToken) { ATOKEN.transferFrom(depositor, address(this), assets); _s.lastVaultBalance += uint128(assets); } else { UNDERLYING.safeTransferFrom(depositor, address(this), assets); uint256 aTokenBalanceBefore = ATOKEN.balanceOf(address(this)); AAVE_POOL.supply(address(UNDERLYING), assets, address(this), REFERRAL_CODE); _s.lastVaultBalance += uint128(ATOKEN.balanceOf(address(this)) - aTokenBalanceBefore); } _mint(receiver, shares); emit Deposit(depositor, receiver, assets, shares); } function _baseWithdraw( uint256 assets, uint256 shares, address owner, address receiver, address allowanceTarget, bool asAToken ) private { if (allowanceTarget != owner) { _spendAllowance(owner, allowanceTarget, shares); } _burn(owner, shares); // Withdraw assets from Aave v3 and send to receiver if (asAToken) { ATOKEN.transfer(receiver, assets); _s.lastVaultBalance -= uint128(assets); } else { uint256 amountWithdrawn = AAVE_POOL.withdraw(address(UNDERLYING), assets, receiver); _s.lastVaultBalance -= uint128(amountWithdrawn); } emit Withdraw(allowanceTarget, receiver, owner, assets, shares); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return payable(msg.sender); } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.10; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.10; import {IERC20} from './IERC20.sol'; interface IERC20Detailed is IERC20 { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol) pragma solidity 0.8.10; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits. */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, 'SafeCast: value must be positive'); return uint256(value); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require( value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits" ); return int128(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require( value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits" ); return int64(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require( value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits" ); return int32(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require( value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits" ); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits. * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require( value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits" ); return int8(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol'; /** * @title IACLManager * @author Aave * @notice Defines the basic interface for the ACL Manager */ interface IACLManager { /** * @notice Returns the contract address of the PoolAddressesProvider * @return The address of the PoolAddressesProvider */ function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider); /** * @notice Returns the identifier of the PoolAdmin role * @return The id of the PoolAdmin role */ function POOL_ADMIN_ROLE() external view returns (bytes32); /** * @notice Returns the identifier of the EmergencyAdmin role * @return The id of the EmergencyAdmin role */ function EMERGENCY_ADMIN_ROLE() external view returns (bytes32); /** * @notice Returns the identifier of the RiskAdmin role * @return The id of the RiskAdmin role */ function RISK_ADMIN_ROLE() external view returns (bytes32); /** * @notice Returns the identifier of the FlashBorrower role * @return The id of the FlashBorrower role */ function FLASH_BORROWER_ROLE() external view returns (bytes32); /** * @notice Returns the identifier of the Bridge role * @return The id of the Bridge role */ function BRIDGE_ROLE() external view returns (bytes32); /** * @notice Returns the identifier of the AssetListingAdmin role * @return The id of the AssetListingAdmin role */ function ASSET_LISTING_ADMIN_ROLE() external view returns (bytes32); /** * @notice Set the role as admin of a specific role. * @dev By default the admin role for all roles is `DEFAULT_ADMIN_ROLE`. * @param role The role to be managed by the admin role * @param adminRole The admin role */ function setRoleAdmin(bytes32 role, bytes32 adminRole) external; /** * @notice Adds a new admin as PoolAdmin * @param admin The address of the new admin */ function addPoolAdmin(address admin) external; /** * @notice Removes an admin as PoolAdmin * @param admin The address of the admin to remove */ function removePoolAdmin(address admin) external; /** * @notice Returns true if the address is PoolAdmin, false otherwise * @param admin The address to check * @return True if the given address is PoolAdmin, false otherwise */ function isPoolAdmin(address admin) external view returns (bool); /** * @notice Adds a new admin as EmergencyAdmin * @param admin The address of the new admin */ function addEmergencyAdmin(address admin) external; /** * @notice Removes an admin as EmergencyAdmin * @param admin The address of the admin to remove */ function removeEmergencyAdmin(address admin) external; /** * @notice Returns true if the address is EmergencyAdmin, false otherwise * @param admin The address to check * @return True if the given address is EmergencyAdmin, false otherwise */ function isEmergencyAdmin(address admin) external view returns (bool); /** * @notice Adds a new admin as RiskAdmin * @param admin The address of the new admin */ function addRiskAdmin(address admin) external; /** * @notice Removes an admin as RiskAdmin * @param admin The address of the admin to remove */ function removeRiskAdmin(address admin) external; /** * @notice Returns true if the address is RiskAdmin, false otherwise * @param admin The address to check * @return True if the given address is RiskAdmin, false otherwise */ function isRiskAdmin(address admin) external view returns (bool); /** * @notice Adds a new address as FlashBorrower * @param borrower The address of the new FlashBorrower */ function addFlashBorrower(address borrower) external; /** * @notice Removes an address as FlashBorrower * @param borrower The address of the FlashBorrower to remove */ function removeFlashBorrower(address borrower) external; /** * @notice Returns true if the address is FlashBorrower, false otherwise * @param borrower The address to check * @return True if the given address is FlashBorrower, false otherwise */ function isFlashBorrower(address borrower) external view returns (bool); /** * @notice Adds a new address as Bridge * @param bridge The address of the new Bridge */ function addBridge(address bridge) external; /** * @notice Removes an address as Bridge * @param bridge The address of the bridge to remove */ function removeBridge(address bridge) external; /** * @notice Returns true if the address is Bridge, false otherwise * @param bridge The address to check * @return True if the given address is Bridge, false otherwise */ function isBridge(address bridge) external view returns (bool); /** * @notice Adds a new admin as AssetListingAdmin * @param admin The address of the new admin */ function addAssetListingAdmin(address admin) external; /** * @notice Removes an admin as AssetListingAdmin * @param admin The address of the admin to remove */ function removeAssetListingAdmin(address admin) external; /** * @notice Returns true if the address is AssetListingAdmin, false otherwise * @param admin The address to check * @return True if the given address is AssetListingAdmin, false otherwise */ function isAssetListingAdmin(address admin) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; import {IScaledBalanceToken} from './IScaledBalanceToken.sol'; import {IInitializableAToken} from './IInitializableAToken.sol'; /** * @title IAToken * @author Aave * @notice Defines the basic interface for an AToken. */ interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken { /** * @dev Emitted during the transfer action * @param from The user whose tokens are being transferred * @param to The recipient * @param value The scaled amount being transferred * @param index The next liquidity index of the reserve */ event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index); /** * @notice Mints `amount` aTokens to `user` * @param caller The address performing the mint * @param onBehalfOf The address of the user that will receive the minted aTokens * @param amount The amount of tokens getting minted * @param index The next liquidity index of the reserve * @return `true` if the the previous balance of the user was 0 */ function mint( address caller, address onBehalfOf, uint256 amount, uint256 index ) external returns (bool); /** * @notice Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying` * @dev In some instances, the mint event could be emitted from a burn transaction * if the amount to burn is less than the interest that the user accrued * @param from The address from which the aTokens will be burned * @param receiverOfUnderlying The address that will receive the underlying * @param amount The amount being burned * @param index The next liquidity index of the reserve */ function burn( address from, address receiverOfUnderlying, uint256 amount, uint256 index ) external; /** * @notice Mints aTokens to the reserve treasury * @param amount The amount of tokens getting minted * @param index The next liquidity index of the reserve */ function mintToTreasury(uint256 amount, uint256 index) external; /** * @notice Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken * @param from The address getting liquidated, current owner of the aTokens * @param to The recipient * @param value The amount of tokens getting transferred */ function transferOnLiquidation( address from, address to, uint256 value ) external; /** * @notice Transfers the underlying asset to `target`. * @dev Used by the Pool to transfer assets in borrow(), withdraw() and flashLoan() * @param target The recipient of the underlying * @param amount The amount getting transferred */ function transferUnderlyingTo(address target, uint256 amount) external; /** * @notice Handles the underlying received by the aToken after the transfer has been completed. * @dev The default implementation is empty as with standard ERC20 tokens, nothing needs to be done after the * transfer is concluded. However in the future there may be aTokens that allow for example to stake the underlying * to receive LM rewards. In that case, `handleRepayment()` would perform the staking of the underlying asset. * @param user The user executing the repayment * @param onBehalfOf The address of the user who will get his debt reduced/removed * @param amount The amount getting repaid */ function handleRepayment( address user, address onBehalfOf, uint256 amount ) external; /** * @notice Allow passing a signed message to approve spending * @dev implements the permit function as for * https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md * @param owner The owner of the funds * @param spender The spender * @param value The amount * @param deadline The deadline timestamp, type(uint256).max for max deadline * @param v Signature param * @param s Signature param * @param r Signature param */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @notice Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) * @return The address of the underlying asset */ function UNDERLYING_ASSET_ADDRESS() external view returns (address); /** * @notice Returns the address of the Aave treasury, receiving the fees on this aToken. * @return Address of the Aave treasury */ function RESERVE_TREASURY_ADDRESS() external view returns (address); /** * @notice Get the domain separator for the token * @dev Return cached value if chainId matches cache, otherwise recomputes separator * @return The domain separator of the token at current chain */ function DOMAIN_SEPARATOR() external view returns (bytes32); /** * @notice Returns the nonce for owner. * @param owner The address of the owner * @return The nonce of the owner */ function nonces(address owner) external view returns (uint256); /** * @notice Rescue and transfer tokens locked in this contract * @param token The address of the token * @param to The address of the recipient * @param amount The amount of token to transfer */ function rescueTokens( address token, address to, uint256 amount ) external; }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; /** * @title IAaveIncentivesController * @author Aave * @notice Defines the basic interface for an Aave Incentives Controller. * @dev It only contains one single function, needed as a hook on aToken and debtToken transfers. */ interface IAaveIncentivesController { /** * @dev Called by the corresponding asset on transfer hook in order to update the rewards distribution. * @dev The units of `totalSupply` and `userBalance` should be the same. * @param user The address of the user whose asset balance has changed * @param totalSupply The total supply of the asset prior to user balance change * @param userBalance The previous user balance prior to balance change */ function handleAction( address user, uint256 totalSupply, uint256 userBalance ) external; }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; import {IPool} from './IPool.sol'; /** * @title IInitializableAToken * @author Aave * @notice Interface for the initialize function on AToken */ interface IInitializableAToken { /** * @dev Emitted when an aToken is initialized * @param underlyingAsset The address of the underlying asset * @param pool The address of the associated pool * @param treasury The address of the treasury * @param incentivesController The address of the incentives controller for this aToken * @param aTokenDecimals The decimals of the underlying * @param aTokenName The name of the aToken * @param aTokenSymbol The symbol of the aToken * @param params A set of encoded parameters for additional initialization */ event Initialized( address indexed underlyingAsset, address indexed pool, address treasury, address incentivesController, uint8 aTokenDecimals, string aTokenName, string aTokenSymbol, bytes params ); /** * @notice Initializes the aToken * @param pool The pool contract that is initializing this contract * @param treasury The address of the Aave treasury, receiving the fees on this aToken * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) * @param incentivesController The smart contract managing potential incentives distribution * @param aTokenDecimals The decimals of the aToken, same as the underlying asset's * @param aTokenName The name of the aToken * @param aTokenSymbol The symbol of the aToken * @param params A set of encoded parameters for additional initialization */ function initialize( IPool pool, address treasury, address underlyingAsset, IAaveIncentivesController incentivesController, uint8 aTokenDecimals, string calldata aTokenName, string calldata aTokenSymbol, bytes calldata params ) external; }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol'; import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; /** * @title IPool * @author Aave * @notice Defines the basic interface for an Aave Pool. */ interface IPool { /** * @dev Emitted on mintUnbacked() * @param reserve The address of the underlying asset of the reserve * @param user The address initiating the supply * @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens * @param amount The amount of supplied assets * @param referralCode The referral code used */ event MintUnbacked( address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, uint16 indexed referralCode ); /** * @dev Emitted on backUnbacked() * @param reserve The address of the underlying asset of the reserve * @param backer The address paying for the backing * @param amount The amount added as backing * @param fee The amount paid in fees */ event BackUnbacked(address indexed reserve, address indexed backer, uint256 amount, uint256 fee); /** * @dev Emitted on supply() * @param reserve The address of the underlying asset of the reserve * @param user The address initiating the supply * @param onBehalfOf The beneficiary of the supply, receiving the aTokens * @param amount The amount supplied * @param referralCode The referral code used */ event Supply( address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, uint16 indexed referralCode ); /** * @dev Emitted on withdraw() * @param reserve The address of the underlying asset being withdrawn * @param user The address initiating the withdrawal, owner of aTokens * @param to The address that will receive the underlying * @param amount The amount to be withdrawn */ event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount); /** * @dev Emitted on borrow() and flashLoan() when debt needs to be opened * @param reserve The address of the underlying asset being borrowed * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just * initiator of the transaction on flashLoan() * @param onBehalfOf The address that will be getting the debt * @param amount The amount borrowed out * @param interestRateMode The rate mode: 1 for Stable, 2 for Variable * @param borrowRate The numeric rate at which the user has borrowed, expressed in ray * @param referralCode The referral code used */ event Borrow( address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, DataTypes.InterestRateMode interestRateMode, uint256 borrowRate, uint16 indexed referralCode ); /** * @dev Emitted on repay() * @param reserve The address of the underlying asset of the reserve * @param user The beneficiary of the repayment, getting his debt reduced * @param repayer The address of the user initiating the repay(), providing the funds * @param amount The amount repaid * @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly */ event Repay( address indexed reserve, address indexed user, address indexed repayer, uint256 amount, bool useATokens ); /** * @dev Emitted on swapBorrowRateMode() * @param reserve The address of the underlying asset of the reserve * @param user The address of the user swapping his rate mode * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable */ event SwapBorrowRateMode( address indexed reserve, address indexed user, DataTypes.InterestRateMode interestRateMode ); /** * @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets * @param asset The address of the underlying asset of the reserve * @param totalDebt The total isolation mode debt for the reserve */ event IsolationModeTotalDebtUpdated(address indexed asset, uint256 totalDebt); /** * @dev Emitted when the user selects a certain asset category for eMode * @param user The address of the user * @param categoryId The category id */ event UserEModeSet(address indexed user, uint8 categoryId); /** * @dev Emitted on setUserUseReserveAsCollateral() * @param reserve The address of the underlying asset of the reserve * @param user The address of the user enabling the usage as collateral */ event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user); /** * @dev Emitted on setUserUseReserveAsCollateral() * @param reserve The address of the underlying asset of the reserve * @param user The address of the user enabling the usage as collateral */ event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user); /** * @dev Emitted on rebalanceStableBorrowRate() * @param reserve The address of the underlying asset of the reserve * @param user The address of the user for which the rebalance has been executed */ event RebalanceStableBorrowRate(address indexed reserve, address indexed user); /** * @dev Emitted on flashLoan() * @param target The address of the flash loan receiver contract * @param initiator The address initiating the flash loan * @param asset The address of the asset being flash borrowed * @param amount The amount flash borrowed * @param interestRateMode The flashloan mode: 0 for regular flashloan, 1 for Stable debt, 2 for Variable debt * @param premium The fee flash borrowed * @param referralCode The referral code used */ event FlashLoan( address indexed target, address initiator, address indexed asset, uint256 amount, DataTypes.InterestRateMode interestRateMode, uint256 premium, uint16 indexed referralCode ); /** * @dev Emitted when a borrower is liquidated. * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation * @param user The address of the borrower getting liquidated * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover * @param liquidatedCollateralAmount The amount of collateral received by the liquidator * @param liquidator The address of the liquidator * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants * to receive the underlying collateral asset directly */ event LiquidationCall( address indexed collateralAsset, address indexed debtAsset, address indexed user, uint256 debtToCover, uint256 liquidatedCollateralAmount, address liquidator, bool receiveAToken ); /** * @dev Emitted when the state of a reserve is updated. * @param reserve The address of the underlying asset of the reserve * @param liquidityRate The next liquidity rate * @param stableBorrowRate The next stable borrow rate * @param variableBorrowRate The next variable borrow rate * @param liquidityIndex The next liquidity index * @param variableBorrowIndex The next variable borrow index */ event ReserveDataUpdated( address indexed reserve, uint256 liquidityRate, uint256 stableBorrowRate, uint256 variableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex ); /** * @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest. * @param reserve The address of the reserve * @param amountMinted The amount minted to the treasury */ event MintedToTreasury(address indexed reserve, uint256 amountMinted); /** * @notice Mints an `amount` of aTokens to the `onBehalfOf` * @param asset The address of the underlying asset to mint * @param amount The amount to mint * @param onBehalfOf The address that will receive the aTokens * @param referralCode Code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man */ function mintUnbacked( address asset, uint256 amount, address onBehalfOf, uint16 referralCode ) external; /** * @notice Back the current unbacked underlying with `amount` and pay `fee`. * @param asset The address of the underlying asset to back * @param amount The amount to back * @param fee The amount paid in fees * @return The backed amount */ function backUnbacked( address asset, uint256 amount, uint256 fee ) external returns (uint256); /** * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. * - E.g. User supplies 100 USDC and gets in return 100 aUSDC * @param asset The address of the underlying asset to supply * @param amount The amount to be supplied * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens * is a different wallet * @param referralCode Code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man */ function supply( address asset, uint256 amount, address onBehalfOf, uint16 referralCode ) external; /** * @notice Supply with transfer approval of asset to be supplied done via permit function * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713 * @param asset The address of the underlying asset to supply * @param amount The amount to be supplied * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens * is a different wallet * @param deadline The deadline timestamp that the permit is valid * @param referralCode Code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man * @param permitV The V parameter of ERC712 permit sig * @param permitR The R parameter of ERC712 permit sig * @param permitS The S parameter of ERC712 permit sig */ function supplyWithPermit( address asset, uint256 amount, address onBehalfOf, uint16 referralCode, uint256 deadline, uint8 permitV, bytes32 permitR, bytes32 permitS ) external; /** * @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC * @param asset The address of the underlying asset to withdraw * @param amount The underlying amount to be withdrawn * - Send the value type(uint256).max in order to withdraw the whole aToken balance * @param to The address that will receive the underlying, same as msg.sender if the user * wants to receive it on his own wallet, or a different address if the beneficiary is a * different wallet * @return The final amount withdrawn */ function withdraw( address asset, uint256 amount, address to ) external returns (uint256); /** * @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower * already supplied enough collateral, or he was given enough allowance by a credit delegator on the * corresponding debt token (StableDebtToken or VariableDebtToken) * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet * and 100 stable/variable debt tokens, depending on the `interestRateMode` * @param asset The address of the underlying asset to borrow * @param amount The amount to be borrowed * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable * @param referralCode The code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man * @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator * if he has been given credit delegation allowance */ function borrow( address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf ) external; /** * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address * @param asset The address of the borrowed underlying asset previously borrowed * @param amount The amount to repay * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable * @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the * user calling the function if he wants to reduce/remove his own debt, or the address of any other * other borrower whose debt should be removed * @return The final amount repaid */ function repay( address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf ) external returns (uint256); /** * @notice Repay with transfer approval of asset to be repaid done via permit function * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713 * @param asset The address of the borrowed underlying asset previously borrowed * @param amount The amount to repay * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the * user calling the function if he wants to reduce/remove his own debt, or the address of any other * other borrower whose debt should be removed * @param deadline The deadline timestamp that the permit is valid * @param permitV The V parameter of ERC712 permit sig * @param permitR The R parameter of ERC712 permit sig * @param permitS The S parameter of ERC712 permit sig * @return The final amount repaid */ function repayWithPermit( address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf, uint256 deadline, uint8 permitV, bytes32 permitR, bytes32 permitS ) external returns (uint256); /** * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the * equivalent debt tokens * - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable/stable debt tokens * @dev Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken * balance is not enough to cover the whole debt * @param asset The address of the borrowed underlying asset previously borrowed * @param amount The amount to repay * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable * @return The final amount repaid */ function repayWithATokens( address asset, uint256 amount, uint256 interestRateMode ) external returns (uint256); /** * @notice Allows a borrower to swap his debt between stable and variable mode, or vice versa * @param asset The address of the underlying asset borrowed * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable */ function swapBorrowRateMode(address asset, uint256 interestRateMode) external; /** * @notice Rebalances the stable interest rate of a user to the current stable rate defined on the reserve. * - Users can be rebalanced if the following conditions are satisfied: * 1. Usage ratio is above 95% * 2. the current supply APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too * much has been borrowed at a stable rate and suppliers are not earning enough * @param asset The address of the underlying asset borrowed * @param user The address of the user to be rebalanced */ function rebalanceStableBorrowRate(address asset, address user) external; /** * @notice Allows suppliers to enable/disable a specific supplied asset as collateral * @param asset The address of the underlying asset supplied * @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise */ function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external; /** * @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1 * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation * @param user The address of the borrower getting liquidated * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants * to receive the underlying collateral asset directly */ function liquidationCall( address collateralAsset, address debtAsset, address user, uint256 debtToCover, bool receiveAToken ) external; /** * @notice Allows smartcontracts to access the liquidity of the pool within one transaction, * as long as the amount taken plus a fee is returned. * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept * into consideration. For further details please visit https://developers.aave.com * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface * @param assets The addresses of the assets being flash-borrowed * @param amounts The amounts of the assets being flash-borrowed * @param interestRateModes Types of the debt to open if the flash loan is not returned: * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2 * @param params Variadic packed params to pass to the receiver as extra information * @param referralCode The code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man */ function flashLoan( address receiverAddress, address[] calldata assets, uint256[] calldata amounts, uint256[] calldata interestRateModes, address onBehalfOf, bytes calldata params, uint16 referralCode ) external; /** * @notice Allows smartcontracts to access the liquidity of the pool within one transaction, * as long as the amount taken plus a fee is returned. * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept * into consideration. For further details please visit https://developers.aave.com * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver interface * @param asset The address of the asset being flash-borrowed * @param amount The amount of the asset being flash-borrowed * @param params Variadic packed params to pass to the receiver as extra information * @param referralCode The code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man */ function flashLoanSimple( address receiverAddress, address asset, uint256 amount, bytes calldata params, uint16 referralCode ) external; /** * @notice Returns the user account data across all the reserves * @param user The address of the user * @return totalCollateralBase The total collateral of the user in the base currency used by the price feed * @return totalDebtBase The total debt of the user in the base currency used by the price feed * @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed * @return currentLiquidationThreshold The liquidation threshold of the user * @return ltv The loan to value of The user * @return healthFactor The current health factor of the user */ function getUserAccountData(address user) external view returns ( uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor ); /** * @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an * interest rate strategy * @dev Only callable by the PoolConfigurator contract * @param asset The address of the underlying asset of the reserve * @param aTokenAddress The address of the aToken that will be assigned to the reserve * @param stableDebtAddress The address of the StableDebtToken that will be assigned to the reserve * @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve * @param interestRateStrategyAddress The address of the interest rate strategy contract */ function initReserve( address asset, address aTokenAddress, address stableDebtAddress, address variableDebtAddress, address interestRateStrategyAddress ) external; /** * @notice Drop a reserve * @dev Only callable by the PoolConfigurator contract * @param asset The address of the underlying asset of the reserve */ function dropReserve(address asset) external; /** * @notice Updates the address of the interest rate strategy contract * @dev Only callable by the PoolConfigurator contract * @param asset The address of the underlying asset of the reserve * @param rateStrategyAddress The address of the interest rate strategy contract */ function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress) external; /** * @notice Sets the configuration bitmap of the reserve as a whole * @dev Only callable by the PoolConfigurator contract * @param asset The address of the underlying asset of the reserve * @param configuration The new configuration bitmap */ function setConfiguration(address asset, DataTypes.ReserveConfigurationMap calldata configuration) external; /** * @notice Returns the configuration of the reserve * @param asset The address of the underlying asset of the reserve * @return The configuration of the reserve */ function getConfiguration(address asset) external view returns (DataTypes.ReserveConfigurationMap memory); /** * @notice Returns the configuration of the user across all the reserves * @param user The user address * @return The configuration of the user */ function getUserConfiguration(address user) external view returns (DataTypes.UserConfigurationMap memory); /** * @notice Returns the normalized income of the reserve * @param asset The address of the underlying asset of the reserve * @return The reserve's normalized income */ function getReserveNormalizedIncome(address asset) external view returns (uint256); /** * @notice Returns the normalized variable debt per unit of asset * @dev WARNING: This function is intended to be used primarily by the protocol itself to get a * "dynamic" variable index based on time, current stored index and virtual rate at the current * moment (approx. a borrower would get if opening a position). This means that is always used in * combination with variable debt supply/balances. * If using this function externally, consider that is possible to have an increasing normalized * variable debt that is not equivalent to how the variable debt index would be updated in storage * (e.g. only updates with non-zero variable debt supply) * @param asset The address of the underlying asset of the reserve * @return The reserve normalized variable debt */ function getReserveNormalizedVariableDebt(address asset) external view returns (uint256); /** * @notice Returns the state and configuration of the reserve * @param asset The address of the underlying asset of the reserve * @return The state and configuration data of the reserve */ function getReserveData(address asset) external view returns (DataTypes.ReserveData memory); /** * @notice Validates and finalizes an aToken transfer * @dev Only callable by the overlying aToken of the `asset` * @param asset The address of the underlying asset of the aToken * @param from The user from which the aTokens are transferred * @param to The user receiving the aTokens * @param amount The amount being transferred/withdrawn * @param balanceFromBefore The aToken balance of the `from` user before the transfer * @param balanceToBefore The aToken balance of the `to` user before the transfer */ function finalizeTransfer( address asset, address from, address to, uint256 amount, uint256 balanceFromBefore, uint256 balanceToBefore ) external; /** * @notice Returns the list of the underlying assets of all the initialized reserves * @dev It does not include dropped reserves * @return The addresses of the underlying assets of the initialized reserves */ function getReservesList() external view returns (address[] memory); /** * @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct * @param id The id of the reserve as stored in the DataTypes.ReserveData struct * @return The address of the reserve associated with id */ function getReserveAddressById(uint16 id) external view returns (address); /** * @notice Returns the PoolAddressesProvider connected to this contract * @return The address of the PoolAddressesProvider */ function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider); /** * @notice Updates the protocol fee on the bridging * @param bridgeProtocolFee The part of the premium sent to the protocol treasury */ function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external; /** * @notice Updates flash loan premiums. Flash loan premium consists of two parts: * - A part is sent to aToken holders as extra, one time accumulated interest * - A part is collected by the protocol treasury * @dev The total premium is calculated on the total borrowed amount * @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal` * @dev Only callable by the PoolConfigurator contract * @param flashLoanPremiumTotal The total premium, expressed in bps * @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps */ function updateFlashloanPremiums( uint128 flashLoanPremiumTotal, uint128 flashLoanPremiumToProtocol ) external; /** * @notice Configures a new category for the eMode. * @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category. * The category 0 is reserved as it's the default for volatile assets * @param id The id of the category * @param config The configuration of the category */ function configureEModeCategory(uint8 id, DataTypes.EModeCategory memory config) external; /** * @notice Returns the data of an eMode category * @param id The id of the category * @return The configuration data of the category */ function getEModeCategoryData(uint8 id) external view returns (DataTypes.EModeCategory memory); /** * @notice Allows a user to use the protocol in eMode * @param categoryId The id of the category */ function setUserEMode(uint8 categoryId) external; /** * @notice Returns the eMode the user is using * @param user The address of the user * @return The eMode id */ function getUserEMode(address user) external view returns (uint256); /** * @notice Resets the isolation mode total debt of the given asset to zero * @dev It requires the given asset has zero debt ceiling * @param asset The address of the underlying asset to reset the isolationModeTotalDebt */ function resetIsolationModeTotalDebt(address asset) external; /** * @notice Returns the percentage of available liquidity that can be borrowed at once at stable rate * @return The percentage of available liquidity to borrow, expressed in bps */ function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() external view returns (uint256); /** * @notice Returns the total fee on flash loans * @return The total fee on flashloans */ function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128); /** * @notice Returns the part of the bridge fees sent to protocol * @return The bridge fee sent to the protocol treasury */ function BRIDGE_PROTOCOL_FEE() external view returns (uint256); /** * @notice Returns the part of the flashloan fees sent to protocol * @return The flashloan fee sent to the protocol treasury */ function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128); /** * @notice Returns the maximum number of reserves supported to be listed in this Pool * @return The maximum number of reserves supported */ function MAX_NUMBER_RESERVES() external view returns (uint16); /** * @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens * @param assets The list of reserves for which the minting needs to be executed */ function mintToTreasury(address[] calldata assets) external; /** * @notice Rescue and transfer tokens locked in this contract * @param token The address of the token * @param to The address of the recipient * @param amount The amount of token to transfer */ function rescueTokens( address token, address to, uint256 amount ) external; /** * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. * - E.g. User supplies 100 USDC and gets in return 100 aUSDC * @dev Deprecated: Use the `supply` function instead * @param asset The address of the underlying asset to supply * @param amount The amount to be supplied * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens * is a different wallet * @param referralCode Code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man */ function deposit( address asset, uint256 amount, address onBehalfOf, uint16 referralCode ) external; }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; /** * @title IPoolAddressesProvider * @author Aave * @notice Defines the basic interface for a Pool Addresses Provider. */ interface IPoolAddressesProvider { /** * @dev Emitted when the market identifier is updated. * @param oldMarketId The old id of the market * @param newMarketId The new id of the market */ event MarketIdSet(string indexed oldMarketId, string indexed newMarketId); /** * @dev Emitted when the pool is updated. * @param oldAddress The old address of the Pool * @param newAddress The new address of the Pool */ event PoolUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the pool configurator is updated. * @param oldAddress The old address of the PoolConfigurator * @param newAddress The new address of the PoolConfigurator */ event PoolConfiguratorUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the price oracle is updated. * @param oldAddress The old address of the PriceOracle * @param newAddress The new address of the PriceOracle */ event PriceOracleUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the ACL manager is updated. * @param oldAddress The old address of the ACLManager * @param newAddress The new address of the ACLManager */ event ACLManagerUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the ACL admin is updated. * @param oldAddress The old address of the ACLAdmin * @param newAddress The new address of the ACLAdmin */ event ACLAdminUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the price oracle sentinel is updated. * @param oldAddress The old address of the PriceOracleSentinel * @param newAddress The new address of the PriceOracleSentinel */ event PriceOracleSentinelUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the pool data provider is updated. * @param oldAddress The old address of the PoolDataProvider * @param newAddress The new address of the PoolDataProvider */ event PoolDataProviderUpdated(address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when a new proxy is created. * @param id The identifier of the proxy * @param proxyAddress The address of the created proxy contract * @param implementationAddress The address of the implementation contract */ event ProxyCreated( bytes32 indexed id, address indexed proxyAddress, address indexed implementationAddress ); /** * @dev Emitted when a new non-proxied contract address is registered. * @param id The identifier of the contract * @param oldAddress The address of the old contract * @param newAddress The address of the new contract */ event AddressSet(bytes32 indexed id, address indexed oldAddress, address indexed newAddress); /** * @dev Emitted when the implementation of the proxy registered with id is updated * @param id The identifier of the contract * @param proxyAddress The address of the proxy contract * @param oldImplementationAddress The address of the old implementation contract * @param newImplementationAddress The address of the new implementation contract */ event AddressSetAsProxy( bytes32 indexed id, address indexed proxyAddress, address oldImplementationAddress, address indexed newImplementationAddress ); /** * @notice Returns the id of the Aave market to which this contract points to. * @return The market id */ function getMarketId() external view returns (string memory); /** * @notice Associates an id with a specific PoolAddressesProvider. * @dev This can be used to create an onchain registry of PoolAddressesProviders to * identify and validate multiple Aave markets. * @param newMarketId The market id */ function setMarketId(string calldata newMarketId) external; /** * @notice Returns an address by its identifier. * @dev The returned address might be an EOA or a contract, potentially proxied * @dev It returns ZERO if there is no registered address with the given id * @param id The id * @return The address of the registered for the specified id */ function getAddress(bytes32 id) external view returns (address); /** * @notice General function to update the implementation of a proxy registered with * certain `id`. If there is no proxy registered, it will instantiate one and * set as implementation the `newImplementationAddress`. * @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit * setter function, in order to avoid unexpected consequences * @param id The id * @param newImplementationAddress The address of the new implementation */ function setAddressAsProxy(bytes32 id, address newImplementationAddress) external; /** * @notice Sets an address for an id replacing the address saved in the addresses map. * @dev IMPORTANT Use this function carefully, as it will do a hard replacement * @param id The id * @param newAddress The address to set */ function setAddress(bytes32 id, address newAddress) external; /** * @notice Returns the address of the Pool proxy. * @return The Pool proxy address */ function getPool() external view returns (address); /** * @notice Updates the implementation of the Pool, or creates a proxy * setting the new `pool` implementation when the function is called for the first time. * @param newPoolImpl The new Pool implementation */ function setPoolImpl(address newPoolImpl) external; /** * @notice Returns the address of the PoolConfigurator proxy. * @return The PoolConfigurator proxy address */ function getPoolConfigurator() external view returns (address); /** * @notice Updates the implementation of the PoolConfigurator, or creates a proxy * setting the new `PoolConfigurator` implementation when the function is called for the first time. * @param newPoolConfiguratorImpl The new PoolConfigurator implementation */ function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external; /** * @notice Returns the address of the price oracle. * @return The address of the PriceOracle */ function getPriceOracle() external view returns (address); /** * @notice Updates the address of the price oracle. * @param newPriceOracle The address of the new PriceOracle */ function setPriceOracle(address newPriceOracle) external; /** * @notice Returns the address of the ACL manager. * @return The address of the ACLManager */ function getACLManager() external view returns (address); /** * @notice Updates the address of the ACL manager. * @param newAclManager The address of the new ACLManager */ function setACLManager(address newAclManager) external; /** * @notice Returns the address of the ACL admin. * @return The address of the ACL admin */ function getACLAdmin() external view returns (address); /** * @notice Updates the address of the ACL admin. * @param newAclAdmin The address of the new ACL admin */ function setACLAdmin(address newAclAdmin) external; /** * @notice Returns the address of the price oracle sentinel. * @return The address of the PriceOracleSentinel */ function getPriceOracleSentinel() external view returns (address); /** * @notice Updates the address of the price oracle sentinel. * @param newPriceOracleSentinel The address of the new PriceOracleSentinel */ function setPriceOracleSentinel(address newPriceOracleSentinel) external; /** * @notice Returns the address of the data provider. * @return The address of the DataProvider */ function getPoolDataProvider() external view returns (address); /** * @notice Updates the address of the data provider. * @param newDataProvider The address of the new DataProvider */ function setPoolDataProvider(address newDataProvider) external; }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; /** * @title IScaledBalanceToken * @author Aave * @notice Defines the basic interface for a scaled-balance token. */ interface IScaledBalanceToken { /** * @dev Emitted after the mint action * @param caller The address performing the mint * @param onBehalfOf The address of the user that will receive the minted tokens * @param value The scaled-up amount being minted (based on user entered amount and balance increase from interest) * @param balanceIncrease The increase in scaled-up balance since the last action of 'onBehalfOf' * @param index The next liquidity index of the reserve */ event Mint( address indexed caller, address indexed onBehalfOf, uint256 value, uint256 balanceIncrease, uint256 index ); /** * @dev Emitted after the burn action * @dev If the burn function does not involve a transfer of the underlying asset, the target defaults to zero address * @param from The address from which the tokens will be burned * @param target The address that will receive the underlying, if any * @param value The scaled-up amount being burned (user entered amount - balance increase from interest) * @param balanceIncrease The increase in scaled-up balance since the last action of 'from' * @param index The next liquidity index of the reserve */ event Burn( address indexed from, address indexed target, uint256 value, uint256 balanceIncrease, uint256 index ); /** * @notice Returns the scaled balance of the user. * @dev The scaled balance is the sum of all the updated stored balance divided by the reserve's liquidity index * at the moment of the update * @param user The user whose balance is calculated * @return The scaled balance of the user */ function scaledBalanceOf(address user) external view returns (uint256); /** * @notice Returns the scaled balance of the user and the scaled total supply. * @param user The address of the user * @return The scaled balance of the user * @return The scaled total supply */ function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256); /** * @notice Returns the scaled total supply of the scaled balance token. Represents sum(debt/index) * @return The scaled total supply */ function scaledTotalSupply() external view returns (uint256); /** * @notice Returns last index interest was accrued to the user's balance * @param user The address of the user * @return The last index interest was accrued to the user's balance, expressed in ray */ function getPreviousIndex(address user) external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; /** * @title Errors library * @author Aave * @notice Defines the error messages emitted by the different contracts of the Aave protocol */ library Errors { string public constant CALLER_NOT_POOL_ADMIN = '1'; // 'The caller of the function is not a pool admin' string public constant CALLER_NOT_EMERGENCY_ADMIN = '2'; // 'The caller of the function is not an emergency admin' string public constant CALLER_NOT_POOL_OR_EMERGENCY_ADMIN = '3'; // 'The caller of the function is not a pool or emergency admin' string public constant CALLER_NOT_RISK_OR_POOL_ADMIN = '4'; // 'The caller of the function is not a risk or pool admin' string public constant CALLER_NOT_ASSET_LISTING_OR_POOL_ADMIN = '5'; // 'The caller of the function is not an asset listing or pool admin' string public constant CALLER_NOT_BRIDGE = '6'; // 'The caller of the function is not a bridge' string public constant ADDRESSES_PROVIDER_NOT_REGISTERED = '7'; // 'Pool addresses provider is not registered' string public constant INVALID_ADDRESSES_PROVIDER_ID = '8'; // 'Invalid id for the pool addresses provider' string public constant NOT_CONTRACT = '9'; // 'Address is not a contract' string public constant CALLER_NOT_POOL_CONFIGURATOR = '10'; // 'The caller of the function is not the pool configurator' string public constant CALLER_NOT_ATOKEN = '11'; // 'The caller of the function is not an AToken' string public constant INVALID_ADDRESSES_PROVIDER = '12'; // 'The address of the pool addresses provider is invalid' string public constant INVALID_FLASHLOAN_EXECUTOR_RETURN = '13'; // 'Invalid return value of the flashloan executor function' string public constant RESERVE_ALREADY_ADDED = '14'; // 'Reserve has already been added to reserve list' string public constant NO_MORE_RESERVES_ALLOWED = '15'; // 'Maximum amount of reserves in the pool reached' string public constant EMODE_CATEGORY_RESERVED = '16'; // 'Zero eMode category is reserved for volatile heterogeneous assets' string public constant INVALID_EMODE_CATEGORY_ASSIGNMENT = '17'; // 'Invalid eMode category assignment to asset' string public constant RESERVE_LIQUIDITY_NOT_ZERO = '18'; // 'The liquidity of the reserve needs to be 0' string public constant FLASHLOAN_PREMIUM_INVALID = '19'; // 'Invalid flashloan premium' string public constant INVALID_RESERVE_PARAMS = '20'; // 'Invalid risk parameters for the reserve' string public constant INVALID_EMODE_CATEGORY_PARAMS = '21'; // 'Invalid risk parameters for the eMode category' string public constant BRIDGE_PROTOCOL_FEE_INVALID = '22'; // 'Invalid bridge protocol fee' string public constant CALLER_MUST_BE_POOL = '23'; // 'The caller of this function must be a pool' string public constant INVALID_MINT_AMOUNT = '24'; // 'Invalid amount to mint' string public constant INVALID_BURN_AMOUNT = '25'; // 'Invalid amount to burn' string public constant INVALID_AMOUNT = '26'; // 'Amount must be greater than 0' string public constant RESERVE_INACTIVE = '27'; // 'Action requires an active reserve' string public constant RESERVE_FROZEN = '28'; // 'Action cannot be performed because the reserve is frozen' string public constant RESERVE_PAUSED = '29'; // 'Action cannot be performed because the reserve is paused' string public constant BORROWING_NOT_ENABLED = '30'; // 'Borrowing is not enabled' string public constant STABLE_BORROWING_NOT_ENABLED = '31'; // 'Stable borrowing is not enabled' string public constant NOT_ENOUGH_AVAILABLE_USER_BALANCE = '32'; // 'User cannot withdraw more than the available balance' string public constant INVALID_INTEREST_RATE_MODE_SELECTED = '33'; // 'Invalid interest rate mode selected' string public constant COLLATERAL_BALANCE_IS_ZERO = '34'; // 'The collateral balance is 0' string public constant HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = '35'; // 'Health factor is lesser than the liquidation threshold' string public constant COLLATERAL_CANNOT_COVER_NEW_BORROW = '36'; // 'There is not enough collateral to cover a new borrow' string public constant COLLATERAL_SAME_AS_BORROWING_CURRENCY = '37'; // 'Collateral is (mostly) the same currency that is being borrowed' string public constant AMOUNT_BIGGER_THAN_MAX_LOAN_SIZE_STABLE = '38'; // 'The requested amount is greater than the max loan size in stable rate mode' string public constant NO_DEBT_OF_SELECTED_TYPE = '39'; // 'For repayment of a specific type of debt, the user needs to have debt that type' string public constant NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = '40'; // 'To repay on behalf of a user an explicit amount to repay is needed' string public constant NO_OUTSTANDING_STABLE_DEBT = '41'; // 'User does not have outstanding stable rate debt on this reserve' string public constant NO_OUTSTANDING_VARIABLE_DEBT = '42'; // 'User does not have outstanding variable rate debt on this reserve' string public constant UNDERLYING_BALANCE_ZERO = '43'; // 'The underlying balance needs to be greater than 0' string public constant INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET = '44'; // 'Interest rate rebalance conditions were not met' string public constant HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '45'; // 'Health factor is not below the threshold' string public constant COLLATERAL_CANNOT_BE_LIQUIDATED = '46'; // 'The collateral chosen cannot be liquidated' string public constant SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = '47'; // 'User did not borrow the specified currency' string public constant INCONSISTENT_FLASHLOAN_PARAMS = '49'; // 'Inconsistent flashloan parameters' string public constant BORROW_CAP_EXCEEDED = '50'; // 'Borrow cap is exceeded' string public constant SUPPLY_CAP_EXCEEDED = '51'; // 'Supply cap is exceeded' string public constant UNBACKED_MINT_CAP_EXCEEDED = '52'; // 'Unbacked mint cap is exceeded' string public constant DEBT_CEILING_EXCEEDED = '53'; // 'Debt ceiling is exceeded' string public constant UNDERLYING_CLAIMABLE_RIGHTS_NOT_ZERO = '54'; // 'Claimable rights over underlying not zero (aToken supply or accruedToTreasury)' string public constant STABLE_DEBT_NOT_ZERO = '55'; // 'Stable debt supply is not zero' string public constant VARIABLE_DEBT_SUPPLY_NOT_ZERO = '56'; // 'Variable debt supply is not zero' string public constant LTV_VALIDATION_FAILED = '57'; // 'Ltv validation failed' string public constant INCONSISTENT_EMODE_CATEGORY = '58'; // 'Inconsistent eMode category' string public constant PRICE_ORACLE_SENTINEL_CHECK_FAILED = '59'; // 'Price oracle sentinel validation failed' string public constant ASSET_NOT_BORROWABLE_IN_ISOLATION = '60'; // 'Asset is not borrowable in isolation mode' string public constant RESERVE_ALREADY_INITIALIZED = '61'; // 'Reserve has already been initialized' string public constant USER_IN_ISOLATION_MODE = '62'; // 'User is in isolation mode' string public constant INVALID_LTV = '63'; // 'Invalid ltv parameter for the reserve' string public constant INVALID_LIQ_THRESHOLD = '64'; // 'Invalid liquidity threshold parameter for the reserve' string public constant INVALID_LIQ_BONUS = '65'; // 'Invalid liquidity bonus parameter for the reserve' string public constant INVALID_DECIMALS = '66'; // 'Invalid decimals parameter of the underlying asset of the reserve' string public constant INVALID_RESERVE_FACTOR = '67'; // 'Invalid reserve factor parameter for the reserve' string public constant INVALID_BORROW_CAP = '68'; // 'Invalid borrow cap for the reserve' string public constant INVALID_SUPPLY_CAP = '69'; // 'Invalid supply cap for the reserve' string public constant INVALID_LIQUIDATION_PROTOCOL_FEE = '70'; // 'Invalid liquidation protocol fee for the reserve' string public constant INVALID_EMODE_CATEGORY = '71'; // 'Invalid eMode category for the reserve' string public constant INVALID_UNBACKED_MINT_CAP = '72'; // 'Invalid unbacked mint cap for the reserve' string public constant INVALID_DEBT_CEILING = '73'; // 'Invalid debt ceiling for the reserve string public constant INVALID_RESERVE_INDEX = '74'; // 'Invalid reserve index' string public constant ACL_ADMIN_CANNOT_BE_ZERO = '75'; // 'ACL admin cannot be set to the zero address' string public constant INCONSISTENT_PARAMS_LENGTH = '76'; // 'Array parameters that should be equal length are not' string public constant ZERO_ADDRESS_NOT_VALID = '77'; // 'Zero address not valid' string public constant INVALID_EXPIRATION = '78'; // 'Invalid expiration' string public constant INVALID_SIGNATURE = '79'; // 'Invalid signature' string public constant OPERATION_NOT_SUPPORTED = '80'; // 'Operation not supported' string public constant DEBT_CEILING_NOT_ZERO = '81'; // 'Debt ceiling is not zero' string public constant ASSET_NOT_LISTED = '82'; // 'Asset is not listed' string public constant INVALID_OPTIMAL_USAGE_RATIO = '83'; // 'Invalid optimal usage ratio' string public constant INVALID_OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO = '84'; // 'Invalid optimal stable to total debt ratio' string public constant UNDERLYING_CANNOT_BE_RESCUED = '85'; // 'The underlying asset cannot be rescued' string public constant ADDRESSES_PROVIDER_ALREADY_ADDED = '86'; // 'Reserve has already been added to reserve list' string public constant POOL_ADDRESSES_DO_NOT_MATCH = '87'; // 'The token implementation pool address and the pool address provided by the initializing pool do not match' string public constant STABLE_BORROWING_ENABLED = '88'; // 'Stable borrowing is enabled' string public constant SILOED_BORROWING_VIOLATION = '89'; // 'User is trying to borrow multiple assets including a siloed one' string public constant RESERVE_DEBT_NOT_ZERO = '90'; // the total debt of the reserve needs to be 0 string public constant FLASHLOAN_DISABLED = '91'; // FlashLoaning for this asset is disabled }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; /** * @title WadRayMath library * @author Aave * @notice Provides functions to perform calculations with Wad and Ray units * @dev Provides mul and div function for wads (decimal numbers with 18 digits of precision) and rays (decimal numbers * with 27 digits of precision) * @dev Operations are rounded. If a value is >=.5, will be rounded up, otherwise rounded down. */ library WadRayMath { // HALF_WAD and HALF_RAY expressed with extended notation as constant with operations are not supported in Yul assembly uint256 internal constant WAD = 1e18; uint256 internal constant HALF_WAD = 0.5e18; uint256 internal constant RAY = 1e27; uint256 internal constant HALF_RAY = 0.5e27; uint256 internal constant WAD_RAY_RATIO = 1e9; /** * @dev Multiplies two wad, rounding half up to the nearest wad * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Wad * @param b Wad * @return c = a*b, in wad */ function wadMul(uint256 a, uint256 b) internal pure returns (uint256 c) { // to avoid overflow, a <= (type(uint256).max - HALF_WAD) / b assembly { if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_WAD), b))))) { revert(0, 0) } c := div(add(mul(a, b), HALF_WAD), WAD) } } /** * @dev Divides two wad, rounding half up to the nearest wad * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Wad * @param b Wad * @return c = a/b, in wad */ function wadDiv(uint256 a, uint256 b) internal pure returns (uint256 c) { // to avoid overflow, a <= (type(uint256).max - halfB) / WAD assembly { if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), WAD))))) { revert(0, 0) } c := div(add(mul(a, WAD), div(b, 2)), b) } } /** * @notice Multiplies two ray, rounding half up to the nearest ray * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Ray * @param b Ray * @return c = a raymul b */ function rayMul(uint256 a, uint256 b) internal pure returns (uint256 c) { // to avoid overflow, a <= (type(uint256).max - HALF_RAY) / b assembly { if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_RAY), b))))) { revert(0, 0) } c := div(add(mul(a, b), HALF_RAY), RAY) } } /** * @notice Divides two ray, rounding half up to the nearest ray * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Ray * @param b Ray * @return c = a raydiv b */ function rayDiv(uint256 a, uint256 b) internal pure returns (uint256 c) { // to avoid overflow, a <= (type(uint256).max - halfB) / RAY assembly { if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), RAY))))) { revert(0, 0) } c := div(add(mul(a, RAY), div(b, 2)), b) } } /** * @dev Casts ray down to wad * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Ray * @return b = a converted to wad, rounded half up to the nearest wad */ function rayToWad(uint256 a) internal pure returns (uint256 b) { assembly { b := div(a, WAD_RAY_RATIO) let remainder := mod(a, WAD_RAY_RATIO) if iszero(lt(remainder, div(WAD_RAY_RATIO, 2))) { b := add(b, 1) } } } /** * @dev Converts wad up to ray * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328 * @param a Wad * @return b = a converted in ray */ function wadToRay(uint256 a) internal pure returns (uint256 b) { // to avoid overflow, b/WAD_RAY_RATIO == a assembly { b := mul(a, WAD_RAY_RATIO) if iszero(eq(div(b, WAD_RAY_RATIO), a)) { revert(0, 0) } } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; library DataTypes { struct ReserveData { //stores the reserve configuration ReserveConfigurationMap configuration; //the liquidity index. Expressed in ray uint128 liquidityIndex; //the current supply rate. Expressed in ray uint128 currentLiquidityRate; //variable borrow index. Expressed in ray uint128 variableBorrowIndex; //the current variable borrow rate. Expressed in ray uint128 currentVariableBorrowRate; //the current stable borrow rate. Expressed in ray uint128 currentStableBorrowRate; //timestamp of last update uint40 lastUpdateTimestamp; //the id of the reserve. Represents the position in the list of the active reserves uint16 id; //aToken address address aTokenAddress; //stableDebtToken address address stableDebtTokenAddress; //variableDebtToken address address variableDebtTokenAddress; //address of the interest rate strategy address interestRateStrategyAddress; //the current treasury balance, scaled uint128 accruedToTreasury; //the outstanding unbacked aTokens minted through the bridging feature uint128 unbacked; //the outstanding debt borrowed against this asset in isolation mode uint128 isolationModeTotalDebt; } struct ReserveConfigurationMap { //bit 0-15: LTV //bit 16-31: Liq. threshold //bit 32-47: Liq. bonus //bit 48-55: Decimals //bit 56: reserve is active //bit 57: reserve is frozen //bit 58: borrowing is enabled //bit 59: stable rate borrowing enabled //bit 60: asset is paused //bit 61: borrowing in isolation mode is enabled //bit 62-63: reserved //bit 64-79: reserve factor //bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap //bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap //bit 152-167 liquidation protocol fee //bit 168-175 eMode category //bit 176-211 unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled //bit 212-251 debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals //bit 252-255 unused uint256 data; } struct UserConfigurationMap { /** * @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset. * The first bit indicates if an asset is used as collateral by the user, the second whether an * asset is borrowed by the user. */ uint256 data; } struct EModeCategory { // each eMode category has a custom ltv and liquidation threshold uint16 ltv; uint16 liquidationThreshold; uint16 liquidationBonus; // each eMode category may or may not have a custom oracle to override the individual assets price oracles address priceSource; string label; } enum InterestRateMode { NONE, STABLE, VARIABLE } struct ReserveCache { uint256 currScaledVariableDebt; uint256 nextScaledVariableDebt; uint256 currPrincipalStableDebt; uint256 currAvgStableBorrowRate; uint256 currTotalStableDebt; uint256 nextAvgStableBorrowRate; uint256 nextTotalStableDebt; uint256 currLiquidityIndex; uint256 nextLiquidityIndex; uint256 currVariableBorrowIndex; uint256 nextVariableBorrowIndex; uint256 currLiquidityRate; uint256 currVariableBorrowRate; uint256 reserveFactor; ReserveConfigurationMap reserveConfiguration; address aTokenAddress; address stableDebtTokenAddress; address variableDebtTokenAddress; uint40 reserveLastUpdateTimestamp; uint40 stableDebtLastUpdateTimestamp; } struct ExecuteLiquidationCallParams { uint256 reservesCount; uint256 debtToCover; address collateralAsset; address debtAsset; address user; bool receiveAToken; address priceOracle; uint8 userEModeCategory; address priceOracleSentinel; } struct ExecuteSupplyParams { address asset; uint256 amount; address onBehalfOf; uint16 referralCode; } struct ExecuteBorrowParams { address asset; address user; address onBehalfOf; uint256 amount; InterestRateMode interestRateMode; uint16 referralCode; bool releaseUnderlying; uint256 maxStableRateBorrowSizePercent; uint256 reservesCount; address oracle; uint8 userEModeCategory; address priceOracleSentinel; } struct ExecuteRepayParams { address asset; uint256 amount; InterestRateMode interestRateMode; address onBehalfOf; bool useATokens; } struct ExecuteWithdrawParams { address asset; uint256 amount; address to; uint256 reservesCount; address oracle; uint8 userEModeCategory; } struct ExecuteSetUserEModeParams { uint256 reservesCount; address oracle; uint8 categoryId; } struct FinalizeTransferParams { address asset; address from; address to; uint256 amount; uint256 balanceFromBefore; uint256 balanceToBefore; uint256 reservesCount; address oracle; uint8 fromEModeCategory; } struct FlashloanParams { address receiverAddress; address[] assets; uint256[] amounts; uint256[] interestRateModes; address onBehalfOf; bytes params; uint16 referralCode; uint256 flashLoanPremiumToProtocol; uint256 flashLoanPremiumTotal; uint256 maxStableRateBorrowSizePercent; uint256 reservesCount; address addressesProvider; uint8 userEModeCategory; bool isAuthorizedFlashBorrower; } struct FlashloanSimpleParams { address receiverAddress; address asset; uint256 amount; bytes params; uint16 referralCode; uint256 flashLoanPremiumToProtocol; uint256 flashLoanPremiumTotal; } struct FlashLoanRepaymentParams { uint256 amount; uint256 totalPremium; uint256 flashLoanPremiumToProtocol; address asset; address receiverAddress; uint16 referralCode; } struct CalculateUserAccountDataParams { UserConfigurationMap userConfig; uint256 reservesCount; address user; address oracle; uint8 userEModeCategory; } struct ValidateBorrowParams { ReserveCache reserveCache; UserConfigurationMap userConfig; address asset; address userAddress; uint256 amount; InterestRateMode interestRateMode; uint256 maxStableLoanPercent; uint256 reservesCount; address oracle; uint8 userEModeCategory; address priceOracleSentinel; bool isolationModeActive; address isolationModeCollateralAddress; uint256 isolationModeDebtCeiling; } struct ValidateLiquidationCallParams { ReserveCache debtReserveCache; uint256 totalDebt; uint256 healthFactor; address priceOracleSentinel; } struct CalculateInterestRatesParams { uint256 unbacked; uint256 liquidityAdded; uint256 liquidityTaken; uint256 totalStableDebt; uint256 totalVariableDebt; uint256 averageStableBorrowRate; uint256 reserveFactor; address reserve; address aToken; } struct InitReserveParams { address asset; address aTokenAddress; address stableDebtAddress; address variableDebtAddress; address interestRateStrategyAddress; uint16 reservesCount; uint16 maxNumberReserves; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.10; import {Context} from '../../../dependencies/openzeppelin/contracts/Context.sol'; import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol'; import {IERC20Detailed} from '../../../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; import {SafeCast} from '../../../dependencies/openzeppelin/contracts/SafeCast.sol'; import {WadRayMath} from '../../libraries/math/WadRayMath.sol'; import {Errors} from '../../libraries/helpers/Errors.sol'; import {IAaveIncentivesController} from '../../../interfaces/IAaveIncentivesController.sol'; import {IPoolAddressesProvider} from '../../../interfaces/IPoolAddressesProvider.sol'; import {IPool} from '../../../interfaces/IPool.sol'; import {IACLManager} from '../../../interfaces/IACLManager.sol'; /** * @title IncentivizedERC20 * @author Aave, inspired by the Openzeppelin ERC20 implementation * @notice Basic ERC20 implementation */ abstract contract IncentivizedERC20 is Context, IERC20Detailed { using WadRayMath for uint256; using SafeCast for uint256; /** * @dev Only pool admin can call functions marked by this modifier. */ modifier onlyPoolAdmin() { IACLManager aclManager = IACLManager(_addressesProvider.getACLManager()); require(aclManager.isPoolAdmin(msg.sender), Errors.CALLER_NOT_POOL_ADMIN); _; } /** * @dev Only pool can call functions marked by this modifier. */ modifier onlyPool() { require(_msgSender() == address(POOL), Errors.CALLER_MUST_BE_POOL); _; } /** * @dev UserState - additionalData is a flexible field. * ATokens and VariableDebtTokens use this field store the index of the * user's last supply/withdrawal/borrow/repayment. StableDebtTokens use * this field to store the user's stable rate. */ struct UserState { uint128 balance; uint128 additionalData; } // Map of users address and their state data (userAddress => userStateData) mapping(address => UserState) internal _userState; // Map of allowances (delegator => delegatee => allowanceAmount) mapping(address => mapping(address => uint256)) private _allowances; uint256 internal _totalSupply; string private _name; string private _symbol; uint8 private _decimals; IAaveIncentivesController internal _incentivesController; IPoolAddressesProvider internal immutable _addressesProvider; IPool public immutable POOL; /** * @dev Constructor. * @param pool The reference to the main Pool contract * @param name The name of the token * @param symbol The symbol of the token * @param decimals The number of decimals of the token */ constructor( IPool pool, string memory name, string memory symbol, uint8 decimals ) { _addressesProvider = pool.ADDRESSES_PROVIDER(); _name = name; _symbol = symbol; _decimals = decimals; POOL = pool; } /// @inheritdoc IERC20Detailed function name() public view override returns (string memory) { return _name; } /// @inheritdoc IERC20Detailed function symbol() external view override returns (string memory) { return _symbol; } /// @inheritdoc IERC20Detailed function decimals() external view override returns (uint8) { return _decimals; } /// @inheritdoc IERC20 function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /// @inheritdoc IERC20 function balanceOf(address account) public view virtual override returns (uint256) { return _userState[account].balance; } /** * @notice Returns the address of the Incentives Controller contract * @return The address of the Incentives Controller */ function getIncentivesController() external view virtual returns (IAaveIncentivesController) { return _incentivesController; } /** * @notice Sets a new Incentives Controller * @param controller the new Incentives controller */ function setIncentivesController(IAaveIncentivesController controller) external onlyPoolAdmin { _incentivesController = controller; } /// @inheritdoc IERC20 function transfer(address recipient, uint256 amount) external virtual override returns (bool) { uint128 castAmount = amount.toUint128(); _transfer(_msgSender(), recipient, castAmount); return true; } /// @inheritdoc IERC20 function allowance(address owner, address spender) external view virtual override returns (uint256) { return _allowances[owner][spender]; } /// @inheritdoc IERC20 function approve(address spender, uint256 amount) external virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /// @inheritdoc IERC20 function transferFrom( address sender, address recipient, uint256 amount ) external virtual override returns (bool) { uint128 castAmount = amount.toUint128(); _approve(sender, _msgSender(), _allowances[sender][_msgSender()] - castAmount); _transfer(sender, recipient, castAmount); return true; } /** * @notice Increases the allowance of spender to spend _msgSender() tokens * @param spender The user allowed to spend on behalf of _msgSender() * @param addedValue The amount being added to the allowance * @return `true` */ function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @notice Decreases the allowance of spender to spend _msgSender() tokens * @param spender The user allowed to spend on behalf of _msgSender() * @param subtractedValue The amount being subtracted to the allowance * @return `true` */ function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] - subtractedValue); return true; } /** * @notice Transfers tokens between two users and apply incentives if defined. * @param sender The source address * @param recipient The destination address * @param amount The amount getting transferred */ function _transfer( address sender, address recipient, uint128 amount ) internal virtual { uint128 oldSenderBalance = _userState[sender].balance; _userState[sender].balance = oldSenderBalance - amount; uint128 oldRecipientBalance = _userState[recipient].balance; _userState[recipient].balance = oldRecipientBalance + amount; IAaveIncentivesController incentivesControllerLocal = _incentivesController; if (address(incentivesControllerLocal) != address(0)) { uint256 currentTotalSupply = _totalSupply; incentivesControllerLocal.handleAction(sender, currentTotalSupply, oldSenderBalance); if (sender != recipient) { incentivesControllerLocal.handleAction(recipient, currentTotalSupply, oldRecipientBalance); } } } /** * @notice Approve `spender` to use `amount` of `owner`s balance * @param owner The address owning the tokens * @param spender The address approved for spending * @param amount The amount of tokens to approve spending of */ function _approve( address owner, address spender, uint256 amount ) internal virtual { _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @notice Update the name of the token * @param newName The new name for the token */ function _setName(string memory newName) internal { _name = newName; } /** * @notice Update the symbol for the token * @param newSymbol The new symbol for the token */ function _setSymbol(string memory newSymbol) internal { _symbol = newSymbol; } /** * @notice Update the number of decimals for the token * @param newDecimals The new number of decimals for the token */ function _setDecimals(uint8 newDecimals) internal { _decimals = newDecimals; } }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; interface IEACAggregatorProxy { function decimals() external view returns (uint8); function latestAnswer() external view returns (int256); function latestTimestamp() external view returns (uint256); function latestRound() external view returns (uint256); function getAnswer(uint256 roundId) external view returns (int256); function getTimestamp(uint256 roundId) external view returns (uint256); event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp); event NewRound(uint256 indexed roundId, address indexed startedBy); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; import {IRewardsDistributor} from './IRewardsDistributor.sol'; import {ITransferStrategyBase} from './ITransferStrategyBase.sol'; import {IEACAggregatorProxy} from '../../misc/interfaces/IEACAggregatorProxy.sol'; import {RewardsDataTypes} from '../libraries/RewardsDataTypes.sol'; /** * @title IRewardsController * @author Aave * @notice Defines the basic interface for a Rewards Controller. */ interface IRewardsController is IRewardsDistributor { /** * @dev Emitted when a new address is whitelisted as claimer of rewards on behalf of a user * @param user The address of the user * @param claimer The address of the claimer */ event ClaimerSet(address indexed user, address indexed claimer); /** * @dev Emitted when rewards are claimed * @param user The address of the user rewards has been claimed on behalf of * @param reward The address of the token reward is claimed * @param to The address of the receiver of the rewards * @param claimer The address of the claimer * @param amount The amount of rewards claimed */ event RewardsClaimed( address indexed user, address indexed reward, address indexed to, address claimer, uint256 amount ); /** * @dev Emitted when a transfer strategy is installed for the reward distribution * @param reward The address of the token reward * @param transferStrategy The address of TransferStrategy contract */ event TransferStrategyInstalled(address indexed reward, address indexed transferStrategy); /** * @dev Emitted when the reward oracle is updated * @param reward The address of the token reward * @param rewardOracle The address of oracle */ event RewardOracleUpdated(address indexed reward, address indexed rewardOracle); /** * @dev Whitelists an address to claim the rewards on behalf of another address * @param user The address of the user * @param claimer The address of the claimer */ function setClaimer(address user, address claimer) external; /** * @dev Sets a TransferStrategy logic contract that determines the logic of the rewards transfer * @param reward The address of the reward token * @param transferStrategy The address of the TransferStrategy logic contract */ function setTransferStrategy(address reward, ITransferStrategyBase transferStrategy) external; /** * @dev Sets an Aave Oracle contract to enforce rewards with a source of value. * @notice At the moment of reward configuration, the Incentives Controller performs * a check to see if the reward asset oracle is compatible with IEACAggregator proxy. * This check is enforced for integrators to be able to show incentives at * the current Aave UI without the need to setup an external price registry * @param reward The address of the reward to set the price aggregator * @param rewardOracle The address of price aggregator that follows IEACAggregatorProxy interface */ function setRewardOracle(address reward, IEACAggregatorProxy rewardOracle) external; /** * @dev Get the price aggregator oracle address * @param reward The address of the reward * @return The price oracle of the reward */ function getRewardOracle(address reward) external view returns (address); /** * @dev Returns the whitelisted claimer for a certain address (0x0 if not set) * @param user The address of the user * @return The claimer address */ function getClaimer(address user) external view returns (address); /** * @dev Returns the Transfer Strategy implementation contract address being used for a reward address * @param reward The address of the reward * @return The address of the TransferStrategy contract */ function getTransferStrategy(address reward) external view returns (address); /** * @dev Configure assets to incentivize with an emission of rewards per second until the end of distribution. * @param config The assets configuration input, the list of structs contains the following fields: * uint104 emissionPerSecond: The emission per second following rewards unit decimals. * uint256 totalSupply: The total supply of the asset to incentivize * uint40 distributionEnd: The end of the distribution of the incentives for an asset * address asset: The asset address to incentivize * address reward: The reward token address * ITransferStrategy transferStrategy: The TransferStrategy address with the install hook and claim logic. * IEACAggregatorProxy rewardOracle: The Price Oracle of a reward to visualize the incentives at the UI Frontend. * Must follow Chainlink Aggregator IEACAggregatorProxy interface to be compatible. */ function configureAssets(RewardsDataTypes.RewardsConfigInput[] memory config) external; /** * @dev Called by the corresponding asset on transfer hook in order to update the rewards distribution. * @dev The units of `totalSupply` and `userBalance` should be the same. * @param user The address of the user whose asset balance has changed * @param totalSupply The total supply of the asset prior to user balance change * @param userBalance The previous user balance prior to balance change **/ function handleAction( address user, uint256 totalSupply, uint256 userBalance ) external; /** * @dev Claims reward for a user to the desired address, on all the assets of the pool, accumulating the pending rewards * @param assets List of assets to check eligible distributions before claiming rewards * @param amount The amount of rewards to claim * @param to The address that will be receiving the rewards * @param reward The address of the reward token * @return The amount of rewards claimed **/ function claimRewards( address[] calldata assets, uint256 amount, address to, address reward ) external returns (uint256); /** * @dev Claims reward for a user on behalf, on all the assets of the pool, accumulating the pending rewards. The * caller must be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager * @param assets The list of assets to check eligible distributions before claiming rewards * @param amount The amount of rewards to claim * @param user The address to check and claim rewards * @param to The address that will be receiving the rewards * @param reward The address of the reward token * @return The amount of rewards claimed **/ function claimRewardsOnBehalf( address[] calldata assets, uint256 amount, address user, address to, address reward ) external returns (uint256); /** * @dev Claims reward for msg.sender, on all the assets of the pool, accumulating the pending rewards * @param assets The list of assets to check eligible distributions before claiming rewards * @param amount The amount of rewards to claim * @param reward The address of the reward token * @return The amount of rewards claimed **/ function claimRewardsToSelf( address[] calldata assets, uint256 amount, address reward ) external returns (uint256); /** * @dev Claims all rewards for a user to the desired address, on all the assets of the pool, accumulating the pending rewards * @param assets The list of assets to check eligible distributions before claiming rewards * @param to The address that will be receiving the rewards * @return rewardsList List of addresses of the reward tokens * @return claimedAmounts List that contains the claimed amount per reward, following same order as "rewardList" **/ function claimAllRewards(address[] calldata assets, address to) external returns (address[] memory rewardsList, uint256[] memory claimedAmounts); /** * @dev Claims all rewards for a user on behalf, on all the assets of the pool, accumulating the pending rewards. The caller must * be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager * @param assets The list of assets to check eligible distributions before claiming rewards * @param user The address to check and claim rewards * @param to The address that will be receiving the rewards * @return rewardsList List of addresses of the reward tokens * @return claimedAmounts List that contains the claimed amount per reward, following same order as "rewardsList" **/ function claimAllRewardsOnBehalf( address[] calldata assets, address user, address to ) external returns (address[] memory rewardsList, uint256[] memory claimedAmounts); /** * @dev Claims all reward for msg.sender, on all the assets of the pool, accumulating the pending rewards * @param assets The list of assets to check eligible distributions before claiming rewards * @return rewardsList List of addresses of the reward tokens * @return claimedAmounts List that contains the claimed amount per reward, following same order as "rewardsList" **/ function claimAllRewardsToSelf(address[] calldata assets) external returns (address[] memory rewardsList, uint256[] memory claimedAmounts); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; /** * @title IRewardsDistributor * @author Aave * @notice Defines the basic interface for a Rewards Distributor. */ interface IRewardsDistributor { /** * @dev Emitted when the configuration of the rewards of an asset is updated. * @param asset The address of the incentivized asset * @param reward The address of the reward token * @param oldEmission The old emissions per second value of the reward distribution * @param newEmission The new emissions per second value of the reward distribution * @param oldDistributionEnd The old end timestamp of the reward distribution * @param newDistributionEnd The new end timestamp of the reward distribution * @param assetIndex The index of the asset distribution */ event AssetConfigUpdated( address indexed asset, address indexed reward, uint256 oldEmission, uint256 newEmission, uint256 oldDistributionEnd, uint256 newDistributionEnd, uint256 assetIndex ); /** * @dev Emitted when rewards of an asset are accrued on behalf of a user. * @param asset The address of the incentivized asset * @param reward The address of the reward token * @param user The address of the user that rewards are accrued on behalf of * @param assetIndex The index of the asset distribution * @param userIndex The index of the asset distribution on behalf of the user * @param rewardsAccrued The amount of rewards accrued */ event Accrued( address indexed asset, address indexed reward, address indexed user, uint256 assetIndex, uint256 userIndex, uint256 rewardsAccrued ); /** * @dev Sets the end date for the distribution * @param asset The asset to incentivize * @param reward The reward token that incentives the asset * @param newDistributionEnd The end date of the incentivization, in unix time format **/ function setDistributionEnd( address asset, address reward, uint32 newDistributionEnd ) external; /** * @dev Sets the emission per second of a set of reward distributions * @param asset The asset is being incentivized * @param rewards List of reward addresses are being distributed * @param newEmissionsPerSecond List of new reward emissions per second */ function setEmissionPerSecond( address asset, address[] calldata rewards, uint88[] calldata newEmissionsPerSecond ) external; /** * @dev Gets the end date for the distribution * @param asset The incentivized asset * @param reward The reward token of the incentivized asset * @return The timestamp with the end of the distribution, in unix time format **/ function getDistributionEnd(address asset, address reward) external view returns (uint256); /** * @dev Returns the index of a user on a reward distribution * @param user Address of the user * @param asset The incentivized asset * @param reward The reward token of the incentivized asset * @return The current user asset index, not including new distributions **/ function getUserAssetIndex( address user, address asset, address reward ) external view returns (uint256); /** * @dev Returns the configuration of the distribution reward for a certain asset * @param asset The incentivized asset * @param reward The reward token of the incentivized asset * @return The index of the asset distribution * @return The emission per second of the reward distribution * @return The timestamp of the last update of the index * @return The timestamp of the distribution end **/ function getRewardsData(address asset, address reward) external view returns ( uint256, uint256, uint256, uint256 ); /** * @dev Calculates the next value of an specific distribution index, with validations. * @param asset The incentivized asset * @param reward The reward token of the incentivized asset * @return The old index of the asset distribution * @return The new index of the asset distribution **/ function getAssetIndex(address asset, address reward) external view returns (uint256, uint256); /** * @dev Returns the list of available reward token addresses of an incentivized asset * @param asset The incentivized asset * @return List of rewards addresses of the input asset **/ function getRewardsByAsset(address asset) external view returns (address[] memory); /** * @dev Returns the list of available reward addresses * @return List of rewards supported in this contract **/ function getRewardsList() external view returns (address[] memory); /** * @dev Returns the accrued rewards balance of a user, not including virtually accrued rewards since last distribution. * @param user The address of the user * @param reward The address of the reward token * @return Unclaimed rewards, not including new distributions **/ function getUserAccruedRewards(address user, address reward) external view returns (uint256); /** * @dev Returns a single rewards balance of a user, including virtually accrued and unrealized claimable rewards. * @param assets List of incentivized assets to check eligible distributions * @param user The address of the user * @param reward The address of the reward token * @return The rewards amount **/ function getUserRewards( address[] calldata assets, address user, address reward ) external view returns (uint256); /** * @dev Returns a list all rewards of a user, including already accrued and unrealized claimable rewards * @param assets List of incentivized assets to check eligible distributions * @param user The address of the user * @return The list of reward addresses * @return The list of unclaimed amount of rewards **/ function getAllUserRewards(address[] calldata assets, address user) external view returns (address[] memory, uint256[] memory); /** * @dev Returns the decimals of an asset to calculate the distribution delta * @param asset The address to retrieve decimals * @return The decimals of an underlying asset */ function getAssetDecimals(address asset) external view returns (uint8); /** * @dev Returns the address of the emission manager * @return The address of the EmissionManager */ function EMISSION_MANAGER() external view returns (address); /** * @dev Returns the address of the emission manager. * Deprecated: This getter is maintained for compatibility purposes. Use the `EMISSION_MANAGER()` function instead. * @return The address of the EmissionManager */ function getEmissionManager() external view returns (address); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; interface ITransferStrategyBase { event EmergencyWithdrawal( address indexed caller, address indexed token, address indexed to, uint256 amount ); /** * @dev Perform custom transfer logic via delegate call from source contract to a TransferStrategy implementation * @param to Account to transfer rewards * @param reward Address of the reward token * @param amount Amount to transfer to the "to" address parameter * @return Returns true bool if transfer logic succeeds */ function performTransfer( address to, address reward, uint256 amount ) external returns (bool); /** * @return Returns the address of the Incentives Controller */ function getIncentivesController() external view returns (address); /** * @return Returns the address of the Rewards admin */ function getRewardsAdmin() external view returns (address); /** * @dev Perform an emergency token withdrawal only callable by the Rewards admin * @param token Address of the token to withdraw funds from this contract * @param to Address of the recipient of the withdrawal * @param amount Amount of the withdrawal */ function emergencyWithdrawal( address token, address to, uint256 amount ) external; }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; import {ITransferStrategyBase} from '../interfaces/ITransferStrategyBase.sol'; import {IEACAggregatorProxy} from '../../misc/interfaces/IEACAggregatorProxy.sol'; library RewardsDataTypes { struct RewardsConfigInput { uint88 emissionPerSecond; uint256 totalSupply; uint32 distributionEnd; address asset; address reward; ITransferStrategyBase transferStrategy; IEACAggregatorProxy rewardOracle; } struct UserAssetBalance { address asset; uint256 userBalance; uint256 totalSupply; } struct UserData { // Liquidity index of the reward distribution for the user uint104 index; // Amount of accrued rewards for the user since last user index update uint128 accrued; } struct RewardData { // Liquidity index of the reward distribution uint104 index; // Amount of reward tokens distributed per second uint88 emissionPerSecond; // Timestamp of the last reward index update uint32 lastUpdateTimestamp; // The end of the distribution of rewards (in seconds) uint32 distributionEnd; // Map of user addresses and their rewards data (userAddress => userData) mapping(address => UserData) usersData; } struct AssetData { // Map of reward token addresses and their data (rewardTokenAddress => rewardData) mapping(address => RewardData) rewards; // List of reward token addresses for the asset mapping(uint128 => address) availableRewards; // Count of reward tokens for the asset uint128 availableRewardsCount; // Number of decimals of the asset uint8 decimals; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20Upgradeable.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (interfaces/IERC4626.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20Upgradeable.sol"; import "../token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; /** * @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626]. * * _Available since v4.7._ */ interface IERC4626Upgradeable is IERC20Upgradeable, IERC20MetadataUpgradeable { event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares); event Withdraw( address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares ); /** * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing. * * - MUST be an ERC-20 token contract. * - MUST NOT revert. */ function asset() external view returns (address assetTokenAddress); /** * @dev Returns the total amount of the underlying asset that is “managed” by Vault. * * - SHOULD include any compounding that occurs from yield. * - MUST be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT revert. */ function totalAssets() external view returns (uint256 totalManagedAssets); /** * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal * scenario where all the conditions are met. * * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT show any variations depending on the caller. * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. * - MUST NOT revert. * * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and * from. */ function convertToShares(uint256 assets) external view returns (uint256 shares); /** * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal * scenario where all the conditions are met. * * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT show any variations depending on the caller. * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. * - MUST NOT revert. * * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and * from. */ function convertToAssets(uint256 shares) external view returns (uint256 assets); /** * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver, * through a deposit call. * * - MUST return a limited value if receiver is subject to some deposit limit. * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited. * - MUST NOT revert. */ function maxDeposit(address receiver) external view returns (uint256 maxAssets); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given * current on-chain conditions. * * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called * in the same transaction. * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the * deposit would be accepted, regardless if the user has enough tokens approved, etc. * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by depositing. */ function previewDeposit(uint256 assets) external view returns (uint256 shares); /** * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens. * * - MUST emit the Deposit event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * deposit execution, and are accounted for during deposit. * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not * approving enough underlying tokens to the Vault contract, etc). * * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. */ function deposit(uint256 assets, address receiver) external returns (uint256 shares); /** * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call. * - MUST return a limited value if receiver is subject to some mint limit. * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted. * - MUST NOT revert. */ function maxMint(address receiver) external view returns (uint256 maxShares); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given * current on-chain conditions. * * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call * in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the * same transaction. * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint * would be accepted, regardless if the user has enough tokens approved, etc. * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by minting. */ function previewMint(uint256 shares) external view returns (uint256 assets); /** * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. * * - MUST emit the Deposit event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint * execution, and are accounted for during mint. * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not * approving enough underlying tokens to the Vault contract, etc). * * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. */ function mint(uint256 shares, address receiver) external returns (uint256 assets); /** * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the * Vault, through a withdraw call. * * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. * - MUST NOT revert. */ function maxWithdraw(address owner) external view returns (uint256 maxAssets); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, * given current on-chain conditions. * * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw * call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if * called * in the same transaction. * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though * the withdrawal would be accepted, regardless if the user has enough shares, etc. * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by depositing. */ function previewWithdraw(uint256 assets) external view returns (uint256 shares); /** * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver. * * - MUST emit the Withdraw event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * withdraw execution, and are accounted for during withdraw. * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner * not having enough shares, etc). * * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. * Those methods should be performed separately. */ function withdraw( uint256 assets, address receiver, address owner ) external returns (uint256 shares); /** * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, * through a redeem call. * * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock. * - MUST NOT revert. */ function maxRedeem(address owner) external view returns (uint256 maxShares); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, * given current on-chain conditions. * * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the * same transaction. * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the * redemption would be accepted, regardless if the user has enough shares, etc. * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by redeeming. */ function previewRedeem(uint256 shares) external view returns (uint256 assets); /** * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver. * * - MUST emit the Withdraw event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * redeem execution, and are accounted for during redeem. * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner * not having enough shares, etc). * * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed. * Those methods should be performed separately. */ function redeem( uint256 shares, address receiver, address owner ) external returns (uint256 assets); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20Upgradeable.sol"; import "./extensions/IERC20MetadataUpgradeable.sol"; import "../../utils/ContextUpgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[45] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.1) (token/ERC20/extensions/ERC4626.sol) pragma solidity ^0.8.0; import "../ERC20Upgradeable.sol"; import "../utils/SafeERC20Upgradeable.sol"; import "../../../interfaces/IERC4626Upgradeable.sol"; import "../../../utils/math/MathUpgradeable.sol"; import "../../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the ERC4626 "Tokenized Vault Standard" as defined in * https://eips.ethereum.org/EIPS/eip-4626[EIP-4626]. * * This extension allows the minting and burning of "shares" (represented using the ERC20 inheritance) in exchange for * underlying "assets" through standardized {deposit}, {mint}, {redeem} and {burn} workflows. This contract extends * the ERC20 standard. Any additional extensions included along it would affect the "shares" token represented by this * contract and not the "assets" token which is an independent contract. * * CAUTION: When the vault is empty or nearly empty, deposits are at high risk of being stolen through frontrunning with * a "donation" to the vault that inflates the price of a share. This is variously known as a donation or inflation * attack and is essentially a problem of slippage. Vault deployers can protect against this attack by making an initial * deposit of a non-trivial amount of the asset, such that price manipulation becomes infeasible. Withdrawals may * similarly be affected by slippage. Users can protect against this attack as well unexpected slippage in general by * verifying the amount received is as expected, using a wrapper that performs these checks such as * https://github.com/fei-protocol/ERC4626#erc4626router-and-base[ERC4626Router]. * * _Available since v4.7._ */ abstract contract ERC4626Upgradeable is Initializable, ERC20Upgradeable, IERC4626Upgradeable { using MathUpgradeable for uint256; IERC20Upgradeable private _asset; uint8 private _decimals; /** * @dev Set the underlying asset contract. This must be an ERC20-compatible contract (ERC20 or ERC777). */ function __ERC4626_init(IERC20Upgradeable asset_) internal onlyInitializing { __ERC4626_init_unchained(asset_); } function __ERC4626_init_unchained(IERC20Upgradeable asset_) internal onlyInitializing { (bool success, uint8 assetDecimals) = _tryGetAssetDecimals(asset_); _decimals = success ? assetDecimals : super.decimals(); _asset = asset_; } /** * @dev Attempts to fetch the asset decimals. A return value of false indicates that the attempt failed in some way. */ function _tryGetAssetDecimals(IERC20Upgradeable asset_) private view returns (bool, uint8) { (bool success, bytes memory encodedDecimals) = address(asset_).staticcall( abi.encodeWithSelector(IERC20MetadataUpgradeable.decimals.selector) ); if (success && encodedDecimals.length >= 32) { uint256 returnedDecimals = abi.decode(encodedDecimals, (uint256)); if (returnedDecimals <= type(uint8).max) { return (true, uint8(returnedDecimals)); } } return (false, 0); } /** * @dev Decimals are read from the underlying asset in the constructor and cached. If this fails (e.g., the asset * has not been created yet), the cached value is set to a default obtained by `super.decimals()` (which depends on * inheritance but is most likely 18). Override this function in order to set a guaranteed hardcoded value. * See {IERC20Metadata-decimals}. */ function decimals() public view virtual override(IERC20MetadataUpgradeable, ERC20Upgradeable) returns (uint8) { return _decimals; } /** @dev See {IERC4626-asset}. */ function asset() public view virtual override returns (address) { return address(_asset); } /** @dev See {IERC4626-totalAssets}. */ function totalAssets() public view virtual override returns (uint256) { return _asset.balanceOf(address(this)); } /** @dev See {IERC4626-convertToShares}. */ function convertToShares(uint256 assets) public view virtual override returns (uint256 shares) { return _convertToShares(assets, MathUpgradeable.Rounding.Down); } /** @dev See {IERC4626-convertToAssets}. */ function convertToAssets(uint256 shares) public view virtual override returns (uint256 assets) { return _convertToAssets(shares, MathUpgradeable.Rounding.Down); } /** @dev See {IERC4626-maxDeposit}. */ function maxDeposit(address) public view virtual override returns (uint256) { return _isVaultCollateralized() ? type(uint256).max : 0; } /** @dev See {IERC4626-maxMint}. */ function maxMint(address) public view virtual override returns (uint256) { return type(uint256).max; } /** @dev See {IERC4626-maxWithdraw}. */ function maxWithdraw(address owner) public view virtual override returns (uint256) { return _convertToAssets(balanceOf(owner), MathUpgradeable.Rounding.Down); } /** @dev See {IERC4626-maxRedeem}. */ function maxRedeem(address owner) public view virtual override returns (uint256) { return balanceOf(owner); } /** @dev See {IERC4626-previewDeposit}. */ function previewDeposit(uint256 assets) public view virtual override returns (uint256) { return _convertToShares(assets, MathUpgradeable.Rounding.Down); } /** @dev See {IERC4626-previewMint}. */ function previewMint(uint256 shares) public view virtual override returns (uint256) { return _convertToAssets(shares, MathUpgradeable.Rounding.Up); } /** @dev See {IERC4626-previewWithdraw}. */ function previewWithdraw(uint256 assets) public view virtual override returns (uint256) { return _convertToShares(assets, MathUpgradeable.Rounding.Up); } /** @dev See {IERC4626-previewRedeem}. */ function previewRedeem(uint256 shares) public view virtual override returns (uint256) { return _convertToAssets(shares, MathUpgradeable.Rounding.Down); } /** @dev See {IERC4626-deposit}. */ function deposit(uint256 assets, address receiver) public virtual override returns (uint256) { require(assets <= maxDeposit(receiver), "ERC4626: deposit more than max"); uint256 shares = previewDeposit(assets); _deposit(_msgSender(), receiver, assets, shares); return shares; } /** @dev See {IERC4626-mint}. * * As opposed to {deposit}, minting is allowed even if the vault is in a state where the price of a share is zero. * In this case, the shares will be minted without requiring any assets to be deposited. */ function mint(uint256 shares, address receiver) public virtual override returns (uint256) { require(shares <= maxMint(receiver), "ERC4626: mint more than max"); uint256 assets = previewMint(shares); _deposit(_msgSender(), receiver, assets, shares); return assets; } /** @dev See {IERC4626-withdraw}. */ function withdraw( uint256 assets, address receiver, address owner ) public virtual override returns (uint256) { require(assets <= maxWithdraw(owner), "ERC4626: withdraw more than max"); uint256 shares = previewWithdraw(assets); _withdraw(_msgSender(), receiver, owner, assets, shares); return shares; } /** @dev See {IERC4626-redeem}. */ function redeem( uint256 shares, address receiver, address owner ) public virtual override returns (uint256) { require(shares <= maxRedeem(owner), "ERC4626: redeem more than max"); uint256 assets = previewRedeem(shares); _withdraw(_msgSender(), receiver, owner, assets, shares); return assets; } /** * @dev Internal conversion function (from assets to shares) with support for rounding direction. * * Will revert if assets > 0, totalSupply > 0 and totalAssets = 0. That corresponds to a case where any asset * would represent an infinite amount of shares. */ function _convertToShares(uint256 assets, MathUpgradeable.Rounding rounding) internal view virtual returns (uint256 shares) { uint256 supply = totalSupply(); return (assets == 0 || supply == 0) ? _initialConvertToShares(assets, rounding) : assets.mulDiv(supply, totalAssets(), rounding); } /** * @dev Internal conversion function (from assets to shares) to apply when the vault is empty. * * NOTE: Make sure to keep this function consistent with {_initialConvertToAssets} when overriding it. */ function _initialConvertToShares( uint256 assets, MathUpgradeable.Rounding /*rounding*/ ) internal view virtual returns (uint256 shares) { return assets; } /** * @dev Internal conversion function (from shares to assets) with support for rounding direction. */ function _convertToAssets(uint256 shares, MathUpgradeable.Rounding rounding) internal view virtual returns (uint256 assets) { uint256 supply = totalSupply(); return (supply == 0) ? _initialConvertToAssets(shares, rounding) : shares.mulDiv(totalAssets(), supply, rounding); } /** * @dev Internal conversion function (from shares to assets) to apply when the vault is empty. * * NOTE: Make sure to keep this function consistent with {_initialConvertToShares} when overriding it. */ function _initialConvertToAssets( uint256 shares, MathUpgradeable.Rounding /*rounding*/ ) internal view virtual returns (uint256 assets) { return shares; } /** * @dev Deposit/mint common workflow. */ function _deposit( address caller, address receiver, uint256 assets, uint256 shares ) internal virtual { // If _asset is ERC777, `transferFrom` can trigger a reenterancy BEFORE the transfer happens through the // `tokensToSend` hook. On the other hand, the `tokenReceived` hook, that is triggered after the transfer, // calls the vault, which is assumed not malicious. // // Conclusion: we need to do the transfer before we mint so that any reentrancy would happen before the // assets are transferred and before the shares are minted, which is a valid state. // slither-disable-next-line reentrancy-no-eth SafeERC20Upgradeable.safeTransferFrom(_asset, caller, address(this), assets); _mint(receiver, shares); emit Deposit(caller, receiver, assets, shares); } /** * @dev Withdraw/redeem common workflow. */ function _withdraw( address caller, address receiver, address owner, uint256 assets, uint256 shares ) internal virtual { if (caller != owner) { _spendAllowance(owner, caller, shares); } // If _asset is ERC777, `transfer` can trigger a reentrancy AFTER the transfer happens through the // `tokensReceived` hook. On the other hand, the `tokensToSend` hook, that is triggered before the transfer, // calls the vault, which is assumed not malicious. // // Conclusion: we need to do the transfer after the burn so that any reentrancy would happen after the // shares are burned and after the assets are transferred, which is a valid state. _burn(owner, shares); SafeERC20Upgradeable.safeTransfer(_asset, receiver, assets); emit Withdraw(caller, receiver, owner, assets, shares); } /** * @dev Checks if vault is "healthy" in the sense of having assets backing the circulating shares. */ function _isVaultCollateralized() private view returns (bool) { return totalAssets() > 0 || totalSupply() == 0; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20MetadataUpgradeable is IERC20Upgradeable { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20PermitUpgradeable { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; import "../extensions/draft-IERC20PermitUpgradeable.sol"; import "../../../utils/AddressUpgradeable.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20Upgradeable { using AddressUpgradeable for address; function safeTransfer( IERC20Upgradeable token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20Upgradeable token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20Upgradeable token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20Upgradeable token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20Upgradeable token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20PermitUpgradeable token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/MathUpgradeable.sol"; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = MathUpgradeable.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, MathUpgradeable.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../StringsUpgradeable.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSAUpgradeable { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", StringsUpgradeable.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.0; import "./ECDSAUpgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ * * @custom:storage-size 52 */ abstract contract EIP712Upgradeable is Initializable { /* solhint-disable var-name-mixedcase */ bytes32 private _HASHED_NAME; bytes32 private _HASHED_VERSION; bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ function __EIP712_init(string memory name, string memory version) internal onlyInitializing { __EIP712_init_unchained(name, version); } function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash()); } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev The hash of the name parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712NameHash() internal virtual view returns (bytes32) { return _HASHED_NAME; } /** * @dev The hash of the version parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712VersionHash() internal virtual view returns (bytes32) { return _HASHED_VERSION; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library MathUpgradeable { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: UNLICENSED // All Rights Reserved © AaveCo pragma solidity ^0.8.10; /** * @title ATokenVaultStorage * @author Aave Protocol * @notice Contains storage variables for the ATokenVault. */ abstract contract ATokenVaultStorage { mapping(address => uint256) internal _sigNonces; struct Storage { // total aToken incl. fees uint128 lastVaultBalance; // fees accrued since last updated uint128 accumulatedFees; // timestamp of last accrueYield action uint40 lastUpdated; // as a fraction of 1e18 uint64 fee; // Reserved storage space to allow for layout changes in the future uint256[50] __gap; } Storage internal _s; }
// SPDX-License-Identifier: UNLICENSED // All Rights Reserved © AaveCo pragma solidity ^0.8.10; import {IERC20Upgradeable} from "@openzeppelin-upgradeable/interfaces/IERC20Upgradeable.sol"; import {IERC4626Upgradeable} from "@openzeppelin-upgradeable/interfaces/IERC4626Upgradeable.sol"; import {IPoolAddressesProvider} from "@aave-v3-core/interfaces/IPoolAddressesProvider.sol"; import {IPool} from "@aave-v3-core/interfaces/IPool.sol"; import {IAToken} from "@aave-v3-core/interfaces/IAToken.sol"; import {IRewardsController} from "@aave-v3-periphery/rewards/interfaces/IRewardsController.sol"; /** * @title IATokenVault * @author Aave Protocol * * @notice Defines the basic interface of the ATokenVault */ interface IATokenVault is IERC4626Upgradeable { /** * @notice A struct containing the necessary information to reconstruct an EIP-712 typed data signature. * * @param v The signature's recovery parameter. * @param r The signature's r parameter. * @param s The signature's s parameter * @param deadline The signature's deadline */ struct EIP712Signature { uint8 v; bytes32 r; bytes32 s; uint256 deadline; } /** * @dev Emitted when the fee is updated * @param oldFee The old value of the fee * @param newFee The new value of the fee */ event FeeUpdated(uint256 indexed oldFee, uint256 indexed newFee); /** * @dev Emitted when fees are withdrawn * @param to The recipient address where the fees are sent to * @param amount The amount of fess withdrawn, in aTokens * @param newVaultBalance The new balance of the vault, in aTokens * @param newTotalFeesAccrued The total amount of fees accrued outstanding after the withdraw, in aTokens */ event FeesWithdrawn(address indexed to, uint256 indexed amount, uint256 newVaultBalance, uint256 newTotalFeesAccrued); /** * @dev Emitted when Aave yield is accrued * @param accruedYield The yield accrued since the last vault interaction, in aTokens * @param newFeesFromYield The amount of fees earned from the accrued yield, in aTokens * @param newVaultBalance The new balance of the vault, in aTokens */ event YieldAccrued(uint256 accruedYield, uint256 newFeesFromYield, uint256 newVaultBalance); /** * @dev Emitted when Aave rewards are claimed * @param to The recipient address where the claimed rewards are sent to * @param rewardsList The list of rewards address that have been claimed * @param claimedAmounts The list of rewards amount that have been claimed */ event RewardsClaimed(address indexed to, address[] rewardsList, uint256[] claimedAmounts); /** * @dev Emitted when an emergency rescue of tokens has been made * @param token The address of the token that has been rescued * @param to The recipient address where the rescued tokens are sent to * @param amount The amount of tokens rescued */ event EmergencyRescue(address indexed token, address indexed to, uint256 amount); /** * @notice Returns the address of the Aave Pool Addresses Provider * @return The address of the Aave PoolAddressesProvider contract */ function POOL_ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider); /** * @notice Returns the address of the Aave Pool * @return The address of the Aave Pool contract */ function AAVE_POOL() external view returns (IPool); /** * @notice Returns the address of the AToken * @return The address of the AToken contract */ function ATOKEN() external view returns (IAToken); /** * @notice Returns the address of the underlying asset of the vault * @return The address of the underlying asset */ function UNDERLYING() external view returns (IERC20Upgradeable); /** * @notice Returns the referral code to use for Aave interactions * @return The Aave referral code */ function REFERRAL_CODE() external view returns (uint16); /** * @notice Deposits a specified amount of assets into the vault, minting a corresponding amount of shares. * @dev The assets transferred in could be lesser than the passed amount due to rounding issues * @param assets The amount of underlying asset to deposit * @param receiver The address to receive the shares * @return shares The amount of shares minted to the receiver */ function deposit(uint256 assets, address receiver) external override returns (uint256 shares); /** * @notice Deposits a specified amount of aToken assets into the vault, minting a corresponding amount of shares. * @dev The assets transferred in could be lesser than the passed amount due to rounding issues * @param assets The amount of aToken assets to deposit * @param receiver The address to receive the shares * @return shares The amount of shares minted to the receiver */ function depositATokens(uint256 assets, address receiver) external returns (uint256 shares); /** * @notice Deposits a specified amount of assets into the vault, minting a corresponding amount of shares, * using an EIP712 signature to enable a third-party to call this function on behalf of the depositor. * @dev The signer of the message must approve the appropriate amount of underlying tokens beforehand * @dev The assets transferred in could be lesser than the passed amount due to rounding issues * @param assets The amount of underlying asset to deposit * @param receiver The address to receive the shares * @param depositor The address from which to pull the assets for the deposit * @param sig An EIP712 signature from the depositor to allow this function to be called on their behalf * @return shares The amount of shares minted to the receiver */ function depositWithSig( uint256 assets, address receiver, address depositor, EIP712Signature calldata sig ) external returns (uint256 shares); /** * @notice Deposits a specified amount of aToken assets into the vault, minting a corresponding amount of * shares, using an EIP712 signature to enable a third-party to call this function on behalf of the depositor. * @dev The signer of the message must approve the appropriate amount of underlying aTokens beforehand * @dev The assets transferred in could be lesser than the passed amount due to rounding issues * @param assets The amount of aToken assets to deposit * @param receiver The address to receive the shares * @param depositor The address from which to pull the aToken assets for the deposit * @param sig An EIP712 signature from the depositor to allow this function to be called on their behalf * @return shares The amount of shares minted to the receiver */ function depositATokensWithSig( uint256 assets, address receiver, address depositor, EIP712Signature calldata sig ) external returns (uint256 shares); /** * @notice Mints a specified amount of shares to the receiver, depositing the corresponding amount of assets. * @param shares The amount of shares to mint * @param receiver The address to receive the shares * @return assets The amount of assets deposited by the caller */ function mint(uint256 shares, address receiver) external override returns (uint256 assets); /** * @notice Mints a specified amount of shares to the receiver, depositing the corresponding amount of aToken * assets. * @param shares The amount of shares to mint * @param receiver The address to receive the shares * @return assets The amount of aToken assets deposited by the caller */ function mintWithATokens(uint256 shares, address receiver) external returns (uint256 assets); /** * @notice Mints a specified amount of shares to the receiver, depositing the corresponding amount of assets, * using an EIP712 signature to enable a third-party to call this function on behalf of the depositor. * @dev The signer of the message must approve the appropriate amount of underlying tokens beforehand * @param shares The amount of shares to mint * @param receiver The address to receive the shares * @param depositor The address from which to pull the assets for the deposit * @param sig An EIP712 signature from the depositor to allow this function to be called on their behalf * @return assets The amount of assets deposited by the depositor */ function mintWithSig( uint256 shares, address receiver, address depositor, EIP712Signature calldata sig ) external returns (uint256 assets); /** * @notice Mints a specified amount of shares to the receiver, depositing the corresponding amount of aToken * assets, using an EIP712 signature to enable a third-party to call this function on behalf of the depositor. * @dev The signer of the message must approve the appropriate amount of underlying aTokens beforehand * @param shares The amount of shares to mint * @param receiver The address to receive the shares * @param depositor The address from which to pull the aToken assets for the deposit * @param sig An EIP712 signature from the depositor to allow this function to be called on their behalf * @return assets The amount of aToken assets deposited by the depositor */ function mintWithATokensWithSig( uint256 shares, address receiver, address depositor, EIP712Signature calldata sig ) external returns (uint256 assets); /** * @notice Withdraws a specified amount of assets from the vault, burning the corresponding amount of shares. * @param assets The amount of assets to withdraw * @param receiver The address to receive the assets * @param owner The address from which to pull the shares for the withdrawal * @return shares The amount of shares burnt in the withdrawal process */ function withdraw(uint256 assets, address receiver, address owner) external override returns (uint256 shares); /** * @notice Withdraws a specified amount of aToken assets from the vault, burning the corresponding amount of * shares. * @param assets The amount of aToken assets to withdraw * @param receiver The address to receive the aToken assets * @param owner The address from which to pull the shares for the withdrawal * @return shares The amount of shares burnt in the withdrawal process */ function withdrawATokens(uint256 assets, address receiver, address owner) external returns (uint256 shares); /** * @notice Withdraws a specified amount of assets from the vault, burning the corresponding amount of shares, * using an EIP712 signature to enable a third-party to call this function on behalf of the owner. * @param assets The amount of assets to withdraw * @param receiver The address to receive the assets * @param owner The address from which to pull the shares for the withdrawal * @param sig An EIP712 signature from the owner to allow this function to be called on their behalf * @return shares The amount of shares burnt in the withdrawal process */ function withdrawWithSig( uint256 assets, address receiver, address owner, EIP712Signature calldata sig ) external returns (uint256 shares); /** * @notice Withdraws a specified amount of aToken assets from the vault, burning the corresponding amount of * shares, using an EIP712 signature to enable a third-party to call this function on behalf of the owner. * @param assets The amount of aToken assets to withdraw * @param receiver The address to receive the aToken assets * @param owner The address from which to pull the shares for the withdrawal * @param sig An EIP712 signature from the owner to allow this function to be called on their behalf * @return shares The amount of shares burnt in the withdrawal process */ function withdrawATokensWithSig( uint256 assets, address receiver, address owner, EIP712Signature calldata sig ) external returns (uint256 shares); /** * @notice Burns a specified amount of shares from the vault, withdrawing the corresponding amount of assets. * @param shares The amount of shares to burn * @param receiver The address to receive the assets * @param owner The address from which to pull the shares for the withdrawal * @return assets The amount of assets withdrawn by the receiver */ function redeem(uint256 shares, address receiver, address owner) external override returns (uint256 assets); /** * @notice Burns a specified amount of shares from the vault, withdrawing the corresponding amount of aToken * assets. * @param shares The amount of shares to burn * @param receiver The address to receive the aToken assets * @param owner The address from which to pull the shares for the withdrawal * @return assets The amount of aToken assets withdrawn by the receiver */ function redeemAsATokens(uint256 shares, address receiver, address owner) external returns (uint256 assets); /** * @notice Burns a specified amount of shares from the vault, withdrawing the corresponding amount of assets, * using an EIP712 signature to enable a third-party to call this function on behalf of the owner. * @param shares The amount of shares to burn * @param receiver The address to receive the assets * @param owner The address from which to pull the shares for the withdrawal * @param sig An EIP712 signature from the owner to allow this function to be called on their behalf * @return assets The amount of assets withdrawn by the receiver */ function redeemWithSig( uint256 shares, address receiver, address owner, EIP712Signature calldata sig ) external returns (uint256 assets); /** * @notice Burns a specified amount of shares from the vault, withdrawing the corresponding amount of aToken * assets, using an EIP712 signature to enable a third-party to call this function on behalf of the owner. * @param shares The amount of shares to burn * @param receiver The address to receive the aToken assets * @param owner The address from which to pull the shares for the withdrawal * @param sig An EIP712 signature from the owner to allow this function to be called on their behalf * @return assets The amount of aToken assets withdrawn by the receiver */ function redeemWithATokensWithSig( uint256 shares, address receiver, address owner, EIP712Signature calldata sig ) external returns (uint256 assets); /** * @notice Returns the maximum amount of assets that can be deposited into the vault. * @dev It takes Aave Pool limitations into consideration * @return maxAssets The maximum amount of assets that can be deposited into the vault */ function maxDeposit(address) external view override returns (uint256 maxAssets); /** * @notice Returns the maximum amount of shares that can be minted for the vault. * @dev It takes Aave Pool limitations into consideration * @return maxShares The maximum amount of shares that can be minted for the vault */ function maxMint(address) external view override returns (uint256 maxShares); /** * @notice Returns the maximum amount of assets that can be withdrawn from the owner balance in the vault. * @dev It takes Aave Pool limitations into consideration * @return maxAssets The maximum amount of assets that can be withdrawn */ function maxWithdraw(address owner) external view override returns (uint256 maxAssets); /** * @notice Returns the maximum amount of shares that can be redeemed from the owner balance in the vault. * @dev It takes Aave Pool limitations into consideration * @return maxShares The maximum amount of shares that can be redeemed */ function maxRedeem(address owner) external view override returns (uint256 maxShares); /** * @notice Allows a user to simulate a deposit at the current block, given current on-chain conditions. * @dev It takes Aave Pool limitations into consideration * @param assets The amount of assets the deposit simulation uses * @return shares The amount of shares that would be minted to the receiver */ function previewDeposit(uint256 assets) external view override returns (uint256 shares); /** * @notice Allows a user to simulate a mint at the current block, given current on-chain conditions. * @dev It takes Aave Pool limitations into consideration * @param shares The amount of shares the mint simulation uses * @return assets The amount of assets that would be deposited by the caller */ function previewMint(uint256 shares) external view override returns (uint256 assets); /** * @notice Allows a user to simulate a withdraw at the current block, given current on-chain conditions. * @dev It takes Aave Pool limitations into consideration * @param assets The amount of assets the withdraw simulation uses * @return shares The amount of shares that would be burnt in the withdrawal process */ function previewWithdraw(uint256 assets) external view override returns (uint256 shares); /** * @notice Allows a user to simulate a redeem at the current block, given current on-chain conditions. * @dev It takes Aave Pool limitations into consideration * @param shares The amount of shares the redeem simulation uses * @return assets The amount of assets that would be withdrawn by the receiver */ function previewRedeem(uint256 shares) external view override returns (uint256 assets); /** * @notice Returns the domain separator for the current chain. * @return The domain separator */ function domainSeparator() external view returns (bytes32); /** * @notice Sets the fee the vault levies on yield earned. * @dev Only callable by the owner * @param newFee The new fee to set, expressed in wad, where 1e18 is 100% */ function setFee(uint256 newFee) external; /** * @notice Withdraws fees earned by the vault, in the form of aTokens, to a specified address. * @dev Only callable by the owner * @param to The address to receive the fees * @param amount The amount of fees to withdraw */ function withdrawFees(address to, uint256 amount) external; /** * @notice Claims any additional Aave rewards earned from vault deposits. * @dev Only callable by the owner * @param to The address to receive any rewards tokens */ function claimRewards(address to) external; /** * @notice Rescue any tokens other than the vault's aToken which may have accidentally been transferred to this * contract. * @dev Only callable by the owner * @param token The address of the token to rescue * @param to The address to receive rescued tokens * @param amount The amount of tokens to transfer */ function emergencyRescue(address token, address to, uint256 amount) external; /** * @notice Returns the total assets less claimable fees. * @return totalManagedAssets The total assets less claimable fees */ function totalAssets() external view override returns (uint256 totalManagedAssets); /** * @notice Returns the claimable fees. * @return The claimable fees */ function getClaimableFees() external view returns (uint256); /** * @notice Returns the signing nonce for meta-transactions for the given signer. * @return The passed signer's nonce */ function getSigNonce(address signer) external view returns (uint256); /** * @notice Returns the latest timestamp when yield was accrued. * @return The last update timestamp */ function getLastUpdated() external view returns (uint256); /** * @notice Returns the vault balance at the latest update timestamp. * @return The latest vault balance */ function getLastVaultBalance() external view returns (uint256); /** * @notice Returns the current fee ratio. * @return The current fee ratio, expressed in wad, where 1e18 is 100% */ function getFee() external view returns (uint256); }
// SPDX-License-Identifier: UNLICENSED // All Rights Reserved © AaveCo pragma solidity ^0.8.10; uint256 constant AAVE_ACTIVE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFF; uint256 constant AAVE_FROZEN_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFF; uint256 constant AAVE_PAUSED_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFF; uint256 constant AAVE_SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF; uint256 constant AAVE_SUPPLY_CAP_BIT_POSITION = 116; bytes4 constant EIP1271_MAGIC_VALUE = 0x1626ba7e; bytes32 constant DEPOSIT_WITH_SIG_TYPEHASH = keccak256( "DepositWithSig(uint256 assets,address receiver,address depositor,uint256 nonce,uint256 deadline)" ); bytes32 constant DEPOSIT_ATOKENS_WITH_SIG_TYPEHASH = keccak256( "DepositATokensWithSig(uint256 assets,address receiver,address depositor,uint256 nonce,uint256 deadline)" ); bytes32 constant MINT_WITH_SIG_TYPEHASH = keccak256( "MintWithSig(uint256 shares,address receiver,address depositor,uint256 nonce,uint256 deadline)" ); bytes32 constant MINT_WITH_ATOKENS_WITH_SIG_TYPEHASH = keccak256( "MintWithATokensWithSig(uint256 shares,address receiver,address depositor,uint256 nonce,uint256 deadline)" ); bytes32 constant WITHDRAW_WITH_SIG_TYPEHASH = keccak256( "WithdrawWithSig(uint256 assets,address receiver,address owner,uint256 nonce,uint256 deadline)" ); bytes32 constant WITHDRAW_ATOKENS_WITH_SIG_TYPEHASH = keccak256( "WithdrawATokensWithSig(uint256 assets,address receiver,address owner,uint256 nonce,uint256 deadline)" ); bytes32 constant REDEEM_WITH_SIG_TYPEHASH = keccak256( "RedeemWithSig(uint256 shares,address receiver,address owner,uint256 nonce,uint256 deadline)" ); bytes32 constant REDEEM_WITH_ATOKENS_WITH_SIG_TYPEHASH = keccak256( "RedeemWithATokensWithSig(uint256 shares,address receiver,address owner,uint256 nonce,uint256 deadline)" ); uint256 constant SCALE = 1e18;
// SPDX-License-Identifier: UNLICENSED // All Rights Reserved © AaveCo pragma solidity ^0.8.10; import {IERC1271} from "@openzeppelin/interfaces/IERC1271.sol"; import {IATokenVault} from "../interfaces/IATokenVault.sol"; import "./Constants.sol"; /** * @title MetaTxHelpers * @author Lens Protocol * @notice A library containing helper functions for meta-transactions. */ library MetaTxHelpers { /** * @dev Wrapper for ecrecover to reduce code size, used in meta-tx specific functions. */ function _validateRecoveredAddress( bytes32 digest, address expectedAddress, IATokenVault.EIP712Signature calldata sig ) internal view { require(sig.deadline >= block.timestamp, "SIG_EXPIRED"); address recoveredAddress = expectedAddress; // If the expected address is a contract, check the signature there. if (recoveredAddress.code.length != 0) { bytes memory concatenatedSig = abi.encodePacked(sig.r, sig.s, sig.v); require(IERC1271(expectedAddress).isValidSignature(digest, concatenatedSig) == EIP1271_MAGIC_VALUE, "SIG_INVALID"); } else { recoveredAddress = ecrecover(digest, sig.v, sig.r, sig.s); require(recoveredAddress != address(0) && recoveredAddress == expectedAddress, "SIG_INVALID"); } } /** * @dev Calculates EIP712 digest based on the current DOMAIN_SEPARATOR. * * @param hashedMessage The message hash from which the digest should be calculated. * @param domainSeparator The domain separator to use in creating the digest. * * @return bytes32 A 32-byte output representing the EIP712 digest. */ function _calculateDigest(bytes32 hashedMessage, bytes32 domainSeparator) internal pure returns (bytes32) { bytes32 digest; unchecked { digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, hashedMessage)); } return digest; } }
{ "remappings": [ "@aave-v3-core/=lib/aave-v3-core/contracts/", "@aave-v3-periphery/=lib/aave-v3-periphery/contracts/", "@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/=lib/openzeppelin-contracts/contracts/", "aave-v3-core/=lib/aave-v3-core/", "aave-v3-periphery/=lib/aave-v3-periphery/contracts/", "ds-test/=lib/solmate/lib/ds-test/src/", "erc4626-tests/=lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 10000000 }, "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"uint16","name":"referralCode","type":"uint16"},{"internalType":"contract IPoolAddressesProvider","name":"poolAddressesProvider","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyRescue","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"FeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVaultBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTotalFeesAccrued","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address[]","name":"rewardsList","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"claimedAmounts","type":"uint256[]"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"accruedYield","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeesFromYield","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVaultBalance","type":"uint256"}],"name":"YieldAccrued","type":"event"},{"inputs":[],"name":"AAVE_POOL","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ATOKEN","outputs":[{"internalType":"contract IAToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_ADDRESSES_PROVIDER","outputs":[{"internalType":"contract IPoolAddressesProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFERRAL_CODE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNDERLYING","outputs":[{"internalType":"contract IERC20Upgradeable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"depositATokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"depositor","type":"address"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IATokenVault.EIP712Signature","name":"sig","type":"tuple"}],"name":"depositATokensWithSig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"depositor","type":"address"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IATokenVault.EIP712Signature","name":"sig","type":"tuple"}],"name":"depositWithSig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyRescue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getClaimableFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastUpdated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastVaultBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"getSigNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"initialFee","type":"uint256"},{"internalType":"string","name":"shareName","type":"string"},{"internalType":"string","name":"shareSymbol","type":"string"},{"internalType":"uint256","name":"initialLockDeposit","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mintWithATokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"depositor","type":"address"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IATokenVault.EIP712Signature","name":"sig","type":"tuple"}],"name":"mintWithATokensWithSig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"depositor","type":"address"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IATokenVault.EIP712Signature","name":"sig","type":"tuple"}],"name":"mintWithSig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"redeemAsATokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IATokenVault.EIP712Signature","name":"sig","type":"tuple"}],"name":"redeemWithATokensWithSig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IATokenVault.EIP712Signature","name":"sig","type":"tuple"}],"name":"redeemWithSig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"withdrawATokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IATokenVault.EIP712Signature","name":"sig","type":"tuple"}],"name":"withdrawATokensWithSig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IATokenVault.EIP712Signature","name":"sig","type":"tuple"}],"name":"withdrawWithSig","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101206040523480156200001257600080fd5b50604051620060de380380620060de8339810160408190526200003591620002ae565b6200003f620001b1565b6001600160a01b03811660808190526040805163026b1d5f60e01b8152905163026b1d5f916004808201926020929091908290030181865afa1580156200008a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b09190620002fe565b6001600160a01b0390811660a081905261ffff84166101005290841660e08190526040516335ea6a7560e01b81526004810191909152600091906335ea6a75906024016101e060405180830381865afa15801562000112573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001389190620003dc565b610100015190506001600160a01b0381166200019b5760405162461bcd60e51b815260206004820152601360248201527f41535345545f4e4f545f535550504f525445440000000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b031660c0525062000520915050565b600054610100900460ff16156200021b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840162000192565b60005460ff90811610156200026e576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b03811681146200028657600080fd5b50565b8051620002968162000270565b919050565b805161ffff811681146200029657600080fd5b600080600060608486031215620002c457600080fd5b8351620002d18162000270565b9250620002e1602085016200029b565b91506040840151620002f38162000270565b809150509250925092565b6000602082840312156200031157600080fd5b81516200031e8162000270565b9392505050565b6040516101e081016001600160401b03811182821017156200035757634e487b7160e01b600052604160045260246000fd5b60405290565b6000602082840312156200037057600080fd5b604051602081016001600160401b0381118282101715620003a157634e487b7160e01b600052604160045260246000fd5b6040529151825250919050565b80516001600160801b03811681146200029657600080fd5b805164ffffffffff811681146200029657600080fd5b60006101e08284031215620003f057600080fd5b620003fa62000325565b6200040684846200035d565b81526200041660208401620003ae565b60208201526200042960408401620003ae565b60408201526200043c60608401620003ae565b60608201526200044f60808401620003ae565b60808201526200046260a08401620003ae565b60a08201526200047560c08401620003c6565b60c08201526200048860e084016200029b565b60e08201526101006200049d81850162000289565b90820152610120620004b184820162000289565b90820152610140620004c584820162000289565b90820152610160620004d984820162000289565b90820152610180620004ed848201620003ae565b908201526101a062000501848201620003ae565b908201526101c062000515848201620003ae565b908201529392505050565b60805160a05160c05160e05161010051615ab5620006296000396000818161053401526141230152600081816107a901528181610b3301528181610bc301528181612e3201528181612f64015281816133fd01528181613fd8015281816140ee015261461e0152600081816105d801528181610cdb01528181611033015281816116fc0152818161182f01528181611ab201528181611da601528181611e1701528181612f3c01528181613536015281816137e601528181613eee01528181614031015281816141dd015261451101526000818161043801528181610be501528181612e5f0152818161342a015281816141500152614658015260006104dd0152615ab56000f3fe608060405234801561001057600080fd5b506004361061038d5760003560e01c80638da5cb5b116101de578063c63d75b61161010f578063dd62ed3e116100ad578063ef8b30f71161007c578063ef8b30f7146108d7578063f2fde38b146108ea578063f698da25146108fd578063ffd7d21f1461090557600080fd5b8063dd62ed3e14610858578063e25ec3491461089e578063ee4535ba146108b1578063ef5cfb8c146108c457600080fd5b8063ce96cb77116100e9578063ce96cb7714610804578063ced72f8714610817578063d687d0b314610832578063d905777e1461084557600080fd5b8063c63d75b6146107cb578063c6e6f592146107de578063c7df1f56146107f157600080fd5b8063b344ed031161017c578063ba08765211610156578063ba08765214610764578063bddd09b714610777578063bfedc2be14610791578063c5d664c6146107a457600080fd5b8063b344ed031461072b578063b3d7f6b91461073e578063b460af941461075157600080fd5b80639d3ebd94116101b85780639d3ebd94146106df578063a457c2d7146106f2578063a9059cbb14610705578063ad3b1b471461071857600080fd5b80638da5cb5b146106a657806394bf804d146106c457806395d89b41146106d757600080fd5b80633583849a116102c35780635be35e1a1161026157806370a082311161023057806370a0823114610646578063715018a61461067c57806378121dd4146106845780637fc1664a1461069357600080fd5b80635be35e1a146105fa5780636738445e1461060d57806369fe0e2d146106205780636e553f651461063357600080fd5b8063402d267d1161029d578063402d267d1461059a578063403c02d0146105ad5780634cdad506146105c057806351c0e061146105d357600080fd5b80633583849a1461052f57806338d52e0f14610569578063395093511461058757600080fd5b8063095ea7b31161033057806323b872dd1161030a57806323b872dd146104bd578063274f0e24146104d0578063311cd5a4146104d8578063313ce567146104ff57600080fd5b8063095ea7b31461047f5780630a28a477146104a257806318160ddd146104b557600080fd5b80630634d4e91161036c5780630634d4e9146103f857806306fdde031461040b57806307a2d13a1461042057806308a016751461043357600080fd5b80628b187b1461039257806301e1d114146103a757806305ac0ab4146103c2575b600080fd5b6103a56103a0366004614fe9565b610918565b005b6103af610ca3565b6040519081526020015b60405180910390f35b6103af6103d0366004615071565b73ffffffffffffffffffffffffffffffffffffffff16600090815260fd602052604090205490565b6103af61040636600461508e565b610d6a565b610413610eaa565b6040516103b9919061517d565b6103af61042e366004615190565b610f3c565b61045a7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103b9565b61049261048d3660046151a9565b610f4f565b60405190151581526020016103b9565b6103af6104b0366004615190565b610f67565b6035546103af565b6104926104cb3660046151d5565b610f9d565b6103af610fc1565b61045a7f000000000000000000000000000000000000000000000000000000000000000081565b60655474010000000000000000000000000000000000000000900460ff1660405160ff90911681526020016103b9565b6105567f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff90911681526020016103b9565b60655473ffffffffffffffffffffffffffffffffffffffff1661045a565b6104926105953660046151a9565b611148565b6103af6105a8366004615071565b611194565b6103af6105bb36600461508e565b61119e565b6103af6105ce366004615190565b611259565b61045a7f000000000000000000000000000000000000000000000000000000000000000081565b6103af610608366004615216565b611281565b6103af61061b36600461508e565b611291565b6103a561062e366004615190565b61134c565b6103af610641366004615258565b611368565b6103af610654366004615071565b73ffffffffffffffffffffffffffffffffffffffff1660009081526033602052604090205490565b6103a5611377565b60ff5464ffffffffff166103af565b6103af6106a136600461508e565b61138b565b60975473ffffffffffffffffffffffffffffffffffffffff1661045a565b6103af6106d2366004615258565b611445565b610413611454565b6103af6106ed36600461508e565b611463565b6104926107003660046151a9565b61151d565b6104926107133660046151a9565b6115ee565b6103a56107263660046151a9565b6115fc565b6103af61073936600461508e565b611922565b6103af61074c366004615190565b6119dd565b6103af61075f366004615216565b6119f5565b6103af610772366004615216565b611a05565b60fe546fffffffffffffffffffffffffffffffff166103af565b6103af61079f366004615258565b611a15565b61045a7f000000000000000000000000000000000000000000000000000000000000000081565b6103af6107d9366004615071565b611a24565b6103af6107ec366004615190565b611a38565b6103af6107ff366004615216565b611a45565b6103af610812366004615071565b611a55565b60ff5465010000000000900467ffffffffffffffff166103af565b6103a56108403660046151d5565b611aa8565b6103af610853366004615071565b611be6565b6103af610866366004615288565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260346020908152604080832093909416825291909152205490565b6103af6108ac366004615258565b611c33565b6103af6108bf36600461508e565b611c42565b6103a56108d2366004615071565b611cfd565b6103af6108e5366004615190565b611f9d565b6103a56108f8366004615071565b611fae565b6103af612062565b6103af61091336600461508e565b61206c565b600054610100900460ff16158080156109385750600054600160ff909116105b806109525750303b158015610952575060005460ff166001145b6109e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a4157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff8616610abe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5a45524f5f414444524553535f4e4f545f56414c49440000000000000000000060448201526064016109da565b81610b25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5a45524f5f494e495449414c5f4c4f434b5f4445504f5349540000000000000060448201526064016109da565b610b2e86612126565b610b577f000000000000000000000000000000000000000000000000000000000000000061219d565b610b61848461223d565b610ba0846040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506122e2565b610ba985612383565b610c2a73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61246d565b610c378230336000612672565b508015610c9b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6000610cad610fc1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5b91906152b6565b610d6591906152fe565b905090565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd602090815260408083208054600181019091559051610e9292610e8b92610e17927f31f715285d0336ec5283088d1b45126d1ce4b6ecda1dacc0018f3af0ab9f2739928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b60405160208183030381529060405280519060200120610e35612779565b604080517f19010000000000000000000000000000000000000000000000000000000000006020808301919091526022820193909352604280820194909452815180820390940184526062019052815191012090565b84846127f4565b610e9f8585856001612b81565b90505b949350505050565b606060368054610eb990615315565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee590615315565b8015610f325780601f10610f0757610100808354040283529160200191610f32565b820191906000526020600020905b815481529060010190602001808311610f1557829003601f168201915b5050505050905090565b6000610f49826000612c17565b92915050565b600033610f5d818585612c4a565b5060019392505050565b600080610f72612df5565b90508015610f9357610f8e610f878285612fd6565b6001612fec565b610f96565b60005b9392505050565b600033610fab85828561301e565b610fb68585856130ef565b506001949350505050565b60ff5460009064ffffffffff16421415611002575060fe5470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1690565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561108f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b391906152b6565b60fe549091506000906110d8906fffffffffffffffffffffffffffffffff16836152fe565b60ff5490915060009061110990839065010000000000900467ffffffffffffffff16670de0b6b3a764000084613365565b60fe5490915061114090829070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16615369565b935050505090565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190610f5d908290869061118f908790615369565b612c4a565b6000610f496133c0565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd60209081526040808320805460018101909155905161124b92610e8b92610e17927ff7a555df330b7da73a95b63b182e2bb0502dca4a55fa99d8b235bea4c1d2fa0f928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f858585866001613626565b600080611264612df5565b90508015610f9357610f8e8161127b856000612c17565b90612fd6565b6000610ea2848484336001613626565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd60209081526040808320805460018101909155905161133e92610e8b92610e17927fc0484d18c6ea2cbf7245b69a4c0ff9eac77560075afcb46f857ca211330d8bfd928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f858585866000613626565b611354613724565b61135c6137a5565b61136581612383565b50565b6000610f968383336000612672565b61137f613724565b6113896000612126565b565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd60209081526040808320805460018101909155905161143892610e8b92610e17927f15eaa5acc15a2b2b4af7fa12919d9e1f33955afd5d7af5764a1c5c88ef95f428928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f8585856001612672565b6000610f968383336000612b81565b606060378054610eb990615315565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd60209081526040808320805460018101909155905161151092610e8b92610e17927fe9c23c17074c4703a97d1bd5244f0b58300a709d3583fdad93de5e134ea685d2928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f8585856000612b81565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190838110156115e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016109da565b610fb68286868403612c4a565b600033610f5d8185856130ef565b611604613724565b600061160e610fc1565b90508082111561167a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e53554646494349454e545f4645455300000000000000000000000000000060448201526064016109da565b61168482826152fe565b60fe80546fffffffffffffffffffffffffffffffff9283167001000000000000000000000000000000000292169190911790556040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152829073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611743573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176791906152b6565b61177191906152fe565b60fe80547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9290921691909117905560ff80547fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000164264ffffffffff161790556040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015611878573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189c9190615381565b5060fe54604080516fffffffffffffffffffffffffffffffff80841682527001000000000000000000000000000000009093049092166020830152839173ffffffffffffffffffffffffffffffffffffffff8616917f2f7b02703a7c602588420b2be2f0a441b52632acdfcb11933bfc01e6226bd96691015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd6020908152604080832080546001810190915590516119cf92610e8b92610e17927f2a779101c1c147a93a0f0f2af51e69be2bf9fcfd59c93571c7dc958f7b00bc9f928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f8585858660016139eb565b6000610f496119ea6133c0565b61127b846001612c17565b6000610ea28484843360006139eb565b6000610ea2848484336000613626565b6000610f968383336001612b81565b6000610f49611a316133c0565b6000612fec565b6000610f49826000612fec565b6000610ea28484843360016139eb565b600080611a60612df5565b90508015610f9357610f8e611aa1611a9a8573ffffffffffffffffffffffffffffffffffffffff1660009081526033602052604090205490565b6000612c17565b8290612fd6565b611ab0613724565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611b66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f43414e4e4f545f5245534355455f41544f4b454e00000000000000000000000060448201526064016109da565b611b8773ffffffffffffffffffffffffffffffffffffffff84168383613a82565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fea4a477e0088f88561958e72554e9c7813468c62643829628924da5793beb9698360405161191591815260200190565b600080611bf1612df5565b90508015610f9357610f8e611c288473ffffffffffffffffffffffffffffffffffffffff1660009081526033602052604090205490565b61127b836000612fec565b6000610f968383336001612672565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd602090815260408083208054600181019091559051611cef92610e8b92610e17927fad42a8f215b27fe0954650488d71791b9850878ebd5d05b6dac694749400a1a6928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f8585858660006139eb565b611d05613724565b73ffffffffffffffffffffffffffffffffffffffff8116611d82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43414e4e4f545f434c41494d5f544f5f5a45524f5f414444524553530000000060448201526064016109da565b604080516001808252818301909252600091602080830190803683370190505090507f000000000000000000000000000000000000000000000000000000000000000081600081518110611dd857611dd86153a3565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166375d264136040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea491906153d2565b73ffffffffffffffffffffffffffffffffffffffff1663bb492bf584866040518363ffffffff1660e01b8152600401611ede929190615440565b6000604051808303816000875af1158015611efd573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f439190810190615517565b915091508373ffffffffffffffffffffffffffffffffffffffff167fc53cb8bc1a7200a84d0b66a538905a245c4915aace7f1ce5dc4a0ba107ebc15c8383604051611f8f9291906155dc565b60405180910390a250505050565b6000610f49611a318361127b6133c0565b611fb6613724565b73ffffffffffffffffffffffffffffffffffffffff8116612059576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016109da565b61136581612126565b6000610d65612779565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd60209081526040808320805460018101909155905161211992610e8b92610e17927f63ae75f148e3e5d376e66254575f23cf64979c3f62382d02bd9616f4f49dc499928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f8585856000612672565b6097805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16612234576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b61136581613ad8565b600054610100900460ff166122d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b6122de8282613c1b565b5050565b600054610100900460ff16612379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b6122de8282613cd9565b670de0b6b3a76400008111156123f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4645455f544f4f5f48494748000000000000000000000000000000000000000060448201526064016109da565b60ff805467ffffffffffffffff838116650100000000009081027fffffffffffffffffffffffffffffffffffffff0000000000000000ffffffffff841617909355604051929091041690829082907f528d9479e9f9889a87a3c30c7f7ba537e5e59c4c85a37733b16e57c62df6130290600090a35050565b80158061250d57506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156124e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250b91906152b6565b155b612599576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016109da565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261266d9084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613d8a565b505050565b600061267d84611194565b8511156126e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4445504f5349545f455843454544535f4d41580000000000000000000000000060448201526064016109da565b6126ee6137a5565b60006126f986611a38565b905080612762576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f53484152455300000000000000000000000000000000000000000060448201526064016109da565b610e9f612770826001612c17565b82868887613e96565b6000610d657f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6127a860c95490565b60ca546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b4281606001351015612862576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5349475f4558504952454400000000000000000000000000000000000000000060448201526064016109da565b8173ffffffffffffffffffffffffffffffffffffffff81163b15612a36576000602083018035906040850135906128999086615633565b6040516020016128e193929190928352602083019190915260f81b7fff0000000000000000000000000000000000000000000000000000000000000016604082015260410190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f1626ba7e000000000000000000000000000000000000000000000000000000008083529092509073ffffffffffffffffffffffffffffffffffffffff861690631626ba7e906129669089908690600401615656565b602060405180830381865afa158015612983573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a7919061566f565b7fffffffff000000000000000000000000000000000000000000000000000000001614612a30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5349475f494e56414c494400000000000000000000000000000000000000000060448201526064016109da565b50612b7b565b600184612a466020850185615633565b604080516000815260208181018084529490945260ff9092168282015291850135606082015290840135608082015260a0016020604051602081039080840390855afa158015612a9a573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590612b1557508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b612b7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5349475f494e56414c494400000000000000000000000000000000000000000060448201526064016109da565b50505050565b6000612b8c84611a24565b851115612bf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4d494e545f455843454544535f4d41580000000000000000000000000000000060448201526064016109da565b612bfd6137a5565b6000612c0886614345565b9050610e9f8187868887613e96565b600080612c2360355490565b90508015612c4457612c3f612c36610ca3565b85908386613365565b610ea2565b83610ea2565b73ffffffffffffffffffffffffffffffffffffffff8316612cec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff8216612d8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259101611915565b6040517f35ea6a7500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015260009182917f000000000000000000000000000000000000000000000000000000000000000016906335ea6a75906024016101e060405180830381865afa158015612ea7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ecb919061573a565b80515190915067010000000000000081161580612ef15750671000000000000000811615155b15612eff5760009250505090565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612fab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fcf91906152b6565b9250505090565b6000818310612fe55781610f96565b5090919050565b600080612ff860355490565b9050831580613005575080155b612c4457612c3f81613015610ca3565b86919086613365565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152603460209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612b7b57818110156130e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016109da565b612b7b8484848403612c4a565b73ffffffffffffffffffffffffffffffffffffffff8316613192576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff8216613235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260336020526040902054818110156132eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff80851660008181526033602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906133589086815260200190565b60405180910390a3612b7b565b600080613373868686614352565b905060018360028111156133895761338961585d565b1480156133a65750600084806133a1576133a161588c565b868809115b15610e9f576133b6600182615369565b9695505050505050565b6040517f35ea6a7500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015260009182917f000000000000000000000000000000000000000000000000000000000000000016906335ea6a75906024016101e060405180830381865afa158015613472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613496919061573a565b805151909150640fffffffff607482901c16670100000000000000821615806134c85750670200000000000000821615155b806134dc5750671000000000000000821615155b156134eb576000935050505090565b80613519577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff935050505090565b6135e98361018001516fffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663b1bf962d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561359f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c391906152b6565b6135cd9190615369565b84602001516fffffffffffffffffffffffffffffffff16614420565b60655474010000000000000000000000000000000000000000900460ff1661361290600a6159db565b61361c90836159ea565b61114091906152fe565b60006136306137a5565b61363984611be6565b8611156136a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f52454445454d5f455843454544535f4d4158000000000000000000000000000060448201526064016109da565b60006136ad87610f3c565b905080613716576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f41535345545300000000000000000000000000000000000000000060448201526064016109da565b6133b6818887898888614477565b60975473ffffffffffffffffffffffffffffffffffffffff163314611389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109da565b60ff5464ffffffffff164214611389576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015613842573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061386691906152b6565b60fe549091506000906fffffffffffffffffffffffffffffffff16821161388e5760006138ad565b60fe546138ad906fffffffffffffffffffffffffffffffff16836152fe565b60ff549091506000906138de90839065010000000000900467ffffffffffffffff16670de0b6b3a764000084613365565b60fe8054919250829160109061391b90849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16615a27565b82546101009290920a6fffffffffffffffffffffffffffffffff81810219909316918316021790915560fe80547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169186169190911790555060ff80547fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000164264ffffffffff1617905560408051838152602081018390529081018490527fd3bca34d88bc8c8d0d3304ca482da710a7f673bcd8e764fdae6f4f2b66bb315d9060600160405180910390a1505050565b60006139f56137a5565b6139fe84611a55565b861115613a67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f57495448445241575f455843454544535f4d415800000000000000000000000060448201526064016109da565b6000613a72876147b7565b90506133b6878287898888614477565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261266d9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016125eb565b600054610100900460ff16613b6f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b600080613b7b836147c4565b9150915081613b8b576012613b8d565b805b6065805473ffffffffffffffffffffffffffffffffffffffff9095167fffffffffffffffffffffffff000000000000000000000000000000000000000060ff939093167401000000000000000000000000000000000000000002929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090951694909417179092555050565b600054610100900460ff16613cb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b8151613cc5906036906020850190614df8565b50805161266d906037906020840190614df8565b600054610100900460ff16613d70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b81516020928301208151919092012060c99190915560ca55565b6000613dec826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166148db9092919063ffffffff16565b80519091501561266d5780806020019051810190613e0a9190615381565b61266d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016109da565b8015613fbe576040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152306024830152604482018790527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af1158015613f37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f5b9190615381565b5060fe8054869190600090613f839084906fffffffffffffffffffffffffffffffff16615a27565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506142c4565b61400073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168430886148ea565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561408d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140b191906152b6565b6040517f617ba03700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018990523060448301527f000000000000000000000000000000000000000000000000000000000000000061ffff1660648301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063617ba03790608401600060405180830381600087803b15801561419657600080fd5b505af11580156141aa573d6000803e3d6000fd5b50506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201528392507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691506370a0823190602401602060405180830381865afa15801561423a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061425e91906152b6565b61426891906152fe565b60fe805460009061428c9084906fffffffffffffffffffffffffffffffff16615a27565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505b6142ce8285614948565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d78787604051614336929190918252602082015260400190565b60405180910390a35050505050565b6000610f49826001612c17565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85870985870292508281108382030391505080600014156143ab578382816143a1576143a161588c565b0492505050610f96565b8084116143b757600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b600081157ffffffffffffffffffffffffffffffffffffffffffe6268e1b017bfe18bffffff8390048411151761445557600080fd5b506b033b2e3c9fd0803ce800000091026b019d971e4fe8401e74000000010490565b8373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146144b5576144b584838761301e565b6144bf8486614a3d565b80156145e1576040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018890527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af115801561455a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061457e9190615381565b5060fe80548791906000906145a69084906fffffffffffffffffffffffffffffffff16615a5b565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550614728565b6040517f69328dec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820188905284811660448301526000917f0000000000000000000000000000000000000000000000000000000000000000909116906369328dec906064016020604051808303816000875af11580156146a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146c791906152b6565b60fe805491925082916000906146f09084906fffffffffffffffffffffffffffffffff16615a5b565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505b8373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db89896040516147a7929190918252602082015260400190565b60405180910390a4505050505050565b6000610f49826001612fec565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052905160009182918291829173ffffffffffffffffffffffffffffffffffffffff87169161484691615a8c565b600060405180830381855afa9150503d8060008114614881576040519150601f19603f3d011682016040523d82523d6000602084013e614886565b606091505b509150915081801561489a57506020815110155b156148ce576000818060200190518101906148b591906152b6565b905060ff81116148cc576001969095509350505050565b505b5060009485945092505050565b6060610ea28484600085614c03565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052612b7b9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016125eb565b73ffffffffffffffffffffffffffffffffffffffff82166149c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016109da565b80603560008282546149d79190615369565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152603360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216614ae0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff821660009081526033602052604090205481811015614b96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff831660008181526033602090815260408083208686039055603580548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b606082471015614c95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016109da565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051614cbe9190615a8c565b60006040518083038185875af1925050503d8060008114614cfb576040519150601f19603f3d011682016040523d82523d6000602084013e614d00565b606091505b5091509150614d1187838387614d1c565b979650505050505050565b60608315614daf578251614da85773ffffffffffffffffffffffffffffffffffffffff85163b614da8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109da565b5081610ea2565b610ea28383815115614dc45781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109da919061517d565b828054614e0490615315565b90600052602060002090601f016020900481019282614e265760008555614e6c565b82601f10614e3f57805160ff1916838001178555614e6c565b82800160010185558215614e6c579182015b82811115614e6c578251825591602001919060010190614e51565b50614e78929150614e7c565b5090565b5b80821115614e785760008155600101614e7d565b73ffffffffffffffffffffffffffffffffffffffff8116811461136557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101e0810167ffffffffffffffff81118282101715614f0657614f06614eb3565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5357614f53614eb3565b604052919050565b600082601f830112614f6c57600080fd5b813567ffffffffffffffff811115614f8657614f86614eb3565b614fb760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f0c565b818152846020838601011115614fcc57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561500157600080fd5b853561500c81614e91565b945060208601359350604086013567ffffffffffffffff8082111561503057600080fd5b61503c89838a01614f5b565b9450606088013591508082111561505257600080fd5b5061505f88828901614f5b565b95989497509295608001359392505050565b60006020828403121561508357600080fd5b8135610f9681614e91565b60008060008084860360e08112156150a557600080fd5b8535945060208601356150b781614e91565b935060408601356150c781614e91565b925060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0820112156150f957600080fd5b509295919450926060019150565b60005b8381101561512257818101518382015260200161510a565b83811115612b7b5750506000910152565b6000815180845261514b816020860160208601615107565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610f966020830184615133565b6000602082840312156151a257600080fd5b5035919050565b600080604083850312156151bc57600080fd5b82356151c781614e91565b946020939093013593505050565b6000806000606084860312156151ea57600080fd5b83356151f581614e91565b9250602084013561520581614e91565b929592945050506040919091013590565b60008060006060848603121561522b57600080fd5b83359250602084013561523d81614e91565b9150604084013561524d81614e91565b809150509250925092565b6000806040838503121561526b57600080fd5b82359150602083013561527d81614e91565b809150509250929050565b6000806040838503121561529b57600080fd5b82356152a681614e91565b9150602083013561527d81614e91565b6000602082840312156152c857600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015615310576153106152cf565b500390565b600181811c9082168061532957607f821691505b60208210811415615363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b6000821982111561537c5761537c6152cf565b500190565b60006020828403121561539357600080fd5b81518015158114610f9657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156153e457600080fd5b8151610f9681614e91565b600081518084526020808501945080840160005b8381101561543557815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101615403565b509495945050505050565b60408152600061545360408301856153ef565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b600067ffffffffffffffff82111561549257615492614eb3565b5060051b60200190565b80516154a781614e91565b919050565b600082601f8301126154bd57600080fd5b815160206154d26154cd83615478565b614f0c565b82815260059290921b840181019181810190868411156154f157600080fd5b8286015b8481101561550c57805183529183019183016154f5565b509695505050505050565b6000806040838503121561552a57600080fd5b825167ffffffffffffffff8082111561554257600080fd5b818501915085601f83011261555657600080fd5b815160206155666154cd83615478565b82815260059290921b8401810191818101908984111561558557600080fd5b948201945b838610156155ac57855161559d81614e91565b8252948201949082019061558a565b918801519196509093505050808211156155c557600080fd5b506155d2858286016154ac565b9150509250929050565b6040815260006155ef60408301856153ef565b82810360208481019190915284518083528582019282019060005b818110156156265784518352938301939183019160010161560a565b5090979650505050505050565b60006020828403121561564557600080fd5b813560ff81168114610f9657600080fd5b828152604060208201526000610ea26040830184615133565b60006020828403121561568157600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114610f9657600080fd5b6000602082840312156156c357600080fd5b6040516020810181811067ffffffffffffffff821117156156e6576156e6614eb3565b6040529151825250919050565b80516fffffffffffffffffffffffffffffffff811681146154a757600080fd5b805164ffffffffff811681146154a757600080fd5b805161ffff811681146154a757600080fd5b60006101e0828403121561574d57600080fd5b615755614ee2565b61575f84846156b1565b815261576d602084016156f3565b602082015261577e604084016156f3565b604082015261578f606084016156f3565b60608201526157a0608084016156f3565b60808201526157b160a084016156f3565b60a08201526157c260c08401615713565b60c08201526157d360e08401615728565b60e08201526101006157e681850161549c565b908201526101206157f884820161549c565b9082015261014061580a84820161549c565b9082015261016061581c84820161549c565b9082015261018061582e8482016156f3565b908201526101a06158408482016156f3565b908201526101c06158528482016156f3565b908201529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600181815b8085111561591457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156158fa576158fa6152cf565b8085161561590757918102915b93841c93908002906158c0565b509250929050565b60008261592b57506001610f49565b8161593857506000610f49565b816001811461594e576002811461595857615974565b6001915050610f49565b60ff841115615969576159696152cf565b50506001821b610f49565b5060208310610133831016604e8410600b8410161715615997575081810a610f49565b6159a183836158bb565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156159d3576159d36152cf565b029392505050565b6000610f9660ff84168361591c565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615a2257615a226152cf565b500290565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615a5257615a526152cf565b01949350505050565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a8457615a846152cf565b039392505050565b60008251615a9e818460208701615107565b919091019291505056fea164736f6c634300080a000a0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000000000000000ba10000000000000000000000002f39d218133afab8f2b819b1066c7e434ad94e9e
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061038d5760003560e01c80638da5cb5b116101de578063c63d75b61161010f578063dd62ed3e116100ad578063ef8b30f71161007c578063ef8b30f7146108d7578063f2fde38b146108ea578063f698da25146108fd578063ffd7d21f1461090557600080fd5b8063dd62ed3e14610858578063e25ec3491461089e578063ee4535ba146108b1578063ef5cfb8c146108c457600080fd5b8063ce96cb77116100e9578063ce96cb7714610804578063ced72f8714610817578063d687d0b314610832578063d905777e1461084557600080fd5b8063c63d75b6146107cb578063c6e6f592146107de578063c7df1f56146107f157600080fd5b8063b344ed031161017c578063ba08765211610156578063ba08765214610764578063bddd09b714610777578063bfedc2be14610791578063c5d664c6146107a457600080fd5b8063b344ed031461072b578063b3d7f6b91461073e578063b460af941461075157600080fd5b80639d3ebd94116101b85780639d3ebd94146106df578063a457c2d7146106f2578063a9059cbb14610705578063ad3b1b471461071857600080fd5b80638da5cb5b146106a657806394bf804d146106c457806395d89b41146106d757600080fd5b80633583849a116102c35780635be35e1a1161026157806370a082311161023057806370a0823114610646578063715018a61461067c57806378121dd4146106845780637fc1664a1461069357600080fd5b80635be35e1a146105fa5780636738445e1461060d57806369fe0e2d146106205780636e553f651461063357600080fd5b8063402d267d1161029d578063402d267d1461059a578063403c02d0146105ad5780634cdad506146105c057806351c0e061146105d357600080fd5b80633583849a1461052f57806338d52e0f14610569578063395093511461058757600080fd5b8063095ea7b31161033057806323b872dd1161030a57806323b872dd146104bd578063274f0e24146104d0578063311cd5a4146104d8578063313ce567146104ff57600080fd5b8063095ea7b31461047f5780630a28a477146104a257806318160ddd146104b557600080fd5b80630634d4e91161036c5780630634d4e9146103f857806306fdde031461040b57806307a2d13a1461042057806308a016751461043357600080fd5b80628b187b1461039257806301e1d114146103a757806305ac0ab4146103c2575b600080fd5b6103a56103a0366004614fe9565b610918565b005b6103af610ca3565b6040519081526020015b60405180910390f35b6103af6103d0366004615071565b73ffffffffffffffffffffffffffffffffffffffff16600090815260fd602052604090205490565b6103af61040636600461508e565b610d6a565b610413610eaa565b6040516103b9919061517d565b6103af61042e366004615190565b610f3c565b61045a7f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e281565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103b9565b61049261048d3660046151a9565b610f4f565b60405190151581526020016103b9565b6103af6104b0366004615190565b610f67565b6035546103af565b6104926104cb3660046151d5565b610f9d565b6103af610fc1565b61045a7f0000000000000000000000002f39d218133afab8f2b819b1066c7e434ad94e9e81565b60655474010000000000000000000000000000000000000000900460ff1660405160ff90911681526020016103b9565b6105567f0000000000000000000000000000000000000000000000000000000000000ba181565b60405161ffff90911681526020016103b9565b60655473ffffffffffffffffffffffffffffffffffffffff1661045a565b6104926105953660046151a9565b611148565b6103af6105a8366004615071565b611194565b6103af6105bb36600461508e565b61119e565b6103af6105ce366004615190565b611259565b61045a7f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6381565b6103af610608366004615216565b611281565b6103af61061b36600461508e565b611291565b6103a561062e366004615190565b61134c565b6103af610641366004615258565b611368565b6103af610654366004615071565b73ffffffffffffffffffffffffffffffffffffffff1660009081526033602052604090205490565b6103a5611377565b60ff5464ffffffffff166103af565b6103af6106a136600461508e565b61138b565b60975473ffffffffffffffffffffffffffffffffffffffff1661045a565b6103af6106d2366004615258565b611445565b610413611454565b6103af6106ed36600461508e565b611463565b6104926107003660046151a9565b61151d565b6104926107133660046151a9565b6115ee565b6103a56107263660046151a9565b6115fc565b6103af61073936600461508e565b611922565b6103af61074c366004615190565b6119dd565b6103af61075f366004615216565b6119f5565b6103af610772366004615216565b611a05565b60fe546fffffffffffffffffffffffffffffffff166103af565b6103af61079f366004615258565b611a15565b61045a7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f81565b6103af6107d9366004615071565b611a24565b6103af6107ec366004615190565b611a38565b6103af6107ff366004615216565b611a45565b6103af610812366004615071565b611a55565b60ff5465010000000000900467ffffffffffffffff166103af565b6103a56108403660046151d5565b611aa8565b6103af610853366004615071565b611be6565b6103af610866366004615288565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260346020908152604080832093909416825291909152205490565b6103af6108ac366004615258565b611c33565b6103af6108bf36600461508e565b611c42565b6103a56108d2366004615071565b611cfd565b6103af6108e5366004615190565b611f9d565b6103a56108f8366004615071565b611fae565b6103af612062565b6103af61091336600461508e565b61206c565b600054610100900460ff16158080156109385750600054600160ff909116105b806109525750303b158015610952575060005460ff166001145b6109e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a4157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff8616610abe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5a45524f5f414444524553535f4e4f545f56414c49440000000000000000000060448201526064016109da565b81610b25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5a45524f5f494e495449414c5f4c4f434b5f4445504f5349540000000000000060448201526064016109da565b610b2e86612126565b610b577f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f61219d565b610b61848461223d565b610ba0846040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506122e2565b610ba985612383565b610c2a73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f167f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61246d565b610c378230336000612672565b508015610c9b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6000610cad610fc1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6373ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5b91906152b6565b610d6591906152fe565b905090565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd602090815260408083208054600181019091559051610e9292610e8b92610e17927f31f715285d0336ec5283088d1b45126d1ce4b6ecda1dacc0018f3af0ab9f2739928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b60405160208183030381529060405280519060200120610e35612779565b604080517f19010000000000000000000000000000000000000000000000000000000000006020808301919091526022820193909352604280820194909452815180820390940184526062019052815191012090565b84846127f4565b610e9f8585856001612b81565b90505b949350505050565b606060368054610eb990615315565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee590615315565b8015610f325780601f10610f0757610100808354040283529160200191610f32565b820191906000526020600020905b815481529060010190602001808311610f1557829003601f168201915b5050505050905090565b6000610f49826000612c17565b92915050565b600033610f5d818585612c4a565b5060019392505050565b600080610f72612df5565b90508015610f9357610f8e610f878285612fd6565b6001612fec565b610f96565b60005b9392505050565b600033610fab85828561301e565b610fb68585856130ef565b506001949350505050565b60ff5460009064ffffffffff16421415611002575060fe5470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1690565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6373ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561108f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b391906152b6565b60fe549091506000906110d8906fffffffffffffffffffffffffffffffff16836152fe565b60ff5490915060009061110990839065010000000000900467ffffffffffffffff16670de0b6b3a764000084613365565b60fe5490915061114090829070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16615369565b935050505090565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190610f5d908290869061118f908790615369565b612c4a565b6000610f496133c0565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd60209081526040808320805460018101909155905161124b92610e8b92610e17927ff7a555df330b7da73a95b63b182e2bb0502dca4a55fa99d8b235bea4c1d2fa0f928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f858585866001613626565b600080611264612df5565b90508015610f9357610f8e8161127b856000612c17565b90612fd6565b6000610ea2848484336001613626565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd60209081526040808320805460018101909155905161133e92610e8b92610e17927fc0484d18c6ea2cbf7245b69a4c0ff9eac77560075afcb46f857ca211330d8bfd928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f858585866000613626565b611354613724565b61135c6137a5565b61136581612383565b50565b6000610f968383336000612672565b61137f613724565b6113896000612126565b565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd60209081526040808320805460018101909155905161143892610e8b92610e17927f15eaa5acc15a2b2b4af7fa12919d9e1f33955afd5d7af5764a1c5c88ef95f428928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f8585856001612672565b6000610f968383336000612b81565b606060378054610eb990615315565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd60209081526040808320805460018101909155905161151092610e8b92610e17927fe9c23c17074c4703a97d1bd5244f0b58300a709d3583fdad93de5e134ea685d2928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f8585856000612b81565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190838110156115e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016109da565b610fb68286868403612c4a565b600033610f5d8185856130ef565b611604613724565b600061160e610fc1565b90508082111561167a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e53554646494349454e545f4645455300000000000000000000000000000060448201526064016109da565b61168482826152fe565b60fe80546fffffffffffffffffffffffffffffffff9283167001000000000000000000000000000000000292169190911790556040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152829073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6316906370a0823190602401602060405180830381865afa158015611743573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176791906152b6565b61177191906152fe565b60fe80547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9290921691909117905560ff80547fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000164264ffffffffff161790556040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490527f000000000000000000000000018008bfb33d285247a21d44e50697654f754e63169063a9059cbb906044016020604051808303816000875af1158015611878573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189c9190615381565b5060fe54604080516fffffffffffffffffffffffffffffffff80841682527001000000000000000000000000000000009093049092166020830152839173ffffffffffffffffffffffffffffffffffffffff8616917f2f7b02703a7c602588420b2be2f0a441b52632acdfcb11933bfc01e6226bd96691015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd6020908152604080832080546001810190915590516119cf92610e8b92610e17927f2a779101c1c147a93a0f0f2af51e69be2bf9fcfd59c93571c7dc958f7b00bc9f928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f8585858660016139eb565b6000610f496119ea6133c0565b61127b846001612c17565b6000610ea28484843360006139eb565b6000610ea2848484336000613626565b6000610f968383336001612b81565b6000610f49611a316133c0565b6000612fec565b6000610f49826000612fec565b6000610ea28484843360016139eb565b600080611a60612df5565b90508015610f9357610f8e611aa1611a9a8573ffffffffffffffffffffffffffffffffffffffff1660009081526033602052604090205490565b6000612c17565b8290612fd6565b611ab0613724565b7f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611b66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f43414e4e4f545f5245534355455f41544f4b454e00000000000000000000000060448201526064016109da565b611b8773ffffffffffffffffffffffffffffffffffffffff84168383613a82565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fea4a477e0088f88561958e72554e9c7813468c62643829628924da5793beb9698360405161191591815260200190565b600080611bf1612df5565b90508015610f9357610f8e611c288473ffffffffffffffffffffffffffffffffffffffff1660009081526033602052604090205490565b61127b836000612fec565b6000610f968383336001612672565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd602090815260408083208054600181019091559051611cef92610e8b92610e17927fad42a8f215b27fe0954650488d71791b9850878ebd5d05b6dac694749400a1a6928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f8585858660006139eb565b611d05613724565b73ffffffffffffffffffffffffffffffffffffffff8116611d82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43414e4e4f545f434c41494d5f544f5f5a45524f5f414444524553530000000060448201526064016109da565b604080516001808252818301909252600091602080830190803683370190505090507f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6381600081518110611dd857611dd86153a3565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506000807f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6373ffffffffffffffffffffffffffffffffffffffff166375d264136040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea491906153d2565b73ffffffffffffffffffffffffffffffffffffffff1663bb492bf584866040518363ffffffff1660e01b8152600401611ede929190615440565b6000604051808303816000875af1158015611efd573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f439190810190615517565b915091508373ffffffffffffffffffffffffffffffffffffffff167fc53cb8bc1a7200a84d0b66a538905a245c4915aace7f1ce5dc4a0ba107ebc15c8383604051611f8f9291906155dc565b60405180910390a250505050565b6000610f49611a318361127b6133c0565b611fb6613724565b73ffffffffffffffffffffffffffffffffffffffff8116612059576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016109da565b61136581612126565b6000610d65612779565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260fd60209081526040808320805460018101909155905161211992610e8b92610e17927f63ae75f148e3e5d376e66254575f23cf64979c3f62382d02bd9616f4f49dc499928b928b928b9260608c01359101958652602086019490945273ffffffffffffffffffffffffffffffffffffffff928316604086015291166060840152608083015260a082015260c00190565b610e9f8585856000612672565b6097805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16612234576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b61136581613ad8565b600054610100900460ff166122d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b6122de8282613c1b565b5050565b600054610100900460ff16612379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b6122de8282613cd9565b670de0b6b3a76400008111156123f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4645455f544f4f5f48494748000000000000000000000000000000000000000060448201526064016109da565b60ff805467ffffffffffffffff838116650100000000009081027fffffffffffffffffffffffffffffffffffffff0000000000000000ffffffffff841617909355604051929091041690829082907f528d9479e9f9889a87a3c30c7f7ba537e5e59c4c85a37733b16e57c62df6130290600090a35050565b80158061250d57506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156124e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250b91906152b6565b155b612599576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016109da565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261266d9084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613d8a565b505050565b600061267d84611194565b8511156126e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4445504f5349545f455843454544535f4d41580000000000000000000000000060448201526064016109da565b6126ee6137a5565b60006126f986611a38565b905080612762576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f53484152455300000000000000000000000000000000000000000060448201526064016109da565b610e9f612770826001612c17565b82868887613e96565b6000610d657f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6127a860c95490565b60ca546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b4281606001351015612862576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5349475f4558504952454400000000000000000000000000000000000000000060448201526064016109da565b8173ffffffffffffffffffffffffffffffffffffffff81163b15612a36576000602083018035906040850135906128999086615633565b6040516020016128e193929190928352602083019190915260f81b7fff0000000000000000000000000000000000000000000000000000000000000016604082015260410190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f1626ba7e000000000000000000000000000000000000000000000000000000008083529092509073ffffffffffffffffffffffffffffffffffffffff861690631626ba7e906129669089908690600401615656565b602060405180830381865afa158015612983573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a7919061566f565b7fffffffff000000000000000000000000000000000000000000000000000000001614612a30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5349475f494e56414c494400000000000000000000000000000000000000000060448201526064016109da565b50612b7b565b600184612a466020850185615633565b604080516000815260208181018084529490945260ff9092168282015291850135606082015290840135608082015260a0016020604051602081039080840390855afa158015612a9a573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590612b1557508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b612b7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5349475f494e56414c494400000000000000000000000000000000000000000060448201526064016109da565b50505050565b6000612b8c84611a24565b851115612bf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4d494e545f455843454544535f4d41580000000000000000000000000000000060448201526064016109da565b612bfd6137a5565b6000612c0886614345565b9050610e9f8187868887613e96565b600080612c2360355490565b90508015612c4457612c3f612c36610ca3565b85908386613365565b610ea2565b83610ea2565b73ffffffffffffffffffffffffffffffffffffffff8316612cec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff8216612d8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259101611915565b6040517f35ea6a7500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f8116600483015260009182917f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e216906335ea6a75906024016101e060405180830381865afa158015612ea7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ecb919061573a565b80515190915067010000000000000081161580612ef15750671000000000000000811615155b15612eff5760009250505090565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000018008bfb33d285247a21d44e50697654f754e63811660048301527f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f16906370a0823190602401602060405180830381865afa158015612fab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fcf91906152b6565b9250505090565b6000818310612fe55781610f96565b5090919050565b600080612ff860355490565b9050831580613005575080155b612c4457612c3f81613015610ca3565b86919086613365565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152603460209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612b7b57818110156130e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016109da565b612b7b8484848403612c4a565b73ffffffffffffffffffffffffffffffffffffffff8316613192576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff8216613235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260336020526040902054818110156132eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff80851660008181526033602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906133589086815260200190565b60405180910390a3612b7b565b600080613373868686614352565b905060018360028111156133895761338961585d565b1480156133a65750600084806133a1576133a161588c565b868809115b15610e9f576133b6600182615369565b9695505050505050565b6040517f35ea6a7500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f8116600483015260009182917f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e216906335ea6a75906024016101e060405180830381865afa158015613472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613496919061573a565b805151909150640fffffffff607482901c16670100000000000000821615806134c85750670200000000000000821615155b806134dc5750671000000000000000821615155b156134eb576000935050505090565b80613519577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff935050505090565b6135e98361018001516fffffffffffffffffffffffffffffffff167f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6373ffffffffffffffffffffffffffffffffffffffff1663b1bf962d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561359f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c391906152b6565b6135cd9190615369565b84602001516fffffffffffffffffffffffffffffffff16614420565b60655474010000000000000000000000000000000000000000900460ff1661361290600a6159db565b61361c90836159ea565b61114091906152fe565b60006136306137a5565b61363984611be6565b8611156136a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f52454445454d5f455843454544535f4d4158000000000000000000000000000060448201526064016109da565b60006136ad87610f3c565b905080613716576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f41535345545300000000000000000000000000000000000000000060448201526064016109da565b6133b6818887898888614477565b60975473ffffffffffffffffffffffffffffffffffffffff163314611389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109da565b60ff5464ffffffffff164214611389576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6373ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015613842573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061386691906152b6565b60fe549091506000906fffffffffffffffffffffffffffffffff16821161388e5760006138ad565b60fe546138ad906fffffffffffffffffffffffffffffffff16836152fe565b60ff549091506000906138de90839065010000000000900467ffffffffffffffff16670de0b6b3a764000084613365565b60fe8054919250829160109061391b90849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16615a27565b82546101009290920a6fffffffffffffffffffffffffffffffff81810219909316918316021790915560fe80547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169186169190911790555060ff80547fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000164264ffffffffff1617905560408051838152602081018390529081018490527fd3bca34d88bc8c8d0d3304ca482da710a7f673bcd8e764fdae6f4f2b66bb315d9060600160405180910390a1505050565b60006139f56137a5565b6139fe84611a55565b861115613a67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f57495448445241575f455843454544535f4d415800000000000000000000000060448201526064016109da565b6000613a72876147b7565b90506133b6878287898888614477565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261266d9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016125eb565b600054610100900460ff16613b6f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b600080613b7b836147c4565b9150915081613b8b576012613b8d565b805b6065805473ffffffffffffffffffffffffffffffffffffffff9095167fffffffffffffffffffffffff000000000000000000000000000000000000000060ff939093167401000000000000000000000000000000000000000002929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090951694909417179092555050565b600054610100900460ff16613cb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b8151613cc5906036906020850190614df8565b50805161266d906037906020840190614df8565b600054610100900460ff16613d70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016109da565b81516020928301208151919092012060c99190915560ca55565b6000613dec826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166148db9092919063ffffffff16565b80519091501561266d5780806020019051810190613e0a9190615381565b61266d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016109da565b8015613fbe576040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152306024830152604482018790527f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6316906323b872dd906064016020604051808303816000875af1158015613f37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f5b9190615381565b5060fe8054869190600090613f839084906fffffffffffffffffffffffffffffffff16615a27565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506142c4565b61400073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f168430886148ea565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6373ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561408d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140b191906152b6565b6040517f617ba03700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f81166004830152602482018990523060448301527f0000000000000000000000000000000000000000000000000000000000000ba161ffff1660648301529192507f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e29091169063617ba03790608401600060405180830381600087803b15801561419657600080fd5b505af11580156141aa573d6000803e3d6000fd5b50506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201528392507f000000000000000000000000018008bfb33d285247a21d44e50697654f754e6373ffffffffffffffffffffffffffffffffffffffff1691506370a0823190602401602060405180830381865afa15801561423a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061425e91906152b6565b61426891906152fe565b60fe805460009061428c9084906fffffffffffffffffffffffffffffffff16615a27565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505b6142ce8285614948565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d78787604051614336929190918252602082015260400190565b60405180910390a35050505050565b6000610f49826001612c17565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85870985870292508281108382030391505080600014156143ab578382816143a1576143a161588c565b0492505050610f96565b8084116143b757600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b600081157ffffffffffffffffffffffffffffffffffffffffffe6268e1b017bfe18bffffff8390048411151761445557600080fd5b506b033b2e3c9fd0803ce800000091026b019d971e4fe8401e74000000010490565b8373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146144b5576144b584838761301e565b6144bf8486614a3d565b80156145e1576040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018890527f000000000000000000000000018008bfb33d285247a21d44e50697654f754e63169063a9059cbb906044016020604051808303816000875af115801561455a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061457e9190615381565b5060fe80548791906000906145a69084906fffffffffffffffffffffffffffffffff16615a5b565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550614728565b6040517f69328dec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f811660048301526024820188905284811660448301526000917f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e2909116906369328dec906064016020604051808303816000875af11580156146a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146c791906152b6565b60fe805491925082916000906146f09084906fffffffffffffffffffffffffffffffff16615a5b565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505b8373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db89896040516147a7929190918252602082015260400190565b60405180910390a4505050505050565b6000610f49826001612fec565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052905160009182918291829173ffffffffffffffffffffffffffffffffffffffff87169161484691615a8c565b600060405180830381855afa9150503d8060008114614881576040519150601f19603f3d011682016040523d82523d6000602084013e614886565b606091505b509150915081801561489a57506020815110155b156148ce576000818060200190518101906148b591906152b6565b905060ff81116148cc576001969095509350505050565b505b5060009485945092505050565b6060610ea28484600085614c03565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052612b7b9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016125eb565b73ffffffffffffffffffffffffffffffffffffffff82166149c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016109da565b80603560008282546149d79190615369565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152603360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216614ae0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff821660009081526033602052604090205481811015614b96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016109da565b73ffffffffffffffffffffffffffffffffffffffff831660008181526033602090815260408083208686039055603580548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b606082471015614c95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016109da565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051614cbe9190615a8c565b60006040518083038185875af1925050503d8060008114614cfb576040519150601f19603f3d011682016040523d82523d6000602084013e614d00565b606091505b5091509150614d1187838387614d1c565b979650505050505050565b60608315614daf578251614da85773ffffffffffffffffffffffffffffffffffffffff85163b614da8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109da565b5081610ea2565b610ea28383815115614dc45781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109da919061517d565b828054614e0490615315565b90600052602060002090601f016020900481019282614e265760008555614e6c565b82601f10614e3f57805160ff1916838001178555614e6c565b82800160010185558215614e6c579182015b82811115614e6c578251825591602001919060010190614e51565b50614e78929150614e7c565b5090565b5b80821115614e785760008155600101614e7d565b73ffffffffffffffffffffffffffffffffffffffff8116811461136557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101e0810167ffffffffffffffff81118282101715614f0657614f06614eb3565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5357614f53614eb3565b604052919050565b600082601f830112614f6c57600080fd5b813567ffffffffffffffff811115614f8657614f86614eb3565b614fb760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f0c565b818152846020838601011115614fcc57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561500157600080fd5b853561500c81614e91565b945060208601359350604086013567ffffffffffffffff8082111561503057600080fd5b61503c89838a01614f5b565b9450606088013591508082111561505257600080fd5b5061505f88828901614f5b565b95989497509295608001359392505050565b60006020828403121561508357600080fd5b8135610f9681614e91565b60008060008084860360e08112156150a557600080fd5b8535945060208601356150b781614e91565b935060408601356150c781614e91565b925060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0820112156150f957600080fd5b509295919450926060019150565b60005b8381101561512257818101518382015260200161510a565b83811115612b7b5750506000910152565b6000815180845261514b816020860160208601615107565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610f966020830184615133565b6000602082840312156151a257600080fd5b5035919050565b600080604083850312156151bc57600080fd5b82356151c781614e91565b946020939093013593505050565b6000806000606084860312156151ea57600080fd5b83356151f581614e91565b9250602084013561520581614e91565b929592945050506040919091013590565b60008060006060848603121561522b57600080fd5b83359250602084013561523d81614e91565b9150604084013561524d81614e91565b809150509250925092565b6000806040838503121561526b57600080fd5b82359150602083013561527d81614e91565b809150509250929050565b6000806040838503121561529b57600080fd5b82356152a681614e91565b9150602083013561527d81614e91565b6000602082840312156152c857600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015615310576153106152cf565b500390565b600181811c9082168061532957607f821691505b60208210811415615363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b6000821982111561537c5761537c6152cf565b500190565b60006020828403121561539357600080fd5b81518015158114610f9657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156153e457600080fd5b8151610f9681614e91565b600081518084526020808501945080840160005b8381101561543557815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101615403565b509495945050505050565b60408152600061545360408301856153ef565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b600067ffffffffffffffff82111561549257615492614eb3565b5060051b60200190565b80516154a781614e91565b919050565b600082601f8301126154bd57600080fd5b815160206154d26154cd83615478565b614f0c565b82815260059290921b840181019181810190868411156154f157600080fd5b8286015b8481101561550c57805183529183019183016154f5565b509695505050505050565b6000806040838503121561552a57600080fd5b825167ffffffffffffffff8082111561554257600080fd5b818501915085601f83011261555657600080fd5b815160206155666154cd83615478565b82815260059290921b8401810191818101908984111561558557600080fd5b948201945b838610156155ac57855161559d81614e91565b8252948201949082019061558a565b918801519196509093505050808211156155c557600080fd5b506155d2858286016154ac565b9150509250929050565b6040815260006155ef60408301856153ef565b82810360208481019190915284518083528582019282019060005b818110156156265784518352938301939183019160010161560a565b5090979650505050505050565b60006020828403121561564557600080fd5b813560ff81168114610f9657600080fd5b828152604060208201526000610ea26040830184615133565b60006020828403121561568157600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114610f9657600080fd5b6000602082840312156156c357600080fd5b6040516020810181811067ffffffffffffffff821117156156e6576156e6614eb3565b6040529151825250919050565b80516fffffffffffffffffffffffffffffffff811681146154a757600080fd5b805164ffffffffff811681146154a757600080fd5b805161ffff811681146154a757600080fd5b60006101e0828403121561574d57600080fd5b615755614ee2565b61575f84846156b1565b815261576d602084016156f3565b602082015261577e604084016156f3565b604082015261578f606084016156f3565b60608201526157a0608084016156f3565b60808201526157b160a084016156f3565b60a08201526157c260c08401615713565b60c08201526157d360e08401615728565b60e08201526101006157e681850161549c565b908201526101206157f884820161549c565b9082015261014061580a84820161549c565b9082015261016061581c84820161549c565b9082015261018061582e8482016156f3565b908201526101a06158408482016156f3565b908201526101c06158528482016156f3565b908201529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600181815b8085111561591457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156158fa576158fa6152cf565b8085161561590757918102915b93841c93908002906158c0565b509250929050565b60008261592b57506001610f49565b8161593857506000610f49565b816001811461594e576002811461595857615974565b6001915050610f49565b60ff841115615969576159696152cf565b50506001821b610f49565b5060208310610133831016604e8410600b8410161715615997575081810a610f49565b6159a183836158bb565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156159d3576159d36152cf565b029392505050565b6000610f9660ff84168361591c565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615a2257615a226152cf565b500290565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615a5257615a526152cf565b01949350505050565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a8457615a846152cf565b039392505050565b60008251615a9e818460208701615107565b919091019291505056fea164736f6c634300080a000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000000000000000ba10000000000000000000000002f39d218133afab8f2b819b1066c7e434ad94e9e
-----Decoded View---------------
Arg [0] : underlying (address): 0x6B175474E89094C44Da98b954EedeAC495271d0F
Arg [1] : referralCode (uint16): 2977
Arg [2] : poolAddressesProvider (address): 0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000ba1
Arg [2] : 0000000000000000000000002f39d218133afab8f2b819b1066c7e434ad94e9e
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
POL | 100.00% | $0.99785 | 108.0719 | $107.84 |
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.