More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 6 from a total of 6 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw Aera Va... | 20762216 | 163 days ago | IN | 0 ETH | 0.00030651 | ||||
Set Profit Max U... | 20515908 | 197 days ago | IN | 0 ETH | 0.00007187 | ||||
Set Performance ... | 20515907 | 197 days ago | IN | 0 ETH | 0.00006073 | ||||
Set Performance ... | 20515906 | 197 days ago | IN | 0 ETH | 0.00006001 | ||||
Set Keeper | 20515905 | 197 days ago | IN | 0 ETH | 0.00006055 | ||||
Set Pending Mana... | 20515904 | 197 days ago | IN | 0 ETH | 0.00009174 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
AeraStrategy
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 10000 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0 pragma solidity >=0.8.18; import "./BaseHooks.sol"; import "./interfaces/IAeraVaultV2.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; contract AeraStrategy is BaseHooks, ReentrancyGuard { using SafeERC20 for IERC20; address public immutable vaultYearn; // vault that can call deposit/withdraw address public vaultAera; // Guantlet Vault address public quickManagement; address public pendingQuickManagement; // Address that is pending to take over `management`. event UpdateQuickManagement(address indexed newQuickManagement); event UpdateVaultAera(address indexed vaultAera); event UpdatePendingQuickManagement(address indexed pendingQuickManagement); constructor( address _asset, string memory _name, address _vaultAera, address _vaultYearn, address _quickManagement ) BaseHooks(_asset, _name) { require(_vaultAera != address(0), "ZERO ADDRESS"); vaultAera = _vaultAera; require(_vaultYearn != address(0), "ZERO ADDRESS"); vaultYearn = _vaultYearn; require(_quickManagement != address(0), "ZERO ADDRESS"); quickManagement = _quickManagement; emit UpdateQuickManagement(_quickManagement); emit UpdateVaultAera(_vaultAera); IERC20(_asset).safeIncreaseAllowance(vaultAera, type(uint256).max); } modifier onlyQuickManagement() { requireQuickManagementOrManagement(msg.sender); _; } /*////////////////////////////////////////////////////////////// AERA FUNCTIONS ///////////////////////////////////////////////////////////////*/ function execute( address to, uint256 value, bytes calldata data ) external payable nonReentrant onlyManagement returns (bool, bytes memory) { (bool success, bytes memory result) = to.call{ value: value }(data); return (success, result); } function executeOnAera(Operation calldata operation) external onlyManagement { IAeraVaultV2(vaultAera).execute(operation); } function claim() external { IAeraVaultV2(vaultAera).claim(); } function setGuardianAndFeeRecipient(address newGuardian, address newFeeRecipient) external onlyManagement { IAeraVaultV2(vaultAera).setGuardianAndFeeRecipient(newGuardian, newFeeRecipient); } function setHooks(address newHooks) external onlyManagement { IAeraVaultV2(vaultAera).setHooks(newHooks); } function finalize() external onlyManagement { IAeraVaultV2(vaultAera).finalize(); } function pause() external onlyManagement { IAeraVaultV2(vaultAera).pause(); } function resume() external onlyManagement { IAeraVaultV2(vaultAera).resume(); } function transferOwnership(address newOwner) external onlyManagement { address _vaultAera = vaultAera; IERC20(asset).safeApprove(_vaultAera, 0); IAeraVaultV2(_vaultAera).transferOwnership(newOwner); } function acceptOwnership() external onlyManagement { IAeraVaultV2(vaultAera).acceptOwnership(); } function depositAeraVault(uint256 amount) external onlyQuickManagement { require(asset.balanceOf(address(this)) >= amount, "AmountTooHigh"); _deployFunds(amount); } function withdrawAeraVault(uint256 amount) external onlyQuickManagement { require(_getAssetBalance() >= amount, "AmountTooHigh"); _freeFunds(amount); } // Setters function setVaultAera(address _vaultAera) external onlyManagement { require(IAeraVaultV2(vaultAera).value() == 0, "!Empty"); _setVaultAera(_vaultAera); } function setForceVaultAera(address _vaultAera) external onlyManagement { _setVaultAera(_vaultAera); } function setPendingQuickManagement(address _pendingQuickManagement) external onlyManagement { require(_pendingQuickManagement != address(0), "ZERO ADDRESS"); pendingQuickManagement = _pendingQuickManagement; emit UpdatePendingQuickManagement(_pendingQuickManagement); } function acceptQuickManagement() external { require(msg.sender == pendingQuickManagement, "!pending"); quickManagement = msg.sender; pendingQuickManagement = address(0); emit UpdateQuickManagement(msg.sender); } // Getters function availableWithdrawLimit(address) public view override returns (uint256) { return asset.balanceOf(address(this)); } function availableDepositLimit(address _owner) public view override returns (uint256) { if (_owner == vaultYearn) return type(uint256).max; return 0; } function requireQuickManagementOrManagement(address _sender) public view { require(_sender == quickManagement || _sender == TokenizedStrategy.management(), "!quickManagement"); } // Internal Functions function _preDepositHook(uint256, uint256, address receiver) internal view override { require(msg.sender == receiver, "!msg.sender"); } function _deployFunds(uint256 _amount) internal override { AssetValue[] memory amounts = new AssetValue[](1); amounts[0] = AssetValue(asset, _amount); IAeraVaultV2(vaultAera).deposit(amounts); } function _freeFunds(uint256 _amount) internal override { AssetValue[] memory amounts = new AssetValue[](1); amounts[0] = AssetValue(asset, _amount); IAeraVaultV2(vaultAera).withdraw(amounts); } function _harvestAndReport() internal view override returns (uint256 _totalAssets) { _totalAssets = asset.balanceOf(address(this)) + IAeraVaultV2(vaultAera).value(); } function _setVaultAera(address _vaultAera) internal { IERC20(asset).safeApprove(vaultAera, 0); vaultAera = _vaultAera; IERC20(asset).safeIncreaseAllowance(_vaultAera, type(uint256).max); emit UpdateVaultAera(_vaultAera); } function _getAssetBalance() internal view returns (uint256) { AssetValue[] memory assetAmounts = IAeraVaultV2(vaultAera).holdings(); uint256 lenAssetAmounts = assetAmounts.length; for (uint256 i; i < lenAssetAmounts; ++i) { if (address(asset) == address(assetAmounts[i].asset)) { return assetAmounts[i].value; } } return 0; } }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity >=0.8.18; import {Hooks} from "./Hooks.sol"; import {BaseStrategy} from "./BaseStrategy.sol"; /** * @title Base Hooks * @author Yearn.finance * @notice This contract can be inherited by any Yearn * strategy wishing to implement pre or post deposit, withdraw * or transfer hooks in their strategy. */ abstract contract BaseHooks is BaseStrategy, Hooks { uint256 internal constant MAX_BPS = 10_000; constructor( address _asset, string memory _name ) BaseStrategy(_asset, _name) {} // Deposit function deposit( uint256 assets, address receiver ) external virtual returns (uint256 shares) { _preDepositHook(assets, shares, receiver); shares = abi.decode( _delegateCall( abi.encodeCall(TokenizedStrategy.deposit, (assets, receiver)) ), (uint256) ); _postDepositHook(assets, shares, receiver); } // Mint function mint( uint256 shares, address receiver ) external virtual returns (uint256 assets) { _preDepositHook(assets, shares, receiver); assets = abi.decode( _delegateCall( abi.encodeCall(TokenizedStrategy.mint, (shares, receiver)) ), (uint256) ); _postDepositHook(assets, shares, receiver); } // Withdraw function withdraw( uint256 assets, address receiver, address owner ) external virtual returns (uint256 shares) { return withdraw(assets, receiver, owner, 0); } function withdraw( uint256 assets, address receiver, address owner, uint256 maxLoss ) public virtual returns (uint256 shares) { _preWithdrawHook(assets, shares, receiver, owner, maxLoss); shares = abi.decode( _delegateCall( // Have to use encodeWithSignature due to overloading parameters. abi.encodeWithSignature( "withdraw(uint256,address,address,uint256)", assets, receiver, owner, maxLoss ) ), (uint256) ); _postWithdrawHook(assets, shares, receiver, owner, maxLoss); } // Redeem function redeem( uint256 shares, address receiver, address owner ) external virtual returns (uint256) { // We default to not limiting a potential loss. return redeem(shares, receiver, owner, MAX_BPS); } function redeem( uint256 shares, address receiver, address owner, uint256 maxLoss ) public returns (uint256 assets) { _preWithdrawHook(assets, shares, receiver, owner, maxLoss); assets = abi.decode( _delegateCall( // Have to use encodeWithSignature due to overloading parameters. abi.encodeWithSignature( "redeem(uint256,address,address,uint256)", shares, receiver, owner, maxLoss ) ), (uint256) ); _postWithdrawHook(assets, shares, receiver, owner, maxLoss); } // Transfer function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool success) { _preTransferHook(from, to, amount); success = abi.decode( _delegateCall( abi.encodeCall( TokenizedStrategy.transferFrom, (from, to, amount) ) ), (bool) ); _postTransferHook(from, to, amount, success); } // Transfer from function transfer( address to, uint256 amount ) external virtual returns (bool success) { _preTransferHook(msg.sender, to, amount); success = abi.decode( _delegateCall( abi.encodeCall(TokenizedStrategy.transfer, (to, amount)) ), (bool) ); _postTransferHook(msg.sender, to, amount, success); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.18; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "src/tokenisedStrategy/interfaces/IAssetRegistry.sol"; import "src/tokenisedStrategy/interfaces/IHooks.sol"; import "src/tokenisedStrategy/Types.sol"; interface IAeraVaultV2 { /// FUNCTIONS /// /// @notice Deposit assets. /// @param amounts Assets and amounts to deposit. /// @dev MUST revert if not called by owner. function deposit(AssetValue[] memory amounts) external; /// @notice Withdraw assets. /// @param amounts Assets and amounts to withdraw. /// @dev MUST revert if not called by owner. function withdraw(AssetValue[] memory amounts) external; /// @notice Set current guardian and fee recipient. /// @param guardian New guardian address. /// @param feeRecipient New fee recipient address. /// @dev MUST revert if not called by owner. function setGuardianAndFeeRecipient(address guardian, address feeRecipient) external; /// @notice Sets the current hooks module. /// @param hooks New hooks module address. /// @dev MUST revert if not called by owner. function setHooks(address hooks) external; /// @notice Execute a transaction via the vault. /// @dev Execution still should work when vault is finalized. /// @param operation Struct details for target and calldata to execute. /// @dev MUST revert if not called by owner. function execute(Operation memory operation) external; /// @notice Terminate the vault and return all funds to owner. /// @dev MUST revert if not called by owner. function finalize() external; /// @notice Stops the guardian from submission and halts fee accrual. /// @dev MUST revert if not called by owner or guardian. function pause() external; /// @notice Resume fee accrual and guardian submissions. /// @dev MUST revert if not called by owner. function resume() external; /// @notice Submit a series of transactions for execution via the vault. /// @param operations Sequence of operations to execute. /// @dev MUST revert if not called by guardian. function submit(Operation[] memory operations) external; /// @notice Claim fees on behalf of a current or previous fee recipient. function claim() external; /// @notice Get the current guardian. /// @return guardian Address of guardian. function guardian() external view returns (address guardian); /// @notice Get the current fee recipient. /// @return feeRecipient Address of fee recipient. function feeRecipient() external view returns (address feeRecipient); /// @notice Get the current asset registry. /// @return assetRegistry Address of asset registry. function assetRegistry() external view returns (IAssetRegistry assetRegistry); /// @notice Get the current hooks module address. /// @return hooks Address of hooks module. function hooks() external view returns (IHooks hooks); /// @notice Get fee per second. /// @return fee Fee per second in 18 decimal fixed point format. function fee() external view returns (uint256 fee); /// @notice Get current balances of all assets. /// @return assetAmounts Amounts of registered assets. function holdings() external view returns (AssetValue[] memory assetAmounts); /// @notice Get current total value of assets in vault. /// @return value Current total value. function value() external view returns (uint256 value); function transferOwnership(address newOwner) external; function acceptOwnership() external; function owner() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.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 SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 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(IERC20 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)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit 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(IERC20 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"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation 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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity >=0.8.18; contract DepositHooks { function _preDepositHook( uint256 assets, uint256 shares, address receiver ) internal virtual {} function _postDepositHook( uint256 assets, uint256 shares, address receiver ) internal virtual {} } contract WithdrawHooks { function _preWithdrawHook( uint256 assets, uint256 shares, address receiver, address owner, uint256 maxLoss ) internal virtual {} function _postWithdrawHook( uint256 assets, uint256 shares, address receiver, address owner, uint256 maxLoss ) internal virtual {} } contract TransferHooks { function _preTransferHook( address from, address to, uint256 amount ) internal virtual {} function _postTransferHook( address from, address to, uint256 amount, bool success ) internal virtual {} } contract Hooks is DepositHooks, WithdrawHooks, TransferHooks {}
// SPDX-License-Identifier: AGPL-3.0 pragma solidity >=0.8.18; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; // TokenizedStrategy interface used for internal view delegateCalls. import { ITokenizedStrategy } from "./interfaces/ITokenizedStrategy.sol"; /** * @title YearnV3 Base Strategy * @author yearn.finance * @notice * BaseStrategy implements all of the required functionality to * seamlessly integrate with the `TokenizedStrategy` implementation contract * allowing anyone to easily build a fully permissionless ERC-4626 compliant * Vault by inheriting this contract and overriding three simple functions. * * It utilizes an immutable proxy pattern that allows the BaseStrategy * to remain simple and small. All standard logic is held within the * `TokenizedStrategy` and is reused over any n strategies all using the * `fallback` function to delegatecall the implementation so that strategists * can only be concerned with writing their strategy specific code. * * This contract should be inherited and the three main abstract methods * `_deployFunds`, `_freeFunds` and `_harvestAndReport` implemented to adapt * the Strategy to the particular needs it has to generate yield. There are * other optional methods that can be implemented to further customize * the strategy if desired. * * All default storage for the strategy is controlled and updated by the * `TokenizedStrategy`. The implementation holds a storage struct that * contains all needed global variables in a manual storage slot. This * means strategists can feel free to implement their own custom storage * variables as they need with no concern of collisions. All global variables * can be viewed within the Strategy by a simple call using the * `TokenizedStrategy` variable. IE: TokenizedStrategy.globalVariable();. */ abstract contract BaseStrategy { /*////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////*/ /** * @dev Used on TokenizedStrategy callback functions to make sure it is post * a delegateCall from this address to the TokenizedStrategy. */ modifier onlySelf() { _onlySelf(); _; } /** * @dev Use to assure that the call is coming from the strategies management. */ modifier onlyManagement() { TokenizedStrategy.requireManagement(msg.sender); _; } /** * @dev Use to assure that the call is coming from either the strategies * management or the keeper. */ modifier onlyKeepers() { TokenizedStrategy.requireKeeperOrManagement(msg.sender); _; } /** * @dev Use to assure that the call is coming from either the strategies * management or the emergency admin. */ modifier onlyEmergencyAuthorized() { TokenizedStrategy.requireEmergencyAuthorized(msg.sender); _; } /** * @dev Require that the msg.sender is this address. */ function _onlySelf() internal view { require(msg.sender == address(this), "!self"); } /*////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////*/ /** * @dev This is the address of the TokenizedStrategy implementation * contract that will be used by all strategies to handle the * accounting, logic, storage etc. * * Any external calls to the that don't hit one of the functions * defined in this base or the strategy will end up being forwarded * through the fallback function, which will delegateCall this address. * * This address should be the same for every strategy, never be adjusted * and always be checked before any integration with the Strategy. */ // NOTE: This is a holder address based on expected deterministic location for testing address public constant tokenizedStrategyAddress = 0x975304C676eB3dc86CD336138328E107A95EaA50; /*////////////////////////////////////////////////////////////// IMMUTABLES //////////////////////////////////////////////////////////////*/ /** * @dev Underlying asset the Strategy is earning yield on. * Stored here for cheap retrievals within the strategy. */ ERC20 internal immutable asset; /** * @dev This variable is set to address(this) during initialization of each strategy. * * This can be used to retrieve storage data within the strategy * contract as if it were a linked library. * * i.e. uint256 totalAssets = TokenizedStrategy.totalAssets() * * Using address(this) will mean any calls using this variable will lead * to a call to itself. Which will hit the fallback function and * delegateCall that to the actual TokenizedStrategy. */ ITokenizedStrategy internal immutable TokenizedStrategy; /** * @notice Used to initialize the strategy on deployment. * * This will set the `TokenizedStrategy` variable for easy * internal view calls to the implementation. As well as * initializing the default storage variables based on the * parameters and using the deployer for the permissioned roles. * * @param _asset Address of the underlying asset. * @param _name Name the strategy will use. */ constructor(address _asset, string memory _name) { asset = ERC20(_asset); // Set instance of the implementation for internal use. TokenizedStrategy = ITokenizedStrategy(address(this)); // Initialize the strategy's storage variables. _delegateCall( abi.encodeCall(ITokenizedStrategy.initialize, (_asset, _name, msg.sender, msg.sender, msg.sender)) ); // Store the tokenizedStrategyAddress at the standard implementation // address storage slot so etherscan picks up the interface. This gets // stored on initialization and never updated. assembly { sstore( // keccak256('eip1967.proxy.implementation' - 1) 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc, tokenizedStrategyAddress ) } } /*////////////////////////////////////////////////////////////// NEEDED TO BE OVERRIDDEN BY STRATEGIST //////////////////////////////////////////////////////////////*/ /** * @dev Can deploy up to '_amount' of 'asset' in the yield source. * * This function is called at the end of a {deposit} or {mint} * call. Meaning that unless a whitelist is implemented it will * be entirely permissionless and thus can be sandwiched or otherwise * manipulated. * * @param _amount The amount of 'asset' that the strategy can attempt * to deposit in the yield source. */ function _deployFunds(uint256 _amount) internal virtual; /** * @dev Should attempt to free the '_amount' of 'asset'. * * NOTE: The amount of 'asset' that is already loose has already * been accounted for. * * This function is called during {withdraw} and {redeem} calls. * Meaning that unless a whitelist is implemented it will be * entirely permissionless and thus can be sandwiched or otherwise * manipulated. * * Should not rely on asset.balanceOf(address(this)) calls other than * for diff accounting purposes. * * Any difference between `_amount` and what is actually freed will be * counted as a loss and passed on to the withdrawer. This means * care should be taken in times of illiquidity. It may be better to revert * if withdraws are simply illiquid so not to realize incorrect losses. * * @param _amount, The amount of 'asset' to be freed. */ function _freeFunds(uint256 _amount) internal virtual; /** * @dev Internal function to harvest all rewards, redeploy any idle * funds and return an accurate accounting of all funds currently * held by the Strategy. * * This should do any needed harvesting, rewards selling, accrual, * redepositing etc. to get the most accurate view of current assets. * * NOTE: All applicable assets including loose assets should be * accounted for in this function. * * Care should be taken when relying on oracles or swap values rather * than actual amounts as all Strategy profit/loss accounting will * be done based on this returned value. * * This can still be called post a shutdown, a strategist can check * `TokenizedStrategy.isShutdown()` to decide if funds should be * redeployed or simply realize any profits/losses. * * @return _totalAssets A trusted and accurate account for the total * amount of 'asset' the strategy currently holds including idle funds. */ function _harvestAndReport() internal virtual returns (uint256 _totalAssets); /*////////////////////////////////////////////////////////////// OPTIONAL TO OVERRIDE BY STRATEGIST //////////////////////////////////////////////////////////////*/ /** * @dev Optional function for strategist to override that can * be called in between reports. * * If '_tend' is used tendTrigger() will also need to be overridden. * * This call can only be called by a permissioned role so may be * through protected relays. * * This can be used to harvest and compound rewards, deposit idle funds, * perform needed position maintenance or anything else that doesn't need * a full report for. * * EX: A strategy that can not deposit funds without getting * sandwiched can use the tend when a certain threshold * of idle to totalAssets has been reached. * * This will have no effect on PPS of the strategy till report() is called. * * @param _totalIdle The current amount of idle funds that are available to deploy. */ function _tend(uint256 _totalIdle) internal virtual { } /** * @dev Optional trigger to override if tend() will be used by the strategy. * This must be implemented if the strategy hopes to invoke _tend(). * * @return . Should return true if tend() should be called by keeper or false if not. */ function _tendTrigger() internal view virtual returns (bool) { return false; } /** * @notice Returns if tend() should be called by a keeper. * * @return . Should return true if tend() should be called by keeper or false if not. * @return . Calldata for the tend call. */ function tendTrigger() external view virtual returns (bool, bytes memory) { return ( // Return the status of the tend trigger. _tendTrigger(), // And the needed calldata either way. abi.encodeWithSelector(ITokenizedStrategy.tend.selector) ); } /** * @notice Gets the max amount of `asset` that an address can deposit. * @dev Defaults to an unlimited amount for any address. But can * be overridden by strategists. * * This function will be called before any deposit or mints to enforce * any limits desired by the strategist. This can be used for either a * traditional deposit limit or for implementing a whitelist etc. * * EX: * if(isAllowed[_owner]) return super.availableDepositLimit(_owner); * * This does not need to take into account any conversion rates * from shares to assets. But should know that any non max uint256 * amounts may be converted to shares. So it is recommended to keep * custom amounts low enough as not to cause overflow when multiplied * by `totalSupply`. * * @param . The address that is depositing into the strategy. * @return . The available amount the `_owner` can deposit in terms of `asset` */ function availableDepositLimit(address /*_owner*/ ) public view virtual returns (uint256) { return type(uint256).max; } /** * @notice Gets the max amount of `asset` that can be withdrawn. * @dev Defaults to an unlimited amount for any address. But can * be overridden by strategists. * * This function will be called before any withdraw or redeem to enforce * any limits desired by the strategist. This can be used for illiquid * or sandwichable strategies. It should never be lower than `totalIdle`. * * EX: * return TokenIzedStrategy.totalIdle(); * * This does not need to take into account the `_owner`'s share balance * or conversion rates from shares to assets. * * @param . The address that is withdrawing from the strategy. * @return . The available amount that can be withdrawn in terms of `asset` */ function availableWithdrawLimit(address /*_owner*/ ) public view virtual returns (uint256) { return type(uint256).max; } /** * @dev Optional function for a strategist to override that will * allow management to manually withdraw deployed funds from the * yield source if a strategy is shutdown. * * This should attempt to free `_amount`, noting that `_amount` may * be more than is currently deployed. * * NOTE: This will not realize any profits or losses. A separate * {report} will be needed in order to record any profit/loss. If * a report may need to be called after a shutdown it is important * to check if the strategy is shutdown during {_harvestAndReport} * so that it does not simply re-deploy all funds that had been freed. * * EX: * if(freeAsset > 0 && !TokenizedStrategy.isShutdown()) { * depositFunds... * } * * @param _amount The amount of asset to attempt to free. */ function _emergencyWithdraw(uint256 _amount) internal virtual { } /*////////////////////////////////////////////////////////////// TokenizedStrategy HOOKS //////////////////////////////////////////////////////////////*/ /** * @notice Can deploy up to '_amount' of 'asset' in yield source. * @dev Callback for the TokenizedStrategy to call during a {deposit} * or {mint} to tell the strategy it can deploy funds. * * Since this can only be called after a {deposit} or {mint} * delegateCall to the TokenizedStrategy msg.sender == address(this). * * Unless a whitelist is implemented this will be entirely permissionless * and thus can be sandwiched or otherwise manipulated. * * @param _amount The amount of 'asset' that the strategy can * attempt to deposit in the yield source. */ function deployFunds(uint256 _amount) external virtual onlySelf { _deployFunds(_amount); } /** * @notice Should attempt to free the '_amount' of 'asset'. * @dev Callback for the TokenizedStrategy to call during a withdraw * or redeem to free the needed funds to service the withdraw. * * This can only be called after a 'withdraw' or 'redeem' delegateCall * to the TokenizedStrategy so msg.sender == address(this). * * @param _amount The amount of 'asset' that the strategy should attempt to free up. */ function freeFunds(uint256 _amount) external virtual onlySelf { _freeFunds(_amount); } /** * @notice Returns the accurate amount of all funds currently * held by the Strategy. * @dev Callback for the TokenizedStrategy to call during a report to * get an accurate accounting of assets the strategy controls. * * This can only be called after a report() delegateCall to the * TokenizedStrategy so msg.sender == address(this). * * @return . A trusted and accurate account for the total amount * of 'asset' the strategy currently holds including idle funds. */ function harvestAndReport() external virtual onlySelf returns (uint256) { return _harvestAndReport(); } /** * @notice Will call the internal '_tend' when a keeper tends the strategy. * @dev Callback for the TokenizedStrategy to initiate a _tend call in the strategy. * * This can only be called after a tend() delegateCall to the TokenizedStrategy * so msg.sender == address(this). * * We name the function `tendThis` so that `tend` calls are forwarded to * the TokenizedStrategy. * * @param _totalIdle The amount of current idle funds that can be * deployed during the tend */ function tendThis(uint256 _totalIdle) external virtual onlySelf { _tend(_totalIdle); } /** * @notice Will call the internal '_emergencyWithdraw' function. * @dev Callback for the TokenizedStrategy during an emergency withdraw. * * This can only be called after a emergencyWithdraw() delegateCall to * the TokenizedStrategy so msg.sender == address(this). * * We name the function `shutdownWithdraw` so that `emergencyWithdraw` * calls are forwarded to the TokenizedStrategy. * * @param _amount The amount of asset to attempt to free. */ function shutdownWithdraw(uint256 _amount) external virtual onlySelf { _emergencyWithdraw(_amount); } /** * @dev Function used to delegate call the TokenizedStrategy with * certain `_calldata` and return any return values. * * This is used to setup the initial storage of the strategy, and * can be used by strategist to forward any other call to the * TokenizedStrategy implementation. * * @param _calldata The abi encoded calldata to use in delegatecall. * @return . The return value if the call was successful in bytes. */ function _delegateCall(bytes memory _calldata) internal returns (bytes memory) { // Delegate call the tokenized strategy with provided calldata. (bool success, bytes memory result) = tokenizedStrategyAddress.delegatecall(_calldata); // If the call reverted. Return the error. if (!success) { assembly { let ptr := mload(0x40) let size := returndatasize() returndatacopy(ptr, 0, size) revert(ptr, size) } } // Return the result. return result; } /** * @dev Execute a function on the TokenizedStrategy and return any value. * * This fallback function will be executed when any of the standard functions * defined in the TokenizedStrategy are called since they wont be defined in * this contract. * * It will delegatecall the TokenizedStrategy implementation with the exact * calldata and return any relevant values. * */ fallback() external { // load our target address address _tokenizedStrategyAddress = tokenizedStrategyAddress; // Execute external function using delegatecall and return any value. assembly { // Copy function selector and any arguments. calldatacopy(0, 0, calldatasize()) // Execute function delegatecall. let result := delegatecall(gas(), _tokenizedStrategyAddress, 0, calldatasize(), 0, 0) // Get any return value returndatacopy(0, 0, returndatasize()) // Return any return value or error back to the caller switch result case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.18; import "./AggregatorV2V3Interface.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @title IAssetRegistry /// @notice Asset registry interface. /// @dev Any implementation MUST also implement Ownable2Step and ERC165. interface IAssetRegistry { /// @param asset Asset address. /// @param heartbeat Frequency of oracle price updates. /// @param isERC4626 True if yield-bearing asset, false if just an ERC20 asset. /// @param oracle If applicable, oracle address for asset. struct AssetInformation { IERC20 asset; uint256 heartbeat; bool isERC4626; AggregatorV2V3Interface oracle; } /// @param asset Asset address. /// @param spotPrice Spot price of an asset in Numeraire token terms. struct AssetPriceReading { IERC20 asset; uint256 spotPrice; } /// @notice Get address of vault. /// @return vault Address of vault. function vault() external view returns (address vault); /// @notice Get a list of all registered assets. /// @return assets List of assets. /// @dev MUST return assets in an order sorted by address. function assets() external view returns (AssetInformation[] memory assets); /// @notice Get address of fee token. /// @return feeToken Address of fee token. /// @dev Represented as an address for efficiency reasons. /// @dev MUST be present in assets array. function feeToken() external view returns (IERC20 feeToken); /// @notice Get the index of the Numeraire token in the assets array. /// @return numeraireToken Numeraire token address. /// @dev Represented as an index for efficiency reasons. /// @dev MUST be a number between 0 (inclusive) and the length of assets array (exclusive). function numeraireToken() external view returns (IERC20 numeraireToken); /// @notice Calculate spot prices of non-ERC4626 assets. /// @return spotPrices Spot prices of non-ERC4626 assets in 18 decimals. /// @dev MUST return assets in the same order as in assets but with ERC4626 assets filtered out. /// @dev MUST also include Numeraire token (spot price = 1). /// @dev MAY revert if oracle prices for any asset are unreliable at the time. function spotPrices() external view returns (AssetPriceReading[] memory spotPrices); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.18; import {AssetValue, Operation} from "../Types.sol"; /// @title IHooks /// @notice Interface for the hooks module. interface IHooks { /// @notice Get address of vault. /// @return vault Vault address. function vault() external view returns (address vault); /// @notice Hook that runs before deposit. /// @param amounts Struct details for assets and amounts to deposit. /// @dev MUST revert if not called by vault. function beforeDeposit(AssetValue[] memory amounts) external; /// @notice Hook that runs after deposit. /// @param amounts Struct details for assets and amounts to deposit. /// @dev MUST revert if not called by vault. function afterDeposit(AssetValue[] memory amounts) external; /// @notice Hook that runs before withdraw. /// @param amounts Struct details for assets and amounts to withdraw. /// @dev MUST revert if not called by vault. function beforeWithdraw(AssetValue[] memory amounts) external; /// @notice Hook that runs after withdraw. /// @param amounts Struct details for assets and amounts to withdraw. /// @dev MUST revert if not called by vault. function afterWithdraw(AssetValue[] memory amounts) external; /// @notice Hook that runs before submit. /// @param operations Array of struct details for target and calldata to submit. /// @dev MUST revert if not called by vault. function beforeSubmit(Operation[] memory operations) external; /// @notice Hook that runs after submit. /// @param operations Array of struct details for target and calldata to submit. /// @dev MUST revert if not called by vault. function afterSubmit(Operation[] memory operations) external; /// @notice Hook that runs before finalize. /// @dev MUST revert if not called by vault. function beforeFinalize() external; /// @notice Hook that runs after finalize. /// @dev MUST revert if not called by vault. function afterFinalize() external; /// @notice Take hooks out of use. function decommission() external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.18; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./interfaces/IAssetRegistry.sol"; // Types.sol // // This file defines the types used in V2. /// @notice Combination of contract address and sighash to be used in allowlist. /// @dev It's packed as follows: /// [target 160 bits] [selector 32 bits] [<empty> 64 bits] type TargetSighash is bytes32; /// @notice Struct encapulating an asset and an associated value. /// @param asset Asset address. /// @param value The associated value for this asset (e.g., amount or price). struct AssetValue { IERC20 asset; uint256 value; } /// @notice Execution details for a vault operation. /// @param target Target contract address. /// @param value Native token amount. /// @param data Calldata. struct Operation { address target; uint256 value; bytes data; } /// @notice Contract address and sighash struct to be used in the public interface. struct TargetSighashData { address target; bytes4 selector; } /// @notice Parameters for vault deployment. /// @param owner Initial owner address. /// @param assetRegistry Asset registry address. /// @param hooks Hooks address. /// @param guardian Guardian address. /// @param feeRecipient Fee recipient address. /// @param fee Fees accrued per second, denoted in 18 decimal fixed point format. struct Parameters { address owner; address assetRegistry; address hooks; address guardian; address feeRecipient; uint256 fee; } /// @notice Vault parameters for vault deployment. /// @param owner Initial owner address. /// @param guardian Guardian address. /// @param feeRecipient Fee recipient address. /// @param fee Fees accrued per second, denoted in 18 decimal fixed point format. struct VaultParameters { address owner; address guardian; address feeRecipient; uint256 fee; } /// @notice Asset registry parameters for asset registry deployment. /// @param factory Asset registry factory address. /// @param owner Initial owner address. /// @param assets Initial list of registered assets. /// @param numeraireToken Numeraire token address. /// @param feeToken Fee token address. /// @param sequencer Sequencer Uptime Feed address for L2. struct AssetRegistryParameters { address factory; address owner; IAssetRegistry.AssetInformation[] assets; IERC20 numeraireToken; IERC20 feeToken; AggregatorV2V3Interface sequencer; } /// @notice Hooks parameters for hooks deployment. /// @param factory Hooks factory address. /// @param owner Initial owner address. /// @param minDailyValue The fraction of value that the vault has to retain per day /// in the course of submissions. /// @param targetSighashAllowlist Array of target contract and sighash combinations to allow. struct HooksParameters { address factory; address owner; uint256 minDailyValue; TargetSighashData[] targetSighashAllowlist; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/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. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @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]. * * CAUTION: See Security Considerations above. */ 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.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(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 (last updated v4.9.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.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]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * 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 ERC20 is Context, IERC20, IERC20Metadata { 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}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _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 default value returned by this function, unless * it's 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 {} }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity >=0.8.18; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol"; import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; // Interface that implements the 4626 standard and the implementation functions interface ITokenizedStrategy is IERC4626, IERC20Permit { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event StrategyShutdown(); event NewTokenizedStrategy( address indexed strategy, address indexed asset, string apiVersion ); event Reported( uint256 profit, uint256 loss, uint256 protocolFees, uint256 performanceFees ); event UpdatePerformanceFeeRecipient( address indexed newPerformanceFeeRecipient ); event UpdateKeeper(address indexed newKeeper); event UpdatePerformanceFee(uint16 newPerformanceFee); event UpdateManagement(address indexed newManagement); event UpdateEmergencyAdmin(address indexed newEmergencyAdmin); event UpdateProfitMaxUnlockTime(uint256 newProfitMaxUnlockTime); event UpdatePendingManagement(address indexed newPendingManagement); /*////////////////////////////////////////////////////////////// INITIALIZATION //////////////////////////////////////////////////////////////*/ function initialize( address _asset, string memory _name, address _management, address _performanceFeeRecipient, address _keeper ) external; /*////////////////////////////////////////////////////////////// NON-STANDARD 4626 OPTIONS //////////////////////////////////////////////////////////////*/ function withdraw( uint256 assets, address receiver, address owner, uint256 maxLoss ) external returns (uint256); function redeem( uint256 shares, address receiver, address owner, uint256 maxLoss ) external returns (uint256); /*////////////////////////////////////////////////////////////// MODIFIER HELPERS //////////////////////////////////////////////////////////////*/ function requireManagement(address _sender) external view; function requireKeeperOrManagement(address _sender) external view; function requireEmergencyAuthorized(address _sender) external view; /*////////////////////////////////////////////////////////////// KEEPERS FUNCTIONS //////////////////////////////////////////////////////////////*/ function tend() external; function report() external returns (uint256 _profit, uint256 _loss); /*////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////*/ function MAX_FEE() external view returns (uint16); function FACTORY() external view returns (address); /*////////////////////////////////////////////////////////////// GETTERS //////////////////////////////////////////////////////////////*/ function apiVersion() external view returns (string memory); function pricePerShare() external view returns (uint256); function management() external view returns (address); function pendingManagement() external view returns (address); function keeper() external view returns (address); function emergencyAdmin() external view returns (address); function performanceFee() external view returns (uint16); function performanceFeeRecipient() external view returns (address); function fullProfitUnlockDate() external view returns (uint256); function profitUnlockingRate() external view returns (uint256); function profitMaxUnlockTime() external view returns (uint256); function lastReport() external view returns (uint256); function isShutdown() external view returns (bool); function unlockedShares() external view returns (uint256); /*////////////////////////////////////////////////////////////// SETTERS //////////////////////////////////////////////////////////////*/ function setPendingManagement(address) external; function acceptManagement() external; function setKeeper(address _keeper) external; function setEmergencyAdmin(address _emergencyAdmin) external; function setPerformanceFee(uint16 _performanceFee) external; function setPerformanceFeeRecipient( address _performanceFeeRecipient ) external; function setProfitMaxUnlockTime(uint256 _profitMaxUnlockTime) external; function shutdownStrategy() external; function emergencyWithdraw(uint256 _amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./AggregatorInterface.sol"; import "./AggregatorV3Interface.sol"; interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @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 (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; /** * @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 Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC4626.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol"; import "../token/ERC20/extensions/IERC20Metadata.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 IERC4626 is IERC20, IERC20Metadata { 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 pragma solidity ^0.8.0; interface AggregatorInterface { 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 updatedAt); event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); }
{ "remappings": [ "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", "forge-std/=node_modules/forge-std/src/", "@solmate/=lib/solmate/src/", "ds-test/=lib/solmate/lib/ds-test/src/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 10000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "shanghai", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_vaultAera","type":"address"},{"internalType":"address","name":"_vaultYearn","type":"address"},{"internalType":"address","name":"_quickManagement","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingQuickManagement","type":"address"}],"name":"UpdatePendingQuickManagement","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newQuickManagement","type":"address"}],"name":"UpdateQuickManagement","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vaultAera","type":"address"}],"name":"UpdateVaultAera","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptQuickManagement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"availableDepositLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"availableWithdrawLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deployFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositAeraVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"execute","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Operation","name":"operation","type":"tuple"}],"name":"executeOnAera","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"freeFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestAndReport","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pendingQuickManagement","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quickManagement","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"maxLoss","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","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":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"}],"name":"requireQuickManagementOrManagement","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultAera","type":"address"}],"name":"setForceVaultAera","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newGuardian","type":"address"},{"internalType":"address","name":"newFeeRecipient","type":"address"}],"name":"setGuardianAndFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newHooks","type":"address"}],"name":"setHooks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pendingQuickManagement","type":"address"}],"name":"setPendingQuickManagement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultAera","type":"address"}],"name":"setVaultAera","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"shutdownWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalIdle","type":"uint256"}],"name":"tendThis","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tendTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenizedStrategyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","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":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vaultAera","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultYearn","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"maxLoss","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"shares","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":"withdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawAeraVault","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e060405234801561000f575f80fd5b506040516135b43803806135b483398101604081905261002e91610680565b6001600160a01b0385166080523060a0526040518590859082908290610097906100649084908490339081908190602401610796565b60408051601f198184030181529190526020810180516001600160e01b03908116634b839d7360e11b1790915261026716565b505073975304c676eb3dc86cd336138328e107a95eaa507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55505060015f55506001600160a01b0383166101215760405162461bcd60e51b815260206004820152600c60248201526b5a45524f204144445245535360a01b60448201526064015b60405180910390fd5b600180546001600160a01b0319166001600160a01b0385811691909117909155821661017e5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f204144445245535360a01b6044820152606401610118565b6001600160a01b0380831660c05281166101c95760405162461bcd60e51b815260206004820152600c60248201526b5a45524f204144445245535360a01b6044820152606401610118565b600280546001600160a01b0319166001600160a01b0383169081179091556040517fba5e4dac32588470aa6505ebac9a57aa2838dad29430315aa039381b52fe6c64905f90a26040516001600160a01b038416907f722981892bc1bd0bc076f436fa60c911556d23f9cb7a89007528b0ee5cc4ec69905f90a260015461025d906001600160a01b0387811691165f196102f1565b505050505061085e565b60605f8073975304c676eb3dc86cd336138328e107a95eaa506001600160a01b03168460405161029791906107d6565b5f60405180830381855af49150503d805f81146102cf576040519150601f19603f3d011682016040523d82523d5f602084013e6102d4565b606091505b5091509150816102ea576040513d805f833e8082fd5b9392505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa15801561033e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061036291906107f1565b90506103ce8463095ea7b360e01b8561037b8686610808565b6040516001600160a01b039092166024830152604482015260640160408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b03938416179052906103d416565b50505050565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908201525f90610420906001600160a01b0385169084906104a4565b905080515f1480610440575080806020019051810190610440919061082d565b61049f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610118565b505050565b60606104b284845f856104ba565b949350505050565b60608247101561051b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610118565b5f80866001600160a01b0316858760405161053691906107d6565b5f6040518083038185875af1925050503d805f8114610570576040519150601f19603f3d011682016040523d82523d5f602084013e610575565b606091505b50909250905061058787838387610592565b979650505050505050565b606083156106005782515f036105f9576001600160a01b0385163b6105f95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610118565b50816104b2565b6104b283838151156106155781518083602001fd5b8060405162461bcd60e51b8152600401610118919061084c565b80516001600160a01b0381168114610645575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b83811015610678578181015183820152602001610660565b50505f910152565b5f805f805f60a08688031215610694575f80fd5b61069d8661062f565b60208701519095506001600160401b03808211156106b9575f80fd5b818801915088601f8301126106cc575f80fd5b8151818111156106de576106de61064a565b604051601f8201601f19908116603f011681019083821181831017156107065761070661064a565b816040528281528b602084870101111561071e575f80fd5b61072f83602083016020880161065e565b80985050505050506107436040870161062f565b92506107516060870161062f565b915061075f6080870161062f565b90509295509295909350565b5f815180845261078281602086016020860161065e565b601f01601f19169290920160200192915050565b5f60018060a01b03808816835260a060208401526107b760a084018861076b565b9581166040840152938416606083015250911660809091015292915050565b5f82516107e781846020870161065e565b9190910192915050565b5f60208284031215610801575f80fd5b5051919050565b8082018082111561082757634e487b7160e01b5f52601160045260245ffd5b92915050565b5f6020828403121561083d575f80fd5b815180151581146102ea575f80fd5b602081525f6102ea602083018461076b565b60805160a05160c051612c7d6109375f395f818161034b0152610b4301525f81816107c10152818161095401528181610a1101528181610bec01528181610d2101528181610e2d01528181610f1501528181610fa8015281816110800152818161113b015281816111d5015281816113b8015281816114400152818161153c01528181611741015281816119520152611ac101525f81816108b301528181611654015281816119c501528181611c8e01528181611dd701528181611e9d01528181611f9d0152818161200401526123330152612c7d5ff3fe608060405260043610610284575f3560e01c806394bf804d11610152578063d19a3bb8116100ca578063f2fde38b1161007e578063f9d5761011610063578063f9d5761014610755578063fb63daa114610774578063fde813a8146105b257610284565b8063f2fde38b14610717578063f98c84e91461073657610284565b8063e6be7ee7116100af578063e6be7ee7146106c5578063e747071c146106e4578063e8f17eb51461070357610284565b8063d19a3bb81461067f578063d543fb52146106a657610284565b8063a318c1a411610121578063b460af9411610106578063b460af941461062e578063b61d27f61461064d578063ba0876521461066057610284565b8063a318c1a4146105f0578063a9059cbb1461060f57610284565b806394bf804d146105745780639bb328ae146105935780639d7fb70c146105b25780639f40a7b3146105d157610284565b80634e71d92d116102005780636df06be6116101b457806379ba50971161019957806379ba50971461052d5780638456cb59146105415780638f3ff5821461055557610284565b80636df06be6146104ef5780636e553f651461050e57610284565b80635d265d3f116101e55780635d265d3f1461043d5780635d682fc2146104b157806369eb50ef146104d057610284565b80634e71d92d1461040a578063503160d91461041e57610284565b80632f86e1f91161025757806346aa2f121161023c57806346aa2f12146103c357806349317f1d146103e25780634bb278f3146103f657610284565b80632f86e1f9146103855780633d6cb575146103a457610284565b8063046f7da2146102c557806304bd4629146102d957806323b872dd1461030b578063271fb1a21461033a575b34801561028f575f80fd5b5073975304c676eb3dc86cd336138328e107a95eaa50365f80375f80365f845af43d5f803e8080156102bf573d5ff35b3d5ffd5b005b3480156102d0575f80fd5b506102c3610793565b3480156102e4575f80fd5b506102f86102f336600461268a565b610883565b6040519081526020015b60405180910390f35b348015610316575f80fd5b5061032a6103253660046126a5565b61092a565b6040519015158152602001610302565b348015610345575f80fd5b5061036d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610302565b348015610390575f80fd5b506102c361039f36600461268a565b6109e3565b3480156103af575f80fd5b506102c36103be3660046126e3565b610b2c565b3480156103ce575f80fd5b506102f86103dd36600461268a565b610b40565b3480156103ed575f80fd5b506102f8610ba8565b348015610401575f80fd5b506102c3610bbe565b348015610415575f80fd5b506102c3610c96565b348015610429575f80fd5b506102c36104383660046126e3565b610ce2565b348015610448575f80fd5b506040805160048152602481019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f440368a3000000000000000000000000000000000000000000000000000000001790525f905b604051610302929190612747565b3480156104bc575f80fd5b5060035461036d906001600160a01b031681565b3480156104db575f80fd5b506102c36104ea366004612761565b610cf3565b3480156104fa575f80fd5b506102c3610509366004612798565b610dff565b348015610519575f80fd5b506102f86105283660046127cf565b610f04565b348015610538575f80fd5b506102c3610f7a565b34801561054c575f80fd5b506102c3611052565b348015610560575f80fd5b5060015461036d906001600160a01b031681565b34801561057f575f80fd5b506102f861058e3660046127cf565b61112a565b34801561059e575f80fd5b506102c36105ad36600461268a565b6111a7565b3480156105bd575f80fd5b506102c36105cc3660046126e3565b61123c565b3480156105dc575f80fd5b506102f86105eb3660046127f2565b611244565b3480156105fb575f80fd5b506102f861060a3660046127f2565b6112ef565b34801561061a575f80fd5b5061032a610629366004612837565b611396565b348015610639575f80fd5b506102f8610648366004612861565b6113fa565b6104a361065b3660046128a0565b611407565b34801561066b575f80fd5b506102f861067a366004612861565b611514565b34801561068a575f80fd5b5061036d73975304c676eb3dc86cd336138328e107a95eaa5081565b3480156106b1575f80fd5b506102c36106c036600461268a565b611523565b3480156106d0575f80fd5b506102c36106df3660046126e3565b61161b565b3480156106ef575f80fd5b506102c36106fe36600461268a565b611713565b34801561070e575f80fd5b506102c3611869565b348015610722575f80fd5b506102c361073136600461268a565b611924565b348015610741575f80fd5b5060025461036d906001600160a01b031681565b348015610760575f80fd5b506102c361076f3660046126e3565b611a33565b34801561077f575f80fd5b506102c361078e36600461268a565b611a93565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015610809575f80fd5b505afa15801561081b573d5f803e3d5ffd5b5050505060015f9054906101000a90046001600160a01b03166001600160a01b031663046f7da26040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561086b575f80fd5b505af115801561087d573d5f803e3d5ffd5b50505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610900573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109249190612922565b92915050565b6040516001600160a01b0384811660248301528381166044830152606482018390525f916109c6917f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611b6f565b8060200190518101906109d99190612939565b90505b9392505050565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015610a59575f80fd5b505afa158015610a6b573d5f803e3d5ffd5b5050506001600160a01b0382169050610acb5760405162461bcd60e51b815260206004820152600c60248201527f5a45524f2041444452455353000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f3a6f8e1a15259a685533cc366da2c0f721841e399cf23f3fed65e269fd7446d8905f90a250565b610b34611bf2565b610b3d81611c43565b50565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603610ba157507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff919050565b505f919050565b5f610bb1611bf2565b610bb9611d25565b905090565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015610c34575f80fd5b505afa158015610c46573d5f803e3d5ffd5b5050505060015f9054906101000a90046001600160a01b03166001600160a01b0316634bb278f36040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561086b575f80fd5b60015f9054906101000a90046001600160a01b03166001600160a01b0316634e71d92d6040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561086b575f80fd5b610cea611bf2565b610b3d81611e52565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015610d69575f80fd5b505afa158015610d7b573d5f803e3d5ffd5b50506001546040517f69eb50ef0000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152858116602483015290911692506369eb50ef91506044015b5f604051808303815f87803b158015610de5575f80fd5b505af1158015610df7573d5f803e3d5ffd5b505050505050565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015610e75575f80fd5b505afa158015610e87573d5f803e3d5ffd5b50506001546040517f5c1c6dcd0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169250635c1c6dcd9150610ed4908490600401612958565b5f604051808303815f87803b158015610eeb575f80fd5b505af1158015610efd573d5f803e3d5ffd5b5050505050565b5f610f10838284611f34565b610f677f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636e553f65858560405160240161097f9291909182526001600160a01b0316602082015260400190565b8060200190518101906109dc9190612922565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015610ff0575f80fd5b505afa158015611002573d5f803e3d5ffd5b5050505060015f9054906101000a90046001600160a01b03166001600160a01b03166379ba50976040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561086b575f80fd5b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b1580156110c8575f80fd5b505afa1580156110da573d5f803e3d5ffd5b5050505060015f9054906101000a90046001600160a01b03166001600160a01b0316638456cb596040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561086b575f80fd5b5f611136818484611f34565b61118d7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166394bf804d858560405160240161097f9291909182526001600160a01b0316602082015260400190565b8060200190518101906111a09190612922565b9050610924565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b15801561121d575f80fd5b505afa15801561122f573d5f803e3d5ffd5b50505050610b3d81611f8c565b610b3d611bf2565b5f604051602481018690526001600160a01b03808616604483015284166064820152608481018390526112d19060a40160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f9f40a7b300000000000000000000000000000000000000000000000000000000179052611b6f565b8060200190518101906112e49190612922565b90505b949350505050565b5f604051602481018690526001600160a01b038086166044830152841660648201526084810183905261137c9060a40160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa318c1a400000000000000000000000000000000000000000000000000000000179052611b6f565b80602001905181019061138f9190612922565b90506112e7565b6040516001600160a01b038381166024830152604482018390525f916113e7917f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb9060640161097f565b8060200190518101906111a09190612939565b5f6109d98484845f6112ef565b5f6060611412612081565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015611488575f80fd5b505afa15801561149a573d5f803e3d5ffd5b505050505f80876001600160a01b03168787876040516114bb929190612a12565b5f6040518083038185875af1925050503d805f81146114f5576040519150601f19603f3d011682016040523d82523d5f602084013e6114fa565b606091505b509094509250505061150b60015f55565b94509492505050565b5f6109d9848484612710611244565b6002546001600160a01b03828116911614806115cf57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166388a8d6026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611596573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115ba9190612a21565b6001600160a01b0316816001600160a01b0316145b610b3d5760405162461bcd60e51b815260206004820152601060248201527f21717569636b4d616e6167656d656e74000000000000000000000000000000006044820152606401610ac2565b61162433611523565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156116a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116c59190612922565b1015610cea5760405162461bcd60e51b815260206004820152600d60248201527f416d6f756e74546f6f48696768000000000000000000000000000000000000006044820152606401610ac2565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015611789575f80fd5b505afa15801561179b573d5f803e3d5ffd5b5050505060015f9054906101000a90046001600160a01b03166001600160a01b0316633fa4f2456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ef573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118139190612922565b156118605760405162461bcd60e51b815260206004820152600660248201527f21456d70747900000000000000000000000000000000000000000000000000006044820152606401610ac2565b610b3d81611f8c565b6003546001600160a01b031633146118c35760405162461bcd60e51b815260206004820152600860248201527f2170656e64696e670000000000000000000000000000000000000000000000006044820152606401610ac2565b60028054337fffffffffffffffffffffffff000000000000000000000000000000000000000091821681179092556003805490911690556040517fba5e4dac32588470aa6505ebac9a57aa2838dad29430315aa039381b52fe6c64905f90a2565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b15801561199a575f80fd5b505afa1580156119ac573d5f803e3d5ffd5b50506001546001600160a01b0390811692506119ec91507f000000000000000000000000000000000000000000000000000000000000000016825f6120d8565b6040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b03838116600483015282169063f2fde38b90602401610dce565b611a3c33611523565b80611a45612284565b1015610b345760405162461bcd60e51b815260206004820152600d60248201527f416d6f756e74546f6f48696768000000000000000000000000000000000000006044820152606401610ac2565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906348e4a649906024015f6040518083038186803b158015611b09575f80fd5b505afa158015611b1b573d5f803e3d5ffd5b50506001546040517ffb63daa10000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152909116925063fb63daa19150602401610ed4565b505050565b60605f8073975304c676eb3dc86cd336138328e107a95eaa506001600160a01b031684604051611b9f9190612a3c565b5f60405180830381855af49150503d805f8114611bd7576040519150601f19603f3d011682016040523d82523d5f602084013e611bdc565b606091505b5091509150816109dc576040513d805f833e8082fd5b333014611c415760405162461bcd60e51b815260206004820152600560248201527f2173656c660000000000000000000000000000000000000000000000000000006044820152606401610ac2565b565b6040805160018082528183019092525f91816020015b604080518082019091525f8082526020820152815260200190600190039081611c5957905050905060405180604001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815260200183815250815f81518110611cd157611cd1612a84565b60209081029190910101526001546040517fecdbb2b30000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063ecdbb2b390610dce908490600401612ab1565b600154604080517f3fa4f24500000000000000000000000000000000000000000000000000000000815290515f926001600160a01b031691633fa4f2459160048083019260209291908290030181865afa158015611d85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611da99190612922565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611e24573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e489190612922565b610bb99190612b08565b6040805160018082528183019092525f91816020015b604080518082019091525f8082526020820152815260200190600190039081611e6857905050905060405180604001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815260200183815250815f81518110611ee057611ee0612a84565b60209081029190910101526001546040517f59e974750000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906359e9747590610dce908490600401612ab1565b336001600160a01b03821614611b6a5760405162461bcd60e51b815260206004820152600b60248201527f216d73672e73656e6465720000000000000000000000000000000000000000006044820152606401610ac2565b600154611fc6906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691165f6120d8565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038381169190911790915561204b907f000000000000000000000000000000000000000000000000000000000000000016827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612397565b6040516001600160a01b038216907f722981892bc1bd0bc076f436fa60c911556d23f9cb7a89007528b0ee5cc4ec69905f90a250565b60025f54036120d25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ac2565b60025f55565b80158061216957506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015612143573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121679190612922565b155b6121db5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610ac2565b6040516001600160a01b038316602482015260448101829052611b6a9084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612473565b5f8060015f9054906101000a90046001600160a01b03166001600160a01b031663e79bf13b6040518163ffffffff1660e01b81526004015f60405180830381865afa1580156122d5573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526122fc9190810190612b9a565b80519091505f5b8181101561238e5782818151811061231d5761231d612a84565b60200260200101515f01516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316036123865782818151811061237257612372612a84565b602002602001015160200151935050505090565b600101612303565b505f9250505090565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa1580156123fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124219190612922565b905061087d847f095ea7b300000000000000000000000000000000000000000000000000000000856124538686612b08565b6040516001600160a01b0390921660248301526044820152606401612220565b5f6124c7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166125599092919063ffffffff16565b905080515f14806124e75750808060200190518101906124e79190612939565b611b6a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610ac2565b60606109d984845f85855f80866001600160a01b0316858760405161257e9190612a3c565b5f6040518083038185875af1925050503d805f81146125b8576040519150601f19603f3d011682016040523d82523d5f602084013e6125bd565b606091505b50915091506125ce878383876125d9565b979650505050505050565b606083156126475782515f03612640576001600160a01b0385163b6126405760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ac2565b50816112e7565b6112e7838381511561265c5781518083602001fd5b8060405162461bcd60e51b8152600401610ac29190612c5e565b6001600160a01b0381168114610b3d575f80fd5b5f6020828403121561269a575f80fd5b81356109dc81612676565b5f805f606084860312156126b7575f80fd5b83356126c281612676565b925060208401356126d281612676565b929592945050506040919091013590565b5f602082840312156126f3575f80fd5b5035919050565b5f5b838110156127145781810151838201526020016126fc565b50505f910152565b5f81518084526127338160208601602086016126fa565b601f01601f19169290920160200192915050565b8215158152604060208201525f6109d9604083018461271c565b5f8060408385031215612772575f80fd5b823561277d81612676565b9150602083013561278d81612676565b809150509250929050565b5f602082840312156127a8575f80fd5b813567ffffffffffffffff8111156127be575f80fd5b8201606081850312156109dc575f80fd5b5f80604083850312156127e0575f80fd5b82359150602083013561278d81612676565b5f805f8060808587031215612805575f80fd5b84359350602085013561281781612676565b9250604085013561282781612676565b9396929550929360600135925050565b5f8060408385031215612848575f80fd5b823561285381612676565b946020939093013593505050565b5f805f60608486031215612873575f80fd5b83359250602084013561288581612676565b9150604084013561289581612676565b809150509250925092565b5f805f80606085870312156128b3575f80fd5b84356128be81612676565b935060208501359250604085013567ffffffffffffffff808211156128e1575f80fd5b818701915087601f8301126128f4575f80fd5b813581811115612902575f80fd5b886020828501011115612913575f80fd5b95989497505060200194505050565b5f60208284031215612932575f80fd5b5051919050565b5f60208284031215612949575f80fd5b815180151581146109dc575f80fd5b602081525f823561296881612676565b6001600160a01b0381166020840152506020830135604083015260408301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126129b6575f80fd5b830160208101903567ffffffffffffffff8111156129d2575f80fd5b8036038213156129e0575f80fd5b606080850152806080850152808260a08601375f60a0828601015260a0601f19601f8301168501019250505092915050565b818382375f9101908152919050565b5f60208284031215612a31575f80fd5b81516109dc81612676565b5f8251612a4d8184602087016126fa565b9190910192915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b602080825282518282018190525f919060409081850190868401855b82811015612afb57815180516001600160a01b03168552860151868501529284019290850190600101612acd565b5091979650505050505050565b80820180821115610924577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6040805190810167ffffffffffffffff81118282101715612b6357612b63612a57565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612b9257612b92612a57565b604052919050565b5f6020808385031215612bab575f80fd5b825167ffffffffffffffff80821115612bc2575f80fd5b818501915085601f830112612bd5575f80fd5b815181811115612be757612be7612a57565b612bf5848260051b01612b69565b818152848101925060069190911b830184019087821115612c14575f80fd5b928401925b818410156125ce5760408489031215612c30575f80fd5b612c38612b40565b8451612c4381612676565b81528486015186820152835260409093019291840191612c19565b602081525f6109dc602083018461271c56fea164736f6c6343000819000a0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c59900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000014c79c24b2a82ce36e3f3d693aeea17e268f5a980000000000000000000000008db2350d78abc13f5673a411d4700bcf87864dde00000000000000000000000020fdf47509c5efc0e1101e3ce443691781c17f90000000000000000000000000000000000000000000000000000000000000000d4165726120537472617465677900000000000000000000000000000000000000
Deployed Bytecode
0x608060405260043610610284575f3560e01c806394bf804d11610152578063d19a3bb8116100ca578063f2fde38b1161007e578063f9d5761011610063578063f9d5761014610755578063fb63daa114610774578063fde813a8146105b257610284565b8063f2fde38b14610717578063f98c84e91461073657610284565b8063e6be7ee7116100af578063e6be7ee7146106c5578063e747071c146106e4578063e8f17eb51461070357610284565b8063d19a3bb81461067f578063d543fb52146106a657610284565b8063a318c1a411610121578063b460af9411610106578063b460af941461062e578063b61d27f61461064d578063ba0876521461066057610284565b8063a318c1a4146105f0578063a9059cbb1461060f57610284565b806394bf804d146105745780639bb328ae146105935780639d7fb70c146105b25780639f40a7b3146105d157610284565b80634e71d92d116102005780636df06be6116101b457806379ba50971161019957806379ba50971461052d5780638456cb59146105415780638f3ff5821461055557610284565b80636df06be6146104ef5780636e553f651461050e57610284565b80635d265d3f116101e55780635d265d3f1461043d5780635d682fc2146104b157806369eb50ef146104d057610284565b80634e71d92d1461040a578063503160d91461041e57610284565b80632f86e1f91161025757806346aa2f121161023c57806346aa2f12146103c357806349317f1d146103e25780634bb278f3146103f657610284565b80632f86e1f9146103855780633d6cb575146103a457610284565b8063046f7da2146102c557806304bd4629146102d957806323b872dd1461030b578063271fb1a21461033a575b34801561028f575f80fd5b5073975304c676eb3dc86cd336138328e107a95eaa50365f80375f80365f845af43d5f803e8080156102bf573d5ff35b3d5ffd5b005b3480156102d0575f80fd5b506102c3610793565b3480156102e4575f80fd5b506102f86102f336600461268a565b610883565b6040519081526020015b60405180910390f35b348015610316575f80fd5b5061032a6103253660046126a5565b61092a565b6040519015158152602001610302565b348015610345575f80fd5b5061036d7f0000000000000000000000008db2350d78abc13f5673a411d4700bcf87864dde81565b6040516001600160a01b039091168152602001610302565b348015610390575f80fd5b506102c361039f36600461268a565b6109e3565b3480156103af575f80fd5b506102c36103be3660046126e3565b610b2c565b3480156103ce575f80fd5b506102f86103dd36600461268a565b610b40565b3480156103ed575f80fd5b506102f8610ba8565b348015610401575f80fd5b506102c3610bbe565b348015610415575f80fd5b506102c3610c96565b348015610429575f80fd5b506102c36104383660046126e3565b610ce2565b348015610448575f80fd5b506040805160048152602481019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f440368a3000000000000000000000000000000000000000000000000000000001790525f905b604051610302929190612747565b3480156104bc575f80fd5b5060035461036d906001600160a01b031681565b3480156104db575f80fd5b506102c36104ea366004612761565b610cf3565b3480156104fa575f80fd5b506102c3610509366004612798565b610dff565b348015610519575f80fd5b506102f86105283660046127cf565b610f04565b348015610538575f80fd5b506102c3610f7a565b34801561054c575f80fd5b506102c3611052565b348015610560575f80fd5b5060015461036d906001600160a01b031681565b34801561057f575f80fd5b506102f861058e3660046127cf565b61112a565b34801561059e575f80fd5b506102c36105ad36600461268a565b6111a7565b3480156105bd575f80fd5b506102c36105cc3660046126e3565b61123c565b3480156105dc575f80fd5b506102f86105eb3660046127f2565b611244565b3480156105fb575f80fd5b506102f861060a3660046127f2565b6112ef565b34801561061a575f80fd5b5061032a610629366004612837565b611396565b348015610639575f80fd5b506102f8610648366004612861565b6113fa565b6104a361065b3660046128a0565b611407565b34801561066b575f80fd5b506102f861067a366004612861565b611514565b34801561068a575f80fd5b5061036d73975304c676eb3dc86cd336138328e107a95eaa5081565b3480156106b1575f80fd5b506102c36106c036600461268a565b611523565b3480156106d0575f80fd5b506102c36106df3660046126e3565b61161b565b3480156106ef575f80fd5b506102c36106fe36600461268a565b611713565b34801561070e575f80fd5b506102c3611869565b348015610722575f80fd5b506102c361073136600461268a565b611924565b348015610741575f80fd5b5060025461036d906001600160a01b031681565b348015610760575f80fd5b506102c361076f3660046126e3565b611a33565b34801561077f575f80fd5b506102c361078e36600461268a565b611a93565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b158015610809575f80fd5b505afa15801561081b573d5f803e3d5ffd5b5050505060015f9054906101000a90046001600160a01b03166001600160a01b031663046f7da26040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561086b575f80fd5b505af115801561087d573d5f803e3d5ffd5b50505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f907f0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5996001600160a01b0316906370a0823190602401602060405180830381865afa158015610900573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109249190612922565b92915050565b6040516001600160a01b0384811660248301528381166044830152606482018390525f916109c6917f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae316906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611b6f565b8060200190518101906109d99190612939565b90505b9392505050565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b158015610a59575f80fd5b505afa158015610a6b573d5f803e3d5ffd5b5050506001600160a01b0382169050610acb5760405162461bcd60e51b815260206004820152600c60248201527f5a45524f2041444452455353000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f3a6f8e1a15259a685533cc366da2c0f721841e399cf23f3fed65e269fd7446d8905f90a250565b610b34611bf2565b610b3d81611c43565b50565b5f7f0000000000000000000000008db2350d78abc13f5673a411d4700bcf87864dde6001600160a01b0316826001600160a01b031603610ba157507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff919050565b505f919050565b5f610bb1611bf2565b610bb9611d25565b905090565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b158015610c34575f80fd5b505afa158015610c46573d5f803e3d5ffd5b5050505060015f9054906101000a90046001600160a01b03166001600160a01b0316634bb278f36040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561086b575f80fd5b60015f9054906101000a90046001600160a01b03166001600160a01b0316634e71d92d6040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561086b575f80fd5b610cea611bf2565b610b3d81611e52565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b158015610d69575f80fd5b505afa158015610d7b573d5f803e3d5ffd5b50506001546040517f69eb50ef0000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152858116602483015290911692506369eb50ef91506044015b5f604051808303815f87803b158015610de5575f80fd5b505af1158015610df7573d5f803e3d5ffd5b505050505050565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b158015610e75575f80fd5b505afa158015610e87573d5f803e3d5ffd5b50506001546040517f5c1c6dcd0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169250635c1c6dcd9150610ed4908490600401612958565b5f604051808303815f87803b158015610eeb575f80fd5b505af1158015610efd573d5f803e3d5ffd5b5050505050565b5f610f10838284611f34565b610f677f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316636e553f65858560405160240161097f9291909182526001600160a01b0316602082015260400190565b8060200190518101906109dc9190612922565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b158015610ff0575f80fd5b505afa158015611002573d5f803e3d5ffd5b5050505060015f9054906101000a90046001600160a01b03166001600160a01b03166379ba50976040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561086b575f80fd5b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b1580156110c8575f80fd5b505afa1580156110da573d5f803e3d5ffd5b5050505060015f9054906101000a90046001600160a01b03166001600160a01b0316638456cb596040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561086b575f80fd5b5f611136818484611f34565b61118d7f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b03166394bf804d858560405160240161097f9291909182526001600160a01b0316602082015260400190565b8060200190518101906111a09190612922565b9050610924565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b15801561121d575f80fd5b505afa15801561122f573d5f803e3d5ffd5b50505050610b3d81611f8c565b610b3d611bf2565b5f604051602481018690526001600160a01b03808616604483015284166064820152608481018390526112d19060a40160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f9f40a7b300000000000000000000000000000000000000000000000000000000179052611b6f565b8060200190518101906112e49190612922565b90505b949350505050565b5f604051602481018690526001600160a01b038086166044830152841660648201526084810183905261137c9060a40160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa318c1a400000000000000000000000000000000000000000000000000000000179052611b6f565b80602001905181019061138f9190612922565b90506112e7565b6040516001600160a01b038381166024830152604482018390525f916113e7917f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae3169063a9059cbb9060640161097f565b8060200190518101906111a09190612939565b5f6109d98484845f6112ef565b5f6060611412612081565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b158015611488575f80fd5b505afa15801561149a573d5f803e3d5ffd5b505050505f80876001600160a01b03168787876040516114bb929190612a12565b5f6040518083038185875af1925050503d805f81146114f5576040519150601f19603f3d011682016040523d82523d5f602084013e6114fa565b606091505b509094509250505061150b60015f55565b94509492505050565b5f6109d9848484612710611244565b6002546001600160a01b03828116911614806115cf57507f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b03166388a8d6026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611596573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115ba9190612a21565b6001600160a01b0316816001600160a01b0316145b610b3d5760405162461bcd60e51b815260206004820152601060248201527f21717569636b4d616e6167656d656e74000000000000000000000000000000006044820152606401610ac2565b61162433611523565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5996001600160a01b0316906370a0823190602401602060405180830381865afa1580156116a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116c59190612922565b1015610cea5760405162461bcd60e51b815260206004820152600d60248201527f416d6f756e74546f6f48696768000000000000000000000000000000000000006044820152606401610ac2565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b158015611789575f80fd5b505afa15801561179b573d5f803e3d5ffd5b5050505060015f9054906101000a90046001600160a01b03166001600160a01b0316633fa4f2456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ef573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118139190612922565b156118605760405162461bcd60e51b815260206004820152600660248201527f21456d70747900000000000000000000000000000000000000000000000000006044820152606401610ac2565b610b3d81611f8c565b6003546001600160a01b031633146118c35760405162461bcd60e51b815260206004820152600860248201527f2170656e64696e670000000000000000000000000000000000000000000000006044820152606401610ac2565b60028054337fffffffffffffffffffffffff000000000000000000000000000000000000000091821681179092556003805490911690556040517fba5e4dac32588470aa6505ebac9a57aa2838dad29430315aa039381b52fe6c64905f90a2565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b15801561199a575f80fd5b505afa1580156119ac573d5f803e3d5ffd5b50506001546001600160a01b0390811692506119ec91507f0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c59916825f6120d8565b6040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b03838116600483015282169063f2fde38b90602401610dce565b611a3c33611523565b80611a45612284565b1015610b345760405162461bcd60e51b815260206004820152600d60248201527f416d6f756e74546f6f48696768000000000000000000000000000000000000006044820152606401610ac2565b6040517f48e4a6490000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000008041ba598f0e656ebe80c67289efb42c09e86ae36001600160a01b0316906348e4a649906024015f6040518083038186803b158015611b09575f80fd5b505afa158015611b1b573d5f803e3d5ffd5b50506001546040517ffb63daa10000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152909116925063fb63daa19150602401610ed4565b505050565b60605f8073975304c676eb3dc86cd336138328e107a95eaa506001600160a01b031684604051611b9f9190612a3c565b5f60405180830381855af49150503d805f8114611bd7576040519150601f19603f3d011682016040523d82523d5f602084013e611bdc565b606091505b5091509150816109dc576040513d805f833e8082fd5b333014611c415760405162461bcd60e51b815260206004820152600560248201527f2173656c660000000000000000000000000000000000000000000000000000006044820152606401610ac2565b565b6040805160018082528183019092525f91816020015b604080518082019091525f8082526020820152815260200190600190039081611c5957905050905060405180604001604052807f0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5996001600160a01b0316815260200183815250815f81518110611cd157611cd1612a84565b60209081029190910101526001546040517fecdbb2b30000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063ecdbb2b390610dce908490600401612ab1565b600154604080517f3fa4f24500000000000000000000000000000000000000000000000000000000815290515f926001600160a01b031691633fa4f2459160048083019260209291908290030181865afa158015611d85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611da99190612922565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5996001600160a01b0316906370a0823190602401602060405180830381865afa158015611e24573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e489190612922565b610bb99190612b08565b6040805160018082528183019092525f91816020015b604080518082019091525f8082526020820152815260200190600190039081611e6857905050905060405180604001604052807f0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5996001600160a01b0316815260200183815250815f81518110611ee057611ee0612a84565b60209081029190910101526001546040517f59e974750000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906359e9747590610dce908490600401612ab1565b336001600160a01b03821614611b6a5760405162461bcd60e51b815260206004820152600b60248201527f216d73672e73656e6465720000000000000000000000000000000000000000006044820152606401610ac2565b600154611fc6906001600160a01b037f0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599811691165f6120d8565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038381169190911790915561204b907f0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c59916827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612397565b6040516001600160a01b038216907f722981892bc1bd0bc076f436fa60c911556d23f9cb7a89007528b0ee5cc4ec69905f90a250565b60025f54036120d25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ac2565b60025f55565b80158061216957506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015612143573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121679190612922565b155b6121db5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610ac2565b6040516001600160a01b038316602482015260448101829052611b6a9084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612473565b5f8060015f9054906101000a90046001600160a01b03166001600160a01b031663e79bf13b6040518163ffffffff1660e01b81526004015f60405180830381865afa1580156122d5573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526122fc9190810190612b9a565b80519091505f5b8181101561238e5782818151811061231d5761231d612a84565b60200260200101515f01516001600160a01b03167f0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5996001600160a01b0316036123865782818151811061237257612372612a84565b602002602001015160200151935050505090565b600101612303565b505f9250505090565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa1580156123fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124219190612922565b905061087d847f095ea7b300000000000000000000000000000000000000000000000000000000856124538686612b08565b6040516001600160a01b0390921660248301526044820152606401612220565b5f6124c7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166125599092919063ffffffff16565b905080515f14806124e75750808060200190518101906124e79190612939565b611b6a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610ac2565b60606109d984845f85855f80866001600160a01b0316858760405161257e9190612a3c565b5f6040518083038185875af1925050503d805f81146125b8576040519150601f19603f3d011682016040523d82523d5f602084013e6125bd565b606091505b50915091506125ce878383876125d9565b979650505050505050565b606083156126475782515f03612640576001600160a01b0385163b6126405760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ac2565b50816112e7565b6112e7838381511561265c5781518083602001fd5b8060405162461bcd60e51b8152600401610ac29190612c5e565b6001600160a01b0381168114610b3d575f80fd5b5f6020828403121561269a575f80fd5b81356109dc81612676565b5f805f606084860312156126b7575f80fd5b83356126c281612676565b925060208401356126d281612676565b929592945050506040919091013590565b5f602082840312156126f3575f80fd5b5035919050565b5f5b838110156127145781810151838201526020016126fc565b50505f910152565b5f81518084526127338160208601602086016126fa565b601f01601f19169290920160200192915050565b8215158152604060208201525f6109d9604083018461271c565b5f8060408385031215612772575f80fd5b823561277d81612676565b9150602083013561278d81612676565b809150509250929050565b5f602082840312156127a8575f80fd5b813567ffffffffffffffff8111156127be575f80fd5b8201606081850312156109dc575f80fd5b5f80604083850312156127e0575f80fd5b82359150602083013561278d81612676565b5f805f8060808587031215612805575f80fd5b84359350602085013561281781612676565b9250604085013561282781612676565b9396929550929360600135925050565b5f8060408385031215612848575f80fd5b823561285381612676565b946020939093013593505050565b5f805f60608486031215612873575f80fd5b83359250602084013561288581612676565b9150604084013561289581612676565b809150509250925092565b5f805f80606085870312156128b3575f80fd5b84356128be81612676565b935060208501359250604085013567ffffffffffffffff808211156128e1575f80fd5b818701915087601f8301126128f4575f80fd5b813581811115612902575f80fd5b886020828501011115612913575f80fd5b95989497505060200194505050565b5f60208284031215612932575f80fd5b5051919050565b5f60208284031215612949575f80fd5b815180151581146109dc575f80fd5b602081525f823561296881612676565b6001600160a01b0381166020840152506020830135604083015260408301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126129b6575f80fd5b830160208101903567ffffffffffffffff8111156129d2575f80fd5b8036038213156129e0575f80fd5b606080850152806080850152808260a08601375f60a0828601015260a0601f19601f8301168501019250505092915050565b818382375f9101908152919050565b5f60208284031215612a31575f80fd5b81516109dc81612676565b5f8251612a4d8184602087016126fa565b9190910192915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b602080825282518282018190525f919060409081850190868401855b82811015612afb57815180516001600160a01b03168552860151868501529284019290850190600101612acd565b5091979650505050505050565b80820180821115610924577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6040805190810167ffffffffffffffff81118282101715612b6357612b63612a57565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612b9257612b92612a57565b604052919050565b5f6020808385031215612bab575f80fd5b825167ffffffffffffffff80821115612bc2575f80fd5b818501915085601f830112612bd5575f80fd5b815181811115612be757612be7612a57565b612bf5848260051b01612b69565b818152848101925060069190911b830184019087821115612c14575f80fd5b928401925b818410156125ce5760408489031215612c30575f80fd5b612c38612b40565b8451612c4381612676565b81528486015186820152835260409093019291840191612c19565b602081525f6109dc602083018461271c56fea164736f6c6343000819000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c59900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000014c79c24b2a82ce36e3f3d693aeea17e268f5a980000000000000000000000008db2350d78abc13f5673a411d4700bcf87864dde00000000000000000000000020fdf47509c5efc0e1101e3ce443691781c17f90000000000000000000000000000000000000000000000000000000000000000d4165726120537472617465677900000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _asset (address): 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599
Arg [1] : _name (string): Aera Strategy
Arg [2] : _vaultAera (address): 0x14c79C24b2A82ce36e3F3D693aEea17e268F5a98
Arg [3] : _vaultYearn (address): 0x8DB2350D78aBc13f5673A411D4700BCF87864dDE
Arg [4] : _quickManagement (address): 0x20fDF47509C5eFC0e1101e3CE443691781C17F90
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 00000000000000000000000014c79c24b2a82ce36e3f3d693aeea17e268f5a98
Arg [3] : 0000000000000000000000008db2350d78abc13f5673a411d4700bcf87864dde
Arg [4] : 00000000000000000000000020fdf47509c5efc0e1101e3ce443691781c17f90
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000d
Arg [6] : 4165726120537472617465677900000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $88,811 | 3.3827 | $300,425.09 |
Loading...
Loading
[ Download: CSV Export ]
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.