Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
5494294 | 74 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Manager
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.20; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { IERC4626 } from "@openzeppelin/contracts/interfaces/IERC4626.sol"; import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { Access } from "../administrator/Access.sol"; import { Common } from "../libs/Common.sol"; import { Constants } from "../libs/Constants.sol"; import { IBlackList } from "../administrator/interface/IBlackList.sol"; import { IManager, ManageAssetAndShares } from "./interface/IManager.sol"; import { IReceipt, Order } from "./interface/IReceipt.sol"; import { IYToken } from "./interface/IYToken.sol"; contract Manager is Access, IManager { address public treasury; mapping(address => mapping(address => bool)) public depositAssets; // yToken => asset => status mapping(address => mapping(address => bool)) public withdrawAssets; // yToken => asset => status mapping(address => bool) public custodyWallets; address public receipt; mapping(address => uint256) public minSharesInYToken; mapping(address => mapping(address => uint256)) public guardrailPercentageForAsset; mapping(address => uint256) public maxRedeemCap; uint256[27] __gap; using SafeERC20 for IERC20; /** * @notice Disable initializer for the implementation contract */ /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /** * @notice Initialize the contract * @param _administrator address of the administrator * @param _treasury address of the treasury * @param _receipt address of the receipt contract * @dev This function is called only once during the contract deployment */ function init(address _administrator, address _treasury, address _receipt) public initializer { __Access_init(_administrator); treasury = _treasury; receipt = _receipt; } /** * @notice Set the treasury address * @param _treasury address of the treasury */ function setTreasury(address _treasury) public onlyAdmin { require(_treasury != address(0), "!valid"); treasury = _treasury; emit TreasurySet(msg.sender, _treasury); } /** * @notice Set the receipt contract address * @param _receipt address of the receipt contract */ function setReceipt(address _receipt) public onlyAdmin { require(Common.isContract(_receipt), "!receipt"); receipt = _receipt; emit ReceiptSet(msg.sender, _receipt); } /** * @notice Set the custody wallet * @param _wallet address of the wallet * @param _status true for custody and false for not custody */ function setCustodyWallet(address _wallet, bool _status) external onlyAdmin { require(_wallet != address(0), "!wallet"); custodyWallets[_wallet] = _status; emit CustodyWalletSet(msg.sender, _wallet, _status); } /** * @notice Set the minimum shares required in a yToken * @param _yToken address of the yToken * @param _minShares minimum shares required */ function setMinSharesInYToken(address _yToken, uint256 _minShares) external onlyMinterAndRedeemer { require(_minShares > 0, "!minShares"); minSharesInYToken[_yToken] = _minShares; emit MinSharesInYTokenSet(msg.sender, _yToken, _minShares); } function setMaxRedeemCap(address _yToken, uint256 _maxRedeemCap) external onlyMinterAndRedeemer { maxRedeemCap[_yToken] = _maxRedeemCap; emit MaxRedeemCapSet(msg.sender, _yToken, _maxRedeemCap); } /** * @notice Set the deposit asset * @param _orderType true for deposit and false for withdraw * @param _yToken address of the yToken * @param _asset address of the asset * @param _guardrailPercentage guardrail percentage for the asset * @param _status true for deposit and false for withdraw * @dev guardrailPercentage is used to ensure that during executeOrder, the value of _amount is not too far from the expected value, * this is just for sanity check and max guardrailPercentage is 100 */ function setAsset(bool _orderType, address _yToken, address _asset, uint256 _guardrailPercentage, bool _status) public onlyAdmin { require(Common.isContract(_asset) && Common.isContract(_yToken), "!asset !yToken"); require(_guardrailPercentage <= Constants.HUNDRED, "!guardrailPercentage"); if (_orderType) { depositAssets[_yToken][_asset] = _status; } else { withdrawAssets[_yToken][_asset] = _status; } guardrailPercentageForAsset[_yToken][_asset] = _guardrailPercentage; emit AssetStatus(_orderType, _yToken, _asset, _status); } function _normalizeAmount(address _yToken, address _asset, uint256 _amount) internal view returns (uint256) { uint256 underlyingDecimals = IERC20Metadata(IERC4626(_yToken).asset()).decimals(); uint256 assetDecimals = IERC20Metadata(_asset).decimals(); return (_amount * (10 ** underlyingDecimals)) / (10 ** assetDecimals); } /** * @notice Internal function for validating the order request */ function _validate(address _caller, address _receiver, address _yToken, address _asset, uint256 _amount, bool _orderType) internal view { require(!IBlackList(administrator).isBlackListed(_caller) && !IBlackList(administrator).isBlackListed(_receiver), "blacklisted"); if (_orderType) { require(depositAssets[_yToken][_asset] && _amount > 0, "!valid"); require(IERC20(_asset).allowance(_caller, address(this)) >= _amount, "!allowance"); require(IERC20(_asset).balanceOf(_caller) >= _amount, "!balance"); // Convert amount from asset decimals to decimals of underlying asset of YToken uint256 normalizedAmount = _normalizeAmount(_yToken, _asset, _amount); require(IERC4626(_yToken).convertToShares(normalizedAmount) >= minSharesInYToken[_yToken], "!minShares"); } else { require(withdrawAssets[_yToken][_asset] && _amount > 0, "!valid"); require(IERC20(_yToken).balanceOf(_caller) >= _amount, "!balance"); require(_amount >= minSharesInYToken[_yToken], "!minShares"); } } /** * @notice Deposit the asset to the vault * @param _yToken address of the yToken * @param _asset address of the asset * @param _amount amount of the asset * @param _receiver address of the receiver * @param _callback address of the callback * @param _callbackData data of the callback * @dev This function is used to deposit the asset to the vault */ function deposit(address _yToken, address _asset, uint256 _amount, address _receiver, address _callback, bytes calldata _callbackData, bytes32 _referralCode) external notPaused nonReentrant { _validate(msg.sender, _receiver, _yToken, _asset, _amount, true); IERC20(_asset).safeTransferFrom(msg.sender, address(this), _amount); // get absolute exchange rate uint256 exchangeRateInUnderlying = IYToken(_yToken).exchangeRate(); // For all deposit via Manager, we mint the receipt and follow 2 step process // callback and callbackData are only for future use and can only be enabled by upgrading the contract uint256 receiptId = IReceipt(receipt).mint(_receiver, Order(true, msg.sender, _asset, _receiver, _yToken, _amount, block.timestamp, exchangeRateInUnderlying, address(0), "", _referralCode)); emit OrderRequest(msg.sender, _yToken, _asset, _receiver, _amount, true, exchangeRateInUnderlying, receiptId, _referralCode); } /** * @notice Redeem the asset from the vault * @param _yToken address of the yToken * @param _asset address of the asset * @param _shares amount of the shares * @param _receiver address of the receiver * @param _callback address of the callback * @param _callbackData data of the callback * @dev This function is used to redeem the asset from the vault * * @dev Example: * When redeeming 100e18 YToken with exchange rate 1 YToken = 1.1 USDC: * 1. Calculate vaultAssetAmount = 110e6 USDC (using convertToAssets) * 2. Update yToken's total assets accounting to reflect the withdrawn amount * 3. Burn the yToken shares immediately to stop yield accrual * 4. Create a receipt for the withdrawal that can be executed after the waiting period */ function redeem(address caller, address _yToken, address _asset, uint256 _shares, address _receiver, address _callback, bytes calldata _callbackData) external notPaused nonReentrant { if (msg.sender == _yToken) { _validate(caller, _receiver, _yToken, _asset, _shares, false); } else { require(caller == msg.sender, "!caller"); _validate(msg.sender, _receiver, _yToken, _asset, _shares, false); } // Calculate the equivalent vault asset amount uint256 vaultAssetAmount = IERC4626(_yToken).convertToAssets(_shares); // update equivalent total assets IYToken(_yToken).updateTotalAssets(vaultAssetAmount, false); // burn shares from caller IYToken(_yToken).burnYToken(caller, _shares); // if redeeming yToken.asset() and vaultAssetAmount is less than maxRedeemCap and balance of contract is greater than vaultAssetAmount, redeem immediately and return if (_asset == IERC4626(_yToken).asset() && vaultAssetAmount <= maxRedeemCap[_yToken] && IERC20(_asset).balanceOf(address(this)) >= vaultAssetAmount) { IERC20(_asset).safeTransfer(_receiver, vaultAssetAmount); emit InstantRedeem(caller, _yToken, _asset, _receiver, vaultAssetAmount); return; } /** * Post burning token, check the remaining shares for caller is either 0 or >= minSharesInYToken * This is to ensure future redeems are not blocked due to low shares */ uint256 remainingShares = IERC20(_yToken).balanceOf(caller); require(remainingShares == 0 || remainingShares >= minSharesInYToken[_yToken], "0 < remainingShares < minShares"); // get exchange rate in underlying uint256 exchangeRateInUnderlying = IYToken(_yToken).exchangeRate(); // callback and callbackData are only for future use and can only be enabled by upgrading the contract uint256 receiptId = IReceipt(receipt).mint(_receiver, Order(false, caller, _asset, _receiver, _yToken, _shares, block.timestamp, exchangeRateInUnderlying, address(0), "", "")); emit OrderRequest(caller, _yToken, _asset, _receiver, _shares, false, exchangeRateInUnderlying, receiptId, ""); } /** * @notice Execute a deposit or withdraw order * @param _receiptId ID of the receipt * @param _amount amount of tokens for the operation * @param _fee fee percentage * @param _gas gas cost in tokens */ function executeOrder(uint256 _receiptId, uint256 _amount, uint256 _fee, uint256 _gas) external onlyMinterAndRedeemer notPaused nonReentrant { Order memory order = IReceipt(receipt).readOrder(_receiptId); require(block.timestamp >= order.eligibleAt, "!waitingPeriod"); require(_fee <= Constants.ONE_PERCENT, "!fee"); if (order.orderType) { _deposit(order, msg.sender, _amount, _fee, _gas); } else { _withdraw(order, msg.sender, _amount, _fee, _gas); } // Burn the receipt IReceipt(receipt).burn(_receiptId); // Execute the callback if (order.callback != address(0)) { (bool success, ) = order.callback.call(order.callbackData); require(success, "callback failed"); } } /** * @notice Transfer fee to the treasury, always fees are transferred in yToken to treasury * @param _yToken address of the yToken * @param _shares amount of the yToken * @param _fee fee percentage * @return amount of fee shares transferred to treasury */ function _transferFee(address _yToken, uint256 _shares, uint256 _fee) internal returns (uint256) { if (_fee == 0) { return 0; } uint256 feeShares = (_shares * _fee) / Constants.HUNDRED_PERCENT; IERC20(_yToken).safeTransfer(treasury, feeShares); return feeShares; } /** * @notice Deposit the asset * @param _order struct containing order details * @param _caller executor address * @param _shares amount of yToken to be minted for the deposited amount * @param _fee fee percentage * @param _gasFeeShares Cost of gas covered in yToken terms */ function _deposit(Order memory _order, address _caller, uint256 _shares, uint256 _fee, uint256 _gasFeeShares) internal { // Normalize asset amount to underlying decimals uint256 normalizedAssetAmount = _normalizeAmount(_order.yToken, _order.asset, _order.amount); // Calculate expected shares using the exchange rate at execution time uint256 yTokenDecimals = IERC20Metadata(_order.yToken).decimals(); // Usually 18 uint256 currentExchangeRate = IYToken(_order.yToken).exchangeRate(); // Calculate expected shares using the exchange rate at requested time uint256 expectedShares = (normalizedAssetAmount * (10 ** yTokenDecimals)) / _order.exchangeRateInUnderlying; // Calculate guardrail amount limits uint256 guardrailPercentage = guardrailPercentageForAsset[_order.yToken][_order.asset]; uint256 lowerBound = (expectedShares * (Constants.HUNDRED - guardrailPercentage)) / Constants.HUNDRED; uint256 upperBound = (expectedShares * (Constants.HUNDRED + guardrailPercentage)) / Constants.HUNDRED; // Check if shares are within guardrail limits require(_shares >= lowerBound && _shares <= upperBound, "!guardrail"); // Adjust shares based on exchange rate change to avoid incorrect calculation due to exchange rate fluctuation // between request and executeOrder uint256 adjustedShares = (_shares * _order.exchangeRateInUnderlying) / currentExchangeRate; // Calculate the asset amount using current exchange rate uint256 underlyingAmount = IERC4626(_order.yToken).convertToAssets(adjustedShares); // Update YToken's total assets accounting IYToken(_order.yToken).updateTotalAssets(underlyingAmount, true); // Mint the adjusted shares (fewer shares at higher exchange rate and vice versa) IYToken(_order.yToken).mintYToken(address(this), adjustedShares, true); // transfer fee to treasury, already applied on adjustedShares uint256 adjustedFeeShares = _transferFee(_order.yToken, adjustedShares, _fee); // Calculate adjusted gas fee shares uint256 adjustedGasFeeShares = (_gasFeeShares * _order.exchangeRateInUnderlying) / currentExchangeRate; // transfer gas to caller IERC20(_order.yToken).safeTransfer(_caller, adjustedGasFeeShares); // remaining shares after gas fee uint256 sharesAfterAllFee = adjustedShares - adjustedFeeShares - adjustedGasFeeShares; // transfer shares to receiver IERC20(_order.yToken).safeTransfer(_order.receiver, sharesAfterAllFee); emit Deposit(_order.owner, _order.asset, _order.amount, _order.receiver, _order.yToken, sharesAfterAllFee, adjustedFeeShares, adjustedGasFeeShares); } /** * @notice Withdraw the asset * @param _order struct containing order details * @param _caller executor address * @param _assetAmountOut amount of to send to user ( this should be asset amount equivalent to yToken - fees for treasury - gas fee) * @param _fee Fee percentage * @param _gasFeeShares Cost of gas covered in yToken terms * * @dev Example: * - User has redeemed 1000e18 YToken (1000 tokens with 18 decimals) * - Exchange rate at redeem time: 1 YToken = 1.1 USDC (USDC has 6 decimals) * - User redeems 1000e18 YToken, which is worth 1100e6 USDC * - Percentage fee: 0.1% = 1e18 YToken = 1.1e6 USDC * - Gas fee: $1 in YToken = 0.909e18 YToken = $1 USDC * - _assetAmountOut should be: 1100e6 - 1.1e6 - 1e6 = 1097.9e6 USDC * * Security considerations: * - Uses the exchange rate captured at redeem time (stored in order.exchangeRateInUnderlying) * - This protects against exchange rate fluctuations during the waiting period between * redeem and executeOrder, which can be up to several days * - If the current exchange rate were used instead, users could be charged incorrect fees * when the value of YToken changes significantly during the waiting period */ function _withdraw(Order memory _order, address _caller, uint256 _assetAmountOut, uint256 _fee, uint256 _gasFeeShares) internal { //check if manager has enough asset balance to cover the withdraw require(IERC20(_order.asset).balanceOf(address(this)) >= _assetAmountOut, "!assetBalance"); // Optimize the _order.yToken address _yToken = _order.yToken; // to optimize the read uint256 _shares = _order.amount; // amount of _yToken redeemed uint256 _expectedSharesAfterGasFee = _shares - _gasFeeShares; uint256 _expectedSharesAfterFee = _expectedSharesAfterGasFee - (_expectedSharesAfterGasFee * _fee) / Constants.HUNDRED_PERCENT; uint256 yTokenDecimals = IERC20Metadata(_yToken).decimals(); uint256 currentExchangeRate = IYToken(_yToken).exchangeRate(); // calculate normalized assetAmountOut in terms of decimals of underlying asset of YToken uint256 normalizedAssetAmountOut = _normalizeAmount(_yToken, _order.asset, _assetAmountOut); // calculate expected shares using the exchange rate at request time uint256 sharesBasedOnAmountOut = (normalizedAssetAmountOut * (10 ** yTokenDecimals)) / _order.exchangeRateInUnderlying; // Calculate guardrail amount limits uint256 guardrailPercentage = guardrailPercentageForAsset[_order.yToken][_order.asset]; uint256 lowerBound = (sharesBasedOnAmountOut * (Constants.HUNDRED - guardrailPercentage)) / Constants.HUNDRED; uint256 upperBound = (sharesBasedOnAmountOut * (Constants.HUNDRED + guardrailPercentage)) / Constants.HUNDRED; // Check if shares are within guardrail limits // NOTE: we can compare shares as normalizedAssetAmountOut already accounts // for _assetAmountOut value while normalizing it to decimals of underlying asset of YToken require(_expectedSharesAfterFee >= lowerBound && _expectedSharesAfterFee <= upperBound, "!guardrail"); // Calculate fee shares based on the original amount redeemed (fixed percentage) uint256 feeShares = (_shares * _fee) / Constants.HUNDRED_PERCENT; uint256 adjustedFeeShares = (feeShares * _order.exchangeRateInUnderlying) / currentExchangeRate; uint256 adjustedGasFeeShares = (_gasFeeShares * _order.exchangeRateInUnderlying) / currentExchangeRate; uint256 adjustedFeeAmount = IERC4626(_yToken).convertToAssets(adjustedFeeShares); uint256 adjustedGasFeeAmount = IERC4626(_yToken).convertToAssets(adjustedGasFeeShares); // update asset amount equivalent to totalFee into Ytoken in terms of exchangeRateInUnderlying IYToken(_yToken).updateTotalAssets(adjustedFeeAmount, true); // mint fee shares to treasury IYToken(_yToken).mintYToken(treasury, adjustedFeeShares, true); // update asset amount equivalent to totalFee into Ytoken in terms of exchangeRateInUnderlying IYToken(_yToken).updateTotalAssets(adjustedGasFeeAmount, true); // mint gas shares to executor IYToken(_yToken).mintYToken(_caller, adjustedGasFeeShares, true); // Transfer asset to the receiver IERC20(_order.asset).safeTransfer(_order.receiver, _assetAmountOut); emit Withdraw(_order.owner, _order.asset, _assetAmountOut, _order.receiver, _order.yToken, _shares, adjustedFeeShares, adjustedGasFeeShares); } /** * @notice Transfer assets to custody wallet * @param _token address of the token * @param _receiver address of the custody wallet * @param _amount amount of the token */ function transferToCustodyWallet(address _token, address _receiver, uint256 _amount) external onlyCollateralManager { require(_receiver != address(0) && _amount > 0, "!receiver !amount"); require(custodyWallets[_receiver], "!custody"); // transfer the asset to the custody wallet IERC20(_token).safeTransfer(_receiver, _amount); } function withdrawBondYield(address _yToken, address receiver, uint256 amount, address assetToken) external onlyBond { // check if the assetToken is allowed to be transferred out require(withdrawAssets[_yToken][assetToken], "!withdraw"); IERC20(assetToken).safeTransfer(receiver, amount); } /** * @notice Manage assets and shares for bridge or lockbox * @param _to address to mint/burn tokens for * @param _order struct containing order details */ function manageAssetAndShares(address _to, ManageAssetAndShares memory _order) external onlyOperator { // update total assets first if needed if (_order.updateAsset) { IYToken(_order.yToken).updateTotalAssets(_order.assetAmount, _order.isMint); } if (_order.isMint) { IYToken(_order.yToken).mintYToken(_to, _order.shares, _order.isNewYToken); } else { IYToken(_order.yToken).burnYToken(_to, _order.shares); } emit AssetAndShareManaged(msg.sender, _order.yToken, _order.shares, _order.assetAmount, _order.updateAsset, _order.isMint, _order.isNewYToken); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reinitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location. * * NOTE: Consider following the ERC-7201 formula to derive storage locations. */ function _initializableStorageSlot() internal pure virtual returns (bytes32) { return INITIALIZABLE_STORAGE; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { bytes32 slot = _initializableStorageSlot(); assembly { $.slot := slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 EIP-1153 (transient storage) is available on the chain you're deploying at, * consider using {ReentrancyGuardTransient} instead. * * 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 ReentrancyGuardUpgradeable is Initializable { // 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; /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard struct ReentrancyGuardStorage { uint256 _status; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) { assembly { $.slot := ReentrancyGuardStorageLocation } } /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); $._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 { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // On the first call to nonReentrant, _status will be NOT_ENTERED if ($._status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail $._status = ENTERED; } function _nonReentrantAfter() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // 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) { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); return $._status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC165} from "./IERC165.sol"; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC4626.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol"; import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol"; /** * @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626]. */ 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 redemption at the current block, * given current on-chain conditions. * * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the * same transaction. * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the * redemption would be accepted, regardless if the user has enough shares, etc. * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by redeeming. */ function previewRedeem(uint256 shares) external view returns (uint256 assets); /** * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver. * * - MUST emit the Withdraw event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * redeem execution, and are accounted for during redeem. * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner * not having enough shares, etc). * * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed. * Those methods should be performed separately. */ function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC-20 standard. */ 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 v5.3.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 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 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @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.encodeCall(token.transfer, (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.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful. */ function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) { return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful. */ function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) { return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, 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. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @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. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @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 {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @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 silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.20; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { Common } from "../libs/Common.sol"; import { Constants } from "../libs/Constants.sol"; import { IBlackList } from "./interface/IBlackList.sol"; import { IPausable } from "./interface/IPausable.sol"; import { IRole } from "./interface/IRole.sol"; // To define all the access modifiers abstract contract Access is ReentrancyGuardUpgradeable { address public administrator; event AdministratorSet(address indexed caller, address indexed newAdministrator); /** * @notice Initialize the contract with administrator address * @param _administrator address of the administrator */ function __Access_init(address _administrator) internal onlyInitializing { __ReentrancyGuard_init(); require(_administrator != address(0), "!administrator"); administrator = _administrator; } modifier onlyAdmin() { require(IRole(administrator).hasRole(Constants.ADMIN_ROLE, msg.sender), "!admin"); _; } modifier onlyCollateralManager() { require(IRole(administrator).hasRole(Constants.COLLATERAL_MANAGER_ROLE, msg.sender), "!cmgr"); _; } modifier onlyBridge() { require(IRole(administrator).hasRole(Constants.BRIDGE_ROLE, msg.sender), "!bridge"); _; } modifier onlyOperator() { require(IRole(administrator).hasRole(Constants.BRIDGE_ROLE, msg.sender) || IRole(administrator).hasRole(Constants.LOCKBOX_ROLE, msg.sender) || IRole(administrator).hasRole(Constants.YIELD_ROLE, msg.sender), "!operator"); _; } modifier onlyManager() { require(IRole(administrator).hasRole(Constants.MANAGER_ROLE, msg.sender), "!manager"); _; } modifier onlyMinterAndRedeemer() { require(IRole(administrator).hasRole(Constants.MINTER_AND_REDEEMER_ROLE, msg.sender), "!minter"); _; } modifier onlyRewarder() { require(IRole(administrator).hasRole(Constants.REWARDER_ROLE, msg.sender), "!rewarder"); _; } modifier onlyBond() { require(IRole(administrator).hasRole(Constants.BOND_ROLE, msg.sender), "!bond"); _; } modifier notPaused() { require(!IPausable(administrator).isPaused(address(this)), "paused"); _; } modifier notBlacklisted(address user) { require(!IBlackList(administrator).isBlackListed(user), "blacklisted"); _; } /** * @notice Set the administrator address * @param _administrator address of the new administrator */ function setAdministrator(address _administrator) external onlyAdmin { require(Common.isContract(_administrator), "!contract"); administrator = _administrator; emit AdministratorSet(msg.sender, _administrator); } }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.20; interface IBlackList { //functions function blackListUsers(address[] calldata _users) external; function removeBlackListUsers(address[] calldata _clearedUsers) external; function isBlackListed(address _user) external view returns (bool); //events event BlackListed(address indexed _sender, address indexed _user); event BlackListCleared(address indexed _sender, address indexed _user); }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.20; interface IPausable { function pause() external; function unpause() external; function pauseSC(address _sc) external; function unpauseSC(address _sc) external; function isPaused(address _sc) external view returns (bool); //events event Paused(address indexed _sender); event Unpaused(address indexed _sender); event Paused(address indexed _sender, address indexed _sc); event Unpaused(address indexed _sender, address indexed _sc); }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.20; interface IRole { //functions function grantRoles(bytes32 _role, address[] calldata _accounts) external; function revokeRoles(bytes32 _role, address[] calldata _accounts) external; function hasRole(bytes32 _role, address _account) external view returns (bool); function hasRoles(bytes32[] calldata _role, address[] calldata _accounts) external view returns (bool[] memory); //events event RoleGranted(bytes32 indexed _role, address indexed _sender, address indexed _account); event RoleRevoked(bytes32 indexed _role, address indexed _sender, address indexed _account); }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.20; /** * @notice ManageAssetAndShares is used to manage the asset and shares of the yToken * @param yToken The address of the yToken * @param shares The number of shares to manage * @param assetAmount The amount of asset to manage * @param updateAsset Whether to update the asset * @param isMint Whether to mint or burn the yToken * @param isNewYToken Whether the yToken is new, only utilised in vyToken and vyTokenL2 whenever asset from outside of YieldFi is deposited into the protocol (i.e during deposits and yield distribution) */ struct ManageAssetAndShares { address yToken; uint256 shares; uint256 assetAmount; bool updateAsset; bool isMint; bool isNewYToken; } interface IManager { event Deposit(address indexed caller, address indexed asset, uint256 amount, address indexed receiver, address yToken, uint256 shares, uint256 feeShare, uint256 gasFeeShare); event Withdraw(address indexed caller, address indexed asset, uint256 amount, address indexed receiver, address yToken, uint256 shares, uint256 feeShare, uint256 gasFeeShare); event Rescue(address indexed caller, address indexed token, address indexed to, uint256 amount); event AssetStatus(bool indexed orderType, address indexed yToken, address indexed asset, bool status); event OrderRequest(address caller, address indexed yToken, address indexed asset, address indexed receiver, uint256 amount, bool orderType, uint256 exchangeRateInUnderlying, uint256 receiptId, bytes32 referralCode); event YieldFeesTransferred(address indexed treasury, address indexed yToken, uint256 shares); event AssetAndShareManaged(address indexed caller, address indexed yToken, uint256 shares, uint256 assetAmount, bool updateAsset, bool isMint, bool isNewYToken); event TreasurySet(address indexed caller, address indexed treasury); event ReceiptSet(address indexed caller, address indexed receipt); event CustodyWalletSet(address indexed caller, address indexed wallet, bool status); event MinSharesInYTokenSet(address indexed caller, address indexed yToken, uint256 minShares); event MaxRedeemCapSet(address indexed caller, address indexed yToken, uint256 maxRedeemCap); event InstantRedeem(address caller, address indexed yToken, address indexed asset, address indexed receiver, uint256 amount); function deposit(address _yToken, address _asset, uint256 _amount, address _receiver, address _callback, bytes calldata _callbackData, bytes32 _referralCode) external; function redeem(address caller, address _yToken, address _asset, uint256 _shares, address _receiver, address _callback, bytes calldata _callbackData) external; function executeOrder(uint256 _receiptId, uint256 _amount, uint256 _fee, uint256 _gas) external; function transferToCustodyWallet(address _token, address _receiver, uint256 _amount) external; function treasury() external view returns (address); function manageAssetAndShares(address _to, ManageAssetAndShares memory _manageAssetAndShares) external; function minSharesInYToken(address _yToken) external view returns (uint256); }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.20; struct Order { // Type of transaction - it can be any variation of transaction it can be Deposit or Withdrawal bool orderType; // true for deposit and false for withdrawal // Caller address address owner; // Owner of asset or yToken // Asset address should be a contract address address asset; // Address who is going to receive the asset address receiver; // Address of the yToken - it can be any variation of yToken address yToken; // For deposit, it is asset amount and for withdrawal, it is yToken amount uint256 amount; // Waiting period is a placeholder if the execution to be postponed uint256 eligibleAt; // Exchange rate in underlying uint256 exchangeRateInUnderlying; // Callback parameters address callback; bytes callbackData; // Referral code bytes32 referralCode; } interface IReceipt { function mint(address _to, Order memory _order) external returns (uint256); function burn(uint256 _tokenId) external; function readOrder(uint256 _tokenId) external view returns (Order memory); }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.20; interface IYToken { // functions function transferInRewards(uint256 amount, bool profit) external; function exchangeRate() external view returns (uint256); function mintYToken(address to, uint256 amount, bool isNewYToken) external; function burnYToken(address from, uint256 amount) external; function updateTotalAssets(uint256 amount, bool add) external; function fee() external view returns (uint256); // events event TransferRewards(address indexed caller, uint256 amount); event ManagerSet(address indexed caller, address indexed manager); event FeeSet(address indexed caller, uint256 fee); event GasFeeSet(address indexed caller, uint256 gasFee); }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.20; library Common { /** * @notice Check if an address is a contract * @param _addr address to check * @return true if the address is a contract, false otherwise */ function isContract(address _addr) internal view returns (bool) { return _addr != address(0) && _addr.code.length != 0; } }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.20; library Constants { // admin role bytes32 public constant ADMIN_ROLE = keccak256("ADMIN"); // role for minting and redeeming tokens bytes32 public constant MINTER_AND_REDEEMER_ROLE = keccak256("MINTER_AND_REDEEMER"); // role for collateral manager who can transfer collateral bytes32 public constant COLLATERAL_MANAGER_ROLE = keccak256("COLLATERAL_MANAGER"); // role for rewarder who can transfer reward bytes32 public constant REWARDER_ROLE = keccak256("REWARDER"); // role for managing blacklist addresses bytes32 public constant MANAGER_ROLE = keccak256("MANAGER"); // role assigned to bridges bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE"); // role for perpetual bond bytes32 public constant BOND_ROLE = keccak256("BOND"); // role for lockbox bytes32 public constant LOCKBOX_ROLE = keccak256("LOCKBOX"); // role for yield bytes32 public constant YIELD_ROLE = keccak256("YIELD"); uint256 constant PINT = 1e18; uint256 constant HUNDRED_PERCENT = 100e18; uint256 constant ONE_PERCENT = 1e18; uint256 constant HUNDRED = 100; // Period for vesting strategy rewards uint256 constant VESTING_PERIOD = 24 hours; // Bridge transaction types bytes32 public constant BRIDGE_SEND_HASH = keccak256("BRIDGE_SEND"); }
{ "evmVersion": "cancun", "libraries": {}, "metadata": { "appendCBOR": true, "bytecodeHash": "ipfs", "useLiteralContent": false }, "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "remappings": [ "@layerzerolabs/oft-evm/=lib/devtools/packages/oft-evm/", "@layerzerolabs/oapp-evm/=lib/devtools/packages/oapp-evm/", "@layerzerolabs/lz-evm-protocol-v2/=lib/layerzero-v2/packages/layerzero-v2/evm/protocol/", "@layerzerolabs/lz-evm-messagelib-v2/=lib/layerzero-v2/packages/layerzero-v2/evm/messagelib/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin-upgradeable/contracts/=lib/openzeppelin-contracts-upgradeable/contracts/", "@chainlink/contracts-ccip/=lib/chainlink/contracts/", "@chainlink/contracts/=lib/chainlink/contracts/", "solidity-bytes-utils/=lib/solidity-bytes-utils/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "chainlink/=lib/chainlink/", "devtools/=lib/devtools/packages/toolbox-foundry/src/", "ds-test/=lib/layerzero-v2/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/", "layerzero-v2/=lib/layerzero-v2/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "viaIR": true }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"newAdministrator","type":"address"}],"name":"AdministratorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"yToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"updateAsset","type":"bool"},{"indexed":false,"internalType":"bool","name":"isMint","type":"bool"},{"indexed":false,"internalType":"bool","name":"isNewYToken","type":"bool"}],"name":"AssetAndShareManaged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"orderType","type":"bool"},{"indexed":true,"internalType":"address","name":"yToken","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"AssetStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"CustodyWalletSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"yToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeShare","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasFeeShare","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"yToken","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"InstantRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"yToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"maxRedeemCap","type":"uint256"}],"name":"MaxRedeemCapSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"yToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"minShares","type":"uint256"}],"name":"MinSharesInYTokenSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"yToken","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"orderType","type":"bool"},{"indexed":false,"internalType":"uint256","name":"exchangeRateInUnderlying","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"receiptId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"referralCode","type":"bytes32"}],"name":"OrderRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receipt","type":"address"}],"name":"ReceiptSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Rescue","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"treasury","type":"address"}],"name":"TreasurySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"yToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeShare","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasFeeShare","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"treasury","type":"address"},{"indexed":true,"internalType":"address","name":"yToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"YieldFeesTransferred","type":"event"},{"inputs":[],"name":"administrator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"custodyWallets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_yToken","type":"address"},{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"address","name":"_callback","type":"address"},{"internalType":"bytes","name":"_callbackData","type":"bytes"},{"internalType":"bytes32","name":"_referralCode","type":"bytes32"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"depositAssets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_receiptId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_gas","type":"uint256"}],"name":"executeOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"guardrailPercentageForAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_administrator","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_receipt","type":"address"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"components":[{"internalType":"address","name":"yToken","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"assetAmount","type":"uint256"},{"internalType":"bool","name":"updateAsset","type":"bool"},{"internalType":"bool","name":"isMint","type":"bool"},{"internalType":"bool","name":"isNewYToken","type":"bool"}],"internalType":"struct ManageAssetAndShares","name":"_order","type":"tuple"}],"name":"manageAssetAndShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxRedeemCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minSharesInYToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"receipt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"_yToken","type":"address"},{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_shares","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"address","name":"_callback","type":"address"},{"internalType":"bytes","name":"_callbackData","type":"bytes"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_administrator","type":"address"}],"name":"setAdministrator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_orderType","type":"bool"},{"internalType":"address","name":"_yToken","type":"address"},{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_guardrailPercentage","type":"uint256"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"setAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"setCustodyWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_yToken","type":"address"},{"internalType":"uint256","name":"_maxRedeemCap","type":"uint256"}],"name":"setMaxRedeemCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_yToken","type":"address"},{"internalType":"uint256","name":"_minShares","type":"uint256"}],"name":"setMinSharesInYToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receipt","type":"address"}],"name":"setReceipt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferToCustodyWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"withdrawAssets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_yToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"assetToken","type":"address"}],"name":"withdrawBondYield","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080806040523460d0577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c1660c1576002600160401b03196001600160401b03821601605c575b6040516138f790816100d58239f35b6001600160401b0319166001600160401b039081177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005581527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f80604d565b63f92ee8a960e01b5f5260045ffd5b5f80fdfe60806040526004361015610011575f80fd5b5f803560e01c8063184b9559146128915780634cb4ec51146127855780634d537b691461268457806352c403d9146124e35780635403a228146124a6578063583ebbad1461239a57806361d027b31461237257806366026e1c1461233a578063674d6630146122e35780636ae4237a146120b35780636defd45514611c3b5780637378576614611af35780639e8250c914611981578063c24e477814611929578063c73f1bd014610b53578063df8089ef14610a1a578063e1e6b898146109f1578063e68507f3146108c2578063eb809ec414610889578063ed0ea2ff1461029a578063f0f4426014610193578063f53d0a8e1461016c5763fbcc776c14610117575f80fd5b34610169576040366003190112610169576040610132612a8c565b9161013b612aa2565b9260018060a01b031681526007602052209060018060a01b03165f52602052602060405f2054604051908152f35b80fd5b5034610169578060031936011261016957546040516001600160a01b039091168152602090f35b5034610169576020366003190112610169576101ad612a8c565b8154604051632474521560e21b81525f80516020613842833981519152600482015233602482015290602090829060449082906001600160a01b03165afa801561028f578390610250575b6102029150613277565b6001600160a01b03166102168115156132ac565b600180546001600160a01b03191682179055337f21eb548722a564f6e09f039f7aa858ae94c911910f3823b37af2250eeca4f4038380a380f35b506020813d602011610287575b8161026a60209383612b6a565b810103126102835761027e61020291612b8c565b6101f8565b8280fd5b3d915061025d565b6040513d85823e3d90fd5b50346101695760e0366003190112610169576102b4612a8c565b6102bc612aa2565b604435916102c8612afa565b926102d1612ace565b5060a43567ffffffffffffffff8111610885576102f2903690600401612b10565b50508454604051635b14f18360e01b815230600482015260c4359291602090829060249082906001600160a01b03165afa801561066857879061084a575b61033b915015612c08565b610343613324565b8554604051630723eb0360e51b81523360048201526001600160a01b0390911690602081602481855afa90811561083f578891610801575b50159081610783575b50156107505760018060a01b0383169283875260026020526040872060018060a01b0386165f5260205260ff60405f20541680610747575b6103c5906132ac565b604051636eb1769f60e11b81523360048201523060248201526001600160a01b03861695906020816044818a5afa80156106295784918a91610712575b50106106e0576040516370a0823160e01b8152336004820152906020826024818a5afa80156106295784928a916106a7575b50926104458361044a95101561335c565b6136b3565b604051906363737ac960e11b82526004820152602081602481875afa8015610668578790610673575b61048c9150848852600660205260408820541115612bcf565b6104c66040516323b872dd60e01b6020820152336024820152306044820152826064820152606481526104c0608482612b6a565b8561365b565b604051633ba0b9a960e01b815291602083600481875afa928315610668578793610634575b5061058660018060a01b0360055416926040519761050889612b4d565b600189523360208a01528760408a015260018060a01b038116988960608201528760808201528260a08201524260c08201528660e08201528a61010082015260209586926040516105598582612b6a565b8d8152610120840152866101408401528c604051809781958294638db63a4560e01b845260048401612c6d565b03925af19182156106295789926105e3575b50905f805160206138a28339815191529460c094939260405194338652850152600160408501526060840152608083015260a0820152a460015f805160206138628339815191525580f35b938093925084813d8311610622575b6105fc8183612b6a565b8101031261061e57925191929091905f805160206138a2833981519152610598565b5f80fd5b503d6105f2565b6040513d8b823e3d90fd5b9092506020813d602011610660575b8161065060209383612b6a565b8101031261061e5751915f6104eb565b3d9150610643565b6040513d89823e3d90fd5b506020813d60201161069f575b8161068d60209383612b6a565b8101031261061e5761048c9051610473565b3d9150610680565b9250506020823d6020116106d8575b816106c360209383612b6a565b8101031261061e579051839190610445610434565b3d91506106b6565b60405162461bcd60e51b815260206004820152600a60248201526921616c6c6f77616e636560b01b6044820152606490fd5b9150506020813d60201161073f575b8161072e60209383612b6a565b8101031261061e578390515f610402565b3d9150610721565b508115156103bc565b60405162461bcd60e51b815260206004820152600b60248201526a189b1858dadb1a5cdd195960aa1b6044820152606490fd5b604051630723eb0360e51b81526001600160a01b03881660048201529150602090829060249082905afa9081156106685787916107c3575b50155f610384565b90506020813d6020116107f9575b816107de60209383612b6a565b810103126107f5576107ef90612b8c565b5f6107bb565b8680fd5b3d91506107d1565b90506020813d602011610837575b8161081c60209383612b6a565b810103126108335761082d90612b8c565b5f61037b565b8780fd5b3d915061080f565b6040513d8a823e3d90fd5b506020813d60201161087d575b8161086460209383612b6a565b810103126107f55761087861033b91612b8c565b610330565b3d9150610857565b8580fd5b5034610169576020366003190112610169576020906040906001600160a01b036108b1612a8c565b168152600883522054604051908152f35b5034610169576020366003190112610169576108dc612a8c565b8154604051632474521560e21b81525f80516020613842833981519152600482015233602482015290602090829060449082906001600160a01b03165afa801561028f5783906109b6575b6109319150613277565b61093a81613560565b1561098657600580546001600160a01b0319166001600160a01b03929092169182179055337fc19bf1ec51bb24ae0bff17764e49ad5028e0e42feb2f24d17bcd8f7ee8e721aa8380a380f35b60405162461bcd60e51b8152602060048201526008602482015267085c9958d95a5c1d60c21b6044820152606490fd5b506020813d6020116109e9575b816109d060209383612b6a565b81010312610283576109e461093191612b8c565b610927565b3d91506109c3565b50346101695780600319360112610169576005546040516001600160a01b039091168152602090f35b503461016957602036600319011261016957610a34612a8c565b8154604051632474521560e21b81525f8051602061384283398151915260048201523360248201529091906020816044816001600160a01b0387165afa8015610b48578490610b09575b610a889150613277565b610a9181613560565b15610ad8576001600160a01b03166001600160a01b03199190911681178255337fbc5dab480bc3beb0582944eefba927e4358ed22805ac40b2078d517b8a036ae78380a380f35b60405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606490fd5b506020813d602011610b40575b81610b2360209383612b6a565b81010312610b3c57610b37610a8891612b8c565b610a7e565b8380fd5b3d9150610b16565b6040513d86823e3d90fd5b50346101695760803660031901126101695760043590602435906044359260643560018060a01b0383541694604051632474521560e21b81527f196445be8e29cb4e505699c67ec8eceb0187441d0913818e000a48d538545d1460048201523360248201526020816044818a5afa9081156118915785916118e0575b50602496610bde602092612b99565b604051635b14f18360e01b815230600482015297889182905afa958615610b4857849661189c575b50610c15602494959615612c08565b610c1d613324565b60055460405163e04f10b560e01b81526004810185905294869186919082906001600160a01b03165afa938415611891578594611753575b5060c0840151421061171d57670de0b6b3a764000081116116f25783511561119b57608084019160018060a01b038351169160408601916004610ca960018060a01b038551169560a08a01968751916136b3565b865160405163313ce56760e01b81529260209184919082906001600160a01b03165afa918215611190578a9261115c575b508651604051633ba0b9a960e01b81529190602090839060049082906001600160a01b03165afa918215611151578b9261111b575b50610d2060ff610d269394166135e9565b9061359f565b90610d3760e08a01928351906135b2565b87516001600160a01b039081168c52600760209081526040808e2089519093165f9081529290915290205490606482810390811161110757610d7b6064918361359f565b04916064019081606411611107578c9d610db4610dc1946064610da28896610dbc9661359f565b049083101590816110fc575b506135f7565b85519061359f565b6135b2565b936024602060018060a01b038a5116604051928380926303d1689d60e11b82528a60048301525afa90811561109f578c916110c7575b5088516001600160a01b031690813b156110c3578c9160448392604051948593849263aa21161f60e01b84526004840152600160248401525af190811561109f578c916110ae575b505087516001600160a01b0316803b156110aa578b8091606460405180948193637bbde4a560e01b83523060048401528b6024840152600160448401525af1801561109f5789918d91611082575b505094610ef9610ee0610f7194610dbc610ed6610efe96867f6d9e3887d4874fde4dadb9d1d055309b33b01e76dda88080ffb5fc966bd0e7bc9c60018060a01b03905116613801565b988998519061359f565b958692610ef9848d339060018060a01b039051166132e1565b61357e565b9260018060a01b0388511692610f238560608d019560018060a01b03875116906132e1565b60208b8101519751985194519951604080519687526001600160a01b0391821692870192909252908501959095526060840152608083015295821695948216949390911692819060a0820190565b0390a45b6005546001600160a01b031690813b1561107d578391602483926040519485938492630852cd8d60e31b845260048401525af190811561028f578391611065575b50506101008101516001600160a01b031680610fe2575b8260015f805160206138628339815191525580f35b610120839201519082602083519301915af13d15611060573d61100481612c51565b906110126040519283612b6a565b81528260203d92013e5b1561102957805f80610fcd565b60405162461bcd60e51b815260206004820152600f60248201526e18d85b1b189858dac819985a5b1959608a1b6044820152606490fd5b61101c565b8161106f91612b6a565b61107a57815f610fb6565b50fd5b505050fd5b8192509061108f91612b6a565b61109b57878b5f610e8d565b8a80fd5b6040513d8e823e3d90fd5b8b80fd5b816110b891612b6a565b61109b578a5f610e3f565b8c80fd5b9b505060208b3d6020116110f4575b816110e360209383612b6a565b8101031261061e578b9a515f610df7565b3d91506110d6565b90508211155f610dae565b634e487b7160e01b8d52601160045260248dfd5b91506020823d602011611149575b8161113660209383612b6a565b8101031261061e57905190610d20610d0f565b3d9150611129565b6040513d8d823e3d90fd5b60049192506111829060203d602011611189575b61117a8183612b6a565b8101906135d0565b9190610cda565b503d611170565b6040513d8c823e3d90fd5b9490604084016024602060018060a01b03835116604051928380926370a0823160e01b82523060048301525afa9081156106685790849188916116bd575b501061168857608085019260018060a01b038451169060a08701519061121d611202868461357e565b68056bc75e2d631000006112168d8361359f565b049061357e565b946040519a63313ce56760e01b8c5260208c600481885afa9b8c15611151578b9c611667575b50604051633ba0b9a960e01b81529b60208d600481895afa9c8d1561109f578c9d611631575b5061128e90610d2060ff6112878760018060a01b038c51168b6136b3565b92166135e9565b9661129f60e08c01988951906135b2565b60018060a01b038a51168d52600760205260408d2060018060a01b0389511660018060a01b03165f5260205260405f205490816064036064811161161d576112e96064918361359f565b0491606401908160641161161d579e8e9f68056bc75e2d63100000611340839761133a610dbc986113519b9860646113276113499a610dbc9961359f565b04908210159182611612575b50506135f7565b8b61359f565b048c519061359f565b98519061359f565b926040516303d1689d60e11b8152866004820152602081602481855afa908115611151578b916115dd575b506040516303d1689d60e11b81526004810186905290602082602481865afa91821561109f578c926115a6575b50823b156110aa576040519063aa21161f60e01b82526004820152600160248201528b8160448183875af190811561109f578c91611591575b50506001546001600160a01b0316823b156110aa5760405190637bbde4a560e01b82526004820152876024820152600160448201528b8160648183875af190811561109f578c9161157c575b5050813b1561109b576040519063aa21161f60e01b82526004820152600160248201528a8160448183865af1908115611151578b91611567575b5050803b1561156357898091606460405180948193637bbde4a560e01b8352336004840152896024840152600160448401525af1908115611190578a9161154a575b5050835160608901805190967f82ca45f66e5ec57290dc1fa286f58cd0c9769079a69574cacfd5d3f6ba68982a956115429390926114f69186916001600160a01b0390811691166132e1565b60208b810151975198519951604080519687526001600160a01b0391821692870192909252908501959095526060840152608083015295821695948216949390911692819060a0820190565b0390a4610f75565b8161155491612b6a565b61155f57885f6114aa565b8880fd5b8980fd5b8161157191612b6a565b61156357895f611468565b8161158691612b6a565b61109b578a5f61142e565b8161159b91612b6a565b61109b578a5f6113e2565b9b50905060208b3d6020116115d5575b816115c360209383612b6a565b8101031261061e578b9a51905f6113a9565b3d91506115b6565b9a505060208a3d60201161160a575b816115f960209383612b6a565b8101031261061e578a99515f61137c565b3d91506115ec565b111590505f80611333565b634e487b7160e01b8f52601160045260248ffd5b909c506020813d60201161165f575b8161164d60209383612b6a565b8101031261061e57519b61128e611269565b3d9150611640565b611681919c5060203d6020116111895761117a8183612b6a565b9a5f611243565b60405162461bcd60e51b815260206004820152600d60248201526c21617373657442616c616e636560981b6044820152606490fd5b9150506020813d6020116116ea575b816116d960209383612b6a565b8101031261061e578390515f6111d9565b3d91506116cc565b606460405162461bcd60e51b81526020600482015260046024820152632166656560e01b6044820152fd5b60405162461bcd60e51b815260206004820152600e60248201526d085dd85a5d1a5b99d4195c9a5bd960921b6044820152606490fd5b9093503d8086833e6117658183612b6a565b8101906020818303126108855780519067ffffffffffffffff82116107f5570161016081830312610885576040519161179d83612b4d565b6117a682612b8c565b83526117b460208301612c3d565b60208401526117c560408301612c3d565b60408401526117d660608301612c3d565b60608401526117e760808301612c3d565b608084015260a082015160a084015260c082015160c084015260e082015160e08401526118176101008301612c3d565b61010084015261012082015167ffffffffffffffff811161083357820181601f820112156108335780519061184b82612c51565b926118596040519485612b6a565b8284526020838301011161155f57602082610140959493828c94018386015e830101526101208401520151610140820152925f610c55565b6040513d87823e3d90fd5b95506020863d6020116118d8575b816118b760209383612b6a565b81010312610b3c57610c156118cf6024959697612b8c565b96959450610c06565b3d91506118aa565b90506020813d602011611921575b816118fb60209383612b6a565b8101031261191d57602496610bde611914602093612b8c565b92505096610bcf565b8480fd5b3d91506118ee565b5034610169576040366003190112610169576040611945612a8c565b9161194e612aa2565b9260018060a01b031681526003602052209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b50346101695760803660031901126101695761199b612a8c565b6119a3612aa2565b906119ac612afa565b8354604051632474521560e21b81527f3812cb515c4c47772b5b6b50b84b6a856abab98cf24bcfb67a83510fb661c133600482015233602482015291929190602090829060449082906001600160a01b03165afa908115611891578591611ab9575b5015611a8c5760018060a01b0316835260036020526040832060018060a01b0382165f5260205260ff60405f20541615611a5b57611a5891604435916001600160a01b03166132e1565b80f35b60405162461bcd60e51b815260206004820152600960248201526821776974686472617760b81b6044820152606490fd5b60405162461bcd60e51b815260206004820152600560248201526408589bdb9960da1b6044820152606490fd5b90506020813d602011611aeb575b81611ad460209383612b6a565b8101031261191d57611ae590612b8c565b5f611a0e565b3d9150611ac7565b503461016957604036600319011261016957611b0d612a8c565b6024359081151590818303610b3c578354604051632474521560e21b81525f80516020613842833981519152600482015233602482015290602090829060449082906001600160a01b03165afa8015611891578590611c00575b611b719150613277565b6001600160a01b0316918215611bd157611ba2908385526004602052604085209060ff801983541691151516179055565b6040519081527f4d838617e2f838c1ab5ced341702d2ce1f6f36052b7b061794cc86012a17a26c60203392a380f35b60405162461bcd60e51b8152602060048201526007602482015266085dd85b1b195d60ca1b6044820152606490fd5b506020813d602011611c33575b81611c1a60209383612b6a565b8101031261191d57611c2e611b7191612b8c565b611b67565b3d9150611c0d565b503461061e5760e036600319011261061e57611c55612a8c565b60c036602319011261061e576040519060c0820182811067ffffffffffffffff82111761209f57604052611c87612aa2565b82526020820191604435835260408101916064358352611ca5612b3e565b916060810192835260a43590811515820361061e576080810191825260c43592831515840361061e5760a082019384525f54604051632474521560e21b81527f08fb31c3e81624356c3314088aa971b73bcc82d22bc3e3b184b4593077ae32786004820152336024820152906001600160a01b0316602082604481845afa918215611efd575f92612063575b508115611fcf575b8115611f39575b5015611f085787908551611e99575b835115611e2d57825188518651151592916001600160a01b0316803b1561191d578492836064926040519687958694637bbde4a560e01b865260018060a01b03166004860152602485015260448401525af18015611e2257611e0d575b50505b60018060a01b03905116945193519251151590511515915115159260405194855260208501526040840152606083015260808201527f1516f6e8af7338a5166f6c531effb2edb3d0f2f37c72c5c06b87618943e7a2ce60a03392a380f35b81611e1791612b6a565b6107f557865f611dac565b6040513d84823e3d90fd5b60018060a01b03835116908851823b15610b3c5760405163eeb8618d60e01b81526001600160a01b0392909216600483015260248201529082908290604490829084905af18015611e2257611e84575b5050611daf565b81611e8e91612b6a565b6107f557865f611e7d565b905060018060a01b03825116865184511515823b1561061e5760445f9283604051958694859363aa21161f60e01b8552600485015260248401525af18015611efd57611ee8575b508790611d4f565b611ef59198505f90612b6a565b5f965f611ee0565b6040513d5f823e3d90fd5b60405162461bcd60e51b815260206004820152600960248201526810b7b832b930ba37b960b91b6044820152606490fd5b604051632474521560e21b81527faeed4774a6ca7dc9eef4423038c2a3abe132048336feddd81b2e9a5e941eb77760048201523360248201529150602090829060449082905afa908115611efd575f91611f95575b505f611d40565b90506020813d602011611fc7575b81611fb060209383612b6a565b8101031261061e57611fc190612b8c565b5f611f8e565b3d9150611fa3565b604051632474521560e21b81527f0f2a9aa9ac2639d8d73bfa84d0682d3e88d5f473437d4e7c341378f9bbebddbd6004820152336024820152909150602081604481855afa908115611efd575f91612029575b5090611d39565b90506020813d60201161205b575b8161204460209383612b6a565b8101031261061e5761205590612b8c565b5f612022565b3d9150612037565b9091506020813d602011612097575b8161207f60209383612b6a565b8101031261061e5761209090612b8c565b905f611d31565b3d9150612072565b634e487b7160e01b5f52604160045260245ffd5b3461061e5760a036600319011261061e576004358015159081810361061e576120da612aa2565b916120e3612ab8565b92606435926120f0612b3e565b5f54604051632474521560e21b81525f80516020613842833981519152600482015233602482015291969190602090829060449082906001600160a01b03165afa8015611efd575f906122a8575b6121489150613277565b61215181613560565b80612299575b156122635760648511612227577f3176f2587b9045e51587a9fcfe247898e237bc0417f5c1ae3220072b422e093d92602092156121f2576001600160a01b038181165f908152600285526040808220928516825291855220805460ff191660ff891515161790555b6001600160a01b039081165f818152600785526040808220949093168082529385528290209690965551951515865294a4005b6001600160a01b038181165f908152600385526040808220928516825291855220805460ff191660ff891515161790556121bf565b60405162461bcd60e51b81526020600482015260146024820152732167756172647261696c50657263656e7461676560601b6044820152606490fd5b60405162461bcd60e51b815260206004820152600e60248201526d10b0b9b9b2ba1010bcaa37b5b2b760911b6044820152606490fd5b506122a383613560565b612157565b506020813d6020116122db575b816122c260209383612b6a565b8101031261061e576122d661214891612b8c565b61213e565b3d91506122b5565b3461061e57604036600319011261061e576122fc612a8c565b612304612aa2565b9060018060a01b03165f52600260205260405f209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b3461061e57602036600319011261061e576001600160a01b0361235b612a8c565b165f526006602052602060405f2054604051908152f35b3461061e575f36600319011261061e576001546040516001600160a01b039091168152602090f35b3461061e5760e036600319011261061e576123b3612a8c565b6123bb612aa2565b906123c4612ab8565b906123cd612ace565b916123d6612ae4565b5060c4359367ffffffffffffffff851161061e576123fa6024953690600401612b10565b50505f54604051635b14f18360e01b81523060048201529560209187919082906001600160a01b03165afa948515611efd575f95612465575b506124416124529515612c08565b612449613324565b60643592612d43565b60015f8051602061386283398151915255005b94506020853d60201161249e575b8161248060209383612b6a565b8101031261061e5761244161249761245296612b8c565b9550612433565b3d9150612473565b3461061e57602036600319011261061e576001600160a01b036124c7612a8c565b165f526004602052602060ff60405f2054166040519015158152f35b3461061e57606036600319011261061e576124fc612a8c565b612504612aa2565b5f54604051632474521560e21b81527f413cc8bb35fe129dacd3dfaae80d6d4c5d313f64cee9dd6712e7ca52e38573a96004820152336024820152604480359392602091839182906001600160a01b03165afa908115611efd575f9161264a575b501561261d576001600160a01b03811680151580612614575b156125db575f52600460205260ff60405f205416156125ab576125a9926001600160a01b03166132e1565b005b60405162461bcd60e51b815260206004820152600860248201526721637573746f647960c01b6044820152606490fd5b60405162461bcd60e51b8152602060048201526011602482015270085c9958d95a5d995c8808585b5bdd5b9d607a1b6044820152606490fd5b5082151561257e565b60405162461bcd60e51b815260206004820152600560248201526410b1b6b3b960d91b6044820152606490fd5b90506020813d60201161267c575b8161266560209383612b6a565b8101031261061e5761267690612b8c565b84612565565b3d9150612658565b3461061e57604036600319011261061e5761269d612a8c565b602435906044602060018060a01b035f541660405192838092632474521560e21b82527f196445be8e29cb4e505699c67ec8eceb0187441d0913818e000a48d538545d1460048301523360248301525afa8015611efd575f9061274a575b6127059150612b99565b60018060a01b031690815f5260086020528060405f20556040519081527f9b5f7fd7d8f1ef48cef00c8a6e22104d55bcdcf2e7bde42fa59dc04660296bb860203392a3005b506020813d60201161277d575b8161276460209383612b6a565b8101031261061e5761277861270591612b8c565b6126fb565b3d9150612757565b3461061e57604036600319011261061e5761279e612a8c565b602435906044602060018060a01b035f541660405192838092632474521560e21b82527f196445be8e29cb4e505699c67ec8eceb0187441d0913818e000a48d538545d1460048301523360248301525afa8015611efd575f90612856575b6128069150612b99565b612811821515612bcf565b60018060a01b031690815f5260066020528060405f20556040519081527f3d159f9ca709b98fbe13933da954dc4650e8387642a88226d601fff8b3158bbb60203392a3005b506020813d602011612889575b8161287060209383612b6a565b8101031261061e5761288461280691612b8c565b6127fc565b3d9150612863565b3461061e57606036600319011261061e576128aa612a8c565b6128b2612aa2565b6128ba612ab8565b905f80516020613882833981519152549260ff8460401c16159367ffffffffffffffff811680159081612a84575b6001149081612a7a575b159081612a71575b50612a625767ffffffffffffffff1981166001175f805160206138828339815191525584612a36575b5061292c613630565b612934613630565b61293c613630565b60015f80516020613862833981519152556001600160a01b03168015612a00576001600160601b0360a01b5f5416175f5560018060a01b03166001600160601b0360a01b600154161760015560018060a01b03166001600160601b0360a01b60055416176005556129a957005b68ff0000000000000000195f8051602061388283398151915254165f80516020613882833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b60405162461bcd60e51b815260206004820152600e60248201526d10b0b236b4b734b9ba3930ba37b960911b6044820152606490fd5b68ffffffffffffffffff191668010000000000000001175f805160206138828339815191525584612923565b63f92ee8a960e01b5f5260045ffd5b905015866128fa565b303b1591506128f2565b8691506128e8565b600435906001600160a01b038216820361061e57565b602435906001600160a01b038216820361061e57565b604435906001600160a01b038216820361061e57565b608435906001600160a01b038216820361061e57565b60a435906001600160a01b038216820361061e57565b606435906001600160a01b038216820361061e57565b9181601f8401121561061e5782359167ffffffffffffffff831161061e576020838186019501011161061e57565b60843590811515820361061e57565b610160810190811067ffffffffffffffff82111761209f57604052565b90601f8019910116810190811067ffffffffffffffff82111761209f57604052565b5190811515820361061e57565b15612ba057565b60405162461bcd60e51b815260206004820152600760248201526610b6b4b73a32b960c91b6044820152606490fd5b15612bd657565b60405162461bcd60e51b815260206004820152600a602482015269216d696e53686172657360b01b6044820152606490fd5b15612c0f57565b60405162461bcd60e51b81526020600482015260066024820152651c185d5cd95960d21b6044820152606490fd5b51906001600160a01b038216820361061e57565b67ffffffffffffffff811161209f57601f01601f191660200190565b906101406101c09360209260018060a01b0316845260408385015280511515604085015260018060a01b038382015116606085015260018060a01b03604082015116608085015260018060a01b0360608201511660a085015260018060a01b0360808201511660c085015260a081015160e085015260c081015161010085015260e081015161012085015260018060a01b036101008201511682850152610120810151610160808601528051938491826101a0880152018686015e5f8484018601520151610180830152601f01601f1916010190565b91926001600160a01b038216929091828533860361322457612d66928885613393565b6040516303d1689d60e11b8152600481018390525f90602081602481885afa908115611efd575f916131f2575b50843b1561061e5760405163aa21161f60e01b81528160048201525f60248201525f81604481838a5af18015611efd576131dd575b50843b156131d95760405163eeb8618d60e01b81526001600160a01b0384166004820152602481018590528281604481838a5af1801561028f579083916131c4575b50506040516338d52e0f60e01b815295602087600481895afa96871561028f578397613188575b506001600160a01b039081169616861480613172575b80613107575b6130b557506040516370a0823160e01b81526001600160a01b039092166004830181905291602081602481885afa908115611e22578291613083575b50801590811561306c575b501561302757604051633ba0b9a960e01b815290602082600481885afa90811561301b578091612fe5575b612f59925060018060a01b036005541660405198612edc8a612b4d565b828a528560208b01528860408b015260018060a01b038116998a60608201528860808201528760a08201524260c08201528460e0820152836101008201526020928392604051612f2c8582612b6a565b8681526101208401528561014084015285604051809981958294638db63a4560e01b845260048401612c6d565b03925af1938415611e22578294612fa3575b50905f805160206138a28339815191529560c0959493926040519586528501526040840152606083015260808201525f60a0820152a4565b94935091908285813d8311612fde575b612fbd8183612b6a565b8101031261061e579351929390915f805160206138a2833981519152612f6b565b503d612fb3565b90506020823d602011613013575b8161300060209383612b6a565b8101031261061e57612f59915190612ebf565b3d9150612ff3565b604051903d90823e3d90fd5b60405162461bcd60e51b815260206004820152601f60248201527f30203c2072656d61696e696e67536861726573203c206d696e536861726573006044820152606490fd5b90508482526006602052604082205411155f612e94565b90506020813d6020116130ad575b8161309e60209383612b6a565b8101031261061e57515f612e89565b3d9150613091565b919590507ff64213ec57f9a9ee68c3166cd3208c68fd79e273eb082be31374e9792caac54092506130e78282876132e1565b604080516001600160a01b039788168152602081019390935295169490a4565b506040516370a0823160e01b81523060048201526020816024818a5afa90811561028f57908291849161313d575b501015612e4d565b9150506020813d60201161316a575b8161315960209383612b6a565b8101031261061e578190515f613135565b3d915061314c565b5084825260086020526040822054811115612e47565b9096506020813d6020116131bc575b816131a460209383612b6a565b81010312610283576131b590612c3d565b955f612e31565b3d9150613197565b816131ce91612b6a565b6131d957815f612e0a565b5080fd5b6131ea9192505f90612b6a565b5f905f612dc8565b90506020813d60201161321c575b8161320d60209383612b6a565b8101031261061e57515f612d93565b3d9150613200565b5050336001600160a01b03831603613248578285613243928833613393565b612d66565b60405162461bcd60e51b815260206004820152600760248201526610b1b0b63632b960c91b6044820152606490fd5b1561327e57565b60405162461bcd60e51b815260206004820152600660248201526510b0b236b4b760d11b6044820152606490fd5b156132b357565b60405162461bcd60e51b8152602060048201526006602482015265085d985b1a5960d21b6044820152606490fd5b60405163a9059cbb60e01b60208201526001600160a01b039290921660248301526044808301939093529181526133229161331d606483612b6a565b61365b565b565b60025f80516020613862833981519152541461334d5760025f8051602061386283398151915255565b633ee5aeb560e01b5f5260045ffd5b1561336357565b60405162461bcd60e51b81526020600482015260086024820152672162616c616e636560c01b6044820152606490fd5b5f54604051630723eb0360e51b81526001600160a01b0392831660048201819052969594939290911690602081602481855afa908115611efd575f91613526575b501591826134aa575b505015610750576001600160a01b039081165f8181526003602090815260408083209590941682529390935291205460ff16806134a1575b61341e906132ac565b604051926370a0823160e01b84526004840152602083602481845afa928315611efd575f9361346b575b506134588261332294101561335c565b5f52600660205260405f20541115612bcf565b92506020833d602011613499575b8161348660209383612b6a565b8101031261061e57915191613458613448565b3d9150613479565b50811515613415565b604051630723eb0360e51b81526001600160a01b0390911660048201529150602090829060249082905afa908115611efd575f916134ec575b50155f806133dd565b90506020813d60201161351e575b8161350760209383612b6a565b8101031261061e5761351890612b8c565b5f6134e3565b3d91506134fa565b90506020813d602011613558575b8161354160209383612b6a565b8101031261061e5761355290612b8c565b5f6133d4565b3d9150613534565b6001600160a01b03811615159081613576575090565b90503b151590565b9190820391821161358b57565b634e487b7160e01b5f52601160045260245ffd5b8181029291811591840414171561358b57565b81156135bc570490565b634e487b7160e01b5f52601260045260245ffd5b9081602091031261061e575160ff8116810361061e5790565b604d811161358b57600a0a90565b156135fe57565b60405162461bcd60e51b815260206004820152600a6024820152690859dd585c991c985a5b60b21b6044820152606490fd5b60ff5f805160206138828339815191525460401c161561364c57565b631afcd79f60e31b5f5260045ffd5b905f602091828151910182855af115611efd575f513d6136aa57506001600160a01b0381163b155b61368a5750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b60011415613683565b6040516338d52e0f60e01b81529290602090849060049082906001600160a01b03165afa928315611efd575f936137c2575b5060405163313ce56760e01b815292602090849060049082906001600160a01b03165afa918215611efd576004935f936137a0575b5060405163313ce56760e01b81529360209185919082906001600160a01b03165afa918215611efd57613769935f9361376c575b5061128761376392610d2060ff8094166135e9565b906135b2565b90565b60ff91935061376392610d20836137946112879460203d6020116111895761117a8183612b6a565b9694505050925061374e565b60209193506137bb90823d84116111895761117a8183612b6a565b929061371a565b92506020833d6020116137f9575b816137dd60209383612b6a565b8101031261061e5760206137f2600494612c3d565b93506136e5565b3d91506137d0565b91801561383a5761381f68056bc75e2d63100000916137699361359f565b6001549190049283916001600160a01b0390811691166132e1565b5050505f9056fedf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec429b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00b969104a5ca6b6a046dadc9ae57ddc551c935e514dd86d427f80403eb3b66722a2646970667358221220bed38d4b91aa6f63242598a656cc9fd5a9517c289078d8576b7b88ca6bc3b2eb64736f6c634300081a0033
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f803560e01c8063184b9559146128915780634cb4ec51146127855780634d537b691461268457806352c403d9146124e35780635403a228146124a6578063583ebbad1461239a57806361d027b31461237257806366026e1c1461233a578063674d6630146122e35780636ae4237a146120b35780636defd45514611c3b5780637378576614611af35780639e8250c914611981578063c24e477814611929578063c73f1bd014610b53578063df8089ef14610a1a578063e1e6b898146109f1578063e68507f3146108c2578063eb809ec414610889578063ed0ea2ff1461029a578063f0f4426014610193578063f53d0a8e1461016c5763fbcc776c14610117575f80fd5b34610169576040366003190112610169576040610132612a8c565b9161013b612aa2565b9260018060a01b031681526007602052209060018060a01b03165f52602052602060405f2054604051908152f35b80fd5b5034610169578060031936011261016957546040516001600160a01b039091168152602090f35b5034610169576020366003190112610169576101ad612a8c565b8154604051632474521560e21b81525f80516020613842833981519152600482015233602482015290602090829060449082906001600160a01b03165afa801561028f578390610250575b6102029150613277565b6001600160a01b03166102168115156132ac565b600180546001600160a01b03191682179055337f21eb548722a564f6e09f039f7aa858ae94c911910f3823b37af2250eeca4f4038380a380f35b506020813d602011610287575b8161026a60209383612b6a565b810103126102835761027e61020291612b8c565b6101f8565b8280fd5b3d915061025d565b6040513d85823e3d90fd5b50346101695760e0366003190112610169576102b4612a8c565b6102bc612aa2565b604435916102c8612afa565b926102d1612ace565b5060a43567ffffffffffffffff8111610885576102f2903690600401612b10565b50508454604051635b14f18360e01b815230600482015260c4359291602090829060249082906001600160a01b03165afa801561066857879061084a575b61033b915015612c08565b610343613324565b8554604051630723eb0360e51b81523360048201526001600160a01b0390911690602081602481855afa90811561083f578891610801575b50159081610783575b50156107505760018060a01b0383169283875260026020526040872060018060a01b0386165f5260205260ff60405f20541680610747575b6103c5906132ac565b604051636eb1769f60e11b81523360048201523060248201526001600160a01b03861695906020816044818a5afa80156106295784918a91610712575b50106106e0576040516370a0823160e01b8152336004820152906020826024818a5afa80156106295784928a916106a7575b50926104458361044a95101561335c565b6136b3565b604051906363737ac960e11b82526004820152602081602481875afa8015610668578790610673575b61048c9150848852600660205260408820541115612bcf565b6104c66040516323b872dd60e01b6020820152336024820152306044820152826064820152606481526104c0608482612b6a565b8561365b565b604051633ba0b9a960e01b815291602083600481875afa928315610668578793610634575b5061058660018060a01b0360055416926040519761050889612b4d565b600189523360208a01528760408a015260018060a01b038116988960608201528760808201528260a08201524260c08201528660e08201528a61010082015260209586926040516105598582612b6a565b8d8152610120840152866101408401528c604051809781958294638db63a4560e01b845260048401612c6d565b03925af19182156106295789926105e3575b50905f805160206138a28339815191529460c094939260405194338652850152600160408501526060840152608083015260a0820152a460015f805160206138628339815191525580f35b938093925084813d8311610622575b6105fc8183612b6a565b8101031261061e57925191929091905f805160206138a2833981519152610598565b5f80fd5b503d6105f2565b6040513d8b823e3d90fd5b9092506020813d602011610660575b8161065060209383612b6a565b8101031261061e5751915f6104eb565b3d9150610643565b6040513d89823e3d90fd5b506020813d60201161069f575b8161068d60209383612b6a565b8101031261061e5761048c9051610473565b3d9150610680565b9250506020823d6020116106d8575b816106c360209383612b6a565b8101031261061e579051839190610445610434565b3d91506106b6565b60405162461bcd60e51b815260206004820152600a60248201526921616c6c6f77616e636560b01b6044820152606490fd5b9150506020813d60201161073f575b8161072e60209383612b6a565b8101031261061e578390515f610402565b3d9150610721565b508115156103bc565b60405162461bcd60e51b815260206004820152600b60248201526a189b1858dadb1a5cdd195960aa1b6044820152606490fd5b604051630723eb0360e51b81526001600160a01b03881660048201529150602090829060249082905afa9081156106685787916107c3575b50155f610384565b90506020813d6020116107f9575b816107de60209383612b6a565b810103126107f5576107ef90612b8c565b5f6107bb565b8680fd5b3d91506107d1565b90506020813d602011610837575b8161081c60209383612b6a565b810103126108335761082d90612b8c565b5f61037b565b8780fd5b3d915061080f565b6040513d8a823e3d90fd5b506020813d60201161087d575b8161086460209383612b6a565b810103126107f55761087861033b91612b8c565b610330565b3d9150610857565b8580fd5b5034610169576020366003190112610169576020906040906001600160a01b036108b1612a8c565b168152600883522054604051908152f35b5034610169576020366003190112610169576108dc612a8c565b8154604051632474521560e21b81525f80516020613842833981519152600482015233602482015290602090829060449082906001600160a01b03165afa801561028f5783906109b6575b6109319150613277565b61093a81613560565b1561098657600580546001600160a01b0319166001600160a01b03929092169182179055337fc19bf1ec51bb24ae0bff17764e49ad5028e0e42feb2f24d17bcd8f7ee8e721aa8380a380f35b60405162461bcd60e51b8152602060048201526008602482015267085c9958d95a5c1d60c21b6044820152606490fd5b506020813d6020116109e9575b816109d060209383612b6a565b81010312610283576109e461093191612b8c565b610927565b3d91506109c3565b50346101695780600319360112610169576005546040516001600160a01b039091168152602090f35b503461016957602036600319011261016957610a34612a8c565b8154604051632474521560e21b81525f8051602061384283398151915260048201523360248201529091906020816044816001600160a01b0387165afa8015610b48578490610b09575b610a889150613277565b610a9181613560565b15610ad8576001600160a01b03166001600160a01b03199190911681178255337fbc5dab480bc3beb0582944eefba927e4358ed22805ac40b2078d517b8a036ae78380a380f35b60405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606490fd5b506020813d602011610b40575b81610b2360209383612b6a565b81010312610b3c57610b37610a8891612b8c565b610a7e565b8380fd5b3d9150610b16565b6040513d86823e3d90fd5b50346101695760803660031901126101695760043590602435906044359260643560018060a01b0383541694604051632474521560e21b81527f196445be8e29cb4e505699c67ec8eceb0187441d0913818e000a48d538545d1460048201523360248201526020816044818a5afa9081156118915785916118e0575b50602496610bde602092612b99565b604051635b14f18360e01b815230600482015297889182905afa958615610b4857849661189c575b50610c15602494959615612c08565b610c1d613324565b60055460405163e04f10b560e01b81526004810185905294869186919082906001600160a01b03165afa938415611891578594611753575b5060c0840151421061171d57670de0b6b3a764000081116116f25783511561119b57608084019160018060a01b038351169160408601916004610ca960018060a01b038551169560a08a01968751916136b3565b865160405163313ce56760e01b81529260209184919082906001600160a01b03165afa918215611190578a9261115c575b508651604051633ba0b9a960e01b81529190602090839060049082906001600160a01b03165afa918215611151578b9261111b575b50610d2060ff610d269394166135e9565b9061359f565b90610d3760e08a01928351906135b2565b87516001600160a01b039081168c52600760209081526040808e2089519093165f9081529290915290205490606482810390811161110757610d7b6064918361359f565b04916064019081606411611107578c9d610db4610dc1946064610da28896610dbc9661359f565b049083101590816110fc575b506135f7565b85519061359f565b6135b2565b936024602060018060a01b038a5116604051928380926303d1689d60e11b82528a60048301525afa90811561109f578c916110c7575b5088516001600160a01b031690813b156110c3578c9160448392604051948593849263aa21161f60e01b84526004840152600160248401525af190811561109f578c916110ae575b505087516001600160a01b0316803b156110aa578b8091606460405180948193637bbde4a560e01b83523060048401528b6024840152600160448401525af1801561109f5789918d91611082575b505094610ef9610ee0610f7194610dbc610ed6610efe96867f6d9e3887d4874fde4dadb9d1d055309b33b01e76dda88080ffb5fc966bd0e7bc9c60018060a01b03905116613801565b988998519061359f565b958692610ef9848d339060018060a01b039051166132e1565b61357e565b9260018060a01b0388511692610f238560608d019560018060a01b03875116906132e1565b60208b8101519751985194519951604080519687526001600160a01b0391821692870192909252908501959095526060840152608083015295821695948216949390911692819060a0820190565b0390a45b6005546001600160a01b031690813b1561107d578391602483926040519485938492630852cd8d60e31b845260048401525af190811561028f578391611065575b50506101008101516001600160a01b031680610fe2575b8260015f805160206138628339815191525580f35b610120839201519082602083519301915af13d15611060573d61100481612c51565b906110126040519283612b6a565b81528260203d92013e5b1561102957805f80610fcd565b60405162461bcd60e51b815260206004820152600f60248201526e18d85b1b189858dac819985a5b1959608a1b6044820152606490fd5b61101c565b8161106f91612b6a565b61107a57815f610fb6565b50fd5b505050fd5b8192509061108f91612b6a565b61109b57878b5f610e8d565b8a80fd5b6040513d8e823e3d90fd5b8b80fd5b816110b891612b6a565b61109b578a5f610e3f565b8c80fd5b9b505060208b3d6020116110f4575b816110e360209383612b6a565b8101031261061e578b9a515f610df7565b3d91506110d6565b90508211155f610dae565b634e487b7160e01b8d52601160045260248dfd5b91506020823d602011611149575b8161113660209383612b6a565b8101031261061e57905190610d20610d0f565b3d9150611129565b6040513d8d823e3d90fd5b60049192506111829060203d602011611189575b61117a8183612b6a565b8101906135d0565b9190610cda565b503d611170565b6040513d8c823e3d90fd5b9490604084016024602060018060a01b03835116604051928380926370a0823160e01b82523060048301525afa9081156106685790849188916116bd575b501061168857608085019260018060a01b038451169060a08701519061121d611202868461357e565b68056bc75e2d631000006112168d8361359f565b049061357e565b946040519a63313ce56760e01b8c5260208c600481885afa9b8c15611151578b9c611667575b50604051633ba0b9a960e01b81529b60208d600481895afa9c8d1561109f578c9d611631575b5061128e90610d2060ff6112878760018060a01b038c51168b6136b3565b92166135e9565b9661129f60e08c01988951906135b2565b60018060a01b038a51168d52600760205260408d2060018060a01b0389511660018060a01b03165f5260205260405f205490816064036064811161161d576112e96064918361359f565b0491606401908160641161161d579e8e9f68056bc75e2d63100000611340839761133a610dbc986113519b9860646113276113499a610dbc9961359f565b04908210159182611612575b50506135f7565b8b61359f565b048c519061359f565b98519061359f565b926040516303d1689d60e11b8152866004820152602081602481855afa908115611151578b916115dd575b506040516303d1689d60e11b81526004810186905290602082602481865afa91821561109f578c926115a6575b50823b156110aa576040519063aa21161f60e01b82526004820152600160248201528b8160448183875af190811561109f578c91611591575b50506001546001600160a01b0316823b156110aa5760405190637bbde4a560e01b82526004820152876024820152600160448201528b8160648183875af190811561109f578c9161157c575b5050813b1561109b576040519063aa21161f60e01b82526004820152600160248201528a8160448183865af1908115611151578b91611567575b5050803b1561156357898091606460405180948193637bbde4a560e01b8352336004840152896024840152600160448401525af1908115611190578a9161154a575b5050835160608901805190967f82ca45f66e5ec57290dc1fa286f58cd0c9769079a69574cacfd5d3f6ba68982a956115429390926114f69186916001600160a01b0390811691166132e1565b60208b810151975198519951604080519687526001600160a01b0391821692870192909252908501959095526060840152608083015295821695948216949390911692819060a0820190565b0390a4610f75565b8161155491612b6a565b61155f57885f6114aa565b8880fd5b8980fd5b8161157191612b6a565b61156357895f611468565b8161158691612b6a565b61109b578a5f61142e565b8161159b91612b6a565b61109b578a5f6113e2565b9b50905060208b3d6020116115d5575b816115c360209383612b6a565b8101031261061e578b9a51905f6113a9565b3d91506115b6565b9a505060208a3d60201161160a575b816115f960209383612b6a565b8101031261061e578a99515f61137c565b3d91506115ec565b111590505f80611333565b634e487b7160e01b8f52601160045260248ffd5b909c506020813d60201161165f575b8161164d60209383612b6a565b8101031261061e57519b61128e611269565b3d9150611640565b611681919c5060203d6020116111895761117a8183612b6a565b9a5f611243565b60405162461bcd60e51b815260206004820152600d60248201526c21617373657442616c616e636560981b6044820152606490fd5b9150506020813d6020116116ea575b816116d960209383612b6a565b8101031261061e578390515f6111d9565b3d91506116cc565b606460405162461bcd60e51b81526020600482015260046024820152632166656560e01b6044820152fd5b60405162461bcd60e51b815260206004820152600e60248201526d085dd85a5d1a5b99d4195c9a5bd960921b6044820152606490fd5b9093503d8086833e6117658183612b6a565b8101906020818303126108855780519067ffffffffffffffff82116107f5570161016081830312610885576040519161179d83612b4d565b6117a682612b8c565b83526117b460208301612c3d565b60208401526117c560408301612c3d565b60408401526117d660608301612c3d565b60608401526117e760808301612c3d565b608084015260a082015160a084015260c082015160c084015260e082015160e08401526118176101008301612c3d565b61010084015261012082015167ffffffffffffffff811161083357820181601f820112156108335780519061184b82612c51565b926118596040519485612b6a565b8284526020838301011161155f57602082610140959493828c94018386015e830101526101208401520151610140820152925f610c55565b6040513d87823e3d90fd5b95506020863d6020116118d8575b816118b760209383612b6a565b81010312610b3c57610c156118cf6024959697612b8c565b96959450610c06565b3d91506118aa565b90506020813d602011611921575b816118fb60209383612b6a565b8101031261191d57602496610bde611914602093612b8c565b92505096610bcf565b8480fd5b3d91506118ee565b5034610169576040366003190112610169576040611945612a8c565b9161194e612aa2565b9260018060a01b031681526003602052209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b50346101695760803660031901126101695761199b612a8c565b6119a3612aa2565b906119ac612afa565b8354604051632474521560e21b81527f3812cb515c4c47772b5b6b50b84b6a856abab98cf24bcfb67a83510fb661c133600482015233602482015291929190602090829060449082906001600160a01b03165afa908115611891578591611ab9575b5015611a8c5760018060a01b0316835260036020526040832060018060a01b0382165f5260205260ff60405f20541615611a5b57611a5891604435916001600160a01b03166132e1565b80f35b60405162461bcd60e51b815260206004820152600960248201526821776974686472617760b81b6044820152606490fd5b60405162461bcd60e51b815260206004820152600560248201526408589bdb9960da1b6044820152606490fd5b90506020813d602011611aeb575b81611ad460209383612b6a565b8101031261191d57611ae590612b8c565b5f611a0e565b3d9150611ac7565b503461016957604036600319011261016957611b0d612a8c565b6024359081151590818303610b3c578354604051632474521560e21b81525f80516020613842833981519152600482015233602482015290602090829060449082906001600160a01b03165afa8015611891578590611c00575b611b719150613277565b6001600160a01b0316918215611bd157611ba2908385526004602052604085209060ff801983541691151516179055565b6040519081527f4d838617e2f838c1ab5ced341702d2ce1f6f36052b7b061794cc86012a17a26c60203392a380f35b60405162461bcd60e51b8152602060048201526007602482015266085dd85b1b195d60ca1b6044820152606490fd5b506020813d602011611c33575b81611c1a60209383612b6a565b8101031261191d57611c2e611b7191612b8c565b611b67565b3d9150611c0d565b503461061e5760e036600319011261061e57611c55612a8c565b60c036602319011261061e576040519060c0820182811067ffffffffffffffff82111761209f57604052611c87612aa2565b82526020820191604435835260408101916064358352611ca5612b3e565b916060810192835260a43590811515820361061e576080810191825260c43592831515840361061e5760a082019384525f54604051632474521560e21b81527f08fb31c3e81624356c3314088aa971b73bcc82d22bc3e3b184b4593077ae32786004820152336024820152906001600160a01b0316602082604481845afa918215611efd575f92612063575b508115611fcf575b8115611f39575b5015611f085787908551611e99575b835115611e2d57825188518651151592916001600160a01b0316803b1561191d578492836064926040519687958694637bbde4a560e01b865260018060a01b03166004860152602485015260448401525af18015611e2257611e0d575b50505b60018060a01b03905116945193519251151590511515915115159260405194855260208501526040840152606083015260808201527f1516f6e8af7338a5166f6c531effb2edb3d0f2f37c72c5c06b87618943e7a2ce60a03392a380f35b81611e1791612b6a565b6107f557865f611dac565b6040513d84823e3d90fd5b60018060a01b03835116908851823b15610b3c5760405163eeb8618d60e01b81526001600160a01b0392909216600483015260248201529082908290604490829084905af18015611e2257611e84575b5050611daf565b81611e8e91612b6a565b6107f557865f611e7d565b905060018060a01b03825116865184511515823b1561061e5760445f9283604051958694859363aa21161f60e01b8552600485015260248401525af18015611efd57611ee8575b508790611d4f565b611ef59198505f90612b6a565b5f965f611ee0565b6040513d5f823e3d90fd5b60405162461bcd60e51b815260206004820152600960248201526810b7b832b930ba37b960b91b6044820152606490fd5b604051632474521560e21b81527faeed4774a6ca7dc9eef4423038c2a3abe132048336feddd81b2e9a5e941eb77760048201523360248201529150602090829060449082905afa908115611efd575f91611f95575b505f611d40565b90506020813d602011611fc7575b81611fb060209383612b6a565b8101031261061e57611fc190612b8c565b5f611f8e565b3d9150611fa3565b604051632474521560e21b81527f0f2a9aa9ac2639d8d73bfa84d0682d3e88d5f473437d4e7c341378f9bbebddbd6004820152336024820152909150602081604481855afa908115611efd575f91612029575b5090611d39565b90506020813d60201161205b575b8161204460209383612b6a565b8101031261061e5761205590612b8c565b5f612022565b3d9150612037565b9091506020813d602011612097575b8161207f60209383612b6a565b8101031261061e5761209090612b8c565b905f611d31565b3d9150612072565b634e487b7160e01b5f52604160045260245ffd5b3461061e5760a036600319011261061e576004358015159081810361061e576120da612aa2565b916120e3612ab8565b92606435926120f0612b3e565b5f54604051632474521560e21b81525f80516020613842833981519152600482015233602482015291969190602090829060449082906001600160a01b03165afa8015611efd575f906122a8575b6121489150613277565b61215181613560565b80612299575b156122635760648511612227577f3176f2587b9045e51587a9fcfe247898e237bc0417f5c1ae3220072b422e093d92602092156121f2576001600160a01b038181165f908152600285526040808220928516825291855220805460ff191660ff891515161790555b6001600160a01b039081165f818152600785526040808220949093168082529385528290209690965551951515865294a4005b6001600160a01b038181165f908152600385526040808220928516825291855220805460ff191660ff891515161790556121bf565b60405162461bcd60e51b81526020600482015260146024820152732167756172647261696c50657263656e7461676560601b6044820152606490fd5b60405162461bcd60e51b815260206004820152600e60248201526d10b0b9b9b2ba1010bcaa37b5b2b760911b6044820152606490fd5b506122a383613560565b612157565b506020813d6020116122db575b816122c260209383612b6a565b8101031261061e576122d661214891612b8c565b61213e565b3d91506122b5565b3461061e57604036600319011261061e576122fc612a8c565b612304612aa2565b9060018060a01b03165f52600260205260405f209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b3461061e57602036600319011261061e576001600160a01b0361235b612a8c565b165f526006602052602060405f2054604051908152f35b3461061e575f36600319011261061e576001546040516001600160a01b039091168152602090f35b3461061e5760e036600319011261061e576123b3612a8c565b6123bb612aa2565b906123c4612ab8565b906123cd612ace565b916123d6612ae4565b5060c4359367ffffffffffffffff851161061e576123fa6024953690600401612b10565b50505f54604051635b14f18360e01b81523060048201529560209187919082906001600160a01b03165afa948515611efd575f95612465575b506124416124529515612c08565b612449613324565b60643592612d43565b60015f8051602061386283398151915255005b94506020853d60201161249e575b8161248060209383612b6a565b8101031261061e5761244161249761245296612b8c565b9550612433565b3d9150612473565b3461061e57602036600319011261061e576001600160a01b036124c7612a8c565b165f526004602052602060ff60405f2054166040519015158152f35b3461061e57606036600319011261061e576124fc612a8c565b612504612aa2565b5f54604051632474521560e21b81527f413cc8bb35fe129dacd3dfaae80d6d4c5d313f64cee9dd6712e7ca52e38573a96004820152336024820152604480359392602091839182906001600160a01b03165afa908115611efd575f9161264a575b501561261d576001600160a01b03811680151580612614575b156125db575f52600460205260ff60405f205416156125ab576125a9926001600160a01b03166132e1565b005b60405162461bcd60e51b815260206004820152600860248201526721637573746f647960c01b6044820152606490fd5b60405162461bcd60e51b8152602060048201526011602482015270085c9958d95a5d995c8808585b5bdd5b9d607a1b6044820152606490fd5b5082151561257e565b60405162461bcd60e51b815260206004820152600560248201526410b1b6b3b960d91b6044820152606490fd5b90506020813d60201161267c575b8161266560209383612b6a565b8101031261061e5761267690612b8c565b84612565565b3d9150612658565b3461061e57604036600319011261061e5761269d612a8c565b602435906044602060018060a01b035f541660405192838092632474521560e21b82527f196445be8e29cb4e505699c67ec8eceb0187441d0913818e000a48d538545d1460048301523360248301525afa8015611efd575f9061274a575b6127059150612b99565b60018060a01b031690815f5260086020528060405f20556040519081527f9b5f7fd7d8f1ef48cef00c8a6e22104d55bcdcf2e7bde42fa59dc04660296bb860203392a3005b506020813d60201161277d575b8161276460209383612b6a565b8101031261061e5761277861270591612b8c565b6126fb565b3d9150612757565b3461061e57604036600319011261061e5761279e612a8c565b602435906044602060018060a01b035f541660405192838092632474521560e21b82527f196445be8e29cb4e505699c67ec8eceb0187441d0913818e000a48d538545d1460048301523360248301525afa8015611efd575f90612856575b6128069150612b99565b612811821515612bcf565b60018060a01b031690815f5260066020528060405f20556040519081527f3d159f9ca709b98fbe13933da954dc4650e8387642a88226d601fff8b3158bbb60203392a3005b506020813d602011612889575b8161287060209383612b6a565b8101031261061e5761288461280691612b8c565b6127fc565b3d9150612863565b3461061e57606036600319011261061e576128aa612a8c565b6128b2612aa2565b6128ba612ab8565b905f80516020613882833981519152549260ff8460401c16159367ffffffffffffffff811680159081612a84575b6001149081612a7a575b159081612a71575b50612a625767ffffffffffffffff1981166001175f805160206138828339815191525584612a36575b5061292c613630565b612934613630565b61293c613630565b60015f80516020613862833981519152556001600160a01b03168015612a00576001600160601b0360a01b5f5416175f5560018060a01b03166001600160601b0360a01b600154161760015560018060a01b03166001600160601b0360a01b60055416176005556129a957005b68ff0000000000000000195f8051602061388283398151915254165f80516020613882833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b60405162461bcd60e51b815260206004820152600e60248201526d10b0b236b4b734b9ba3930ba37b960911b6044820152606490fd5b68ffffffffffffffffff191668010000000000000001175f805160206138828339815191525584612923565b63f92ee8a960e01b5f5260045ffd5b905015866128fa565b303b1591506128f2565b8691506128e8565b600435906001600160a01b038216820361061e57565b602435906001600160a01b038216820361061e57565b604435906001600160a01b038216820361061e57565b608435906001600160a01b038216820361061e57565b60a435906001600160a01b038216820361061e57565b606435906001600160a01b038216820361061e57565b9181601f8401121561061e5782359167ffffffffffffffff831161061e576020838186019501011161061e57565b60843590811515820361061e57565b610160810190811067ffffffffffffffff82111761209f57604052565b90601f8019910116810190811067ffffffffffffffff82111761209f57604052565b5190811515820361061e57565b15612ba057565b60405162461bcd60e51b815260206004820152600760248201526610b6b4b73a32b960c91b6044820152606490fd5b15612bd657565b60405162461bcd60e51b815260206004820152600a602482015269216d696e53686172657360b01b6044820152606490fd5b15612c0f57565b60405162461bcd60e51b81526020600482015260066024820152651c185d5cd95960d21b6044820152606490fd5b51906001600160a01b038216820361061e57565b67ffffffffffffffff811161209f57601f01601f191660200190565b906101406101c09360209260018060a01b0316845260408385015280511515604085015260018060a01b038382015116606085015260018060a01b03604082015116608085015260018060a01b0360608201511660a085015260018060a01b0360808201511660c085015260a081015160e085015260c081015161010085015260e081015161012085015260018060a01b036101008201511682850152610120810151610160808601528051938491826101a0880152018686015e5f8484018601520151610180830152601f01601f1916010190565b91926001600160a01b038216929091828533860361322457612d66928885613393565b6040516303d1689d60e11b8152600481018390525f90602081602481885afa908115611efd575f916131f2575b50843b1561061e5760405163aa21161f60e01b81528160048201525f60248201525f81604481838a5af18015611efd576131dd575b50843b156131d95760405163eeb8618d60e01b81526001600160a01b0384166004820152602481018590528281604481838a5af1801561028f579083916131c4575b50506040516338d52e0f60e01b815295602087600481895afa96871561028f578397613188575b506001600160a01b039081169616861480613172575b80613107575b6130b557506040516370a0823160e01b81526001600160a01b039092166004830181905291602081602481885afa908115611e22578291613083575b50801590811561306c575b501561302757604051633ba0b9a960e01b815290602082600481885afa90811561301b578091612fe5575b612f59925060018060a01b036005541660405198612edc8a612b4d565b828a528560208b01528860408b015260018060a01b038116998a60608201528860808201528760a08201524260c08201528460e0820152836101008201526020928392604051612f2c8582612b6a565b8681526101208401528561014084015285604051809981958294638db63a4560e01b845260048401612c6d565b03925af1938415611e22578294612fa3575b50905f805160206138a28339815191529560c0959493926040519586528501526040840152606083015260808201525f60a0820152a4565b94935091908285813d8311612fde575b612fbd8183612b6a565b8101031261061e579351929390915f805160206138a2833981519152612f6b565b503d612fb3565b90506020823d602011613013575b8161300060209383612b6a565b8101031261061e57612f59915190612ebf565b3d9150612ff3565b604051903d90823e3d90fd5b60405162461bcd60e51b815260206004820152601f60248201527f30203c2072656d61696e696e67536861726573203c206d696e536861726573006044820152606490fd5b90508482526006602052604082205411155f612e94565b90506020813d6020116130ad575b8161309e60209383612b6a565b8101031261061e57515f612e89565b3d9150613091565b919590507ff64213ec57f9a9ee68c3166cd3208c68fd79e273eb082be31374e9792caac54092506130e78282876132e1565b604080516001600160a01b039788168152602081019390935295169490a4565b506040516370a0823160e01b81523060048201526020816024818a5afa90811561028f57908291849161313d575b501015612e4d565b9150506020813d60201161316a575b8161315960209383612b6a565b8101031261061e578190515f613135565b3d915061314c565b5084825260086020526040822054811115612e47565b9096506020813d6020116131bc575b816131a460209383612b6a565b81010312610283576131b590612c3d565b955f612e31565b3d9150613197565b816131ce91612b6a565b6131d957815f612e0a565b5080fd5b6131ea9192505f90612b6a565b5f905f612dc8565b90506020813d60201161321c575b8161320d60209383612b6a565b8101031261061e57515f612d93565b3d9150613200565b5050336001600160a01b03831603613248578285613243928833613393565b612d66565b60405162461bcd60e51b815260206004820152600760248201526610b1b0b63632b960c91b6044820152606490fd5b1561327e57565b60405162461bcd60e51b815260206004820152600660248201526510b0b236b4b760d11b6044820152606490fd5b156132b357565b60405162461bcd60e51b8152602060048201526006602482015265085d985b1a5960d21b6044820152606490fd5b60405163a9059cbb60e01b60208201526001600160a01b039290921660248301526044808301939093529181526133229161331d606483612b6a565b61365b565b565b60025f80516020613862833981519152541461334d5760025f8051602061386283398151915255565b633ee5aeb560e01b5f5260045ffd5b1561336357565b60405162461bcd60e51b81526020600482015260086024820152672162616c616e636560c01b6044820152606490fd5b5f54604051630723eb0360e51b81526001600160a01b0392831660048201819052969594939290911690602081602481855afa908115611efd575f91613526575b501591826134aa575b505015610750576001600160a01b039081165f8181526003602090815260408083209590941682529390935291205460ff16806134a1575b61341e906132ac565b604051926370a0823160e01b84526004840152602083602481845afa928315611efd575f9361346b575b506134588261332294101561335c565b5f52600660205260405f20541115612bcf565b92506020833d602011613499575b8161348660209383612b6a565b8101031261061e57915191613458613448565b3d9150613479565b50811515613415565b604051630723eb0360e51b81526001600160a01b0390911660048201529150602090829060249082905afa908115611efd575f916134ec575b50155f806133dd565b90506020813d60201161351e575b8161350760209383612b6a565b8101031261061e5761351890612b8c565b5f6134e3565b3d91506134fa565b90506020813d602011613558575b8161354160209383612b6a565b8101031261061e5761355290612b8c565b5f6133d4565b3d9150613534565b6001600160a01b03811615159081613576575090565b90503b151590565b9190820391821161358b57565b634e487b7160e01b5f52601160045260245ffd5b8181029291811591840414171561358b57565b81156135bc570490565b634e487b7160e01b5f52601260045260245ffd5b9081602091031261061e575160ff8116810361061e5790565b604d811161358b57600a0a90565b156135fe57565b60405162461bcd60e51b815260206004820152600a6024820152690859dd585c991c985a5b60b21b6044820152606490fd5b60ff5f805160206138828339815191525460401c161561364c57565b631afcd79f60e31b5f5260045ffd5b905f602091828151910182855af115611efd575f513d6136aa57506001600160a01b0381163b155b61368a5750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b60011415613683565b6040516338d52e0f60e01b81529290602090849060049082906001600160a01b03165afa928315611efd575f936137c2575b5060405163313ce56760e01b815292602090849060049082906001600160a01b03165afa918215611efd576004935f936137a0575b5060405163313ce56760e01b81529360209185919082906001600160a01b03165afa918215611efd57613769935f9361376c575b5061128761376392610d2060ff8094166135e9565b906135b2565b90565b60ff91935061376392610d20836137946112879460203d6020116111895761117a8183612b6a565b9694505050925061374e565b60209193506137bb90823d84116111895761117a8183612b6a565b929061371a565b92506020833d6020116137f9575b816137dd60209383612b6a565b8101031261061e5760206137f2600494612c3d565b93506136e5565b3d91506137d0565b91801561383a5761381f68056bc75e2d63100000916137699361359f565b6001549190049283916001600160a01b0390811691166132e1565b5050505f9056fedf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec429b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00b969104a5ca6b6a046dadc9ae57ddc551c935e514dd86d427f80403eb3b66722a2646970667358221220bed38d4b91aa6f63242598a656cc9fd5a9517c289078d8576b7b88ca6bc3b2eb64736f6c634300081a0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.