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:
EigenLayerFacet
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 {BeaconProxy} from "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; import "../InceptionVaultStorage_EL.sol"; /** * @title The EigenLayerFacet contract * @author The InceptionLRT team */ contract EigenLayerFacet is InceptionVaultStorage_EL { constructor() payable {} /** * @dev checks whether it's still possible to deposit into the strategy */ function _beforeDepositAssetIntoStrategy(uint256 amount) internal view { if (amount > getFreeBalance()) revert InsufficientCapacity(totalAssets()); (uint256 maxPerDeposit, uint256 maxTotalDeposits) = strategy .getTVLLimits(); if (amount > maxPerDeposit) revert ExceedsMaxPerDeposit(maxPerDeposit, amount); uint256 currentBalance = _asset.balanceOf(address(strategy)); if (currentBalance + amount > maxTotalDeposits) revert ExceedsMaxTotalDeposited(maxTotalDeposits, currentBalance); } function delegateToOperator( uint256 amount, address elOperator, bytes32 approverSalt, IDelegationManager.SignatureWithExpiry memory approverSignatureAndExpiry ) external { if (elOperator == address(0)) revert NullParams(); _beforeDepositAssetIntoStrategy(amount); // try to find a restaker for the specific EL operator address restaker = _operatorRestakers[elOperator]; if (restaker == address(0)) revert OperatorNotRegistered(); bool delegate = false; if (restaker == _MOCK_ADDRESS) { delegate = true; // deploy a new restaker restaker = _deployNewStub(); _operatorRestakers[elOperator] = restaker; restakers.push(restaker); } _depositAssetIntoStrategy(restaker, amount); if (delegate) _delegateToOperator( restaker, elOperator, approverSalt, approverSignatureAndExpiry ); emit DelegatedTo(restaker, elOperator, amount); } /** * @dev delegates assets held in the strategy to the EL operator. */ function _delegateToOperator( address restaker, address elOperator, bytes32 approverSalt, IDelegationManager.SignatureWithExpiry memory approverSignatureAndExpiry ) internal { IInceptionEigenRestaker(restaker).delegateToOperator( elOperator, approverSalt, approverSignatureAndExpiry ); } /// @dev deposits asset to the corresponding strategy function _depositAssetIntoStrategy( address restaker, uint256 amount ) internal { _asset.approve(restaker, amount); IInceptionEigenRestaker(restaker).depositAssetIntoStrategy(amount); emit DepositedToEL(restaker, amount); } /** * @dev performs creating a withdrawal request from EigenLayer * @dev requires a specific amount to withdraw */ function undelegateVault(uint256 amount) external nonReentrant { address staker = address(this); uint256[] memory sharesToWithdraw = new uint256[](1); IStrategy[] memory strategies = new IStrategy[](1); sharesToWithdraw[0] = _undelegate(amount, staker); strategies[0] = strategy; IDelegationManager.QueuedWithdrawalParams[] memory withdrawals = new IDelegationManager.QueuedWithdrawalParams[]( 1 ); /// @notice from Vault withdrawals[0] = IDelegationManager.QueuedWithdrawalParams({ strategies: strategies, shares: sharesToWithdraw, withdrawer: address(this) }); delegationManager.queueWithdrawals(withdrawals); } /** * @dev performs creating a withdrawal request from EigenLayer * @dev requires a specific amount to withdraw */ function undelegateFrom( address elOperatorAddress, uint256 amount ) external nonReentrant { address staker = _operatorRestakers[elOperatorAddress]; if (staker == address(0)) revert OperatorNotRegistered(); if (staker == _MOCK_ADDRESS) revert NullParams(); IInceptionEigenRestaker(staker).withdrawFromEL( _undelegate(amount, staker) ); } function _undelegate( uint256 amount, address staker ) internal returns (uint256) { uint256 nonce = delegationManager.cumulativeWithdrawalsQueued(staker); uint256 totalAssetSharesInEL = strategyManager.stakerStrategyShares( staker, strategy ); uint256 shares = strategy.underlyingToSharesView(amount); amount = strategy.sharesToUnderlyingView(shares); // we need to withdraw the remaining dust from EigenLayer if (totalAssetSharesInEL < shares + 5) shares = totalAssetSharesInEL; _pendingWithdrawalAmount += amount; emit StartWithdrawal( staker, strategy, shares, uint32(block.number), delegationManager.delegatedTo(staker), nonce ); return shares; } /** * @dev claims completed withdrawals from EigenLayer, if they exist */ function claimCompletedWithdrawals( address restaker, IDelegationManager.Withdrawal[] calldata withdrawals ) public nonReentrant { uint256 withdrawalsNum = withdrawals.length; IERC20[][] memory tokens = new IERC20[][](withdrawalsNum); uint256[] memory middlewareTimesIndexes = new uint256[](withdrawalsNum); bool[] memory receiveAsTokens = new bool[](withdrawalsNum); for (uint256 i = 0; i < withdrawalsNum; ++i) { tokens[i] = new IERC20[](1); tokens[i][0] = _asset; receiveAsTokens[i] = true; } uint256 availableBalance = getFreeBalance(); uint256 withdrawnAmount; if (restaker == address(this)) { withdrawnAmount = _claimCompletedWithdrawalsForVault( withdrawals, tokens, middlewareTimesIndexes, receiveAsTokens ); } else { if (!_restakerExists(restaker)) revert RestakerNotRegistered(); withdrawnAmount = IInceptionEigenRestaker(restaker) .claimWithdrawals( withdrawals, tokens, middlewareTimesIndexes, receiveAsTokens ); } emit WithdrawalClaimed(withdrawnAmount); _pendingWithdrawalAmount = _pendingWithdrawalAmount < withdrawnAmount ? 0 : _pendingWithdrawalAmount - withdrawnAmount; if (_pendingWithdrawalAmount < 7) { _pendingWithdrawalAmount = 0; } _updateEpoch(availableBalance + withdrawnAmount); } function _claimCompletedWithdrawalsForVault( IDelegationManager.Withdrawal[] memory withdrawals, IERC20[][] memory tokens, uint256[] memory middlewareTimesIndexes, bool[] memory receiveAsTokens ) internal returns (uint256) { uint256 balanceBefore = _asset.balanceOf(address(this)); delegationManager.completeQueuedWithdrawals( withdrawals, tokens, middlewareTimesIndexes, receiveAsTokens ); // send tokens to the vault uint256 withdrawnAmount = _asset.balanceOf(address(this)) - balanceBefore; return withdrawnAmount; } function updateEpoch() external nonReentrant { _updateEpoch(getFreeBalance()); } function _restakerExists( address restakerAddress ) internal view returns (bool) { uint256 numOfRestakers = restakers.length; for (uint256 i = 0; i < numOfRestakers; ++i) { if (restakerAddress == restakers[i]) return true; } return false; } function _updateEpoch(uint256 availableBalance) internal { uint256 withdrawalsNum = claimerWithdrawalsQueue.length; for (uint256 i = epoch; i < withdrawalsNum; ) { uint256 amount = claimerWithdrawalsQueue[i].amount; unchecked { if (amount > availableBalance) { break; } redeemReservedAmount += amount; availableBalance -= amount; ++epoch; ++i; } } } function forceUndelegateRecovery( uint256 amount, address restaker ) external { if (restaker == address(0)) revert NullParams(); for (uint256 i = 0; i < restakers.length; ++i) { if ( restakers[i] == restaker && !delegationManager.isDelegated(restakers[i]) ) { restakers[i] == _MOCK_ADDRESS; break; } } _pendingWithdrawalAmount += amount; } function _deployNewStub() internal returns (address) { if (stakerImplementation == address(0)) revert ImplementationNotSet(); // deploy new beacon proxy and do init call bytes memory data = abi.encodeWithSignature( "initialize(address,address,address,address,address,address,address)", owner(), rewardsCoordinator, delegationManager, strategyManager, strategy, _asset, _operator ); address deployedAddress = address(new BeaconProxy(address(this), data)); IOwnable asOwnable = IOwnable(deployedAddress); asOwnable.transferOwnership(owner()); emit RestakerDeployed(deployedAddress); return deployedAddress; } /** * @notice Adds new rewards to the contract, starting a new rewards timeline. * @dev The function allows the operator to deposit Ether as rewards. * It verifies that the previous rewards timeline is over before accepting new rewards. */ function addRewards(uint256 amount) external nonReentrant { /// @dev verify whether the prev timeline is over if (currentRewards > 0) { uint256 totalDays = rewardsTimeline / 1 days; uint256 dayNum = (block.timestamp - startTimeline) / 1 days; if (dayNum < totalDays) revert TimelineNotOver(); } currentRewards = _transferAssetFrom(_operator, amount); startTimeline = block.timestamp; emit RewardsAdded(amount, startTimeline); } }
// 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.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":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addRewards","outputs":[],"stateMutability":"nonpayable","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":"address","name":"restaker","type":"address"},{"components":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"delegatedTo","type":"address"},{"internalType":"address","name":"withdrawer","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint32","name":"startBlock","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"}],"internalType":"struct IDelegationManager.Withdrawal[]","name":"withdrawals","type":"tuple[]"}],"name":"claimCompletedWithdrawals","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"elOperator","type":"address"},{"internalType":"bytes32","name":"approverSalt","type":"bytes32"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"internalType":"struct IDelegationManager.SignatureWithExpiry","name":"approverSignatureAndExpiry","type":"tuple"}],"name":"delegateToOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"delegationManager","outputs":[{"internalType":"contract IDelegationManager","name":"","type":"address"}],"stateMutability":"view","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":[],"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":"amount","type":"uint256"},{"internalType":"address","name":"restaker","type":"address"}],"name":"forceUndelegateRecovery","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":[],"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":[],"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":"address","name":"elOperatorAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"undelegateFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"undelegateVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawUtilizationKink","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052614988806100136000396000f3fe60806040523480156200001157600080fd5b5060043610620004745760003560e01c8063841143d21162000259578063c235fb141162000149578063e780789711620000c7578063eae43a441162000092578063eae43a4414620009e9578063ef13b2c71462000a00578063ef8b30f71462000a27578063f29768711462000a3e578063f2fde38b1462000a4857600080fd5b8063e7807897146200097e578063e91bb844146200098f578063e93c4f1514620009ca578063ea4d3c9b14620009d457600080fd5b8063cea6443a1162000114578063cea6443a146200090d578063d1ef0c941462000924578063d8266c181462000939578063d905777e1462000950578063d9540d6a146200096757600080fd5b8063c235fb1414620008b3578063c63d75b614620008c8578063c6e6f59214620008df578063ce5119ee14620008f657600080fd5b8063a8c62e7611620001d7578063b637d66911620001a2578063b637d6691462000865578063b68ef5591462000870578063beceed39146200087a578063c059a38e1462000891578063c137d8ad146200089c57600080fd5b8063a8c62e7614620007ee578063ab89b6af1462000802578063ac48eb9f1462000832578063b0e21e8a146200084957600080fd5b8063900cf0cf1162000224578063900cf0cf14620007a8578063901a7d5314620007b25780639669c7cf14620007bd57806396c8d48e14620007c75780639b2cb5d814620007e357600080fd5b8063841143d214620007555780638a2fc4e3146200076c5780638da5cb5b14620007815780638e29ebb5146200079357600080fd5b80634a6b629d11620003755780636a1ae05311620002f3578063715018a611620002be578063715018a614620006fe57806371ca337d1462000708578063779a6cdd14620007125780637839030f14620007275780637b487a65146200073e57600080fd5b80636a1ae05314620006b05780636b77b2f514620006c55780636ba176c714620006d057806370a0823114620006e757600080fd5b806353268ad0116200034057806353268ad0146200065c5780635c60da1b14620006675780635c975abb146200067a57806361d027b3146200069157806366bcd64114620006a657600080fd5b80634a6b629d146200060e5780634baa619314620006195780634cdad506146200062e5780634fe2bb82146200064557600080fd5b80632b6fd4f1116200040357806338d52e0f11620003ce57806338d52e0f146200059e57806339b70e3814620005b0578063402d267d14620005c4578063470a567c14620005db5780634886a95714620005f257600080fd5b80632b6fd4f114620005475780632df2228a146200057557806330e4cf3a146200057f57806336f4fb02146200059457600080fd5b80631036bbe211620004445780631036bbe214620004fb57806318160ddd14620005085780631f2ed36f1462000512578063252b7edc146200052e57600080fd5b8062928917146200047957806301e1d11414620004b257806306fdde0314620004cb57806307a2d13a14620004e4575b600080fd5b610134546200049590600160c01b90046001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b620004bc62000a5f565b604051908152602001620004a9565b620004d562000bcf565b604051620004a991906200339a565b620004bc620004f5366004620033af565b62000c66565b620004956402540be40081565b620004bc62000c79565b610134546200049590600160401b90046001600160401b031681565b620005456200053f366004620033ec565b62000cf0565b005b610138546200055c906001600160a01b031681565b6040516001600160a01b039091168152602001620004a9565b61010054620004bc565b610137546200055c906001600160a01b031681565b6200054562000de5565b60c9546001600160a01b03166200055c565b60fb546200055c906001600160a01b031681565b620004bc620005d53660046200341b565b62000e10565b62000545620005ec36600462003489565b62000e9f565b610134546200049590600160801b90046001600160401b031681565b620004bc6101075481565b610131546200055c906001600160a01b031681565b620004bc6200063f366004620033af565b62001028565b6200054562000656366004620033af565b62001050565b620004bc6101035481565b610131546001600160a01b03166200055c565b60335460ff166040519015158152602001620004a9565b610133546200055c906001600160a01b031681565b620004bc60ff5481565b6101355462000495906001600160401b031681565b620004bc61013b5481565b620004bc620006e1366004620033af565b6200122b565b620004bc620006f83660046200341b565b62001318565b620005456200134d565b620004bc62001363565b6101345462000495906001600160401b031681565b62000545620007383660046200341b565b620013b7565b620005456200074f3660046200341b565b62001455565b62000545620007663660046200352c565b620014f3565b610136546200055c906001600160a01b031681565b6097546001600160a01b03166200055c565b610132546200055c906001600160a01b031681565b620004bc60fd5481565b620004bc61013a5481565b620004bc62001672565b610135546200049590600160401b90046001600160401b031681565b620004bc61012e5481565b60fc546200055c906001600160a01b031681565b620004bc620008133660046200341b565b6001600160a01b0316600090815261012f602052604090206002015490565b62000545620008433660046200355f565b6200169e565b610133546200049590600160a01b90046001600160401b031681565b620004bc61013c5481565b620004bc620019ee565b620005456200088b366004620033af565b62001a24565b620004bc6101065481565b62000545620008ad366004620035e0565b62001b02565b61012d546200055c906001600160a01b031681565b620004bc620008d93660046200341b565b62001c01565b620004bc620008f0366004620033af565b62001c92565b620004bc620009073660046200341b565b62001c9f565b620004bc6200091e366004620033af565b62001ce8565b610139546200055c906001600160a01b031681565b620005456200094a3660046200341b565b62001e3a565b620004bc620009613660046200341b565b62001ed8565b6200054562000978366004620036c9565b62001f9a565b620004bc68056bc75e2d6310000081565b620009a6620009a0366004620033af565b62002113565b604080519384526001600160a01b03909216602084015290820152606001620004a9565b620004bc62002154565b610101546200055c906001600160a01b031681565b6200055c620009fa366004620033af565b6200218a565b62000a1762000a113660046200341b565b620021b6565b604051620004a992919062003802565b620004bc62000a38366004620033af565b6200232a565b620004bc6200236f565b6200054562000a593660046200341b565b620024fd565b6000806201518061013b544262000a77919062003835565b62000a83919062003861565b905060006201518061013c5462000a9b919062003861565b90508082111562000b1c5760c9546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801562000aef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b15919062003878565b9250505090565b600062000b2a838362003835565b8261013a5462000b3b919062003861565b62000b47919062003892565b60c9546040516370a0823160e01b815230600482015291925082916001600160a01b03909116906370a0823190602401602060405180830381865afa15801562000b95573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000bbb919062003878565b62000bc7919062003835565b935050505090565b610130805462000bdf90620038ac565b80601f016020809104026020016040519081016040528092919081815260200182805462000c0d90620038ac565b801562000c5e5780601f1062000c325761010080835404028352916020019162000c5e565b820191906000526020600020905b81548152906001019060200180831162000c4057829003601f168201915b505050505081565b600062000c738262002579565b92915050565b61012d54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa15801562000cc5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ceb919062003878565b905090565b62000cfa62002599565b6001600160a01b0380831660009081526101046020526040902054168062000d35576040516325ec6c1f60e01b815260040160405180910390fd5b6612344fffffffff196001600160a01b0382160162000d675760405163a22b4cd760e01b815260040160405180910390fd5b806001600160a01b031663b64d26ab62000d828484620025f4565b6040518263ffffffff1660e01b815260040162000da191815260200190565b600060405180830381600087803b15801562000dbc57600080fd5b505af115801562000dd1573d6000803e3d6000fd5b505050505062000de16001606555565b5050565b62000def62002599565b62000e0362000dfd62002154565b620028ef565b62000e0e6001606555565b565b600062000e1f60335460ff1690565b1562000e2d57600062000c73565b60c9546040516370a0823160e01b81526001600160a01b038481166004830152909116906370a08231906024015b602060405180830381865afa15801562000e79573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c73919062003878565b62000ea96200295b565b84838114158062000eba5750808214155b1562000ed95760405163afff5f7760e01b815260040160405180910390fd5b60005b818110156200101e57604051806040016040528087878481811062000f055762000f05620038e8565b905060200201602081019062000f1c9190620038fe565b600281111562000f305762000f306200391e565b815260200185858481811062000f4a5762000f4a620038e8565b905060200201602081019062000f619190620038fe565b600281111562000f755762000f756200391e565b905261013d60008a8a8581811062000f915762000f91620038e8565b905060200201602081019062000fa8919062003934565b6001600160e01b0319168152602081019190915260400160002081518154829060ff1916600183600281111562000fe35762000fe36200391e565b021790555060208201518154829061ff0019166101008360028111156200100e576200100e6200391e565b0217905550505060010162000edc565b5050505050505050565b6000620010396200091e8362000c66565b620010448362002579565b62000c73919062003835565b6200105a62002599565b604080516001808252818301909252309160009190602080830190803683375050604080516001808252818301909252929350600092915060208083019080368337019050509050620010ae8484620025f4565b82600081518110620010c457620010c4620038e8565b602090810291909101015260fc5481516001600160a01b03909116908290600090620010f457620010f4620038e8565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020015b60408051606080820183528082526020820152600091810191909152815260200190600190039081620011245790505090506040518060600160405280838152602001848152602001306001600160a01b031681525081600081518110620011905762001190620038e8565b6020908102919091010152610101546040516306ec6e8160e11b81526001600160a01b0390911690630dd8dd0290620011ce9084906004016200398e565b6000604051808303816000875af1158015620011ee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001218919081019062003a56565b5050505050620012286001606555565b50565b6000738a6a8a7233b16d0ecaa7510bfd110464a0d69f6663fea65f72836200125262001672565b610134546402540be40090600160801b90046001600160401b031662001277620029b7565b62001283919062003892565b6200128f919062003861565b610134546001600160401b03600160401b820481169116620012b0620029b7565b6040516001600160e01b031960e089901b1681526004810196909652602486019490945260448501929092526001600160401b03908116606485015216608483015260a482015260c401602060405180830381865af415801562000e79573d6000803e3d6000fd5b61012d546040516370a0823160e01b81526001600160a01b03838116600483015260009216906370a082319060240162000e5b565b620013576200295b565b62000e0e6000620029e9565b6101325461012d5460405163a1f1d48d60e01b81526001600160a01b039182166004820152600092919091169063a1f1d48d90602401602060405180830381865afa15801562000cc5573d6000803e3d6000fd5b620013c16200295b565b6001600160a01b0381163b620013ea57604051636f7c43f160e01b815260040160405180910390fd5b61013954604080516001600160a01b03928316815291831660208301527f16b3a5b47cfc3418106cb8fd15fc5df8b17ea324464f7655b052d9e4a3a14df2910160405180910390a161013980546001600160a01b0319166001600160a01b0392909216919091179055565b6200145f6200295b565b6001600160a01b0381163b6200148857604051636f7c43f160e01b815260040160405180910390fd5b61013754604080516001600160a01b03928316815291831660208301527fe6b9ab4b050c05a6c2d41e35b5c0112bb6c563134cc0daccc29a7a44d5da47fe910160405180910390a161013780546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166200151b5760405163a22b4cd760e01b815260040160405180910390fd5b60005b610105548110156200165357816001600160a01b031661010582815481106200154b576200154b620038e8565b6000918252602090912001546001600160a01b03161480156200161157506101015461010580546001600160a01b0390921691633e28391d919084908110620015985762001598620038e8565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa158015620015e9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200160f919062003aea565b155b156200164a5766123450000000006001600160a01b031661010582815481106200163f576200163f620038e8565b506000525062001653565b6001016200151e565b5081610100600082825462001669919062003b0e565b90915550505050565b600061010654610103546200168662000a5f565b62001692919062003835565b62000ceb919062003835565b620016a862002599565b806000816001600160401b03811115620016c657620016c662003630565b604051908082528060200260200182016040528015620016fb57816020015b6060815260200190600190039081620016e55790505b5090506000826001600160401b038111156200171b576200171b62003630565b60405190808252806020026020018201604052801562001745578160200160208202803683370190505b5090506000836001600160401b0381111562001765576200176562003630565b6040519080825280602002602001820160405280156200178f578160200160208202803683370190505b50905060005b848110156200186f57604080516001808252818301909252906020808301908036833701905050848281518110620017d157620017d1620038e8565b602090810291909101015260c95484516001600160a01b0390911690859083908110620018025762001802620038e8565b60200260200101516000815181106200181f576200181f620038e8565b60200260200101906001600160a01b031690816001600160a01b0316815250506001828281518110620018565762001856620038e8565b9115156020928302919091019091015260010162001795565b5060006200187c62002154565b90506000306001600160a01b038a1603620018b257620018aa620018a1888a62003c1b565b86868662002a3b565b90506200195a565b620018bd8962002ba8565b620018db5760405163563fb6d760e11b815260040160405180910390fd5b604051631de1b03360e01b81526001600160a01b038a1690631de1b0339062001911908b908b908a908a908a9060040162003ecf565b6020604051808303816000875af115801562001931573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001957919062003878565b90505b6040518181527f8772d6f79a1845a0c0e90ef18d99f91242bbc0ba98c9ca780feaad42b81f02ba9060200160405180910390a1806101005410620019af578061010054620019a9919062003835565b620019b2565b60005b61010081905560071115620019c8576000610100555b620019d862000dfd828462003b0e565b505050505050620019e96001606555565b505050565b6000610106546101005462001a0262000a5f565b62001a0c6200236f565b62001a18919062003b0e565b62001692919062003b0e565b62001a2e62002599565b61013a541562001a9a5760006201518061013c5462001a4e919062003861565b905060006201518061013b544262001a67919062003835565b62001a73919062003861565b90508181101562001a9757604051637f50d1ab60e11b815260040160405180910390fd5b50505b60fe5462001ab2906001600160a01b03168262002c0e565b61013a554261013b8190556040805183815260208101929092527f40df43107e8b4d467127964bd3c966687c0a6a39aaede970755397fd09535e98910160405180910390a1620012286001606555565b62001b0c6200295b565b604051806040016040528083600281111562001b2c5762001b2c6200391e565b815260200182600281111562001b465762001b466200391e565b90526001600160e01b03198416600090815261013d6020526040902081518154829060ff1916600183600281111562001b835762001b836200391e565b021790555060208201518154829061ff00191661010083600281111562001bae5762001bae6200391e565b0217905550905050826001600160e01b0319167ffc2ae1ef55404e9b12cfaca1546ea9cdcac8ae491f101a407462bc926655c157838360405162001bf492919062004062565b60405180910390a2505050565b600062001c1060335460ff1690565b1562001c1e57600062000c73565b60c9546040516370a0823160e01b81526001600160a01b03848116600483015262000c739216906370a0823190602401602060405180830381865afa15801562001c6c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a38919062003878565b600062000c738262002dad565b60fc546001600160a01b0382811660009081526101046020526040808220549051630aa794bf60e31b815290831660048201529092919091169063553ca5f89060240162000e5b565b60008062001cf562001672565b90508083111562001d2157604051636688dd2d60e11b8152600481018290526024015b60405180910390fd5b61013554738a6a8a7233b16d0ecaa7510bfd110464a0d69f669063cfe6424490859084906402540be40090600160401b90046001600160401b031662001d66620029b7565b62001d72919062003892565b62001d7e919062003861565b61013554610134546001600160401b0391821691600160c01b9091041662001da5620029b7565b6040516001600160e01b031960e089901b1681526004810196909652602486019490945260448501929092526001600160401b03908116606485015216608483015260a482015260c401602060405180830381865af415801562001e0d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001e33919062003878565b9392505050565b62001e446200295b565b6001600160a01b0381163b62001e6d57604051636f7c43f160e01b815260040160405180910390fd5b61013854604080516001600160a01b03928316815291831660208301527f86214bbaa96d45f51d9923d72e74002d58b5554ccd07b1dbf67a6781adfa9e7c910160405180910390a161013880546001600160a01b0319166001600160a01b0392909216919091179055565b600062001ee760335460ff1690565b1562001ef557506000919050565b61012d546040516370a0823160e01b81526001600160a01b03848116600483015260009216906370a0823190602401602060405180830381865afa15801562001f42573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001f68919062003878565b9050600062001f7a620008f062001672565b905081811162001f8b578062001f8d565b815b949350505050565b919050565b6001600160a01b03831662001fc25760405163a22b4cd760e01b815260040160405180910390fd5b62001fcd8462002dcd565b6001600160a01b0380841660009081526101046020526040902054168062002008576040516325ec6c1f60e01b815260040160405180910390fd5b60006612344fffffffff196001600160a01b038316016200209c575060016200203062002f60565b6001600160a01b0380871660009081526101046020526040812080549284166001600160a01b03199384168117909155610105805460018101825592527ffc62abc8c0fc47c2d92f5aec99bf8b60f375828e14394d89345cae11a9867371909101805490921617905591505b620020a8828762003123565b8015620020bd57620020bd8286868662003242565b846001600160a01b0316826001600160a01b03167faf37ed177c8603b1d023b3de651b407ee740e2488f18bd5f0a2a1eb2f0023e1c886040516200210391815260200190565b60405180910390a3505050505050565b61010281815481106200212557600080fd5b60009182526020909120600390910201805460018201546002909201549092506001600160a01b039091169083565b600062002160620029b7565b6200216a62001672565b1062002184576200217a620029b7565b6200169262001672565b50600090565b61010581815481106200219c57600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b03808216600090815261012f6020908152604080832081516060818101845282548083526001840154909716948201949094526002909101549181019190915260fd54929391928492839162002214919062003835565b6001600160401b038111156200222e576200222e62003630565b60405190808252806020026020018201604052801562002258578160200160208202803683370190505b509050816040015160000362002275576000969095509350505050565b60005b60fd548110156200230357866001600160a01b03166101028281548110620022a457620022a4620038e8565b60009182526020909120600160039092020101546001600160a01b031603620022fa576001955080828581518110620022e157620022e1620038e8565b6020908102919091010152620022f7846200408c565b93505b60010162002278565b50600083825162002315919062003835565b111562002320578281525b9395939450505050565b6000806000610106541115620023595762002345836200122b565b905061010654811115620023595750610106545b62001e3362002369828562003b0e565b62002dad565b61010554600090815b818110156200247b5760006001600160a01b03166101058281548110620023a357620023a3620038e8565b6000918252602090912001546001600160a01b031614620024725760fc5461010580546001600160a01b039092169163553ca5f8919084908110620023ec57620023ec620038e8565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa1580156200243d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002463919062003878565b6200246f908462003b0e565b92505b60010162002378565b5060fc54604051630aa794bf60e31b81523060048201526001600160a01b039091169063553ca5f890602401602060405180830381865afa158015620024c5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620024eb919062003878565b620024f7908362003b0e565b91505090565b620025076200295b565b6001600160a01b0381166200256e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162001d18565b6200122881620029e9565b600062000c7382670de0b6b3a76400006200259362001363565b620032a4565b600260655403620025ed5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162001d18565b6002606555565b6101015460405163285e212160e21b81526001600160a01b038381166004830152600092839291169063a178848490602401602060405180830381865afa15801562002644573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200266a919062003878565b60fb5460fc54604051633d3f06c960e11b81526001600160a01b0387811660048301529182166024820152929350600092911690637a7e0d9290604401602060405180830381865afa158015620026c5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620026eb919062003878565b60fc546040516338f6b94760e21b8152600481018890529192506000916001600160a01b039091169063e3dae51c90602401602060405180830381865afa1580156200273b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002761919062003878565b60fc54604051637a8b263760e01b8152600481018390529192506001600160a01b031690637a8b263790602401602060405180830381865afa158015620027ac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620027d2919062003878565b9550620027e181600562003b0e565b821015620027ec5750805b85610100600082825462002801919062003b0e565b909155505060fc5461010154604051631976849960e21b81526001600160a01b0388811660048301819052937fdbee882832247c009fcded16f057a75cfd42a40de981aae8f96c49496ec5208293908216928692439216906365da126490602401602060405180830381865afa15801562002880573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620028a69190620040a8565b604080516001600160a01b039586168152602081019490945263ffffffff929092168383015290921660608201526080810187905290519081900360a00190a295945050505050565b6101025460fd545b81811015620019e95760006101028281548110620029195762002919620038e8565b9060005260206000209060030201600201549050838111156200293c5750505050565b61010380548201905560fd8054600190810190915593039201620028f7565b6097546001600160a01b0316331462000e0e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162001d18565b600068056bc75e2d63100000620029cd620019ee565b61010754620029dd919062003892565b62000ceb919062003861565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60c9546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa15801562002a89573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002aaf919062003878565b610101546040516319a021cb60e11b81529192506001600160a01b03169063334043969062002ae9908990899089908990600401620040c8565b600060405180830381600087803b15801562002b0457600080fd5b505af115801562002b19573d6000803e3d6000fd5b505060c9546040516370a0823160e01b8152306004820152600093508492506001600160a01b03909116906370a0823190602401602060405180830381865afa15801562002b6b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002b91919062003878565b62002b9d919062003835565b979650505050505050565b61010554600090815b8181101562002c0457610105818154811062002bd15762002bd1620038e8565b6000918252602090912001546001600160a01b039081169085160362002bfb575060019392505050565b60010162002bb1565b5060009392505050565b60c9546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa15801562002c5c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002c82919062003878565b60c9546040516323b872dd60e01b81526001600160a01b038781166004830152306024830152604482018790529293509116906323b872dd906064016020604051808303816000875af115801562002cde573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002d04919062003aea565b62002d325760c9546040516302ce902360e61b81526001600160a01b03909116600482015260240162001d18565b60c9546040516370a0823160e01b815230600482015282916001600160a01b0316906370a0823190602401602060405180830381865afa15801562002d7b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002da1919062003878565b62001f8d919062003835565b600062000c738262002dbe62001363565b670de0b6b3a7640000620032a4565b62002dd762002154565b81111562002e065762002de962000a5f565b604051636688dd2d60e11b815260040162001d1891815260200190565b60fc546040805163df6fadc160e01b8152815160009384936001600160a01b039091169263df6fadc192600480830193928290030181865afa15801562002e51573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002e779190620041da565b915091508183111562002ea857604051633c690bcb60e11b8152600481018390526024810184905260440162001d18565b60c95460fc546040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a0823190602401602060405180830381865afa15801562002efa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002f20919062003878565b90508162002f2f858362003b0e565b111562002f5a57604051630dbbc86f60e11b8152600481018390526024810182905260440162001d18565b50505050565b610131546000906001600160a01b031662002f8e576040516340dde93560e01b815260040160405180910390fd5b600062002fa36097546001600160a01b031690565b610136546101015460fb5460fc5460c95460fe546040516001600160a01b039788166024820152958716604487015293861660648601529185166084850152841660a4840152831660c48301529190911660e48201526101040160408051601f198184030181529181526020820180516001600160e01b0316631ac3b23b60e11b17905251909150600090309083906200303d9062003344565b6200304a929190620041ff565b604051809103906000f08015801562003067573d6000803e3d6000fd5b509050806001600160a01b03811663f2fde38b6200308d6097546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015620030cf57600080fd5b505af1158015620030e4573d6000803e3d6000fd5b50506040516001600160a01b03851692507f9e676714ad2ee7d362cccabb3a543102aada709f27c2bda6bf6ef42fce70ff259150600090a25092915050565b60c95460405163095ea7b360e01b81526001600160a01b038481166004830152602482018490529091169063095ea7b3906044016020604051808303816000875af115801562003177573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200319d919062003aea565b50604051635466590560e01b8152600481018290526001600160a01b03831690635466590590602401600060405180830381600087803b158015620031e157600080fd5b505af1158015620031f6573d6000803e3d6000fd5b50505050816001600160a01b03167f890a6c1c3db8b3fa62f2928d2c9851b5c456f019d09d93f72d984454511b87b7826040516200323691815260200190565b60405180910390a25050565b60405163511e274f60e01b81526001600160a01b0385169063511e274f90620032749086908690869060040162004225565b600060405180830381600087803b1580156200328f57600080fd5b505af11580156200101e573d6000803e3d6000fd5b600062001f8d620032c1620032ba848762003861565b85620032ed565b8385620032cf82896200426f565b620032db919062003892565b620032e7919062003861565b6200332a565b600082600003620033015750600062000c73565b828202828482816200331757620033176200384b565b041462001e335760001991505062000c73565b60008282018381101562001e335760001991505062000c73565b6106cc806200428783390190565b6000815180845260005b818110156200337a576020818501810151868301820152016200335c565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600062001e33602083018462003352565b600060208284031215620033c257600080fd5b5035919050565b6001600160a01b03811681146200122857600080fd5b803562001f9581620033c9565b600080604083850312156200340057600080fd5b82356200340d81620033c9565b946020939093013593505050565b6000602082840312156200342e57600080fd5b813562001e3381620033c9565b60008083601f8401126200344e57600080fd5b5081356001600160401b038111156200346657600080fd5b6020830191508360208260051b85010111156200348257600080fd5b9250929050565b60008060008060008060608789031215620034a357600080fd5b86356001600160401b0380821115620034bb57600080fd5b620034c98a838b016200343b565b90985096506020890135915080821115620034e357600080fd5b620034f18a838b016200343b565b909650945060408901359150808211156200350b57600080fd5b506200351a89828a016200343b565b979a9699509497509295939492505050565b600080604083850312156200354057600080fd5b8235915060208301356200355481620033c9565b809150509250929050565b6000806000604084860312156200357557600080fd5b83356200358281620033c9565b925060208401356001600160401b038111156200359e57600080fd5b620035ac868287016200343b565b9497909650939450505050565b80356001600160e01b03198116811462001f9557600080fd5b600381106200122857600080fd5b600080600060608486031215620035f657600080fd5b6200360184620035b9565b925060208401356200361381620035d2565b915060408401356200362581620035d2565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200366b576200366b62003630565b60405290565b60405160e081016001600160401b03811182821017156200366b576200366b62003630565b604051601f8201601f191681016001600160401b0381118282101715620036c157620036c162003630565b604052919050565b60008060008060808587031215620036e057600080fd5b84359350602080860135620036f581620033c9565b93506040860135925060608601356001600160401b03808211156200371957600080fd5b908701906040828a0312156200372e57600080fd5b6200373862003646565b8235828111156200374857600080fd5b8301601f81018b136200375a57600080fd5b8035838111156200376f576200376f62003630565b62003783601f8201601f1916870162003696565b93508084528b868284010111156200379a57600080fd5b80868301878601376000908401860152509081529082013591810191909152939692955090935050565b60008151808452602080850194506020840160005b83811015620037f757815187529582019590820190600101620037d9565b509495945050505050565b821515815260406020820152600062001f8d6040830184620037c4565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000c735762000c736200381f565b634e487b7160e01b600052601260045260246000fd5b6000826200387357620038736200384b565b500490565b6000602082840312156200388b57600080fd5b5051919050565b808202811582820484141762000c735762000c736200381f565b600181811c90821680620038c157607f821691505b602082108103620038e257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156200391157600080fd5b813562001e3381620035d2565b634e487b7160e01b600052602160045260246000fd5b6000602082840312156200394757600080fd5b62001e3382620035b9565b60008151808452602080850194506020840160005b83811015620037f75781516001600160a01b03168752958201959082019060010162003967565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101562003a2257603f19898403018552815160608151818652620039e08287018262003952565b915050888201518582038a870152620039fa8282620037c4565b928901516001600160a01b0316958901959095525094870194925090860190600101620039b7565b509098975050505050505050565b60006001600160401b0382111562003a4c5762003a4c62003630565b5060051b60200190565b6000602080838503121562003a6a57600080fd5b82516001600160401b0381111562003a8157600080fd5b8301601f8101851362003a9357600080fd5b805162003aaa62003aa48262003a30565b62003696565b81815260059190911b8201830190838101908783111562003aca57600080fd5b928401925b8284101562002b9d5783518252928401929084019062003acf565b60006020828403121562003afd57600080fd5b8151801515811462001e3357600080fd5b8082018082111562000c735762000c736200381f565b803563ffffffff8116811462001f9557600080fd5b600082601f83011262003b4b57600080fd5b8135602062003b5e62003aa48362003a30565b8083825260208201915060208460051b87010193508684111562003b8157600080fd5b602086015b8481101562003baa57803562003b9c81620033c9565b835291830191830162003b86565b509695505050505050565b600082601f83011262003bc757600080fd5b8135602062003bda62003aa48362003a30565b8083825260208201915060208460051b87010193508684111562003bfd57600080fd5b602086015b8481101562003baa578035835291830191830162003c02565b600062003c2c62003aa48462003a30565b80848252602080830192508560051b85013681111562003c4b57600080fd5b855b8181101562003d425780356001600160401b038082111562003c6f5760008081fd5b818901915060e0823603121562003c865760008081fd5b62003c9062003671565b62003c9b83620033df565b815262003caa868401620033df565b86820152604062003cbd818501620033df565b9082015260608381013590820152608062003cda81850162003b24565b9082015260a0838101358381111562003cf35760008081fd5b62003d013682870162003b39565b82840152505060c0808401358381111562003d1c5760008081fd5b62003d2a3682870162003bb5565b91830191909152508752505093820193820162003c4d565b50919695505050505050565b6000808335601e1984360301811262003d6657600080fd5b83016020810192503590506001600160401b0381111562003d8657600080fd5b8060051b36038213156200348257600080fd5b8183526000602080850194508260005b85811015620037f757813562003dbf81620033c9565b6001600160a01b03168752958201959082019060010162003da9565b81835260006001600160fb1b0383111562003df557600080fd5b8260051b80836020870137939093016020019392505050565b600082825180855260208086019550808260051b8401018186016000805b8581101562003e8c57868403601f19018a52825180518086529086019086860190845b8181101562003e765783516001600160a01b03168352928801929188019160010162003e4f565b50509a86019a9450509184019160010162003e2c565b509198975050505050505050565b60008151808452602080850194506020840160005b83811015620037f757815115158752958201959082019060010162003eaf565b608080825281810186905260009060a0808401600589901b850182018a85805b8c81101562003ff157888403609f190185528235368f900360de1901811262003f16578283fd5b8e0160e0813562003f2781620033c9565b6001600160a01b0316865260208281013562003f4381620033c9565b6001600160a01b031681880152604062003f5f848201620033df565b6001600160a01b0316908801526060838101359088015262003f838a840162003b24565b63ffffffff168a88015262003f9b838a018462003d4e565b838b8a015262003faf848a01828462003d99565b9350505060c062003fc38185018562003d4e565b9450888403828a015262003fd984868362003ddb565b99830199985050509490940193505060010162003eef565b505050858103602087015262004008818a62003e0e565b93505050508281036040840152620040218186620037c4565b9050828103606084015262004037818562003e9a565b98975050505050505050565b600381106200122857634e487b7160e01b600052602160045260246000fd5b60408101620040718462004043565b8382526200407f8362004043565b8260208301529392505050565b600060018201620040a157620040a16200381f565b5060010190565b600060208284031215620040bb57600080fd5b815162001e3381620033c9565b600060808083016080845280885180835260a0925060a08601915060a08160051b8701016020808c0160005b848110156200419557898403609f19018652815180516001600160a01b0390811686528482015181168587015260408083015190911690860152606080820151908601528881015163ffffffff16898601528781015160e089870181905290620041618288018262003952565b91505060c08083015192508682038188015250620041808183620037c4565b978501979550505090820190600101620040f4565b505087820390880152620041aa818b62003e0e565b9450505050508281036040840152620041c48186620037c4565b9050828103606084015262002b9d818562003e9a565b60008060408385031215620041ee57600080fd5b505080516020909101519092909150565b6001600160a01b038316815260406020820181905260009062001f8d9083018462003352565b60018060a01b03841681528260208201526060604082015260008251604060608401526200425760a084018262003352565b90506020840151608084015280915050949350505050565b6000826200428157620042816200384b565b50069056fe60806040526040516106cc3803806106cc83398101604081905261002291610420565b61002e82826000610035565b505061054a565b61003e836100f6565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100f1576100ef836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e991906104e0565b8361027a565b505b505050565b6001600160a01b0381163b6101605760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101d4816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c591906104e0565b6001600160a01b03163b151590565b6102395760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610157565b7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b0392909216919091179055565b606061029f83836040518060600160405280602781526020016106a5602791396102a6565b9392505050565b6060600080856001600160a01b0316856040516102c391906104fb565b600060405180830381855af49150503d80600081146102fe576040519150601f19603f3d011682016040523d82523d6000602084013e610303565b606091505b5090925090506103158683838761031f565b9695505050505050565b6060831561038e578251600003610387576001600160a01b0385163b6103875760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610157565b5081610398565b61039883836103a0565b949350505050565b8151156103b05781518083602001fd5b8060405162461bcd60e51b81526004016101579190610517565b80516001600160a01b03811681146103e157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156104175781810151838201526020016103ff565b50506000910152565b6000806040838503121561043357600080fd5b61043c836103ca565b60208401519092506001600160401b038082111561045957600080fd5b818501915085601f83011261046d57600080fd5b81518181111561047f5761047f6103e6565b604051601f8201601f19908116603f011681019083821181831017156104a7576104a76103e6565b816040528281528860208487010111156104c057600080fd5b6104d18360208301602088016103fc565b80955050505050509250929050565b6000602082840312156104f257600080fd5b61029f826103ca565b6000825161050d8184602087016103fc565b9190910192915050565b60208152600082518060208401526105368160408501602087016103fc565b601f01601f19169190910160400192915050565b61014c806105596000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610029565b6100c2565b565b600061005c7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610099573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100bd91906100e6565b905090565b3660008037600080366000845af43d6000803e8080156100e1573d6000f35b3d6000fd5b6000602082840312156100f857600080fd5b81516001600160a01b038116811461010f57600080fd5b939250505056fea2646970667358221220b56935c588face108abef8b1e72ef1babd8d1377fb7d73534ea44bb80f729e3764736f6c63430008180033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122060805f0a761a94157f391e4822a4b7713415e286ae24ddcb791dd6c5a09b6a4964736f6c63430008180033
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620004745760003560e01c8063841143d21162000259578063c235fb141162000149578063e780789711620000c7578063eae43a441162000092578063eae43a4414620009e9578063ef13b2c71462000a00578063ef8b30f71462000a27578063f29768711462000a3e578063f2fde38b1462000a4857600080fd5b8063e7807897146200097e578063e91bb844146200098f578063e93c4f1514620009ca578063ea4d3c9b14620009d457600080fd5b8063cea6443a1162000114578063cea6443a146200090d578063d1ef0c941462000924578063d8266c181462000939578063d905777e1462000950578063d9540d6a146200096757600080fd5b8063c235fb1414620008b3578063c63d75b614620008c8578063c6e6f59214620008df578063ce5119ee14620008f657600080fd5b8063a8c62e7611620001d7578063b637d66911620001a2578063b637d6691462000865578063b68ef5591462000870578063beceed39146200087a578063c059a38e1462000891578063c137d8ad146200089c57600080fd5b8063a8c62e7614620007ee578063ab89b6af1462000802578063ac48eb9f1462000832578063b0e21e8a146200084957600080fd5b8063900cf0cf1162000224578063900cf0cf14620007a8578063901a7d5314620007b25780639669c7cf14620007bd57806396c8d48e14620007c75780639b2cb5d814620007e357600080fd5b8063841143d214620007555780638a2fc4e3146200076c5780638da5cb5b14620007815780638e29ebb5146200079357600080fd5b80634a6b629d11620003755780636a1ae05311620002f3578063715018a611620002be578063715018a614620006fe57806371ca337d1462000708578063779a6cdd14620007125780637839030f14620007275780637b487a65146200073e57600080fd5b80636a1ae05314620006b05780636b77b2f514620006c55780636ba176c714620006d057806370a0823114620006e757600080fd5b806353268ad0116200034057806353268ad0146200065c5780635c60da1b14620006675780635c975abb146200067a57806361d027b3146200069157806366bcd64114620006a657600080fd5b80634a6b629d146200060e5780634baa619314620006195780634cdad506146200062e5780634fe2bb82146200064557600080fd5b80632b6fd4f1116200040357806338d52e0f11620003ce57806338d52e0f146200059e57806339b70e3814620005b0578063402d267d14620005c4578063470a567c14620005db5780634886a95714620005f257600080fd5b80632b6fd4f114620005475780632df2228a146200057557806330e4cf3a146200057f57806336f4fb02146200059457600080fd5b80631036bbe211620004445780631036bbe214620004fb57806318160ddd14620005085780631f2ed36f1462000512578063252b7edc146200052e57600080fd5b8062928917146200047957806301e1d11414620004b257806306fdde0314620004cb57806307a2d13a14620004e4575b600080fd5b610134546200049590600160c01b90046001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b620004bc62000a5f565b604051908152602001620004a9565b620004d562000bcf565b604051620004a991906200339a565b620004bc620004f5366004620033af565b62000c66565b620004956402540be40081565b620004bc62000c79565b610134546200049590600160401b90046001600160401b031681565b620005456200053f366004620033ec565b62000cf0565b005b610138546200055c906001600160a01b031681565b6040516001600160a01b039091168152602001620004a9565b61010054620004bc565b610137546200055c906001600160a01b031681565b6200054562000de5565b60c9546001600160a01b03166200055c565b60fb546200055c906001600160a01b031681565b620004bc620005d53660046200341b565b62000e10565b62000545620005ec36600462003489565b62000e9f565b610134546200049590600160801b90046001600160401b031681565b620004bc6101075481565b610131546200055c906001600160a01b031681565b620004bc6200063f366004620033af565b62001028565b6200054562000656366004620033af565b62001050565b620004bc6101035481565b610131546001600160a01b03166200055c565b60335460ff166040519015158152602001620004a9565b610133546200055c906001600160a01b031681565b620004bc60ff5481565b6101355462000495906001600160401b031681565b620004bc61013b5481565b620004bc620006e1366004620033af565b6200122b565b620004bc620006f83660046200341b565b62001318565b620005456200134d565b620004bc62001363565b6101345462000495906001600160401b031681565b62000545620007383660046200341b565b620013b7565b620005456200074f3660046200341b565b62001455565b62000545620007663660046200352c565b620014f3565b610136546200055c906001600160a01b031681565b6097546001600160a01b03166200055c565b610132546200055c906001600160a01b031681565b620004bc60fd5481565b620004bc61013a5481565b620004bc62001672565b610135546200049590600160401b90046001600160401b031681565b620004bc61012e5481565b60fc546200055c906001600160a01b031681565b620004bc620008133660046200341b565b6001600160a01b0316600090815261012f602052604090206002015490565b62000545620008433660046200355f565b6200169e565b610133546200049590600160a01b90046001600160401b031681565b620004bc61013c5481565b620004bc620019ee565b620005456200088b366004620033af565b62001a24565b620004bc6101065481565b62000545620008ad366004620035e0565b62001b02565b61012d546200055c906001600160a01b031681565b620004bc620008d93660046200341b565b62001c01565b620004bc620008f0366004620033af565b62001c92565b620004bc620009073660046200341b565b62001c9f565b620004bc6200091e366004620033af565b62001ce8565b610139546200055c906001600160a01b031681565b620005456200094a3660046200341b565b62001e3a565b620004bc620009613660046200341b565b62001ed8565b6200054562000978366004620036c9565b62001f9a565b620004bc68056bc75e2d6310000081565b620009a6620009a0366004620033af565b62002113565b604080519384526001600160a01b03909216602084015290820152606001620004a9565b620004bc62002154565b610101546200055c906001600160a01b031681565b6200055c620009fa366004620033af565b6200218a565b62000a1762000a113660046200341b565b620021b6565b604051620004a992919062003802565b620004bc62000a38366004620033af565b6200232a565b620004bc6200236f565b6200054562000a593660046200341b565b620024fd565b6000806201518061013b544262000a77919062003835565b62000a83919062003861565b905060006201518061013c5462000a9b919062003861565b90508082111562000b1c5760c9546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801562000aef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b15919062003878565b9250505090565b600062000b2a838362003835565b8261013a5462000b3b919062003861565b62000b47919062003892565b60c9546040516370a0823160e01b815230600482015291925082916001600160a01b03909116906370a0823190602401602060405180830381865afa15801562000b95573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000bbb919062003878565b62000bc7919062003835565b935050505090565b610130805462000bdf90620038ac565b80601f016020809104026020016040519081016040528092919081815260200182805462000c0d90620038ac565b801562000c5e5780601f1062000c325761010080835404028352916020019162000c5e565b820191906000526020600020905b81548152906001019060200180831162000c4057829003601f168201915b505050505081565b600062000c738262002579565b92915050565b61012d54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa15801562000cc5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ceb919062003878565b905090565b62000cfa62002599565b6001600160a01b0380831660009081526101046020526040902054168062000d35576040516325ec6c1f60e01b815260040160405180910390fd5b6612344fffffffff196001600160a01b0382160162000d675760405163a22b4cd760e01b815260040160405180910390fd5b806001600160a01b031663b64d26ab62000d828484620025f4565b6040518263ffffffff1660e01b815260040162000da191815260200190565b600060405180830381600087803b15801562000dbc57600080fd5b505af115801562000dd1573d6000803e3d6000fd5b505050505062000de16001606555565b5050565b62000def62002599565b62000e0362000dfd62002154565b620028ef565b62000e0e6001606555565b565b600062000e1f60335460ff1690565b1562000e2d57600062000c73565b60c9546040516370a0823160e01b81526001600160a01b038481166004830152909116906370a08231906024015b602060405180830381865afa15801562000e79573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c73919062003878565b62000ea96200295b565b84838114158062000eba5750808214155b1562000ed95760405163afff5f7760e01b815260040160405180910390fd5b60005b818110156200101e57604051806040016040528087878481811062000f055762000f05620038e8565b905060200201602081019062000f1c9190620038fe565b600281111562000f305762000f306200391e565b815260200185858481811062000f4a5762000f4a620038e8565b905060200201602081019062000f619190620038fe565b600281111562000f755762000f756200391e565b905261013d60008a8a8581811062000f915762000f91620038e8565b905060200201602081019062000fa8919062003934565b6001600160e01b0319168152602081019190915260400160002081518154829060ff1916600183600281111562000fe35762000fe36200391e565b021790555060208201518154829061ff0019166101008360028111156200100e576200100e6200391e565b0217905550505060010162000edc565b5050505050505050565b6000620010396200091e8362000c66565b620010448362002579565b62000c73919062003835565b6200105a62002599565b604080516001808252818301909252309160009190602080830190803683375050604080516001808252818301909252929350600092915060208083019080368337019050509050620010ae8484620025f4565b82600081518110620010c457620010c4620038e8565b602090810291909101015260fc5481516001600160a01b03909116908290600090620010f457620010f4620038e8565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020015b60408051606080820183528082526020820152600091810191909152815260200190600190039081620011245790505090506040518060600160405280838152602001848152602001306001600160a01b031681525081600081518110620011905762001190620038e8565b6020908102919091010152610101546040516306ec6e8160e11b81526001600160a01b0390911690630dd8dd0290620011ce9084906004016200398e565b6000604051808303816000875af1158015620011ee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262001218919081019062003a56565b5050505050620012286001606555565b50565b6000738a6a8a7233b16d0ecaa7510bfd110464a0d69f6663fea65f72836200125262001672565b610134546402540be40090600160801b90046001600160401b031662001277620029b7565b62001283919062003892565b6200128f919062003861565b610134546001600160401b03600160401b820481169116620012b0620029b7565b6040516001600160e01b031960e089901b1681526004810196909652602486019490945260448501929092526001600160401b03908116606485015216608483015260a482015260c401602060405180830381865af415801562000e79573d6000803e3d6000fd5b61012d546040516370a0823160e01b81526001600160a01b03838116600483015260009216906370a082319060240162000e5b565b620013576200295b565b62000e0e6000620029e9565b6101325461012d5460405163a1f1d48d60e01b81526001600160a01b039182166004820152600092919091169063a1f1d48d90602401602060405180830381865afa15801562000cc5573d6000803e3d6000fd5b620013c16200295b565b6001600160a01b0381163b620013ea57604051636f7c43f160e01b815260040160405180910390fd5b61013954604080516001600160a01b03928316815291831660208301527f16b3a5b47cfc3418106cb8fd15fc5df8b17ea324464f7655b052d9e4a3a14df2910160405180910390a161013980546001600160a01b0319166001600160a01b0392909216919091179055565b6200145f6200295b565b6001600160a01b0381163b6200148857604051636f7c43f160e01b815260040160405180910390fd5b61013754604080516001600160a01b03928316815291831660208301527fe6b9ab4b050c05a6c2d41e35b5c0112bb6c563134cc0daccc29a7a44d5da47fe910160405180910390a161013780546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166200151b5760405163a22b4cd760e01b815260040160405180910390fd5b60005b610105548110156200165357816001600160a01b031661010582815481106200154b576200154b620038e8565b6000918252602090912001546001600160a01b03161480156200161157506101015461010580546001600160a01b0390921691633e28391d919084908110620015985762001598620038e8565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa158015620015e9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200160f919062003aea565b155b156200164a5766123450000000006001600160a01b031661010582815481106200163f576200163f620038e8565b506000525062001653565b6001016200151e565b5081610100600082825462001669919062003b0e565b90915550505050565b600061010654610103546200168662000a5f565b62001692919062003835565b62000ceb919062003835565b620016a862002599565b806000816001600160401b03811115620016c657620016c662003630565b604051908082528060200260200182016040528015620016fb57816020015b6060815260200190600190039081620016e55790505b5090506000826001600160401b038111156200171b576200171b62003630565b60405190808252806020026020018201604052801562001745578160200160208202803683370190505b5090506000836001600160401b0381111562001765576200176562003630565b6040519080825280602002602001820160405280156200178f578160200160208202803683370190505b50905060005b848110156200186f57604080516001808252818301909252906020808301908036833701905050848281518110620017d157620017d1620038e8565b602090810291909101015260c95484516001600160a01b0390911690859083908110620018025762001802620038e8565b60200260200101516000815181106200181f576200181f620038e8565b60200260200101906001600160a01b031690816001600160a01b0316815250506001828281518110620018565762001856620038e8565b9115156020928302919091019091015260010162001795565b5060006200187c62002154565b90506000306001600160a01b038a1603620018b257620018aa620018a1888a62003c1b565b86868662002a3b565b90506200195a565b620018bd8962002ba8565b620018db5760405163563fb6d760e11b815260040160405180910390fd5b604051631de1b03360e01b81526001600160a01b038a1690631de1b0339062001911908b908b908a908a908a9060040162003ecf565b6020604051808303816000875af115801562001931573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001957919062003878565b90505b6040518181527f8772d6f79a1845a0c0e90ef18d99f91242bbc0ba98c9ca780feaad42b81f02ba9060200160405180910390a1806101005410620019af578061010054620019a9919062003835565b620019b2565b60005b61010081905560071115620019c8576000610100555b620019d862000dfd828462003b0e565b505050505050620019e96001606555565b505050565b6000610106546101005462001a0262000a5f565b62001a0c6200236f565b62001a18919062003b0e565b62001692919062003b0e565b62001a2e62002599565b61013a541562001a9a5760006201518061013c5462001a4e919062003861565b905060006201518061013b544262001a67919062003835565b62001a73919062003861565b90508181101562001a9757604051637f50d1ab60e11b815260040160405180910390fd5b50505b60fe5462001ab2906001600160a01b03168262002c0e565b61013a554261013b8190556040805183815260208101929092527f40df43107e8b4d467127964bd3c966687c0a6a39aaede970755397fd09535e98910160405180910390a1620012286001606555565b62001b0c6200295b565b604051806040016040528083600281111562001b2c5762001b2c6200391e565b815260200182600281111562001b465762001b466200391e565b90526001600160e01b03198416600090815261013d6020526040902081518154829060ff1916600183600281111562001b835762001b836200391e565b021790555060208201518154829061ff00191661010083600281111562001bae5762001bae6200391e565b0217905550905050826001600160e01b0319167ffc2ae1ef55404e9b12cfaca1546ea9cdcac8ae491f101a407462bc926655c157838360405162001bf492919062004062565b60405180910390a2505050565b600062001c1060335460ff1690565b1562001c1e57600062000c73565b60c9546040516370a0823160e01b81526001600160a01b03848116600483015262000c739216906370a0823190602401602060405180830381865afa15801562001c6c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a38919062003878565b600062000c738262002dad565b60fc546001600160a01b0382811660009081526101046020526040808220549051630aa794bf60e31b815290831660048201529092919091169063553ca5f89060240162000e5b565b60008062001cf562001672565b90508083111562001d2157604051636688dd2d60e11b8152600481018290526024015b60405180910390fd5b61013554738a6a8a7233b16d0ecaa7510bfd110464a0d69f669063cfe6424490859084906402540be40090600160401b90046001600160401b031662001d66620029b7565b62001d72919062003892565b62001d7e919062003861565b61013554610134546001600160401b0391821691600160c01b9091041662001da5620029b7565b6040516001600160e01b031960e089901b1681526004810196909652602486019490945260448501929092526001600160401b03908116606485015216608483015260a482015260c401602060405180830381865af415801562001e0d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001e33919062003878565b9392505050565b62001e446200295b565b6001600160a01b0381163b62001e6d57604051636f7c43f160e01b815260040160405180910390fd5b61013854604080516001600160a01b03928316815291831660208301527f86214bbaa96d45f51d9923d72e74002d58b5554ccd07b1dbf67a6781adfa9e7c910160405180910390a161013880546001600160a01b0319166001600160a01b0392909216919091179055565b600062001ee760335460ff1690565b1562001ef557506000919050565b61012d546040516370a0823160e01b81526001600160a01b03848116600483015260009216906370a0823190602401602060405180830381865afa15801562001f42573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001f68919062003878565b9050600062001f7a620008f062001672565b905081811162001f8b578062001f8d565b815b949350505050565b919050565b6001600160a01b03831662001fc25760405163a22b4cd760e01b815260040160405180910390fd5b62001fcd8462002dcd565b6001600160a01b0380841660009081526101046020526040902054168062002008576040516325ec6c1f60e01b815260040160405180910390fd5b60006612344fffffffff196001600160a01b038316016200209c575060016200203062002f60565b6001600160a01b0380871660009081526101046020526040812080549284166001600160a01b03199384168117909155610105805460018101825592527ffc62abc8c0fc47c2d92f5aec99bf8b60f375828e14394d89345cae11a9867371909101805490921617905591505b620020a8828762003123565b8015620020bd57620020bd8286868662003242565b846001600160a01b0316826001600160a01b03167faf37ed177c8603b1d023b3de651b407ee740e2488f18bd5f0a2a1eb2f0023e1c886040516200210391815260200190565b60405180910390a3505050505050565b61010281815481106200212557600080fd5b60009182526020909120600390910201805460018201546002909201549092506001600160a01b039091169083565b600062002160620029b7565b6200216a62001672565b1062002184576200217a620029b7565b6200169262001672565b50600090565b61010581815481106200219c57600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b03808216600090815261012f6020908152604080832081516060818101845282548083526001840154909716948201949094526002909101549181019190915260fd54929391928492839162002214919062003835565b6001600160401b038111156200222e576200222e62003630565b60405190808252806020026020018201604052801562002258578160200160208202803683370190505b509050816040015160000362002275576000969095509350505050565b60005b60fd548110156200230357866001600160a01b03166101028281548110620022a457620022a4620038e8565b60009182526020909120600160039092020101546001600160a01b031603620022fa576001955080828581518110620022e157620022e1620038e8565b6020908102919091010152620022f7846200408c565b93505b60010162002278565b50600083825162002315919062003835565b111562002320578281525b9395939450505050565b6000806000610106541115620023595762002345836200122b565b905061010654811115620023595750610106545b62001e3362002369828562003b0e565b62002dad565b61010554600090815b818110156200247b5760006001600160a01b03166101058281548110620023a357620023a3620038e8565b6000918252602090912001546001600160a01b031614620024725760fc5461010580546001600160a01b039092169163553ca5f8919084908110620023ec57620023ec620038e8565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401602060405180830381865afa1580156200243d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002463919062003878565b6200246f908462003b0e565b92505b60010162002378565b5060fc54604051630aa794bf60e31b81523060048201526001600160a01b039091169063553ca5f890602401602060405180830381865afa158015620024c5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620024eb919062003878565b620024f7908362003b0e565b91505090565b620025076200295b565b6001600160a01b0381166200256e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162001d18565b6200122881620029e9565b600062000c7382670de0b6b3a76400006200259362001363565b620032a4565b600260655403620025ed5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162001d18565b6002606555565b6101015460405163285e212160e21b81526001600160a01b038381166004830152600092839291169063a178848490602401602060405180830381865afa15801562002644573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200266a919062003878565b60fb5460fc54604051633d3f06c960e11b81526001600160a01b0387811660048301529182166024820152929350600092911690637a7e0d9290604401602060405180830381865afa158015620026c5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620026eb919062003878565b60fc546040516338f6b94760e21b8152600481018890529192506000916001600160a01b039091169063e3dae51c90602401602060405180830381865afa1580156200273b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002761919062003878565b60fc54604051637a8b263760e01b8152600481018390529192506001600160a01b031690637a8b263790602401602060405180830381865afa158015620027ac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620027d2919062003878565b9550620027e181600562003b0e565b821015620027ec5750805b85610100600082825462002801919062003b0e565b909155505060fc5461010154604051631976849960e21b81526001600160a01b0388811660048301819052937fdbee882832247c009fcded16f057a75cfd42a40de981aae8f96c49496ec5208293908216928692439216906365da126490602401602060405180830381865afa15801562002880573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620028a69190620040a8565b604080516001600160a01b039586168152602081019490945263ffffffff929092168383015290921660608201526080810187905290519081900360a00190a295945050505050565b6101025460fd545b81811015620019e95760006101028281548110620029195762002919620038e8565b9060005260206000209060030201600201549050838111156200293c5750505050565b61010380548201905560fd8054600190810190915593039201620028f7565b6097546001600160a01b0316331462000e0e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162001d18565b600068056bc75e2d63100000620029cd620019ee565b61010754620029dd919062003892565b62000ceb919062003861565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60c9546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa15801562002a89573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002aaf919062003878565b610101546040516319a021cb60e11b81529192506001600160a01b03169063334043969062002ae9908990899089908990600401620040c8565b600060405180830381600087803b15801562002b0457600080fd5b505af115801562002b19573d6000803e3d6000fd5b505060c9546040516370a0823160e01b8152306004820152600093508492506001600160a01b03909116906370a0823190602401602060405180830381865afa15801562002b6b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002b91919062003878565b62002b9d919062003835565b979650505050505050565b61010554600090815b8181101562002c0457610105818154811062002bd15762002bd1620038e8565b6000918252602090912001546001600160a01b039081169085160362002bfb575060019392505050565b60010162002bb1565b5060009392505050565b60c9546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa15801562002c5c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002c82919062003878565b60c9546040516323b872dd60e01b81526001600160a01b038781166004830152306024830152604482018790529293509116906323b872dd906064016020604051808303816000875af115801562002cde573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002d04919062003aea565b62002d325760c9546040516302ce902360e61b81526001600160a01b03909116600482015260240162001d18565b60c9546040516370a0823160e01b815230600482015282916001600160a01b0316906370a0823190602401602060405180830381865afa15801562002d7b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002da1919062003878565b62001f8d919062003835565b600062000c738262002dbe62001363565b670de0b6b3a7640000620032a4565b62002dd762002154565b81111562002e065762002de962000a5f565b604051636688dd2d60e11b815260040162001d1891815260200190565b60fc546040805163df6fadc160e01b8152815160009384936001600160a01b039091169263df6fadc192600480830193928290030181865afa15801562002e51573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002e779190620041da565b915091508183111562002ea857604051633c690bcb60e11b8152600481018390526024810184905260440162001d18565b60c95460fc546040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a0823190602401602060405180830381865afa15801562002efa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002f20919062003878565b90508162002f2f858362003b0e565b111562002f5a57604051630dbbc86f60e11b8152600481018390526024810182905260440162001d18565b50505050565b610131546000906001600160a01b031662002f8e576040516340dde93560e01b815260040160405180910390fd5b600062002fa36097546001600160a01b031690565b610136546101015460fb5460fc5460c95460fe546040516001600160a01b039788166024820152958716604487015293861660648601529185166084850152841660a4840152831660c48301529190911660e48201526101040160408051601f198184030181529181526020820180516001600160e01b0316631ac3b23b60e11b17905251909150600090309083906200303d9062003344565b6200304a929190620041ff565b604051809103906000f08015801562003067573d6000803e3d6000fd5b509050806001600160a01b03811663f2fde38b6200308d6097546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015620030cf57600080fd5b505af1158015620030e4573d6000803e3d6000fd5b50506040516001600160a01b03851692507f9e676714ad2ee7d362cccabb3a543102aada709f27c2bda6bf6ef42fce70ff259150600090a25092915050565b60c95460405163095ea7b360e01b81526001600160a01b038481166004830152602482018490529091169063095ea7b3906044016020604051808303816000875af115801562003177573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200319d919062003aea565b50604051635466590560e01b8152600481018290526001600160a01b03831690635466590590602401600060405180830381600087803b158015620031e157600080fd5b505af1158015620031f6573d6000803e3d6000fd5b50505050816001600160a01b03167f890a6c1c3db8b3fa62f2928d2c9851b5c456f019d09d93f72d984454511b87b7826040516200323691815260200190565b60405180910390a25050565b60405163511e274f60e01b81526001600160a01b0385169063511e274f90620032749086908690869060040162004225565b600060405180830381600087803b1580156200328f57600080fd5b505af11580156200101e573d6000803e3d6000fd5b600062001f8d620032c1620032ba848762003861565b85620032ed565b8385620032cf82896200426f565b620032db919062003892565b620032e7919062003861565b6200332a565b600082600003620033015750600062000c73565b828202828482816200331757620033176200384b565b041462001e335760001991505062000c73565b60008282018381101562001e335760001991505062000c73565b6106cc806200428783390190565b6000815180845260005b818110156200337a576020818501810151868301820152016200335c565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600062001e33602083018462003352565b600060208284031215620033c257600080fd5b5035919050565b6001600160a01b03811681146200122857600080fd5b803562001f9581620033c9565b600080604083850312156200340057600080fd5b82356200340d81620033c9565b946020939093013593505050565b6000602082840312156200342e57600080fd5b813562001e3381620033c9565b60008083601f8401126200344e57600080fd5b5081356001600160401b038111156200346657600080fd5b6020830191508360208260051b85010111156200348257600080fd5b9250929050565b60008060008060008060608789031215620034a357600080fd5b86356001600160401b0380821115620034bb57600080fd5b620034c98a838b016200343b565b90985096506020890135915080821115620034e357600080fd5b620034f18a838b016200343b565b909650945060408901359150808211156200350b57600080fd5b506200351a89828a016200343b565b979a9699509497509295939492505050565b600080604083850312156200354057600080fd5b8235915060208301356200355481620033c9565b809150509250929050565b6000806000604084860312156200357557600080fd5b83356200358281620033c9565b925060208401356001600160401b038111156200359e57600080fd5b620035ac868287016200343b565b9497909650939450505050565b80356001600160e01b03198116811462001f9557600080fd5b600381106200122857600080fd5b600080600060608486031215620035f657600080fd5b6200360184620035b9565b925060208401356200361381620035d2565b915060408401356200362581620035d2565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200366b576200366b62003630565b60405290565b60405160e081016001600160401b03811182821017156200366b576200366b62003630565b604051601f8201601f191681016001600160401b0381118282101715620036c157620036c162003630565b604052919050565b60008060008060808587031215620036e057600080fd5b84359350602080860135620036f581620033c9565b93506040860135925060608601356001600160401b03808211156200371957600080fd5b908701906040828a0312156200372e57600080fd5b6200373862003646565b8235828111156200374857600080fd5b8301601f81018b136200375a57600080fd5b8035838111156200376f576200376f62003630565b62003783601f8201601f1916870162003696565b93508084528b868284010111156200379a57600080fd5b80868301878601376000908401860152509081529082013591810191909152939692955090935050565b60008151808452602080850194506020840160005b83811015620037f757815187529582019590820190600101620037d9565b509495945050505050565b821515815260406020820152600062001f8d6040830184620037c4565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000c735762000c736200381f565b634e487b7160e01b600052601260045260246000fd5b6000826200387357620038736200384b565b500490565b6000602082840312156200388b57600080fd5b5051919050565b808202811582820484141762000c735762000c736200381f565b600181811c90821680620038c157607f821691505b602082108103620038e257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156200391157600080fd5b813562001e3381620035d2565b634e487b7160e01b600052602160045260246000fd5b6000602082840312156200394757600080fd5b62001e3382620035b9565b60008151808452602080850194506020840160005b83811015620037f75781516001600160a01b03168752958201959082019060010162003967565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101562003a2257603f19898403018552815160608151818652620039e08287018262003952565b915050888201518582038a870152620039fa8282620037c4565b928901516001600160a01b0316958901959095525094870194925090860190600101620039b7565b509098975050505050505050565b60006001600160401b0382111562003a4c5762003a4c62003630565b5060051b60200190565b6000602080838503121562003a6a57600080fd5b82516001600160401b0381111562003a8157600080fd5b8301601f8101851362003a9357600080fd5b805162003aaa62003aa48262003a30565b62003696565b81815260059190911b8201830190838101908783111562003aca57600080fd5b928401925b8284101562002b9d5783518252928401929084019062003acf565b60006020828403121562003afd57600080fd5b8151801515811462001e3357600080fd5b8082018082111562000c735762000c736200381f565b803563ffffffff8116811462001f9557600080fd5b600082601f83011262003b4b57600080fd5b8135602062003b5e62003aa48362003a30565b8083825260208201915060208460051b87010193508684111562003b8157600080fd5b602086015b8481101562003baa57803562003b9c81620033c9565b835291830191830162003b86565b509695505050505050565b600082601f83011262003bc757600080fd5b8135602062003bda62003aa48362003a30565b8083825260208201915060208460051b87010193508684111562003bfd57600080fd5b602086015b8481101562003baa578035835291830191830162003c02565b600062003c2c62003aa48462003a30565b80848252602080830192508560051b85013681111562003c4b57600080fd5b855b8181101562003d425780356001600160401b038082111562003c6f5760008081fd5b818901915060e0823603121562003c865760008081fd5b62003c9062003671565b62003c9b83620033df565b815262003caa868401620033df565b86820152604062003cbd818501620033df565b9082015260608381013590820152608062003cda81850162003b24565b9082015260a0838101358381111562003cf35760008081fd5b62003d013682870162003b39565b82840152505060c0808401358381111562003d1c5760008081fd5b62003d2a3682870162003bb5565b91830191909152508752505093820193820162003c4d565b50919695505050505050565b6000808335601e1984360301811262003d6657600080fd5b83016020810192503590506001600160401b0381111562003d8657600080fd5b8060051b36038213156200348257600080fd5b8183526000602080850194508260005b85811015620037f757813562003dbf81620033c9565b6001600160a01b03168752958201959082019060010162003da9565b81835260006001600160fb1b0383111562003df557600080fd5b8260051b80836020870137939093016020019392505050565b600082825180855260208086019550808260051b8401018186016000805b8581101562003e8c57868403601f19018a52825180518086529086019086860190845b8181101562003e765783516001600160a01b03168352928801929188019160010162003e4f565b50509a86019a9450509184019160010162003e2c565b509198975050505050505050565b60008151808452602080850194506020840160005b83811015620037f757815115158752958201959082019060010162003eaf565b608080825281810186905260009060a0808401600589901b850182018a85805b8c81101562003ff157888403609f190185528235368f900360de1901811262003f16578283fd5b8e0160e0813562003f2781620033c9565b6001600160a01b0316865260208281013562003f4381620033c9565b6001600160a01b031681880152604062003f5f848201620033df565b6001600160a01b0316908801526060838101359088015262003f838a840162003b24565b63ffffffff168a88015262003f9b838a018462003d4e565b838b8a015262003faf848a01828462003d99565b9350505060c062003fc38185018562003d4e565b9450888403828a015262003fd984868362003ddb565b99830199985050509490940193505060010162003eef565b505050858103602087015262004008818a62003e0e565b93505050508281036040840152620040218186620037c4565b9050828103606084015262004037818562003e9a565b98975050505050505050565b600381106200122857634e487b7160e01b600052602160045260246000fd5b60408101620040718462004043565b8382526200407f8362004043565b8260208301529392505050565b600060018201620040a157620040a16200381f565b5060010190565b600060208284031215620040bb57600080fd5b815162001e3381620033c9565b600060808083016080845280885180835260a0925060a08601915060a08160051b8701016020808c0160005b848110156200419557898403609f19018652815180516001600160a01b0390811686528482015181168587015260408083015190911690860152606080820151908601528881015163ffffffff16898601528781015160e089870181905290620041618288018262003952565b91505060c08083015192508682038188015250620041808183620037c4565b978501979550505090820190600101620040f4565b505087820390880152620041aa818b62003e0e565b9450505050508281036040840152620041c48186620037c4565b9050828103606084015262002b9d818562003e9a565b60008060408385031215620041ee57600080fd5b505080516020909101519092909150565b6001600160a01b038316815260406020820181905260009062001f8d9083018462003352565b60018060a01b03841681528260208201526060604082015260008251604060608401526200425760a084018262003352565b90506020840151608084015280915050949350505050565b6000826200428157620042816200384b565b50069056fe60806040526040516106cc3803806106cc83398101604081905261002291610420565b61002e82826000610035565b505061054a565b61003e836100f6565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100f1576100ef836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e991906104e0565b8361027a565b505b505050565b6001600160a01b0381163b6101605760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101d4816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c591906104e0565b6001600160a01b03163b151590565b6102395760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610157565b7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b0392909216919091179055565b606061029f83836040518060600160405280602781526020016106a5602791396102a6565b9392505050565b6060600080856001600160a01b0316856040516102c391906104fb565b600060405180830381855af49150503d80600081146102fe576040519150601f19603f3d011682016040523d82523d6000602084013e610303565b606091505b5090925090506103158683838761031f565b9695505050505050565b6060831561038e578251600003610387576001600160a01b0385163b6103875760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610157565b5081610398565b61039883836103a0565b949350505050565b8151156103b05781518083602001fd5b8060405162461bcd60e51b81526004016101579190610517565b80516001600160a01b03811681146103e157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156104175781810151838201526020016103ff565b50506000910152565b6000806040838503121561043357600080fd5b61043c836103ca565b60208401519092506001600160401b038082111561045957600080fd5b818501915085601f83011261046d57600080fd5b81518181111561047f5761047f6103e6565b604051601f8201601f19908116603f011681019083821181831017156104a7576104a76103e6565b816040528281528860208487010111156104c057600080fd5b6104d18360208301602088016103fc565b80955050505050509250929050565b6000602082840312156104f257600080fd5b61029f826103ca565b6000825161050d8184602087016103fc565b9190910192915050565b60208152600082518060208401526105368160408501602087016103fc565b601f01601f19169190910160400192915050565b61014c806105596000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610029565b6100c2565b565b600061005c7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610099573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100bd91906100e6565b905090565b3660008037600080366000845af43d6000803e8080156100e1573d6000f35b3d6000fd5b6000602082840312156100f857600080fd5b81516001600160a01b038116811461010f57600080fd5b939250505056fea2646970667358221220b56935c588face108abef8b1e72ef1babd8d1377fb7d73534ea44bb80f729e3764736f6c63430008180033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122060805f0a761a94157f391e4822a4b7713415e286ae24ddcb791dd6c5a09b6a4964736f6c63430008180033
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.