Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
ERC4626Facet_EL_E2
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {ERC4626Facet_EL} from "./ERC4626Facet_EL.sol"; /** * @title The ERC4626Facet_EL_E2 contract * @author The InceptionLRT team */ contract ERC4626Facet_EL_E2 is ERC4626Facet_EL { constructor() payable {} function _getAssetWithdrawAmount( uint256 amount ) internal pure override returns (uint256) { return amount + 2; } function _getAssetReceivedAmount( uint256 amount ) internal pure override returns (uint256) { return amount - 2; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```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 Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; 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 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; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol) pragma solidity ^0.8.0; import "./IBeacon.sol"; import "../Proxy.sol"; import "../ERC1967/ERC1967Upgrade.sol"; /** * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. * * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't * conflict with the storage layout of the implementation behind the proxy. * * _Available since v3.4._ */ contract BeaconProxy is Proxy, ERC1967Upgrade { /** * @dev Initializes the proxy with `beacon`. * * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity * constructor. * * Requirements: * * - `beacon` must be a contract with the interface {IBeacon}. */ constructor(address beacon, bytes memory data) payable { _upgradeBeaconToAndCall(beacon, data, false); } /** * @dev Returns the current beacon address. */ function _beacon() internal view virtual returns (address) { return _getBeacon(); } /** * @dev Returns the current implementation address of the associated beacon. */ function _implementation() internal view virtual override returns (address) { return IBeacon(_getBeacon()).implementation(); } /** * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}. * * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. * * Requirements: * * - `beacon` must be a contract. * - The implementation returned by `beacon` must be a contract. */ function _setBeacon(address beacon, bytes memory data) internal virtual { _upgradeBeaconToAndCall(beacon, data, false); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) pragma solidity ^0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _fallback() internal virtual { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive() external payable virtual { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overridden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IInceptionRatioFeed { function getRatioFor(address) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IInceptionToken { event VaultChanged(address prevValue, address newValue); event Paused(address account); event Unpaused(address account); function mint(address account, uint256 amount) external; function burn(address account, uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IInceptionVaultErrors { error ExceededMaxMint(address receiver, uint256 shares, uint256 maxShares); error MsgSenderIsNotOwner(); error FunctionNotSupported(); error TransferAssetFailed(address assetAddress); error TransferAssetFromFailed(address assetAddress); error InsufficientCapacity(uint256 capacity); error InvalidTargetFlashCapacity(); error InceptionOnPause(); error InconsistentData(); error ApproveError(); error NullParams(); error ParameterExceedsLimits(uint256 param); error NotContract(); error DepositInconsistentResultedState(); error OperatorNotRegistered(); error RestakerNotRegistered(); error ImplementationNotSet(); error OnlyOperatorAllowed(); error AlreadyDelegated(); error DelegationManagerImmutable(); error IsNotAbleToRedeem(); error LowerMinAmount(uint256 minAmount); error ZeroFlashWithdrawFee(); /// TVL errors error ExceedsMaxPerDeposit(uint256 max, uint256 amount); error ExceedsMaxTotalDeposited(uint256 max, uint256 amount); /// EigenLayer Operators error NotEigenLayerOperator(); error EigenLayerOperatorAlreadyExists(); error TimelineNotOver(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IOwnable { function transferOwnership(address newOwner) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "./IStrategy.sol"; interface IDelegationManager { // @notice Struct that bundles together a signature and an expiration time for the signature. Used primarily for stack management. struct SignatureWithExpiry { // the signature itself, formatted as a single bytes object bytes signature; // the expiration timestamp (UTC) of the signature uint256 expiry; } // @notice Struct that bundles together a signature, a salt for uniqueness, and an expiration time for the signature. Used primarily for stack management. struct SignatureWithSaltAndExpiry { // the signature itself, formatted as a single bytes object bytes signature; // the salt used to generate the signature bytes32 salt; // the expiration timestamp (UTC) of the signature uint256 expiry; } struct QueuedWithdrawalParams { // Array of strategies that the QueuedWithdrawal contains IStrategy[] strategies; // Array containing the amount of shares in each Strategy in the `strategies` array uint256[] shares; // The address of the withdrawer address withdrawer; } struct Withdrawal { // The address that originated the Withdrawal address staker; // The address that the staker was delegated to at the time that the Withdrawal was created address delegatedTo; // The address that can complete the Withdrawal + will receive funds when completing the withdrawal address withdrawer; // Nonce used to guarantee that otherwise identical withdrawals have unique hashes uint256 nonce; // Block number when the Withdrawal was created uint32 startBlock; // Array of strategies that the Withdrawal contains IStrategy[] strategies; // Array containing the amount of shares in each Strategy in the `strategies` array uint256[] shares; } function delegateTo( address operator, SignatureWithExpiry memory approverSignatureAndExpiry, bytes32 approverSalt ) external; function undelegate(address staker) external; event WithdrawalQueued(bytes32 withdrawalRoot, Withdrawal withdrawal); function completeQueuedWithdrawal( Withdrawal calldata withdrawal, IERC20[] calldata tokens, uint256 middlewareTimesIndex, bool receiveAsTokens ) external; function completeQueuedWithdrawals( Withdrawal[] calldata withdrawals, IERC20[][] calldata tokens, uint256[] calldata middlewareTimesIndexes, bool[] calldata receiveAsTokens ) external; function queueWithdrawals( QueuedWithdrawalParams[] calldata queuedWithdrawalParams ) external returns (bytes32[] memory); function delegatedTo(address staker) external view returns (address); function operatorShares( address operator, address strategy ) external view returns (uint256); function cumulativeWithdrawalsQueued( address staker ) external view returns (uint256); function withdrawalDelayBlocks() external view returns (uint256); function isOperator(address operator) external view returns (bool); function isDelegated(address staker) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IStrategy { function deposit(IERC20 token, uint256 amount) external returns (uint256); function withdraw( address depositor, IERC20 token, uint256 amountShares ) external; function sharesToUnderlying( uint256 amountShares ) external returns (uint256); function underlyingToShares( uint256 amountUnderlying ) external returns (uint256); function userUnderlying(address user) external returns (uint256); function sharesToUnderlyingView( uint256 amountShares ) external view returns (uint256); function underlyingToSharesView( uint256 amountUnderlying ) external view returns (uint256); /** * @notice convenience function for fetching the current underlying value of all of the `user`'s shares in * this strategy. In contrast to `userUnderlying`, this function guarantees no state modifications */ function userUnderlyingView(address user) external view returns (uint256); /// @notice The underlying token for shares in this Strategy function underlyingToken() external view returns (IERC20); /// @notice The total number of extant shares in this Strategy function totalShares() external view returns (uint256); /// @notice Returns either a brief string explaining the strategy's goal & purpose, or a link to metadata that explains in more detail. function explanation() external view returns (string memory); /// @notice Simple getter function that returns the current values of `maxPerDeposit` and `maxTotalDeposits`. function getTVLLimits() external view returns (uint256, uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "./IStrategy.sol"; interface IStrategyManager { struct WithdrawerAndNonce { address withdrawer; uint96 nonce; } struct QueuedWithdrawal { IStrategy[] strategies; uint256[] shares; address depositor; WithdrawerAndNonce withdrawerAndNonce; uint32 withdrawalStartBlock; address delegatedAddress; } function withdrawalRootPending(bytes32) external returns (bool); function depositIntoStrategy( IStrategy strategy, IERC20 token, uint256 amount ) external returns (uint256 shares); function stakerStrategyShares( address user, IStrategy strategy ) external view returns (uint256 shares); function getDeposits( address depositor ) external view returns (IStrategy[] memory, uint256[] memory); function stakerStrategyListLength( address staker ) external view returns (uint256); function queueWithdrawal( uint256[] calldata strategyIndexes, IStrategy[] calldata strategies, uint256[] calldata shares, address withdrawer, bool undelegateIfPossible ) external returns (bytes32); function completeQueuedWithdrawal( QueuedWithdrawal calldata queuedWithdrawal, IERC20[] calldata tokens, uint256 middlewareTimesIndex, bool receiveAsTokens ) external; function completeQueuedWithdrawals( QueuedWithdrawal[] calldata queuedWithdrawals, IERC20[][] calldata tokens, uint256[] calldata middlewareTimesIndexes, bool[] calldata receiveAsTokens ) external; function slashShares( address slashedAddress, address recipient, IStrategy[] calldata strategies, IERC20[] calldata tokens, uint256[] calldata strategyIndexes, uint256[] calldata shareAmounts ) external; function slashQueuedWithdrawal( address recipient, QueuedWithdrawal calldata queuedWithdrawal, IERC20[] calldata tokens, uint256[] calldata indicesToSkip ) external; function calculateWithdrawalRoot( QueuedWithdrawal memory queuedWithdrawal ) external pure returns (bytes32); function addStrategiesToDepositWhitelist( IStrategy[] calldata strategiesToWhitelist ) external; function removeStrategiesFromDepositWhitelist( IStrategy[] calldata strategiesToRemoveFromWhitelist ) external; function withdrawalDelayBlocks() external view returns (uint256); function numWithdrawalsQueued( address account ) external view returns (uint256); function delegation() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IDelegationManager, IStrategy, IERC20} from "./eigen-core/IDelegationManager.sol"; interface IInceptionEigenRestakerErrors { error OnlyTrusteeAllowed(); error InconsistentData(); error WrongClaimWithdrawalParams(); error NullParams(); } interface IInceptionEigenRestaker { event StartWithdrawal( address indexed stakerAddress, bytes32 withdrawalRoot, IStrategy[] strategies, uint256[] shares, uint32 withdrawalStartBlock, address delegatedAddress, uint256 nonce ); event Withdrawal( bytes32 withdrawalRoot, IStrategy[] strategies, uint256[] shares, uint32 withdrawalStartBlock ); event RewardCoordinatorChanged( address indexed prevValue, address indexed newValue ); function depositAssetIntoStrategy(uint256 amount) external; function delegateToOperator( address operator, bytes32 approverSalt, IDelegationManager.SignatureWithExpiry memory approverSignatureAndExpiry ) external; function withdrawFromEL(uint256 shares) external; function claimWithdrawals( IDelegationManager.Withdrawal[] calldata withdrawals, IERC20[][] calldata tokens, uint256[] calldata middlewareTimesIndexes, bool[] calldata receiveAsTokens ) external returns (uint256); function setRewardsCoordinator(address newRewardCoordinator) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IStrategyManager, IStrategy} from "./eigen-core/IStrategyManager.sol"; import {IInceptionToken} from "../common/IInceptionToken.sol"; interface IInceptionVault_EL { /*///////////////////////////////////////////////////////////////////// ///////////////////////////// Structures ///////////////////////////// ///////////////////////////////////////////////////////////////////*/ enum FuncTarget { SETTER_FACET, EIGEN_LAYER_FACET, ERC4626_FACET } enum FuncAccess { EVERYONE, ONLY_OPERATOR, ONLY_OWNER } struct FuncData { FuncTarget facet; FuncAccess access; } /** * @dev Epoch represents the period of the rebalancing process * @dev Receiver is a receiver of assets in claim() * @dev Amount represents the exact amount of the asset to be claimed */ struct Withdrawal { uint256 epoch; address receiver; uint256 amount; } /*///////////////////////////////////////////////////////////////////// /////////////////////////////// Events /////////////////////////////// ///////////////////////////////////////////////////////////////////*/ event StartWithdrawal( address indexed stakerAddress, IStrategy strategy, uint256 shares, uint32 withdrawalStartBlock, address delegatedAddress, uint256 nonce ); event DepositedToEL(address indexed stakerAddress, uint256 amount); event DelegatedTo( address indexed stakerAddress, address indexed operatorAddress, uint256 amount ); event WithdrawalClaimed(uint256 totalAmount); event DelegationManagerChanged(address prevValue, address newValue); event TargetCapacityChanged(uint256 prevValue, uint256 newValue); event Deposit( address indexed sender, address indexed receiver, uint256 amount, uint256 iShares ); event Withdraw( address indexed sender, address indexed receiver, address indexed owner, uint256 amount, uint256 iShares ); event FlashWithdraw( address indexed sender, address indexed receiver, address indexed owner, uint256 amount, uint256 iShares, uint256 fee ); event Redeem( address indexed sender, address indexed receiver, uint256 amount ); event WithdrawalFee(uint256 fee); event RedeemedRequests(uint256[] withdrawals); event OperatorChanged(address prevValue, address newValue); event MinAmountChanged(uint256 prevValue, uint256 newValue); event ELOperatorAdded(address indexed newELOperator); event RestakerDeployed(address indexed restaker); event ImplementationUpgraded(address prevValue, address newValue); event RatioFeedChanged(address prevValue, address newValue); event NameChanged(string prevValue, string newValue); event TreasuryChanged(address prevValue, address newValue); event ReferralCode(bytes32 indexed code); event DepositBonus(uint256 amount); event DepositBonusParamsChanged( uint256 newMaxBonusRate, uint256 newOptimalBonusRate, uint256 newDepositUtilizationKink ); event WithdrawFeeParamsChanged( uint256 newMaxFlashFeeRate, uint256 newOptimalWithdrawalRate, uint256 newWithdrawUtilizationKink ); event ProtocolFeeChanged(uint256 prevValue, uint256 newValue); event RewardsTimelineChanged(uint256 prevValue, uint256 newValue); event RewardsAdded(uint256 amount, uint256 startTimeline); event EigenLayerFacetChanged(address prevValue, address newValue); event SetterFacetChanged(address prevValue, address newValue); event ERC4626FacetChanged(address prevValue, address newValue); event SignatureAdded( bytes4 indexed sig, FuncTarget target, FuncAccess access ); event RewardsCoordinatorChanged(address prevValue, address newValue); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; library Convert { function saturatingMultiply( uint256 a, uint256 b ) internal pure returns (uint256) { unchecked { if (a == 0) return 0; uint256 c = a * b; if (c / a != b) return type(uint256).max; return c; } } function saturatingAdd( uint256 a, uint256 b ) internal pure returns (uint256) { unchecked { uint256 c = a + b; if (c < a) return type(uint256).max; return c; } } // Preconditions: // 1. a may be arbitrary (up to 2 ** 256 - 1) // 2. b * c < 2 ** 256 // Returned value: min(floor((a * b) / c), 2 ** 256 - 1) function multiplyAndDivideFloor( uint256 a, uint256 b, uint256 c ) internal pure returns (uint256) { return saturatingAdd( saturatingMultiply(a / c, b), ((a % c) * b) / c // can't fail because of assumption 2. ); } // Preconditions: // 1. a may be arbitrary (up to 2 ** 256 - 1) // 2. b * c < 2 ** 256 // Returned value: min(ceil((a * b) / c), 2 ** 256 - 1) function multiplyAndDivideCeil( uint256 a, uint256 b, uint256 c ) internal pure returns (uint256) { require(c != 0, "c == 0"); return saturatingAdd( saturatingMultiply(a / c, b), ((a % c) * b + (c - 1)) / c // can't fail because of assumption 2. ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /// @author The InceptionLRT team /// @title The InceptionLibrary library /// @dev It serves two primary functions: /// 1. Flash vault-related logic for the calculations of deposit bonus and withdrawal fee /// 2. Conversions between shares and assets library InceptionLibrary { uint256 constant MAX_PERCENT = 100 * 1e8; /************************************************************ ************************ Flash Vault *********************** ************************************************************/ function calculateDepositBonus( uint256 amount, uint256 capacity, uint256 optimalCapacity, uint256 optimalBonusRate, uint256 maxDepositBonusRate, uint256 targetCapacity ) external pure returns (uint256 bonus) { /// @dev the utilization rate is in the range [0:25] % if (amount > 0 && capacity < optimalCapacity) { uint256 replenished = amount; if (optimalCapacity < capacity + amount) replenished = optimalCapacity - capacity; uint256 bonusSlope = ((maxDepositBonusRate - optimalBonusRate) * 1e18) / ((optimalCapacity * 1e18) / targetCapacity); uint256 bonusPercent = maxDepositBonusRate - (bonusSlope * (capacity + replenished / 2)) / targetCapacity; capacity += replenished; bonus += (replenished * bonusPercent) / MAX_PERCENT; amount -= replenished; } /// @dev the utilization rate is in the range [25: ] % if (amount > 0 && capacity <= targetCapacity) { uint256 replenished = targetCapacity > capacity + amount ? amount : targetCapacity - capacity; bonus += (replenished * optimalBonusRate) / MAX_PERCENT; } } function calculateWithdrawalFee( uint256 amount, uint256 capacity, uint256 optimalCapacity, uint256 optimaFeeRate, uint256 maxFlashWithdrawalFeeRate, uint256 targetCapacity ) external pure returns (uint256 fee) { /// @dev the utilization rate is in the range [100:25] % if (amount > 0 && capacity > optimalCapacity) { uint256 replenished = amount; if (capacity - amount < optimalCapacity) replenished = capacity - optimalCapacity; fee += (replenished * optimaFeeRate) / MAX_PERCENT; amount -= replenished; capacity -= replenished; if (fee == 0) ++fee; } /// @dev the utilization rate is in the range [25:0] % if (amount > 0) { uint256 feeSlope = ((maxFlashWithdrawalFeeRate - optimaFeeRate) * 1e18) / ((optimalCapacity * 1e18) / targetCapacity); uint256 bonusPercent = maxFlashWithdrawalFeeRate - (feeSlope * (capacity - amount / 2)) / targetCapacity; fee += (amount * bonusPercent) / MAX_PERCENT; if (fee == 0) ++fee; } if (fee == 0) ++fee; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import "../../InceptionVaultStorage_EL.sol"; contract ERC4626Facet_EL is InceptionVaultStorage_EL { function __beforeDeposit(address receiver, uint256 amount) internal view { if (receiver == address(0)) revert NullParams(); if (amount < minAmount) revert LowerMinAmount(minAmount); if (targetCapacity == 0) revert InceptionOnPause(); if (!_verifyDelegated()) revert InceptionOnPause(); } function __afterDeposit(uint256 iShares) internal pure { if (iShares == 0) revert DepositInconsistentResultedState(); } /** * @dev Transfers the msg.sender's assets to the vault. * @dev Mints Inception tokens in accordance with the current ratio. * @dev Issues the tokens to the specified receiver address. * @dev See {IERC4626-deposit}. */ function deposit( uint256 amount, address receiver ) external nonReentrant returns (uint256) { return _deposit(amount, msg.sender, receiver); } /** * @dev The `mint` function is used to mint the specified amount of shares * in exchange of the corresponding assets amount from owner. * @param shares The shares amount to be converted into underlying assets. * @param receiver The address of the shares receiver. * @dev See {IERC4626-mint}. */ function mint( uint256 shares, address receiver ) external nonReentrant returns (uint256) { uint256 maxShares = maxMint(receiver); if (shares > maxShares) revert ExceededMaxMint(receiver, shares, maxShares); uint256 assetsAmount = convertToAssets(shares); _deposit(assetsAmount, msg.sender, receiver); return assetsAmount; } /// @notice The deposit function but with a referral code function depositWithReferral( uint256 amount, address receiver, bytes32 code ) external nonReentrant returns (uint256) { emit ReferralCode(code); return _deposit(amount, msg.sender, receiver); } function _deposit( uint256 amount, address sender, address receiver ) internal returns (uint256) { // transfers assets from the sender and returns the received amount // the actual received amount might slightly differ from the specified amount, // approximately by -2 wei __beforeDeposit(receiver, amount); uint256 depositedBefore = totalAssets(); uint256 depositBonus; uint256 availableBonusAmount = depositBonusAmount; if (availableBonusAmount > 0) { depositBonus = calculateDepositBonus(amount); if (depositBonus > availableBonusAmount) { depositBonus = availableBonusAmount; depositBonusAmount = 0; } else { depositBonusAmount -= depositBonus; } emit DepositBonus(depositBonus); } // get the amount from the sender _transferAssetFrom(sender, amount); amount = totalAssets() - depositedBefore; uint256 iShares = convertToShares(amount + depositBonus); inceptionToken.mint(receiver, iShares); __afterDeposit(iShares); emit Deposit(sender, receiver, amount, iShares); return iShares; } function __beforeWithdraw(address receiver, uint256 iShares) internal view { if (iShares == 0) revert NullParams(); if (receiver == address(0)) revert NullParams(); if (targetCapacity == 0) revert InceptionOnPause(); if (treasury == address(0)) revert InceptionOnPause(); if (!_verifyDelegated()) revert InceptionOnPause(); } /** * @dev Performs burning iToken from mgs.sender * @dev Creates a withdrawal requests based on the current ratio * @param iShares is measured in Inception token(shares) */ function withdraw(uint256 iShares, address receiver) external nonReentrant { __beforeWithdraw(receiver, iShares); address claimer = msg.sender; uint256 amount = convertToAssets(iShares); if (amount < minAmount) revert LowerMinAmount(minAmount); // burn Inception token in view of the current ratio inceptionToken.burn(claimer, iShares); // update global state and claimer's state totalAmountToWithdraw += amount; Withdrawal storage genRequest = _claimerWithdrawals[receiver]; genRequest.amount += _getAssetReceivedAmount(amount); claimerWithdrawalsQueue.push( Withdrawal({ epoch: claimerWithdrawalsQueue.length, receiver: receiver, amount: _getAssetReceivedAmount(amount) }) ); emit Withdraw(claimer, receiver, claimer, amount, iShares); } /** * @notice Utilizes `_flashWithdraw()` and Charges! a flash fee. * @dev This function redeems a specific number of shares from owner and * sends assets of underlying token from the vault to receiver. * @dev See {IERC4626-withdraw} */ function redeem( uint256 shares, address receiver, address owner ) external nonReentrant returns (uint256 assets) { if (owner != msg.sender) revert MsgSenderIsNotOwner(); __beforeWithdraw(receiver, shares); assets = convertToAssets(shares); uint256 fee; (assets, fee) = _flashWithdraw(shares, receiver, owner); emit Withdraw(owner, receiver, owner, assets, shares); emit WithdrawalFee(fee); return assets; } function _flashWithdraw( uint256 iShares, address receiver, address owner ) internal returns (uint256, uint256) { uint256 amount = convertToAssets(iShares); if (amount < minAmount) revert LowerMinAmount(minAmount); // burn Inception token in view of the current ratio inceptionToken.burn(owner, iShares); uint256 fee = calculateFlashWithdrawFee(amount); if (fee == 0) revert ZeroFlashWithdrawFee(); uint256 protocolWithdrawalFee = (fee * protocolFee) / MAX_PERCENT; amount -= fee; depositBonusAmount += (fee - protocolWithdrawalFee); /// @notice instant transfer fee to the treasury _transferAssetTo(treasury, protocolWithdrawalFee); /// @notice instant transfer amount to the receiver _transferAssetTo(receiver, amount); return (amount, fee); } /** * @dev Performs burning iToken from mgs.sender * @dev Creates a withdrawal requests based on the current ratio * @param iShares is measured in Inception token(shares) */ function flashWithdraw( uint256 iShares, address receiver ) external nonReentrant { __beforeWithdraw(receiver, iShares); address claimer = msg.sender; (uint256 amount, uint256 fee) = _flashWithdraw( iShares, receiver, claimer ); emit FlashWithdraw(claimer, receiver, claimer, amount, iShares, fee); } function redeem(address receiver) external nonReentrant { (bool isAble, uint256[] memory availableWithdrawals) = isAbleToRedeem( receiver ); if (!isAble) revert IsNotAbleToRedeem(); uint256 numOfWithdrawals = availableWithdrawals.length; uint256[] memory redeemedWithdrawals = new uint256[](numOfWithdrawals); Withdrawal storage genRequest = _claimerWithdrawals[receiver]; uint256 redeemedAmount; for (uint256 i = 0; i < numOfWithdrawals; ++i) { uint256 withdrawalNum = availableWithdrawals[i]; Withdrawal storage request = claimerWithdrawalsQueue[withdrawalNum]; uint256 amount = request.amount; // update the genRequest and the global state genRequest.amount -= amount; totalAmountToWithdraw -= _getAssetWithdrawAmount(amount); redeemReservedAmount -= amount; redeemedAmount += amount; redeemedWithdrawals[i] = withdrawalNum; delete claimerWithdrawalsQueue[availableWithdrawals[i]]; } // let's update the lowest epoch associated with the claimer genRequest.epoch = availableWithdrawals[numOfWithdrawals - 1]; _transferAssetTo(receiver, redeemedAmount); emit RedeemedRequests(redeemedWithdrawals); emit Redeem(msg.sender, receiver, redeemedAmount); } function _verifyDelegated() internal view returns (bool) { for (uint256 i = 0; i < restakers.length; i++) { if (restakers[i] == address(0)) { continue; } if (!delegationManager.isDelegated(restakers[i])) return false; } if ( strategy.userUnderlyingView(address(this)) > 0 && !delegationManager.isDelegated(address(this)) ) return false; return true; } /// @dev The functions below serve the proper withdrawal and claiming operations /// @notice Since a particular LST loses some wei on each transfer, /// this needs to be taken into account function _getAssetWithdrawAmount( uint256 amount ) internal view virtual returns (uint256) { return amount; } function _getAssetReceivedAmount( uint256 amount ) internal view virtual returns (uint256) { return amount; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {BeaconProxy, Address} from "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IOwnable} from "../../interfaces/common/IOwnable.sol"; import {IInceptionVault_EL} from "../../interfaces/eigenlayer-vault/IInceptionVault_EL.sol"; import {IInceptionToken} from "../../interfaces/common/IInceptionToken.sol"; import {IDelegationManager} from "../../interfaces/eigenlayer-vault/eigen-core/IDelegationManager.sol"; import {IInceptionRatioFeed} from "../../interfaces/common/IInceptionRatioFeed.sol"; import {IInceptionVaultErrors} from "../../interfaces/common/IInceptionVaultErrors.sol"; import {IInceptionEigenRestaker, IInceptionEigenRestakerErrors} from "../../interfaces/eigenlayer-vault/IInceptionEigenRestaker.sol"; import {IStrategyManager, IStrategy} from "../../interfaces/eigenlayer-vault/eigen-core/IStrategyManager.sol"; import {Convert} from "../../lib/Convert.sol"; import {InceptionLibrary} from "../../lib/InceptionLibrary.sol"; /** * @title InceptionVaultStorage_EL * @author The InceptionLRT team * @notice Manages the storage variables and getter functions for the Inception Vault, which interacts with EigenLayer and manages delegation, withdrawals, and rewards. * @dev This contract extends the Pausable, Ownable, and ReentrancyGuard patterns. */ contract InceptionVaultStorage_EL is PausableUpgradeable, ReentrancyGuardUpgradeable, OwnableUpgradeable, IInceptionVault_EL, IInceptionVaultErrors { IERC20 internal _asset; uint256[49] private __gap; IStrategyManager public strategyManager; IStrategy public strategy; uint256 public epoch; /// @dev Operator for the inception vault address internal _operator; /// @notice Represents the pending amount to be redeemed by claimers and to be undelegated from EigenLayer. uint256 public totalAmountToWithdraw; /// @dev Represents the amount pending processing until claimed. /// @notice Amount is measured in the vault's asset. uint256 internal _pendingWithdrawalAmount; IDelegationManager public delegationManager; Withdrawal[] public claimerWithdrawalsQueue; address internal constant _MOCK_ADDRESS = 0x0000000000000000000000000012345000000000; /// @dev Reserved for claimers' withdrawal requests. uint256 public redeemReservedAmount; /// @dev Maps EigenLayer operators to Inception stakers. mapping(address => address) internal _operatorRestakers; address[] public restakers; uint256 public depositBonusAmount; /// @dev Target capacity for the vault, represented in percentage terms (max 100%). uint256 public targetCapacity; uint256 public constant MAX_TARGET_PERCENT = 100 * 1e18; /// @dev constants are not stored in the storage uint256[50 - 13] private __reserver; IInceptionToken public inceptionToken; /// @dev Reduces rounding issues uint256 public minAmount; mapping(address => Withdrawal) internal _claimerWithdrawals; /// @dev Unique name of the InceptionVault. string public name; /// @dev Factory implementation address for creating stakers. address public stakerImplementation; // Flash withdrawal parameters /// @dev 100% uint64 public constant MAX_PERCENT = 100 * 1e8; IInceptionRatioFeed public ratioFeed; address public treasury; uint64 public protocolFee; uint64 public maxBonusRate; uint64 public optimalBonusRate; uint64 public depositUtilizationKink; uint64 public maxFlashFeeRate; uint64 public optimalWithdrawalRate; uint64 public withdrawUtilizationKink; address public rewardsCoordinator; address public eigenLayerFacet; address public erc4626Facet; address public setterFacet; uint256 public currentRewards; uint256 public startTimeline; uint256 public rewardsTimeline; mapping(bytes4 => FuncData) internal _selectorToTarget; /** * @notice Initializes the Inception Assets Handler * @dev This function is called during contract deployment. * @param assetAddress The address of the underlying ERC20 token. */ function __InceptionVaultStorage_EL_init( IERC20 assetAddress ) internal onlyInitializing { __Pausable_init(); __ReentrancyGuard_init(); __Ownable_init(); _asset = assetAddress; } /** * @notice Returns the total deposited amount in the vault strategy. * @return The total assets delegated, held in the vault, and pending withdrawal. */ function getTotalDeposited() public view returns (uint256) { return getTotalDelegated() + totalAssets() + _pendingWithdrawalAmount - depositBonusAmount; } /** * @notice Returns the total amount delegated to all restakers in EigenLayer. * @return total The total delegated amount. */ function getTotalDelegated() public view returns (uint256 total) { uint256 stakersNum = restakers.length; for (uint256 i = 0; i < stakersNum; ++i) { if (restakers[i] == address(0)) continue; total += strategy.userUnderlyingView(restakers[i]); } return total + strategy.userUnderlyingView(address(this)); } /** * @notice Returns the available balance that can be used for flash withdrawals. * @return total The total free balance available for flash withdrawals. */ function getFreeBalance() public view returns (uint256 total) { return getFlashCapacity() < _getTargetCapacity() ? 0 : getFlashCapacity() - _getTargetCapacity(); } /** * @notice Returns the amount pending withdrawal from EigenLayer. * @return total The pending withdrawal amount. */ function getPendingWithdrawalAmountFromEL() public view returns (uint256 total) { return _pendingWithdrawalAmount; } function implementation() external view returns (address) { return stakerImplementation; } /** * @notice Returns the current vault-to-underlying token ratio from the InceptionRatioFeed. * @return The ratio used for converting between vault shares and assets. */ function ratio() public view returns (uint256) { return ratioFeed.getRatioFor(address(inceptionToken)); } function getDelegatedTo( address elOperator ) external view returns (uint256) { return strategy.userUnderlyingView(_operatorRestakers[elOperator]); } function getPendingWithdrawalOf( address claimer ) external view returns (uint256) { return _claimerWithdrawals[claimer].amount; } /** * @notice Checks if the given claimer is able to redeem any withdrawals. * @param claimer The address of the claimer. * @return able Indicates whether the claimer can redeem withdrawals. * @return availableWithdrawals The array of indices where the claimer has available withdrawals. */ function isAbleToRedeem( address claimer ) public view returns (bool able, uint256[] memory) { // get the general request uint256 index; Withdrawal memory genRequest = _claimerWithdrawals[claimer]; uint256[] memory availableWithdrawals = new uint256[]( epoch - genRequest.epoch ); if (genRequest.amount == 0) return (false, availableWithdrawals); for (uint256 i = 0; i < epoch; ++i) { if (claimerWithdrawalsQueue[i].receiver == claimer) { able = true; availableWithdrawals[index] = i; ++index; } } // decrease arrays if (availableWithdrawals.length - index > 0) assembly { mstore(availableWithdrawals, index) } return (able, availableWithdrawals); } /********************************************************************* ****************************** ERC4626 ****************************** *********************************************************************/ /** * @notice Returns the address of the asset used in the vault. * @return The address of the underlying ERC20 token used for accounting, depositing, and withdrawing. */ function asset() public view returns (address) { return address(_asset); } /** * @notice Returns the total assets held by the vault. * @return The total balance of the vault in the underlying asset. */ function totalAssets() public view returns (uint256) { uint256 dayNum = (block.timestamp - startTimeline) / 1 days; uint256 totalDays = rewardsTimeline / 1 days; if (dayNum > totalDays) return _asset.balanceOf(address(this)); uint256 reservedRewards = (currentRewards / totalDays) * (totalDays - dayNum); return (_asset.balanceOf(address(this)) - reservedRewards); } /** * @dev See {IERC4626-convertToShares}. */ function convertToShares(uint256 assets) public view returns (uint256) { return _convertToShares(assets); } function _convertToShares( uint256 assets ) internal view returns (uint256 shares) { return Convert.multiplyAndDivideFloor(assets, ratio(), 1e18); } /** * @dev See {IERC4626-convertToAssets}. */ function convertToAssets(uint256 shares) public view returns (uint256) { return _convertToAssets(shares); } function _convertToAssets( uint256 iShares ) internal view returns (uint256 assets) { return Convert.multiplyAndDivideFloor(iShares, 1e18, ratio()); } /** * @dev See {IERC4626-maxDeposit}. * @dev The `maxDeposit` function is used to calculate the maximum deposit. * @notice If the vault is locked or paused, users are not allowed to deposit, the maxDeposit is 0. * @return Amount of the maximum underlying assets deposit amount. */ function maxDeposit(address receiver) public view returns (uint256) { return !paused() ? _asset.balanceOf(receiver) : 0; } /** * @dev See {IERC4626-maxMint} * @dev The `maxMint` function is used to calculate the maximum amount of shares you can mint. * @notice If the vault is locked or paused, the maxMint is 0. * @return Amount of the maximum shares mintable for the specified address. */ function maxMint(address receiver) public view returns (uint256) { return !paused() ? previewDeposit(_asset.balanceOf(receiver)) : 0; } /** * @dev See {IERC4626-maxRedeem}. * @notice If the function is called during the lock period the maxRedeem is `0`; * @param owner The address of the owner. * @return Amount of the maximum number of redeemable shares. */ function maxRedeem(address owner) public view returns (uint256) { if (paused()) { return 0; } else { uint256 ownerShares = IERC20(address(inceptionToken)).balanceOf( owner ); uint256 flashShares = convertToShares(getFlashCapacity()); return flashShares > ownerShares ? ownerShares : flashShares; } } /** * @dev See {IERC4626-previewDeposit}. */ function previewDeposit(uint256 assets) public view returns (uint256) { uint256 depositBonus; if (depositBonusAmount > 0) { depositBonus = calculateDepositBonus(assets); if (depositBonus > depositBonusAmount) depositBonus = depositBonusAmount; } return _convertToShares(assets + depositBonus); } /** * @notice Utilizes `inceptionToken.balanceOf()`. * @dev Returns the total amount of vault shares the owner currently has. * @dev See {IERC4626-balanceOf} */ function balanceOf(address owner) public view returns (uint256) { return IERC20(address(inceptionToken)).balanceOf(owner); } /** * @notice Utilizes `inceptionToken.totalSupply()`. * @dev Returns the total number of unredeemed vault shares in circulation. * @dev See {IERC4626-totalSupply} */ function totalSupply() public view returns (uint256) { return IERC20(address(inceptionToken)).totalSupply(); } /** * @dev This function allows users to simulate the effects of their redemption at the current block. * @dev See {IERC4626-previewRedeem} */ function previewRedeem( uint256 shares ) public view returns (uint256 assets) { return _convertToAssets(shares) - calculateFlashWithdrawFee(convertToAssets(shares)); } /*********************************************************************** ************************* FlashPool Functions ************************* ***********************************************************************/ /** * @notice Returns the flash withdrawal capacity. * @return total The total assets available for flash withdrawal. */ function getFlashCapacity() public view returns (uint256 total) { return totalAssets() - redeemReservedAmount - depositBonusAmount; } /// @notice Function to calculate deposit bonus based on the utilization rate function calculateDepositBonus( uint256 amount ) public view returns (uint256) { return InceptionLibrary.calculateDepositBonus( amount, getFlashCapacity(), (_getTargetCapacity() * depositUtilizationKink) / MAX_PERCENT, optimalBonusRate, maxBonusRate, _getTargetCapacity() ); } /// @dev Function to calculate flash withdrawal fee based on the utilization rate function calculateFlashWithdrawFee( uint256 amount ) public view returns (uint256) { uint256 capacity = getFlashCapacity(); if (amount > capacity) revert InsufficientCapacity(capacity); return InceptionLibrary.calculateWithdrawalFee( amount, capacity, (_getTargetCapacity() * withdrawUtilizationKink) / MAX_PERCENT, optimalWithdrawalRate, maxFlashFeeRate, _getTargetCapacity() ); } /** * @notice Sets the target and access level for a given function signature * @dev Updates the `_selectorToTarget` mapping with the provided function signature, target, and access level * @param sigs The function signature to configure * @param targets The target facet (contract) associated with the function signature * @param accesses The access level for the function signature */ function setSignaturesBatch( bytes4[] calldata sigs, FuncTarget[] calldata targets, FuncAccess[] calldata accesses ) external onlyOwner { uint256 num = sigs.length; if (num != targets.length || num != accesses.length) revert InconsistentData(); for (uint256 i = 0; i < num; ) { _selectorToTarget[sigs[i]] = FuncData({ facet: targets[i], access: accesses[i] }); unchecked { ++i; } } } /** * @notice Sets the target and access level for a given function signature * @dev Updates the `_selectorToTarget` mapping with the provided function signature, target, and access level * @param sig The function signature to configure * @param _target The target facet (contract) associated with the function signature * @param _access The access level for the function signature */ function setSignature( bytes4 sig, FuncTarget _target, FuncAccess _access ) external onlyOwner { _selectorToTarget[sig] = FuncData({facet: _target, access: _access}); emit SignatureAdded(sig, _target, _access); } function setEigenLayerFacet(address newEigenLayerFacet) external onlyOwner { if (!Address.isContract(newEigenLayerFacet)) revert NotContract(); emit EigenLayerFacetChanged(eigenLayerFacet, newEigenLayerFacet); eigenLayerFacet = newEigenLayerFacet; } function setERC4626Facet(address newERC4626Facet) external onlyOwner { if (!Address.isContract(newERC4626Facet)) revert NotContract(); emit ERC4626FacetChanged(erc4626Facet, newERC4626Facet); erc4626Facet = newERC4626Facet; } function setSetterFacet(address newSetterFacet) external onlyOwner { if (!Address.isContract(newSetterFacet)) revert NotContract(); emit SetterFacetChanged(setterFacet, newSetterFacet); setterFacet = newSetterFacet; } /********************************************************************* ************************* Internal function ************************* *********************************************************************/ /** * @notice Returns the target capacity based on the vault's configuration. * @dev This function calculates the vault's target capacity as a percentage of the total deposited amount. * @return The target capacity. */ function _getTargetCapacity() internal view returns (uint256) { return (targetCapacity * getTotalDeposited()) / MAX_TARGET_PERCENT; } function _getSelectorToTarget( bytes4 sig ) internal view returns (address, FuncAccess) { _requireNotPaused(); FuncData memory target = _selectorToTarget[sig]; if ( target.facet == FuncTarget.SETTER_FACET && target.access == FuncAccess.EVERYONE ) return (address(0), FuncAccess.EVERYONE); if (target.facet == FuncTarget.ERC4626_FACET) return (erc4626Facet, target.access); if (target.facet == FuncTarget.EIGEN_LAYER_FACET) return (eigenLayerFacet, target.access); if (target.facet == FuncTarget.SETTER_FACET) return (setterFacet, target.access); return (address(0), FuncAccess.EVERYONE); } function _verifyAccess(FuncAccess access) internal view { if (access == FuncAccess.ONLY_OWNER) { _checkOwner(); } else if (access == FuncAccess.ONLY_OPERATOR) { if (msg.sender != _operator) revert OnlyOperatorAllowed(); } } /** * @dev Internal function to transfer assets from the staker to the vault. * @param staker The address of the staker. * @param amount The amount to transfer. * @return The actual amount transferred. */ function _transferAssetFrom( address staker, uint256 amount ) internal returns (uint256) { uint256 depositedBefore = _asset.balanceOf(address(this)); if (!_asset.transferFrom(staker, address(this), amount)) revert TransferAssetFromFailed(address(_asset)); return _asset.balanceOf(address(this)) - depositedBefore; } /** * @dev Internal function to transfer assets from the vault to the receiver. * @param receiver The address to receive the assets. * @param amount The amount to transfer. */ function _transferAssetTo(address receiver, uint256 amount) internal { if (!_asset.transfer(receiver, amount)) revert TransferAssetFailed(address(_asset)); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": { "contracts/lib/InceptionLibrary.sol": { "InceptionLibrary": "0x8a6a8a7233b16d0ecaa7510bfd110464a0d69f66" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"payable","type":"constructor"},{"inputs":[],"name":"AlreadyDelegated","type":"error"},{"inputs":[],"name":"ApproveError","type":"error"},{"inputs":[],"name":"DelegationManagerImmutable","type":"error"},{"inputs":[],"name":"DepositInconsistentResultedState","type":"error"},{"inputs":[],"name":"EigenLayerOperatorAlreadyExists","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"maxShares","type":"uint256"}],"name":"ExceededMaxMint","type":"error"},{"inputs":[{"internalType":"uint256","name":"max","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExceedsMaxPerDeposit","type":"error"},{"inputs":[{"internalType":"uint256","name":"max","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExceedsMaxTotalDeposited","type":"error"},{"inputs":[],"name":"FunctionNotSupported","type":"error"},{"inputs":[],"name":"ImplementationNotSet","type":"error"},{"inputs":[],"name":"InceptionOnPause","type":"error"},{"inputs":[],"name":"InconsistentData","type":"error"},{"inputs":[{"internalType":"uint256","name":"capacity","type":"uint256"}],"name":"InsufficientCapacity","type":"error"},{"inputs":[],"name":"InvalidTargetFlashCapacity","type":"error"},{"inputs":[],"name":"IsNotAbleToRedeem","type":"error"},{"inputs":[{"internalType":"uint256","name":"minAmount","type":"uint256"}],"name":"LowerMinAmount","type":"error"},{"inputs":[],"name":"MsgSenderIsNotOwner","type":"error"},{"inputs":[],"name":"NotContract","type":"error"},{"inputs":[],"name":"NotEigenLayerOperator","type":"error"},{"inputs":[],"name":"NullParams","type":"error"},{"inputs":[],"name":"OnlyOperatorAllowed","type":"error"},{"inputs":[],"name":"OperatorNotRegistered","type":"error"},{"inputs":[{"internalType":"uint256","name":"param","type":"uint256"}],"name":"ParameterExceedsLimits","type":"error"},{"inputs":[],"name":"RestakerNotRegistered","type":"error"},{"inputs":[],"name":"TimelineNotOver","type":"error"},{"inputs":[{"internalType":"address","name":"assetAddress","type":"address"}],"name":"TransferAssetFailed","type":"error"},{"inputs":[{"internalType":"address","name":"assetAddress","type":"address"}],"name":"TransferAssetFromFailed","type":"error"},{"inputs":[],"name":"ZeroFlashWithdrawFee","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":true,"internalType":"address","name":"operatorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DelegatedTo","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"prevValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"DelegationManagerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"iShares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositBonus","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxBonusRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newOptimalBonusRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDepositUtilizationKink","type":"uint256"}],"name":"DepositBonusParamsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositedToEL","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newELOperator","type":"address"}],"name":"ELOperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"prevValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"ERC4626FacetChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"prevValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"EigenLayerFacetChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"iShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"FlashWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"prevValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"ImplementationUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"prevValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"MinAmountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"prevValue","type":"string"},{"indexed":false,"internalType":"string","name":"newValue","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"prevValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"OperatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"prevValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"ProtocolFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"prevValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"RatioFeedChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"withdrawals","type":"uint256[]"}],"name":"RedeemedRequests","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"code","type":"bytes32"}],"name":"ReferralCode","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"restaker","type":"address"}],"name":"RestakerDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTimeline","type":"uint256"}],"name":"RewardsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"prevValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"RewardsCoordinatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"prevValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"RewardsTimelineChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"prevValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"SetterFacetChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":false,"internalType":"enum IInceptionVault_EL.FuncTarget","name":"target","type":"uint8"},{"indexed":false,"internalType":"enum IInceptionVault_EL.FuncAccess","name":"access","type":"uint8"}],"name":"SignatureAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":false,"internalType":"contract IStrategy","name":"strategy","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"withdrawalStartBlock","type":"uint32"},{"indexed":false,"internalType":"address","name":"delegatedAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"StartWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"prevValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"TargetCapacityChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"prevValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"TreasuryChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"iShares","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxFlashFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newOptimalWithdrawalRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newWithdrawUtilizationKink","type":"uint256"}],"name":"WithdrawFeeParamsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"WithdrawalClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"WithdrawalFee","type":"event"},{"inputs":[],"name":"MAX_PERCENT","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TARGET_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"calculateDepositBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"calculateFlashWithdrawFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimerWithdrawalsQueue","outputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delegationManager","outputs":[{"internalType":"contract IDelegationManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositBonusAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositUtilizationKink","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes32","name":"code","type":"bytes32"}],"name":"depositWithReferral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"eigenLayerFacet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc4626Facet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"iShares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"flashWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"elOperator","type":"address"}],"name":"getDelegatedTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFlashCapacity","outputs":[{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFreeBalance","outputs":[{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingWithdrawalAmountFromEL","outputs":[{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"claimer","type":"address"}],"name":"getPendingWithdrawalOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDelegated","outputs":[{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inceptionToken","outputs":[{"internalType":"contract IInceptionToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"claimer","type":"address"}],"name":"isAbleToRedeem","outputs":[{"internalType":"bool","name":"able","type":"bool"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxBonusRate","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxFlashFeeRate","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"optimalBonusRate","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"optimalWithdrawalRate","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFee","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ratio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ratioFeed","outputs":[{"internalType":"contract IInceptionRatioFeed","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redeemReservedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"restakers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsCoordinator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsTimeline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newERC4626Facet","type":"address"}],"name":"setERC4626Facet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newEigenLayerFacet","type":"address"}],"name":"setEigenLayerFacet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSetterFacet","type":"address"}],"name":"setSetterFacet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"sig","type":"bytes4"},{"internalType":"enum IInceptionVault_EL.FuncTarget","name":"_target","type":"uint8"},{"internalType":"enum IInceptionVault_EL.FuncAccess","name":"_access","type":"uint8"}],"name":"setSignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"sigs","type":"bytes4[]"},{"internalType":"enum IInceptionVault_EL.FuncTarget[]","name":"targets","type":"uint8[]"},{"internalType":"enum IInceptionVault_EL.FuncAccess[]","name":"accesses","type":"uint8[]"}],"name":"setSignaturesBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setterFacet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakerImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startTimeline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategy","outputs":[{"internalType":"contract IStrategy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategyManager","outputs":[{"internalType":"contract IStrategyManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetCapacity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAmountToWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"iShares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawUtilizationKink","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052612fa7806100136000396000f3fe608060405234801561001057600080fd5b506004361061041b5760003560e01c80638da5cb5b1161022b578063c235fb1411610130578063e91bb844116100b8578063edb594fc11610087578063edb594fc14610907578063ef13b2c71461091a578063ef8b30f71461093b578063f29768711461094e578063f2fde38b1461095657600080fd5b8063e91bb844146108a2578063e93c4f15146108d8578063ea4d3c9b146108e0578063eae43a44146108f457600080fd5b8063cea6443a116100ff578063cea6443a14610845578063d1ef0c9414610858578063d8266c181461086c578063d905777e1461087f578063e78078971461089257600080fd5b8063c235fb14146107f8578063c63d75b61461080c578063c6e6f5921461081f578063ce5119ee1461083257600080fd5b80639b2cb5d8116101b3578063b637d66911610182578063b637d669146107b6578063b68ef559146107c0578063ba087652146107c8578063c059a38e146107db578063c137d8ad146107e557600080fd5b80639b2cb5d814610751578063a8c62e761461075b578063ab89b6af1461076e578063b0e21e8a1461079b57600080fd5b806390fed28d116101fa57806390fed28d146106f557806394bf804d1461070857806395a2251f1461071b5780639669c7cf1461072e57806396c8d48e1461073657600080fd5b80638da5cb5b146106bd5780638e29ebb5146106ce578063900cf0cf146106e2578063901a7d53146106eb57600080fd5b80634baa6193116103315780636ba176c7116102b957806371ca337d1161028857806371ca337d14610667578063779a6cdd1461066f5780637839030f146106835780637b487a65146106965780638a2fc4e3146106a957600080fd5b80636ba176c7146106265780636e553f651461063957806370a082311461064c578063715018a61461065f57600080fd5b80635c975abb116103005780635c975abb146105d557806361d027b3146105eb57806366bcd641146105ff5780636a1ae053146106085780636b77b2f51461061c57600080fd5b80634baa6193146105925780634cdad506146105a657806353268ad0146105b95780635c60da1b146105c357600080fd5b80632b6fd4f1116103b457806339b70e381161038357806339b70e3814610534578063402d267d14610547578063470a567c1461055a5780634886a9571461056d5780634a6b629d1461058857600080fd5b80632b6fd4f1146104da5780632df2228a1461050657806330e4cf3a1461050f57806338d52e0f1461052357600080fd5b806307a2d13a116103f057806307a2d13a146104985780631036bbe2146104ab57806318160ddd146104b75780631f2ed36f146104bf57600080fd5b806292891714610420578062f714ce1461045857806301e1d1141461046d57806306fdde0314610483575b600080fd5b6101345461043b90600160c01b90046001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b61046b610466366004612ab8565b610969565b005b610475610b44565b60405190815260200161044f565b61048b610c9f565b60405161044f9190612ae4565b6104756104a6366004612b33565b610d2e565b61043b6402540be40081565b610475610d3f565b6101345461043b90600160401b90046001600160401b031681565b610138546104ee906001600160a01b031681565b6040516001600160a01b03909116815260200161044f565b61010054610475565b610137546104ee906001600160a01b031681565b60c9546001600160a01b03166104ee565b60fb546104ee906001600160a01b031681565b610475610555366004612b4c565b610db3565b61046b610568366004612bb2565b610e3c565b6101345461043b90600160801b90046001600160401b031681565b6104756101075481565b610131546104ee906001600160a01b031681565b6104756105b4366004612b33565b610fa4565b6104756101035481565b610131546001600160a01b03166104ee565b60335460ff16604051901515815260200161044f565b610133546104ee906001600160a01b031681565b61047560ff5481565b6101355461043b906001600160401b031681565b61047561013b5481565b610475610634366004612b33565b610fc5565b610475610647366004612ab8565b6110a7565b61047561065a366004612b4c565b6110c8565b61046b6110fc565b610475611110565b6101345461043b906001600160401b031681565b61046b610691366004612b4c565b611163565b61046b6106a4366004612b4c565b6111fe565b610136546104ee906001600160a01b031681565b6097546001600160a01b03166104ee565b610132546104ee906001600160a01b031681565b61047560fd5481565b61047561013a5481565b61046b610703366004612ab8565b611299565b610475610716366004612ab8565b61130f565b61046b610729366004612b4c565b611386565b61047561161e565b6101355461043b90600160401b90046001600160401b031681565b61047561012e5481565b60fc546104ee906001600160a01b031681565b61047561077c366004612b4c565b6001600160a01b0316600090815261012f602052604090206002015490565b6101335461043b90600160a01b90046001600160401b031681565b61047561013c5481565b610475611644565b6104756107d6366004612c4b565b611672565b6104756101065481565b61046b6107f3366004612cac565b61175d565b61012d546104ee906001600160a01b031681565b61047561081a366004612b4c565b61184c565b61047561082d366004612b33565b6118d6565b610475610840366004612b4c565b6118e1565b610475610853366004612b33565b611929565b610139546104ee906001600160a01b031681565b61046b61087a366004612b4c565b611a61565b61047561088d366004612b4c565b611afc565b61047568056bc75e2d6310000081565b6108b56108b0366004612b33565b611bb4565b604080519384526001600160a01b0390921660208401529082015260600161044f565b610475611bf4565b610101546104ee906001600160a01b031681565b6104ee610902366004612b33565b611c21565b610475610915366004612cf5565b611c4c565b61092d610928366004612b4c565b611c98565b60405161044f929190612d66565b610475610949366004612b33565b611df7565b610475611e34565b61046b610964366004612b4c565b611faf565b610971612025565b61097b818361207e565b33600061098784610d2e565b905061012e548110156109bd5761012e5460405163279dbb3d60e11b81526004016109b491815260200190565b60405180910390fd5b61012d54604051632770a7eb60e21b81526001600160a01b0384811660048301526024820187905290911690639dc29fac90604401600060405180830381600087803b158015610a0c57600080fd5b505af1158015610a20573d6000803e3d6000fd5b505050508060ff6000828254610a369190612d97565b90915550506001600160a01b038316600090815261012f60205260409020610a5d82612139565b816002016000828254610a709190612d97565b909155505060408051606081018252610102805482526001600160a01b0387166020830152918101610aa185612139565b9052815460018082018455600093845260209384902083516003909302019182558284015190820180546001600160a01b0319166001600160a01b039283161790556040928301516002909201919091558151858152928301889052858116929087169183917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db91015b60405180910390a4505050610b406001606555565b5050565b6000806201518061013b5442610b5a9190612daa565b610b649190612dd3565b905060006201518061013c54610b7a9190612dd3565b905080821115610bf75760c9546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610bcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf09190612de7565b9250505090565b6000610c038383612daa565b8261013a54610c129190612dd3565b610c1c9190612e00565b60c9546040516370a0823160e01b815230600482015291925082916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d9190612de7565b610c979190612daa565b935050505090565b6101308054610cad90612e17565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd990612e17565b8015610d265780601f10610cfb57610100808354040283529160200191610d26565b820191906000526020600020905b815481529060010190602001808311610d0957829003601f168201915b505050505081565b6000610d3982612146565b92915050565b61012d54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae9190612de7565b905090565b6000610dc160335460ff1690565b15610dcd576000610d39565b60c9546040516370a0823160e01b81526001600160a01b038481166004830152909116906370a08231906024015b602060405180830381865afa158015610e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d399190612de7565b610e44612162565b848381141580610e545750808214155b15610e725760405163afff5f7760e01b815260040160405180910390fd5b60005b81811015610f9a576040518060400160405280878784818110610e9a57610e9a612e51565b9050602002016020810190610eaf9190612e67565b6002811115610ec057610ec0612e84565b8152602001858584818110610ed757610ed7612e51565b9050602002016020810190610eec9190612e67565b6002811115610efd57610efd612e84565b905261013d60008a8a85818110610f1657610f16612e51565b9050602002016020810190610f2b9190612e9a565b6001600160e01b0319168152602081019190915260400160002081518154829060ff19166001836002811115610f6357610f63612e84565b021790555060208201518154829061ff001916610100836002811115610f8b57610f8b612e84565b02179055505050600101610e75565b5050505050505050565b6000610fb261085383610d2e565b610fbb83612146565b610d399190612daa565b6000738a6a8a7233b16d0ecaa7510bfd110464a0d69f6663fea65f7283610fea61161e565b610134546402540be40090600160801b90046001600160401b031661100d6121bc565b6110179190612e00565b6110219190612dd3565b610134546001600160401b03600160401b8204811691166110406121bc565b6040516001600160e01b031960e089901b1681526004810196909652602486019490945260448501929092526001600160401b03908116606485015216608483015260a482015260c401602060405180830381865af4158015610e18573d6000803e3d6000fd5b60006110b1612025565b6110bc8333846121e8565b9050610d396001606555565b61012d546040516370a0823160e01b81526001600160a01b03838116600483015260009216906370a0823190602401610dfb565b611104612162565b61110e600061237e565b565b6101325461012d5460405163a1f1d48d60e01b81526001600160a01b039182166004820152600092919091169063a1f1d48d90602401602060405180830381865afa158015610d8a573d6000803e3d6000fd5b61116b612162565b6001600160a01b0381163b61119357604051636f7c43f160e01b815260040160405180910390fd5b61013954604080516001600160a01b03928316815291831660208301527f16b3a5b47cfc3418106cb8fd15fc5df8b17ea324464f7655b052d9e4a3a14df2910160405180910390a161013980546001600160a01b0319166001600160a01b0392909216919091179055565b611206612162565b6001600160a01b0381163b61122e57604051636f7c43f160e01b815260040160405180910390fd5b61013754604080516001600160a01b03928316815291831660208301527fe6b9ab4b050c05a6c2d41e35b5c0112bb6c563134cc0daccc29a7a44d5da47fe910160405180910390a161013780546001600160a01b0319166001600160a01b0392909216919091179055565b6112a1612025565b6112ab818361207e565b336000806112ba8585856123d0565b604080518381526020810189905290810182905291935091506001600160a01b03808516919086169082907f22b8f008297894112d5322d194442062aad3c25bbcdd07d2b0fa30a9e026e53c90606001610b2b565b6000611319612025565b60006113248361184c565b905080841115611360576040516330ac82f560e11b81526001600160a01b038416600482015260248101859052604481018290526064016109b4565b600061136b85610d2e565b90506113788133866121e8565b50915050610d396001606555565b61138e612025565b60008061139a83611c98565b91509150816113bf5760405160016289337960e01b0319815260040160405180910390fd5b80516000816001600160401b038111156113db576113db612eb5565b604051908082528060200260200182016040528015611404578160200160208202803683370190505b506001600160a01b038616600090815261012f60205260408120919250805b8481101561156057600086828151811061143f5761143f612e51565b602002602001015190506000610102828154811061145f5761145f612e51565b906000526020600020906003020190506000816002015490508086600201600082825461148c9190612daa565b9091555061149b90508161252f565b60ff60008282546114ac9190612daa565b925050819055508061010360008282546114c69190612daa565b909155506114d690508186612d97565b9450828785815181106114eb576114eb612e51565b60200260200101818152505061010289858151811061150c5761150c612e51565b60200260200101518154811061152457611524612e51565b600091825260208220600390910201818155600180820180546001600160a01b0319169055600290910191909155939093019250611423915050565b508461156d600186612daa565b8151811061157d5761157d612e51565b60209081029190910101518255611594878261253c565b7fd4e9104c456539f8bc402dcb01d19f8d74a18e45395a5b518feb89fbbda5961c836040516115c39190612ecb565b60405180910390a16040518181526001600160a01b0388169033907fd12200efa34901b99367694174c3b0d32c99585fdf37c7c26892136ddd0836d99060200160405180910390a350505050505061161b6001606555565b50565b60006101065461010354611630610b44565b61163a9190612daa565b610dae9190612daa565b60006101065461010054611656610b44565b61165e611e34565b6116689190612d97565b61163a9190612d97565b600061167c612025565b6001600160a01b03821633146116a55760405163469a130f60e01b815260040160405180910390fd5b6116af838561207e565b6116b884610d2e565b905060006116c78585856123d0565b60408051838152602081018990529294509092506001600160a01b03808616929087169183917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a46040518181527f7a0ce3009764b2f1677c7f67b18dc519c5b2d47d0d7f45081e2edf36c8474dd79060200160405180910390a1506117566001606555565b9392505050565b611765612162565b604051806040016040528083600281111561178257611782612e84565b815260200182600281111561179957611799612e84565b90526001600160e01b03198416600090815261013d6020526040902081518154829060ff191660018360028111156117d3576117d3612e84565b021790555060208201518154829061ff0019166101008360028111156117fb576117fb612e84565b0217905550905050826001600160e01b0319167ffc2ae1ef55404e9b12cfaca1546ea9cdcac8ae491f101a407462bc926655c157838360405161183f929190612efc565b60405180910390a2505050565b600061185a60335460ff1690565b15611866576000610d39565b60c9546040516370a0823160e01b81526001600160a01b038481166004830152610d399216906370a0823190602401602060405180830381865afa1580156118b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109499190612de7565b6000610d39826125df565b60fc546001600160a01b0382811660009081526101046020526040808220549051630aa794bf60e31b815290831660048201529092919091169063553ca5f890602401610dfb565b60008061193461161e565b90508083111561195a57604051636688dd2d60e11b8152600481018290526024016109b4565b61013554738a6a8a7233b16d0ecaa7510bfd110464a0d69f669063cfe6424490859084906402540be40090600160401b90046001600160401b031661199d6121bc565b6119a79190612e00565b6119b19190612dd3565b61013554610134546001600160401b0391821691600160c01b909104166119d66121bc565b6040516001600160e01b031960e089901b1681526004810196909652602486019490945260448501929092526001600160401b03908116606485015216608483015260a482015260c401602060405180830381865af4158015611a3d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190612de7565b611a69612162565b6001600160a01b0381163b611a9157604051636f7c43f160e01b815260040160405180910390fd5b61013854604080516001600160a01b03928316815291831660208301527f86214bbaa96d45f51d9923d72e74002d58b5554ccd07b1dbf67a6781adfa9e7c910160405180910390a161013880546001600160a01b0319166001600160a01b0392909216919091179055565b6000611b0a60335460ff1690565b15611b1757506000919050565b61012d546040516370a0823160e01b81526001600160a01b03848116600483015260009216906370a0823190602401602060405180830381865afa158015611b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b879190612de7565b90506000611b9661082d61161e565b9050818111611ba55780611ba7565b815b949350505050565b919050565b6101028181548110611bc557600080fd5b60009182526020909120600390910201805460018201546002909201549092506001600160a01b039091169083565b6000611bfe6121bc565b611c0661161e565b10611c1b57611c136121bc565b61163a61161e565b50600090565b6101058181548110611c3257600080fd5b6000918252602090912001546001600160a01b0316905081565b6000611c56612025565b60405182907f3c16de186f1ef5ecb8049424d69d8038355dfdd932e194e95067b0dadd05259890600090a2611c8c8433856121e8565b90506117566001606555565b6001600160a01b03808216600090815261012f6020908152604080832081516060818101845282548083526001840154909716948201949094526002909101549181019190915260fd549293919284928391611cf49190612daa565b6001600160401b03811115611d0b57611d0b612eb5565b604051908082528060200260200182016040528015611d34578160200160208202803683370190505b5090508160400151600003611d50576000969095509350505050565b60005b60fd54811015611dd357866001600160a01b03166101028281548110611d7b57611d7b612e51565b60009182526020909120600160039092020101546001600160a01b031603611dcb576001955080828581518110611db457611db4612e51565b6020908102919091010152611dc884612f22565b93505b600101611d53565b506000838251611de39190612daa565b1115611ded578281525b9395939450505050565b6000806000610106541115611e2257611e0f83610fc5565b905061010654811115611e225750610106545b611756611e2f8285612d97565b6125df565b61010554600090815b81811015611f325760006001600160a01b03166101058281548110611e6457611e64612e51565b6000918252602090912001546001600160a01b031614611f2a5760fc5461010580546001600160a01b039092169163553ca5f8919084908110611ea957611ea9612e51565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa158015611ef9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f1d9190612de7565b611f279084612d97565b92505b600101611e3d565b5060fc54604051630aa794bf60e31b81523060048201526001600160a01b039091169063553ca5f890602401602060405180830381865afa158015611f7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9f9190612de7565b611fa99083612d97565b91505090565b611fb7612162565b6001600160a01b03811661201c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109b4565b61161b8161237e565b6002606554036120775760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b4565b6002606555565b8060000361209f5760405163a22b4cd760e01b815260040160405180910390fd5b6001600160a01b0382166120c65760405163a22b4cd760e01b815260040160405180910390fd5b610107546000036120ea57604051638e201a8b60e01b815260040160405180910390fd5b610133546001600160a01b031661211457604051638e201a8b60e01b815260040160405180910390fd5b61211c6125fb565b610b4057604051638e201a8b60e01b815260040160405180910390fd5b6000610d39600283612daa565b6000610d3982670de0b6b3a764000061215d611110565b6127ed565b6097546001600160a01b0316331461110e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109b4565b600068056bc75e2d631000006121d0611644565b610107546121de9190612e00565b610dae9190612dd3565b60006121f4828561282a565b60006121fe610b44565b61010654909150600090801561227c5761221787610fc5565b91508082111561222f57600061010655905080612248565b8161010660008282546122429190612daa565b90915550505b6040518281527f077077dea12adfa76313c61094bf1bc51a7e07cba7ea862339145674988e8a079060200160405180910390a15b61228686886128a0565b5082612290610b44565b61229a9190612daa565b965060006122ab61082d848a612d97565b61012d546040516340c10f1960e01b81526001600160a01b038981166004830152602482018490529293509116906340c10f1990604401600060405180830381600087803b1580156122fc57600080fd5b505af1158015612310573d6000803e3d6000fd5b5050505061231d81612a32565b856001600160a01b0316876001600160a01b03167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d78a8460405161236b929190918252602082015260400190565b60405180910390a3979650505050505050565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008060006123de86610d2e565b905061012e5481101561240b5761012e5460405163279dbb3d60e11b81526004016109b491815260200190565b61012d54604051632770a7eb60e21b81526001600160a01b0386811660048301526024820189905290911690639dc29fac90604401600060405180830381600087803b15801561245a57600080fd5b505af115801561246e573d6000803e3d6000fd5b50505050600061247d82611929565b9050806000036124a057604051636a21a0e160e11b815260040160405180910390fd5b610133546000906402540be400906124c890600160a01b90046001600160401b031684612e00565b6124d29190612dd3565b90506124de8284612daa565b92506124ea8183612daa565b61010660008282546124fc9190612d97565b909155505061013354612518906001600160a01b03168261253c565b612522878461253c565b5090969095509350505050565b6000610d39826002612d97565b60c95460405163a9059cbb60e01b81526001600160a01b038481166004830152602482018490529091169063a9059cbb906044016020604051808303816000875af115801561258f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b39190612f3b565b610b405760c954604051631fca53a760e11b81526001600160a01b0390911660048201526024016109b4565b6000610d39826125ed611110565b670de0b6b3a76400006127ed565b6000805b610105548110156126f75760006001600160a01b0316610105828154811061262957612629612e51565b6000918252602090912001546001600160a01b0316146126ef576101015461010580546001600160a01b0390921691633e28391d91908490811061266f5761266f612e51565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa1580156126bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e39190612f3b565b6126ef57600091505090565b6001016125ff565b5060fc54604051630aa794bf60e31b81523060048201526000916001600160a01b03169063553ca5f890602401602060405180830381865afa158015612741573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127659190612de7565b1180156127dc575061010154604051633e28391d60e01b81523060048201526001600160a01b0390911690633e28391d90602401602060405180830381865afa1580156127b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127da9190612f3b565b155b156127e75750600090565b50600190565b6000611ba76128056127ff8487612dd3565b85612a53565b83856128118289612f5d565b61281b9190612e00565b6128259190612dd3565b612a89565b6001600160a01b0382166128515760405163a22b4cd760e01b815260040160405180910390fd5b61012e5481101561287c5761012e5460405163279dbb3d60e11b81526004016109b491815260200190565b6101075460000361211457604051638e201a8b60e01b815260040160405180910390fd5b60c9546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156128ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129119190612de7565b60c9546040516323b872dd60e01b81526001600160a01b038781166004830152306024830152604482018790529293509116906323b872dd906064016020604051808303816000875af115801561296c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129909190612f3b565b6129bc5760c9546040516302ce902360e61b81526001600160a01b0390911660048201526024016109b4565b60c9546040516370a0823160e01b815230600482015282916001600160a01b0316906370a0823190602401602060405180830381865afa158015612a04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a289190612de7565b611ba79190612daa565b8060000361161b5760405163fa86b6d160e01b815260040160405180910390fd5b600082600003612a6557506000610d39565b82820282848281612a7857612a78612dbd565b041461175657600019915050610d39565b60008282018381101561175657600019915050610d39565b80356001600160a01b0381168114611baf57600080fd5b60008060408385031215612acb57600080fd5b82359150612adb60208401612aa1565b90509250929050565b60006020808352835180602085015260005b81811015612b1257858101830151858201604001528201612af6565b506000604082860101526040601f19601f8301168501019250505092915050565b600060208284031215612b4557600080fd5b5035919050565b600060208284031215612b5e57600080fd5b61175682612aa1565b60008083601f840112612b7957600080fd5b5081356001600160401b03811115612b9057600080fd5b6020830191508360208260051b8501011115612bab57600080fd5b9250929050565b60008060008060008060608789031215612bcb57600080fd5b86356001600160401b0380821115612be257600080fd5b612bee8a838b01612b67565b90985096506020890135915080821115612c0757600080fd5b612c138a838b01612b67565b90965094506040890135915080821115612c2c57600080fd5b50612c3989828a01612b67565b979a9699509497509295939492505050565b600080600060608486031215612c6057600080fd5b83359250612c7060208501612aa1565b9150612c7e60408501612aa1565b90509250925092565b80356001600160e01b031981168114611baf57600080fd5b6003811061161b57600080fd5b600080600060608486031215612cc157600080fd5b612cca84612c87565b92506020840135612cda81612c9f565b91506040840135612cea81612c9f565b809150509250925092565b600080600060608486031215612d0a57600080fd5b83359250612d1a60208501612aa1565b9150604084013590509250925092565b60008151808452602080850194506020840160005b83811015612d5b57815187529582019590820190600101612d3f565b509495945050505050565b8215158152604060208201526000611ba76040830184612d2a565b634e487b7160e01b600052601160045260246000fd5b80820180821115610d3957610d39612d81565b81810381811115610d3957610d39612d81565b634e487b7160e01b600052601260045260246000fd5b600082612de257612de2612dbd565b500490565b600060208284031215612df957600080fd5b5051919050565b8082028115828204841417610d3957610d39612d81565b600181811c90821680612e2b57607f821691505b602082108103612e4b57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612e7957600080fd5b813561175681612c9f565b634e487b7160e01b600052602160045260246000fd5b600060208284031215612eac57600080fd5b61175682612c87565b634e487b7160e01b600052604160045260246000fd5b6020815260006117566020830184612d2a565b6003811061161b57634e487b7160e01b600052602160045260246000fd5b60408101612f0984612ede565b838252612f1583612ede565b8260208301529392505050565b600060018201612f3457612f34612d81565b5060010190565b600060208284031215612f4d57600080fd5b8151801515811461175657600080fd5b600082612f6c57612f6c612dbd565b50069056fea264697066735822122060bb82fa1ead8e2b29d101bd6fae098d98501f26717e3240172262c6a61c02c164736f6c63430008180033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061041b5760003560e01c80638da5cb5b1161022b578063c235fb1411610130578063e91bb844116100b8578063edb594fc11610087578063edb594fc14610907578063ef13b2c71461091a578063ef8b30f71461093b578063f29768711461094e578063f2fde38b1461095657600080fd5b8063e91bb844146108a2578063e93c4f15146108d8578063ea4d3c9b146108e0578063eae43a44146108f457600080fd5b8063cea6443a116100ff578063cea6443a14610845578063d1ef0c9414610858578063d8266c181461086c578063d905777e1461087f578063e78078971461089257600080fd5b8063c235fb14146107f8578063c63d75b61461080c578063c6e6f5921461081f578063ce5119ee1461083257600080fd5b80639b2cb5d8116101b3578063b637d66911610182578063b637d669146107b6578063b68ef559146107c0578063ba087652146107c8578063c059a38e146107db578063c137d8ad146107e557600080fd5b80639b2cb5d814610751578063a8c62e761461075b578063ab89b6af1461076e578063b0e21e8a1461079b57600080fd5b806390fed28d116101fa57806390fed28d146106f557806394bf804d1461070857806395a2251f1461071b5780639669c7cf1461072e57806396c8d48e1461073657600080fd5b80638da5cb5b146106bd5780638e29ebb5146106ce578063900cf0cf146106e2578063901a7d53146106eb57600080fd5b80634baa6193116103315780636ba176c7116102b957806371ca337d1161028857806371ca337d14610667578063779a6cdd1461066f5780637839030f146106835780637b487a65146106965780638a2fc4e3146106a957600080fd5b80636ba176c7146106265780636e553f651461063957806370a082311461064c578063715018a61461065f57600080fd5b80635c975abb116103005780635c975abb146105d557806361d027b3146105eb57806366bcd641146105ff5780636a1ae053146106085780636b77b2f51461061c57600080fd5b80634baa6193146105925780634cdad506146105a657806353268ad0146105b95780635c60da1b146105c357600080fd5b80632b6fd4f1116103b457806339b70e381161038357806339b70e3814610534578063402d267d14610547578063470a567c1461055a5780634886a9571461056d5780634a6b629d1461058857600080fd5b80632b6fd4f1146104da5780632df2228a1461050657806330e4cf3a1461050f57806338d52e0f1461052357600080fd5b806307a2d13a116103f057806307a2d13a146104985780631036bbe2146104ab57806318160ddd146104b75780631f2ed36f146104bf57600080fd5b806292891714610420578062f714ce1461045857806301e1d1141461046d57806306fdde0314610483575b600080fd5b6101345461043b90600160c01b90046001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b61046b610466366004612ab8565b610969565b005b610475610b44565b60405190815260200161044f565b61048b610c9f565b60405161044f9190612ae4565b6104756104a6366004612b33565b610d2e565b61043b6402540be40081565b610475610d3f565b6101345461043b90600160401b90046001600160401b031681565b610138546104ee906001600160a01b031681565b6040516001600160a01b03909116815260200161044f565b61010054610475565b610137546104ee906001600160a01b031681565b60c9546001600160a01b03166104ee565b60fb546104ee906001600160a01b031681565b610475610555366004612b4c565b610db3565b61046b610568366004612bb2565b610e3c565b6101345461043b90600160801b90046001600160401b031681565b6104756101075481565b610131546104ee906001600160a01b031681565b6104756105b4366004612b33565b610fa4565b6104756101035481565b610131546001600160a01b03166104ee565b60335460ff16604051901515815260200161044f565b610133546104ee906001600160a01b031681565b61047560ff5481565b6101355461043b906001600160401b031681565b61047561013b5481565b610475610634366004612b33565b610fc5565b610475610647366004612ab8565b6110a7565b61047561065a366004612b4c565b6110c8565b61046b6110fc565b610475611110565b6101345461043b906001600160401b031681565b61046b610691366004612b4c565b611163565b61046b6106a4366004612b4c565b6111fe565b610136546104ee906001600160a01b031681565b6097546001600160a01b03166104ee565b610132546104ee906001600160a01b031681565b61047560fd5481565b61047561013a5481565b61046b610703366004612ab8565b611299565b610475610716366004612ab8565b61130f565b61046b610729366004612b4c565b611386565b61047561161e565b6101355461043b90600160401b90046001600160401b031681565b61047561012e5481565b60fc546104ee906001600160a01b031681565b61047561077c366004612b4c565b6001600160a01b0316600090815261012f602052604090206002015490565b6101335461043b90600160a01b90046001600160401b031681565b61047561013c5481565b610475611644565b6104756107d6366004612c4b565b611672565b6104756101065481565b61046b6107f3366004612cac565b61175d565b61012d546104ee906001600160a01b031681565b61047561081a366004612b4c565b61184c565b61047561082d366004612b33565b6118d6565b610475610840366004612b4c565b6118e1565b610475610853366004612b33565b611929565b610139546104ee906001600160a01b031681565b61046b61087a366004612b4c565b611a61565b61047561088d366004612b4c565b611afc565b61047568056bc75e2d6310000081565b6108b56108b0366004612b33565b611bb4565b604080519384526001600160a01b0390921660208401529082015260600161044f565b610475611bf4565b610101546104ee906001600160a01b031681565b6104ee610902366004612b33565b611c21565b610475610915366004612cf5565b611c4c565b61092d610928366004612b4c565b611c98565b60405161044f929190612d66565b610475610949366004612b33565b611df7565b610475611e34565b61046b610964366004612b4c565b611faf565b610971612025565b61097b818361207e565b33600061098784610d2e565b905061012e548110156109bd5761012e5460405163279dbb3d60e11b81526004016109b491815260200190565b60405180910390fd5b61012d54604051632770a7eb60e21b81526001600160a01b0384811660048301526024820187905290911690639dc29fac90604401600060405180830381600087803b158015610a0c57600080fd5b505af1158015610a20573d6000803e3d6000fd5b505050508060ff6000828254610a369190612d97565b90915550506001600160a01b038316600090815261012f60205260409020610a5d82612139565b816002016000828254610a709190612d97565b909155505060408051606081018252610102805482526001600160a01b0387166020830152918101610aa185612139565b9052815460018082018455600093845260209384902083516003909302019182558284015190820180546001600160a01b0319166001600160a01b039283161790556040928301516002909201919091558151858152928301889052858116929087169183917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db91015b60405180910390a4505050610b406001606555565b5050565b6000806201518061013b5442610b5a9190612daa565b610b649190612dd3565b905060006201518061013c54610b7a9190612dd3565b905080821115610bf75760c9546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610bcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf09190612de7565b9250505090565b6000610c038383612daa565b8261013a54610c129190612dd3565b610c1c9190612e00565b60c9546040516370a0823160e01b815230600482015291925082916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d9190612de7565b610c979190612daa565b935050505090565b6101308054610cad90612e17565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd990612e17565b8015610d265780601f10610cfb57610100808354040283529160200191610d26565b820191906000526020600020905b815481529060010190602001808311610d0957829003601f168201915b505050505081565b6000610d3982612146565b92915050565b61012d54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae9190612de7565b905090565b6000610dc160335460ff1690565b15610dcd576000610d39565b60c9546040516370a0823160e01b81526001600160a01b038481166004830152909116906370a08231906024015b602060405180830381865afa158015610e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d399190612de7565b610e44612162565b848381141580610e545750808214155b15610e725760405163afff5f7760e01b815260040160405180910390fd5b60005b81811015610f9a576040518060400160405280878784818110610e9a57610e9a612e51565b9050602002016020810190610eaf9190612e67565b6002811115610ec057610ec0612e84565b8152602001858584818110610ed757610ed7612e51565b9050602002016020810190610eec9190612e67565b6002811115610efd57610efd612e84565b905261013d60008a8a85818110610f1657610f16612e51565b9050602002016020810190610f2b9190612e9a565b6001600160e01b0319168152602081019190915260400160002081518154829060ff19166001836002811115610f6357610f63612e84565b021790555060208201518154829061ff001916610100836002811115610f8b57610f8b612e84565b02179055505050600101610e75565b5050505050505050565b6000610fb261085383610d2e565b610fbb83612146565b610d399190612daa565b6000738a6a8a7233b16d0ecaa7510bfd110464a0d69f6663fea65f7283610fea61161e565b610134546402540be40090600160801b90046001600160401b031661100d6121bc565b6110179190612e00565b6110219190612dd3565b610134546001600160401b03600160401b8204811691166110406121bc565b6040516001600160e01b031960e089901b1681526004810196909652602486019490945260448501929092526001600160401b03908116606485015216608483015260a482015260c401602060405180830381865af4158015610e18573d6000803e3d6000fd5b60006110b1612025565b6110bc8333846121e8565b9050610d396001606555565b61012d546040516370a0823160e01b81526001600160a01b03838116600483015260009216906370a0823190602401610dfb565b611104612162565b61110e600061237e565b565b6101325461012d5460405163a1f1d48d60e01b81526001600160a01b039182166004820152600092919091169063a1f1d48d90602401602060405180830381865afa158015610d8a573d6000803e3d6000fd5b61116b612162565b6001600160a01b0381163b61119357604051636f7c43f160e01b815260040160405180910390fd5b61013954604080516001600160a01b03928316815291831660208301527f16b3a5b47cfc3418106cb8fd15fc5df8b17ea324464f7655b052d9e4a3a14df2910160405180910390a161013980546001600160a01b0319166001600160a01b0392909216919091179055565b611206612162565b6001600160a01b0381163b61122e57604051636f7c43f160e01b815260040160405180910390fd5b61013754604080516001600160a01b03928316815291831660208301527fe6b9ab4b050c05a6c2d41e35b5c0112bb6c563134cc0daccc29a7a44d5da47fe910160405180910390a161013780546001600160a01b0319166001600160a01b0392909216919091179055565b6112a1612025565b6112ab818361207e565b336000806112ba8585856123d0565b604080518381526020810189905290810182905291935091506001600160a01b03808516919086169082907f22b8f008297894112d5322d194442062aad3c25bbcdd07d2b0fa30a9e026e53c90606001610b2b565b6000611319612025565b60006113248361184c565b905080841115611360576040516330ac82f560e11b81526001600160a01b038416600482015260248101859052604481018290526064016109b4565b600061136b85610d2e565b90506113788133866121e8565b50915050610d396001606555565b61138e612025565b60008061139a83611c98565b91509150816113bf5760405160016289337960e01b0319815260040160405180910390fd5b80516000816001600160401b038111156113db576113db612eb5565b604051908082528060200260200182016040528015611404578160200160208202803683370190505b506001600160a01b038616600090815261012f60205260408120919250805b8481101561156057600086828151811061143f5761143f612e51565b602002602001015190506000610102828154811061145f5761145f612e51565b906000526020600020906003020190506000816002015490508086600201600082825461148c9190612daa565b9091555061149b90508161252f565b60ff60008282546114ac9190612daa565b925050819055508061010360008282546114c69190612daa565b909155506114d690508186612d97565b9450828785815181106114eb576114eb612e51565b60200260200101818152505061010289858151811061150c5761150c612e51565b60200260200101518154811061152457611524612e51565b600091825260208220600390910201818155600180820180546001600160a01b0319169055600290910191909155939093019250611423915050565b508461156d600186612daa565b8151811061157d5761157d612e51565b60209081029190910101518255611594878261253c565b7fd4e9104c456539f8bc402dcb01d19f8d74a18e45395a5b518feb89fbbda5961c836040516115c39190612ecb565b60405180910390a16040518181526001600160a01b0388169033907fd12200efa34901b99367694174c3b0d32c99585fdf37c7c26892136ddd0836d99060200160405180910390a350505050505061161b6001606555565b50565b60006101065461010354611630610b44565b61163a9190612daa565b610dae9190612daa565b60006101065461010054611656610b44565b61165e611e34565b6116689190612d97565b61163a9190612d97565b600061167c612025565b6001600160a01b03821633146116a55760405163469a130f60e01b815260040160405180910390fd5b6116af838561207e565b6116b884610d2e565b905060006116c78585856123d0565b60408051838152602081018990529294509092506001600160a01b03808616929087169183917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a46040518181527f7a0ce3009764b2f1677c7f67b18dc519c5b2d47d0d7f45081e2edf36c8474dd79060200160405180910390a1506117566001606555565b9392505050565b611765612162565b604051806040016040528083600281111561178257611782612e84565b815260200182600281111561179957611799612e84565b90526001600160e01b03198416600090815261013d6020526040902081518154829060ff191660018360028111156117d3576117d3612e84565b021790555060208201518154829061ff0019166101008360028111156117fb576117fb612e84565b0217905550905050826001600160e01b0319167ffc2ae1ef55404e9b12cfaca1546ea9cdcac8ae491f101a407462bc926655c157838360405161183f929190612efc565b60405180910390a2505050565b600061185a60335460ff1690565b15611866576000610d39565b60c9546040516370a0823160e01b81526001600160a01b038481166004830152610d399216906370a0823190602401602060405180830381865afa1580156118b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109499190612de7565b6000610d39826125df565b60fc546001600160a01b0382811660009081526101046020526040808220549051630aa794bf60e31b815290831660048201529092919091169063553ca5f890602401610dfb565b60008061193461161e565b90508083111561195a57604051636688dd2d60e11b8152600481018290526024016109b4565b61013554738a6a8a7233b16d0ecaa7510bfd110464a0d69f669063cfe6424490859084906402540be40090600160401b90046001600160401b031661199d6121bc565b6119a79190612e00565b6119b19190612dd3565b61013554610134546001600160401b0391821691600160c01b909104166119d66121bc565b6040516001600160e01b031960e089901b1681526004810196909652602486019490945260448501929092526001600160401b03908116606485015216608483015260a482015260c401602060405180830381865af4158015611a3d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190612de7565b611a69612162565b6001600160a01b0381163b611a9157604051636f7c43f160e01b815260040160405180910390fd5b61013854604080516001600160a01b03928316815291831660208301527f86214bbaa96d45f51d9923d72e74002d58b5554ccd07b1dbf67a6781adfa9e7c910160405180910390a161013880546001600160a01b0319166001600160a01b0392909216919091179055565b6000611b0a60335460ff1690565b15611b1757506000919050565b61012d546040516370a0823160e01b81526001600160a01b03848116600483015260009216906370a0823190602401602060405180830381865afa158015611b63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b879190612de7565b90506000611b9661082d61161e565b9050818111611ba55780611ba7565b815b949350505050565b919050565b6101028181548110611bc557600080fd5b60009182526020909120600390910201805460018201546002909201549092506001600160a01b039091169083565b6000611bfe6121bc565b611c0661161e565b10611c1b57611c136121bc565b61163a61161e565b50600090565b6101058181548110611c3257600080fd5b6000918252602090912001546001600160a01b0316905081565b6000611c56612025565b60405182907f3c16de186f1ef5ecb8049424d69d8038355dfdd932e194e95067b0dadd05259890600090a2611c8c8433856121e8565b90506117566001606555565b6001600160a01b03808216600090815261012f6020908152604080832081516060818101845282548083526001840154909716948201949094526002909101549181019190915260fd549293919284928391611cf49190612daa565b6001600160401b03811115611d0b57611d0b612eb5565b604051908082528060200260200182016040528015611d34578160200160208202803683370190505b5090508160400151600003611d50576000969095509350505050565b60005b60fd54811015611dd357866001600160a01b03166101028281548110611d7b57611d7b612e51565b60009182526020909120600160039092020101546001600160a01b031603611dcb576001955080828581518110611db457611db4612e51565b6020908102919091010152611dc884612f22565b93505b600101611d53565b506000838251611de39190612daa565b1115611ded578281525b9395939450505050565b6000806000610106541115611e2257611e0f83610fc5565b905061010654811115611e225750610106545b611756611e2f8285612d97565b6125df565b61010554600090815b81811015611f325760006001600160a01b03166101058281548110611e6457611e64612e51565b6000918252602090912001546001600160a01b031614611f2a5760fc5461010580546001600160a01b039092169163553ca5f8919084908110611ea957611ea9612e51565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa158015611ef9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f1d9190612de7565b611f279084612d97565b92505b600101611e3d565b5060fc54604051630aa794bf60e31b81523060048201526001600160a01b039091169063553ca5f890602401602060405180830381865afa158015611f7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9f9190612de7565b611fa99083612d97565b91505090565b611fb7612162565b6001600160a01b03811661201c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109b4565b61161b8161237e565b6002606554036120775760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b4565b6002606555565b8060000361209f5760405163a22b4cd760e01b815260040160405180910390fd5b6001600160a01b0382166120c65760405163a22b4cd760e01b815260040160405180910390fd5b610107546000036120ea57604051638e201a8b60e01b815260040160405180910390fd5b610133546001600160a01b031661211457604051638e201a8b60e01b815260040160405180910390fd5b61211c6125fb565b610b4057604051638e201a8b60e01b815260040160405180910390fd5b6000610d39600283612daa565b6000610d3982670de0b6b3a764000061215d611110565b6127ed565b6097546001600160a01b0316331461110e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109b4565b600068056bc75e2d631000006121d0611644565b610107546121de9190612e00565b610dae9190612dd3565b60006121f4828561282a565b60006121fe610b44565b61010654909150600090801561227c5761221787610fc5565b91508082111561222f57600061010655905080612248565b8161010660008282546122429190612daa565b90915550505b6040518281527f077077dea12adfa76313c61094bf1bc51a7e07cba7ea862339145674988e8a079060200160405180910390a15b61228686886128a0565b5082612290610b44565b61229a9190612daa565b965060006122ab61082d848a612d97565b61012d546040516340c10f1960e01b81526001600160a01b038981166004830152602482018490529293509116906340c10f1990604401600060405180830381600087803b1580156122fc57600080fd5b505af1158015612310573d6000803e3d6000fd5b5050505061231d81612a32565b856001600160a01b0316876001600160a01b03167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d78a8460405161236b929190918252602082015260400190565b60405180910390a3979650505050505050565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008060006123de86610d2e565b905061012e5481101561240b5761012e5460405163279dbb3d60e11b81526004016109b491815260200190565b61012d54604051632770a7eb60e21b81526001600160a01b0386811660048301526024820189905290911690639dc29fac90604401600060405180830381600087803b15801561245a57600080fd5b505af115801561246e573d6000803e3d6000fd5b50505050600061247d82611929565b9050806000036124a057604051636a21a0e160e11b815260040160405180910390fd5b610133546000906402540be400906124c890600160a01b90046001600160401b031684612e00565b6124d29190612dd3565b90506124de8284612daa565b92506124ea8183612daa565b61010660008282546124fc9190612d97565b909155505061013354612518906001600160a01b03168261253c565b612522878461253c565b5090969095509350505050565b6000610d39826002612d97565b60c95460405163a9059cbb60e01b81526001600160a01b038481166004830152602482018490529091169063a9059cbb906044016020604051808303816000875af115801561258f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b39190612f3b565b610b405760c954604051631fca53a760e11b81526001600160a01b0390911660048201526024016109b4565b6000610d39826125ed611110565b670de0b6b3a76400006127ed565b6000805b610105548110156126f75760006001600160a01b0316610105828154811061262957612629612e51565b6000918252602090912001546001600160a01b0316146126ef576101015461010580546001600160a01b0390921691633e28391d91908490811061266f5761266f612e51565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa1580156126bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e39190612f3b565b6126ef57600091505090565b6001016125ff565b5060fc54604051630aa794bf60e31b81523060048201526000916001600160a01b03169063553ca5f890602401602060405180830381865afa158015612741573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127659190612de7565b1180156127dc575061010154604051633e28391d60e01b81523060048201526001600160a01b0390911690633e28391d90602401602060405180830381865afa1580156127b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127da9190612f3b565b155b156127e75750600090565b50600190565b6000611ba76128056127ff8487612dd3565b85612a53565b83856128118289612f5d565b61281b9190612e00565b6128259190612dd3565b612a89565b6001600160a01b0382166128515760405163a22b4cd760e01b815260040160405180910390fd5b61012e5481101561287c5761012e5460405163279dbb3d60e11b81526004016109b491815260200190565b6101075460000361211457604051638e201a8b60e01b815260040160405180910390fd5b60c9546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156128ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129119190612de7565b60c9546040516323b872dd60e01b81526001600160a01b038781166004830152306024830152604482018790529293509116906323b872dd906064016020604051808303816000875af115801561296c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129909190612f3b565b6129bc5760c9546040516302ce902360e61b81526001600160a01b0390911660048201526024016109b4565b60c9546040516370a0823160e01b815230600482015282916001600160a01b0316906370a0823190602401602060405180830381865afa158015612a04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a289190612de7565b611ba79190612daa565b8060000361161b5760405163fa86b6d160e01b815260040160405180910390fd5b600082600003612a6557506000610d39565b82820282848281612a7857612a78612dbd565b041461175657600019915050610d39565b60008282018381101561175657600019915050610d39565b80356001600160a01b0381168114611baf57600080fd5b60008060408385031215612acb57600080fd5b82359150612adb60208401612aa1565b90509250929050565b60006020808352835180602085015260005b81811015612b1257858101830151858201604001528201612af6565b506000604082860101526040601f19601f8301168501019250505092915050565b600060208284031215612b4557600080fd5b5035919050565b600060208284031215612b5e57600080fd5b61175682612aa1565b60008083601f840112612b7957600080fd5b5081356001600160401b03811115612b9057600080fd5b6020830191508360208260051b8501011115612bab57600080fd5b9250929050565b60008060008060008060608789031215612bcb57600080fd5b86356001600160401b0380821115612be257600080fd5b612bee8a838b01612b67565b90985096506020890135915080821115612c0757600080fd5b612c138a838b01612b67565b90965094506040890135915080821115612c2c57600080fd5b50612c3989828a01612b67565b979a9699509497509295939492505050565b600080600060608486031215612c6057600080fd5b83359250612c7060208501612aa1565b9150612c7e60408501612aa1565b90509250925092565b80356001600160e01b031981168114611baf57600080fd5b6003811061161b57600080fd5b600080600060608486031215612cc157600080fd5b612cca84612c87565b92506020840135612cda81612c9f565b91506040840135612cea81612c9f565b809150509250925092565b600080600060608486031215612d0a57600080fd5b83359250612d1a60208501612aa1565b9150604084013590509250925092565b60008151808452602080850194506020840160005b83811015612d5b57815187529582019590820190600101612d3f565b509495945050505050565b8215158152604060208201526000611ba76040830184612d2a565b634e487b7160e01b600052601160045260246000fd5b80820180821115610d3957610d39612d81565b81810381811115610d3957610d39612d81565b634e487b7160e01b600052601260045260246000fd5b600082612de257612de2612dbd565b500490565b600060208284031215612df957600080fd5b5051919050565b8082028115828204841417610d3957610d39612d81565b600181811c90821680612e2b57607f821691505b602082108103612e4b57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612e7957600080fd5b813561175681612c9f565b634e487b7160e01b600052602160045260246000fd5b600060208284031215612eac57600080fd5b61175682612c87565b634e487b7160e01b600052604160045260246000fd5b6020815260006117566020830184612d2a565b6003811061161b57634e487b7160e01b600052602160045260246000fd5b60408101612f0984612ede565b838252612f1583612ede565b8260208301529392505050565b600060018201612f3457612f34612d81565b5060010190565b600060208284031215612f4d57600080fd5b8151801515811461175657600080fd5b600082612f6c57612f6c612dbd565b50069056fea264697066735822122060bb82fa1ead8e2b29d101bd6fae098d98501f26717e3240172262c6a61c02c164736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.