Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60e06040 | 19039200 | 288 days ago | IN | 0 ETH | 0.09658711 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
CorePrimary
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "./library/PauseGuardian.sol"; import "./library/Manable.sol"; import "./core/CoreTreasury.sol"; import "./core/CoreStrategy.sol"; import "./core/StakingModel.sol"; import "./core/Submit.sol"; import "./core/WithdrawalQueue.sol"; import "./interface/IRewardOracle.sol"; /** * @title Aspida's ETH 2.0 staking Core(primary) * @author Aspida engineer * @notice This contract is the primary contract for Aspida's ETH 2.0 staking Core. * It inherits from several other contracts and contains various functions for managing the Core. * @dev This contract is implemented using the OpenZeppelin library. * It is used for staking ETH 2.0 and managing the Core's treasury, strategies, and actions. * It also contains functions for submitting and withdrawing ETH, as well as managing the withdrawal queue. */ contract CorePrimary is Ownable2StepUpgradeable, PauseGuardian, ReentrancyGuardUpgradeable, Manable, CoreTreasury, CoreStrategy, Submit, StakingModel, WithdrawalQueue { address internal rewardOracle_; uint256 internal received_; event SetRewardOracle(address rewardOracle); event Received(uint256 _ethValue); /** * @dev Throws if called by any account other than the rewardOracle. */ modifier onlyRewardOracle() { require(rewardOracle_ == msg.sender, "onlyRewardOracle: caller is not the rewardOracle"); _; } /** * @dev Modifier to check if the contract has enough balance to deposit for the given validators. * It throws if the contract's balance minus the strategy reserve and pending claim amount divided by the deposit size is less than the number of validators. * @param _validators The array of validators to check for. */ modifier depositBalanceCheck(Validator[] calldata _validators) { require( (address(this).balance - strategyReserve_ - pendingClaimAmount_) / DEPOSIT_SIZE >= _validators.length, "depositBalanceCheck: Not enough ETH" ); _; } /** * @notice Only for the implementation contract, as for the proxy pattern, * should call `initialize()` separately. */ constructor( IDepositContract _depositContract, IaETH _aETH, IsaETH _saETH ) StakingModel(_depositContract) Submit(_aETH, _saETH) { _disableInitializers(); } /** * @notice Expects to call only once to initialize CorePrimary. */ function initialize() public initializer { __Ownable2Step_init(); _setTreasuryInternal(owner()); _setWithdrawalCredentialsInternal(_addressToWithdrawalCredentials(address(this))); } /** * @notice Receives ETH sent to the contract. */ receive() external payable { received_ += msg.value; emit Received(msg.value); } /** * @dev Unpause when Core is paused. */ function _open() external onlyOwner { _unpause(); } /** * @dev Pause Core. */ function _close() external onlyPauseGuardian { _pause(); } /** * @notice Adds a new pause guardian to the Core. * @param _pauseGuardian The address of the new pause guardian. */ function _addPauseGuardian(address _pauseGuardian) external onlyOwner { _addPauseGuardianInternal(_pauseGuardian); } /** * @notice Removes a pause guardian from the Core. * @param _pauseGuardian The address of the pause guardian to remove. */ function _removePauseGuardian(address _pauseGuardian) external onlyOwner { _removePauseGuardianInternal(_pauseGuardian); } /** * @notice Adds a new manager to the Core. * @param _manager The address of the new manager. */ function _addManager(address _manager) external onlyOwner { _addManagerInternal(_manager); } /** * @notice Removes a manager from the Core. * @param _manager The address of the manager to remove. */ function _removeManager(address _manager) external onlyOwner { _removeManagerInternal(_manager); } /** * @notice Sets the treasury address. * @param _treasury The address of the new treasury. */ function _setTreasury(address _treasury) external onlyOwner { _setTreasuryInternal(_treasury); } /** * @notice Sets the treasury ratio. * @param _treasuryRatio The new treasury ratio. */ function _setTreasuryRatio(uint256 _treasuryRatio) external onlyOwner { _setTreasuryRatioInternal(_treasuryRatio); } /** * @notice Sets the reserve ratio. * @param _reserveRatio The new reserve ratio. */ function _setReserveRatio(uint256 _reserveRatio) external onlyOwner { _setReserveRatioInternal(_reserveRatio); } /** * @notice Adds a new strategy. * @param _strategy The address of the new strategy. */ function _addStrategy(address _strategy) external onlyOwner { _addStrategyInternal(_strategy); } /** * @notice Removes a strategy. * @param _strategy The address of the strategy to remove. */ function _removeStrategy(address _strategy) external onlyOwner { _removeStrategyInternal(_strategy); } /** * @notice Releases the strategy reserve. * @param _releaseAmount The amount to release. */ function _releaseStrategyReserve(uint256 _releaseAmount) external onlyOwner { _decreaseStrategyReserve(_releaseAmount); } /** * @notice Sets the reward oracle address. * @param _rewardOracle The address of the new reward oracle. */ function _setRewardOracle(address _rewardOracle) external onlyOwner { require( _rewardOracle != rewardOracle_ && IRewardOracle(_rewardOracle).core() == address(this), "_setRewardOracle: Invalid reward oracle address" ); rewardOracle_ = _rewardOracle; emit SetRewardOracle(_rewardOracle); } /** * @notice Disables the reward oracle. */ function _disableRewardOracle() external onlyOwner { rewardOracle_ = address(0); emit SetRewardOracle(address(0)); } /** * @notice Deposits ETH into a strategy. * @param _strategy The address of the strategy. * @param _ethAmount The amount of ETH to deposit. */ function _depositIntoStrategy(address _strategy, uint256 _ethAmount) external onlyOwner { _depositIntoStrategyInternal(_strategy, _ethAmount); } /** * @notice Recap the loss(Slashing and strategy losses). * @param _loss The amount of loss * * Requirements: * - the caller must be `owner`. */ function _recapLoss(uint256 _loss) external onlyOwner { // Burn the loss from the treasury AETH.burnFrom(treasury_, _loss); } /** * @notice Deposits ETH into the contract for staking. * @param _validators The array of validators to deposit. */ function deposit( Validator[] calldata _validators ) external whenNotPaused nonReentrant onlyManager depositBalanceCheck(_validators) { _deposit(_validators); } /** * @notice The whitelist operator deposits ETH into the contract for staking. * @param _validators The array of validators to deposit. * @param _depositRoot The expected deposit root. */ function depositCheck( Validator[] calldata _validators, bytes32 _depositRoot ) external whenNotPaused nonReentrant onlyManager depositBalanceCheck(_validators) { _depositCheck(_validators, _depositRoot); } /** * @notice Supplies reward. * @param _amount The amount to supply. */ function supplyReward(uint256 _amount) external whenNotPaused onlyRewardOracle { require(_amount != 0, "supplyReward: Amount cannot be 0"); uint256 _treasuryAmount = _getTreasuryAmount(_amount); if (_treasuryAmount > 0) AETH.mint(treasury_, _treasuryAmount); uint256 _reward = _amount - _treasuryAmount; if (_reward > 0) AETH.mint(address(SAETH), _reward); } /** * @notice Receives earnings from a strategy. */ function receiveStrategyEarning() external payable { _receiveStrategyEarning(msg.sender); } /** * @notice Submits a transaction to the CorePrimary contract. * @dev This function is called internally when a user submits a transaction. * @param _receiver The address of the receiver of the transaction. */ function _submit(address _receiver) internal override whenNotPaused nonReentrant { _increaseReservesByRatio(msg.value); Submit._submit(_receiver); } /** * @dev Internal function to withdraw funds from the contract. * @param _sender The address of the sender. * @param _receiver The address of the receiver. * @param _amount The amount to withdraw. */ function _withdraw( address _sender, address _receiver, uint256 _amount ) internal override whenNotPaused nonReentrant { AETH.burnFrom(_sender, _amount); WithdrawalQueue._withdraw(_sender, _receiver, _amount); } /** * @notice Claims the rewards by queue ID. * @param _sender The address of the sender. * @param _receiver The address of the receiver. * @param _queueIds The array of queue IDs. * @param _userQueueIds The set of user queue IDs. */ function _claimByQueueId( address _sender, address _receiver, uint256[] memory _queueIds, EnumerableSet.UintSet storage _userQueueIds ) internal override whenNotPaused nonReentrant { WithdrawalQueue._claimByQueueId(_sender, _receiver, _queueIds, _userQueueIds); } /** * @dev Returns the amount of ETH that can be withdrawn from the contract. * @return _availableAmount The available amount of ETH that can be withdrawn. */ function _withdrawableAmount() internal view override returns (uint256 _availableAmount) { uint256 _balance = address(this).balance; uint256 _locked = pendingClaimAmount_ + strategyReserve_; if (_balance > _locked) { _availableAmount = _balance - _locked; } } /** * @dev Returns the amount of ETH that can be claimed from the contract. * @return _claimableAmount The amount of ETH that can be claimed. */ function _claimableAmount() internal view override returns (uint256) { return address(this).balance - strategyReserve_ + totalClaimed_; } /** * @notice Withdraws a specified amount of tokens with permit functionality. * @param _amount The amount of tokens to withdraw. * @param _receiver The address to receive the tokens. * @param _deadline The deadline for the permit. * @param _approveMax Boolean indicating whether to approve the maximum amount. * @param _v The recovery id of the permit signature. * @param _r The R value of the permit signature. * @param _s The S value of the permit signature. */ function withdrawWithPermit( uint256 _amount, address _receiver, uint256 _deadline, bool _approveMax, uint8 _v, bytes32 _r, bytes32 _s ) external { // Determine the value to be approved uint256 _value = _approveMax ? type(uint256).max : _amount; // Call the permit function of the token contract AETH.permit(msg.sender, address(this), _value, _deadline, _v, _r, _s); // Withdraw the specified amount of tokens _withdraw(msg.sender, _receiver, _amount); } /** * @notice Redeems a specified amount of saETH and withdraws the underlying ETH. * @param _saETHAmount The amount of saETH to redeem. */ function redeemAndWithdraw(uint256 _saETHAmount) external { address _sender = msg.sender; uint256 _amount = SAETH.redeem(_saETHAmount, address(this), _sender); _withdraw(address(this), _sender, _amount); } /** * @notice Withdraws a specified amount of underlying ETH and saETH. * @param _amount The amount of underlying ETH to withdraw. */ function redeemUnderlyingAndWithdraw(uint256 _amount) external { address _sender = msg.sender; SAETH.withdraw(_amount, address(this), _sender); _withdraw(address(this), _sender, _amount); } /** * @dev Returns the address of the reward oracle. * @return The address of the reward oracle. */ function rewardOracle() external view returns (address) { return rewardOracle_; } /** * @dev Returns the amount of ETH received by the contract. * @return The amount of ETH received by the contract. */ function received() external view returns (uint256) { return received_; } /** * @dev Returns whether the given address is a pause guardian. * @param _pauseGuardian The address to check. * @return Whether the given address is a pause guardian. */ function isPauseGuardian(address _pauseGuardian) public view override returns (bool) { return PauseGuardian.isPauseGuardian(_pauseGuardian) || _pauseGuardian == owner(); } /** * @dev Returns the staking reward. * @param _deposited The amount deposited. * @param _exited The amount exited. * @return _stakingReward The staking reward. */ function stakingReward(uint256 _deposited, uint256 _exited) external view returns (uint256 _stakingReward) { uint256 _minuend = address(this).balance + totalWithdrawn_ + totalClaimed_ + depositStrategy_ + _deposited * DEPOSIT_SIZE; uint256 _subtrahend = submitted_ + received_ + receiveStrategy_ + _exited * DEPOSIT_SIZE; if (_minuend > _subtrahend) _stakingReward = _minuend - _subtrahend; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./OwnableUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides 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} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { function __Ownable2Step_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable2Step_init_unchained() internal onlyInitializing { } address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } /** * @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) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. 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 "../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 "../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) (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; // EIP-2612 is Final as of 2022-11-01. This file is deprecated. import "./IERC20PermitUpgradeable.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (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. */ interface IERC20PermitUpgradeable { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.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 v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "../interface/IStrategy.sol"; /** * @title Aspida's CoreStrategy module * @dev This contract is an abstract contract that defines the core strategy functions and variables. * @author Aspida engineer */ abstract contract CoreStrategy { using EnumerableSet for EnumerableSet.AddressSet; uint256 internal constant MAX_RESERVE_RATIO = 1e18; uint256 internal reserveRatio_; uint256 internal strategyReserve_; uint256 internal depositStrategy_; uint256 internal receiveStrategy_; /// @dev EnumerableSet of strategists EnumerableSet.AddressSet internal strategists_; /** * @dev Emitted when "reserveRatio_" has changed. */ event SetReserveRatio(uint256 reserveRatio); /** * @dev Emitted when "strategyReserve_" has been updated. */ event UpdateStrategyReserve(uint256 strategyReserve); /** * @dev Emitted when 'strategy' is added to 'strategists_'. */ event StrategyAdded(address strategy); /** * @dev Emitted when `strategy` is removed from `strategists_`. */ event StrategyRemoved(address strategy); /** * @dev Emitted when a deposit is made to a `strategy`. */ event DepositToStrategy(address strategy, uint256 amount); /** * @dev Emitted when an amount is received from a `strategy`. */ event ReceiveFromStrategy(address strategy, uint256 amount); /** * @dev Throws an exception if strategic addresses are not enabled. */ modifier isStrategy(address _strategy) { require(strategists_.contains(_strategy), "isStrategy: invalid strategy address"); _; } /** * @notice Set the reserve ratio internally. * @dev This function sets the reserve ratio to the specified value. * @param _reserveRatio The new reserve ratio to be set. */ function _setReserveRatioInternal(uint256 _reserveRatio) internal { require(_reserveRatio <= MAX_RESERVE_RATIO, "_setReserveRatioInternal: ReserveRatio too large"); require(_reserveRatio != reserveRatio_, "_setReserveRatioInternal: Cannot set the same value"); reserveRatio_ = _reserveRatio; emit SetReserveRatio(_reserveRatio); } /** * @notice Add `strategy` into strategists_. * If `strategy` have not been a strategy, emits a `StrategyAdded` event. * * @param _strategy The strategy to add */ function _addStrategyInternal(address _strategy) internal virtual { require( _strategy != address(0) && IStrategy(_strategy).core() == address(this), "_addStrategyInternal: invalid strategy address" ); require(strategists_.add(_strategy), "_addStrategyInternal: Strategy has been added"); emit StrategyAdded(_strategy); } /** * @notice Remove `strategy` from strategists_. * If `strategy` is a strategy, emits a `StrategyRemoved` event. * * @param _strategy The strategy to remove */ function _removeStrategyInternal(address _strategy) internal virtual { require(strategists_.remove(_strategy), "_removeStrategyInternal: Strategy has been removed"); emit StrategyRemoved(_strategy); } /** * @notice Update the strategy reserve with the specified value. * @dev This function updates the strategy reserve to the given value. * @param _strategyReserve The new value for the strategy reserve. */ function _updateStrategyReserve(uint256 _strategyReserve) internal { strategyReserve_ = _strategyReserve; emit UpdateStrategyReserve(_strategyReserve); } /** * @notice Increase the strategy reserve by the specified amount. * @dev This function increases the strategy reserve by the given amount. * @param _increaseReserve The amount to increase the strategy reserve by. */ function _increaseStrategyReserve(uint256 _increaseReserve) internal { _updateStrategyReserve(strategyReserve_ + _increaseReserve); } /** * @notice Decrease the strategy reserve by the specified amount. * @dev This function decreases the strategy reserve by the given amount. * @param _decreaseReserve The amount to decrease the strategy reserve by. */ function _decreaseStrategyReserve(uint256 _decreaseReserve) internal { _updateStrategyReserve(strategyReserve_ - _decreaseReserve); } /** * @notice Increase the reserves by a ratio of the specified amount. * @dev This function increases the reserves by a ratio of the given amount. * @param _amount The amount to increase the reserves by. */ function _increaseReservesByRatio(uint256 _amount) internal { _increaseStrategyReserve((_amount * reserveRatio_) / MAX_RESERVE_RATIO); } /** * @notice Deposit ETH into the specified strategy. * @dev This function deposits the specified amount of ETH into the strategy. * @param _strategy The address of the strategy to deposit into. * @param _ethAmount The amount of ETH to deposit. */ function _depositIntoStrategyInternal( address _strategy, uint256 _ethAmount ) internal virtual isStrategy(_strategy) { _decreaseStrategyReserve(_ethAmount); depositStrategy_ += _ethAmount; IStrategy(_strategy).strategyReceive{ value: _ethAmount }(); emit DepositToStrategy(_strategy, _ethAmount); } /** * @notice Receive strategy earnings from the specified strategy. * @dev This function receives the earnings from the specified strategy. * @param _strategy The address of the strategy to receive earnings from. */ function _receiveStrategyEarning(address _strategy) internal virtual isStrategy(_strategy) { uint256 _ethValue = msg.value; _increaseStrategyReserve(_ethValue); receiveStrategy_ += _ethValue; emit ReceiveFromStrategy(_strategy, _ethValue); } /** * @notice Get the reserve ratio. * @return The reserve ratio. */ function reserveRatio() external view returns (uint256) { return reserveRatio_; } /** * @notice Get the strategy reserve. * @return The strategy reserve. */ function strategyReserve() external view returns (uint256) { return strategyReserve_; } /** * @notice Get the deposit strategy. * @return The deposit strategy. */ function depositStrategy() external view returns (uint256) { return depositStrategy_; } /** * @notice Get the receive strategy. * @return The receive strategy. */ function receiveStrategy() external view returns (uint256) { return receiveStrategy_; } /** * @notice Get all strategists. * @return _strategists The list of strategy addresses. */ function strategists() external view returns (address[] memory _strategists) { _strategists = strategists_.values(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Aspida's CoreTreasury module * @dev This contract is an abstract contract that defines the core treasury functionality of Aspida. * @dev It contains internal functions to set the treasury and treasury ratio, and a function to calculate the treasury amount. * @dev It also contains external functions to get the treasury address and treasury ratio. * @dev The maximum treasury ratio is set to 1e18. * @author Aspida engineer */ abstract contract CoreTreasury { uint256 internal constant MAX_TREASURY_RATIO = 1e18; // The address of the treasury address internal treasury_; // The treasury ratio uint256 internal treasuryRatio_; /** * @dev Emitted when the treasury address is set */ event SetTreasury(address treasury); /** * @dev Emitted when the treasury ratio is set */ event SetTreasuryRatio(uint256 treasuryRatio); /** * @dev Sets the treasury address. * @param _treasury The address of the treasury. */ function _setTreasuryInternal(address _treasury) internal { require(_treasury != address(0) && _treasury != treasury_, "_setTreasuryInternal: Invalid treasury"); treasury_ = _treasury; emit SetTreasury(_treasury); } /** * @dev Sets the treasury ratio. * @param _treasuryRatio The treasury ratio. */ function _setTreasuryRatioInternal(uint256 _treasuryRatio) internal { require(_treasuryRatio <= MAX_TREASURY_RATIO, "_setTreasuryRatioInternal: TreasuryRatio too large"); require(_treasuryRatio != treasuryRatio_, "_setTreasuryRatioInternal: Cannot set the same value"); treasuryRatio_ = _treasuryRatio; emit SetTreasuryRatio(_treasuryRatio); } /** * @dev Calculates the treasury amount. * @param _amount The amount to calculate the treasury amount for. * @return The treasury amount. */ function _getTreasuryAmount(uint256 _amount) internal view returns (uint256) { return (_amount * treasuryRatio_) / MAX_TREASURY_RATIO; } /** * @dev Gets the treasury address. * @return The address of the treasury. */ function treasury() external view returns (address) { return treasury_; } /** * @dev Gets the treasury ratio. * @return The treasury ratio. */ function treasuryRatio() external view returns (uint256) { return treasuryRatio_; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../interface/IDepositContract.sol"; /** * @title Aspida's StakingModel * @dev This contract manages the deposit of validators to the Ethereum 2.0 deposit contract. * @author Aspida engineer */ abstract contract StakingModel { uint256 internal constant DEPOSIT_SIZE = 32 ether; uint256 internal constant SIGNATURE_INDEX = 64; uint64 internal constant DEPOSIT_SIZE_IN_GWEI_LE64 = 0x0040597307000000; IDepositContract internal immutable DEPOSIT_CONTRACT; // Deposit contract is immutable bytes internal withdrawalCredentials_; // Withdrawal credentials are stored as bytes mapping(bytes => bool) internal pubKeyExpired_; // Mapping to check if a public key has expired /** * @dev Emitted when the withdrawal credentials are set. */ event SetWithdrawalCredentials(bytes withdrawalCredential); /** * @dev Emitted when a validator is deposited. */ event ValidatorDeposited( address operator, bytes pubKey, bytes signature, bytes withdrawalCredential, bytes32 depositDataRoot ); /** * @dev Event emitted when a deposit is made. */ event Deposit(uint256 depositValue, uint256 validatorCount); constructor(IDepositContract _depositContract) { DEPOSIT_CONTRACT = _depositContract; } /** * @dev Sets the withdrawal credentials. * @param _withdrawalCredentials The withdrawal credentials. */ function _setWithdrawalCredentialsInternal(bytes memory _withdrawalCredentials) internal { require( _withdrawalCredentials.length == 32, "_setWithdrawalCredentialsInternal: Invalid withdrawalCredentials length" ); withdrawalCredentials_ = _withdrawalCredentials; emit SetWithdrawalCredentials(_withdrawalCredentials); } struct Validator { address operator; bytes pubKey; bytes signature; } /** * @dev Deposits validators. * @param _validators The validators to deposit. */ function _deposit(Validator[] calldata _validators) internal { require(_validators.length > 0, "_deposit: Deposit 0 is invalid"); bytes memory _withdrawalCredentials = withdrawalCredentials_; for (uint256 i = 0; i < _validators.length; i++) { require(!pubKeyExpired_[_validators[i].pubKey], "_deposit: Invalid validator public key"); bytes32 _depositDataRoot = _calculateDepositDataRoot( _validators[i].pubKey, _validators[i].signature, _withdrawalCredentials ); DEPOSIT_CONTRACT.deposit{ value: DEPOSIT_SIZE }( _validators[i].pubKey, _withdrawalCredentials, _validators[i].signature, _depositDataRoot ); pubKeyExpired_[_validators[i].pubKey] = true; emit ValidatorDeposited( _validators[i].operator, _validators[i].pubKey, _validators[i].signature, _withdrawalCredentials, _depositDataRoot ); } emit Deposit(_validators.length * DEPOSIT_SIZE, _validators.length); } /** * @dev Checks the deposit root and deposits validators. * @param _validators The validators to deposit. * @param _depositRoot The expected deposit root. */ function _depositCheck(Validator[] calldata _validators, bytes32 _depositRoot) internal { // Require that the deposit root has not changed require( _depositRoot == IDepositContract(DEPOSIT_CONTRACT).get_deposit_root(), "_depositCheck: Deposit root has changed" ); _deposit(_validators); } /** * @dev Slices a portion of a bytes array. * @param _src The source bytes array. * @param _srcStart The starting index of the slice. * @param _length The length of the slice. * @return _dst The sliced bytes array. */ function _bytesSlice( bytes memory _src, uint256 _srcStart, uint256 _length ) internal pure returns (bytes memory _dst) { require(_srcStart + _length <= _src.length, "_bytesSlice: Slice param error"); _dst = new bytes(_length); for (uint256 i = 0; i < _length; i++) { _dst[i] = _src[i + _srcStart]; } } /** * @dev Calculates the deposit data root. * @param _pubKey The public key. * @param _signature The signature. * @param _withdrawalCredentials The withdrawal credentials. * @return _depositDataRoot The deposit data root. */ function _calculateDepositDataRoot( bytes memory _pubKey, bytes memory _signature, bytes memory _withdrawalCredentials ) internal pure returns (bytes32 _depositDataRoot) { bytes32 _pubkeyRoot = sha256(abi.encodePacked(_pubKey, bytes16(0))); bytes32 _signatureRoot = sha256( abi.encodePacked( sha256(abi.encodePacked(_bytesSlice(_signature, 0, SIGNATURE_INDEX))), sha256(abi.encodePacked(_bytesSlice(_signature, SIGNATURE_INDEX, 32), bytes32(0))) ) ); _depositDataRoot = sha256( abi.encodePacked( sha256(abi.encodePacked(_pubkeyRoot, _withdrawalCredentials)), sha256(abi.encodePacked(DEPOSIT_SIZE_IN_GWEI_LE64, bytes24(0), _signatureRoot)) ) ); } /** * @dev Converts an address to withdrawal credentials. * @param _withdrawalAddress The withdrawal address. * @return The withdrawal credentials. */ function _addressToWithdrawalCredentials(address _withdrawalAddress) internal pure returns (bytes memory) { return abi.encodePacked(uint256(uint160(_withdrawalAddress)) | (1 << 248)); } /** * @dev Returns the deposit contract. * @return The deposit contract. */ function depositContract() external view returns (IDepositContract) { return DEPOSIT_CONTRACT; } /** * @dev Returns the withdrawal credentials. * @return The withdrawal credentials. */ function withdrawalCredentials() external view returns (bytes memory) { return withdrawalCredentials_; } /** * @dev Checks if a public key has expired. * @param _pubKey The public key. * @return True if the public key has expired, false otherwise. */ function pubKeyExpired(bytes memory _pubKey) external view returns (bool) { return pubKeyExpired_[_pubKey]; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../interface/IaETH.sol"; import "../interface/IsaETH.sol"; /** * @title Aspida's Submit model * @dev This contract allows users to submit ETH and mint aETH tokens in return. * Users can also submit ETH and stake it to receive saETH tokens. * @author Aspida engineer */ abstract contract Submit { IaETH internal immutable AETH; // aETH token contract IsaETH internal immutable SAETH; // saETH token contract uint256 internal submitted_; // total amount of ETH submitted /** * @dev Emitted when the withdrawal credentials are set. */ event Submitted(address sender, address recipient, uint256 ethValue); constructor(IaETH _aETH, IsaETH _saETH) { AETH = _aETH; SAETH = _saETH; } /** * @dev Internal function to submit ETH and mint aETH tokens * @param _receiver The address of the receiver of the aETH tokens */ function _submit(address _receiver) internal virtual { uint256 _ethValue = msg.value; require(_ethValue != 0, "_submit: ETH cannot be 0"); submitted_ += _ethValue; AETH.mint(_receiver, _ethValue); emit Submitted(msg.sender, _receiver, _ethValue); } /** * @dev External function to submit ETH and mint aETH tokens */ function submit() external payable { _submit(msg.sender); } /** * @dev External function to submit ETH and mint aETH tokens for a specific receiver * @param _receiver The address of the receiver of the aETH tokens */ function submit(address _receiver) external payable { _submit(_receiver); } /** * @dev External function to submit ETH, mint aETH tokens and stake them to receive saETH tokens * @param _receiver The address of the receiver of the saETH tokens */ function submitAndStake(address _receiver) external payable { _submit(address(this)); AETH.approve(address(SAETH), msg.value); require(SAETH.deposit(msg.value, _receiver) > 0, "No saETH was returned"); } /** * @dev External function to return the aETH token contract * @return The aETH token contract */ function aETH() external view returns (IaETH) { return AETH; } /** * @dev External function to return the saETH token contract * @return The saETH token contract */ function saETH() external view returns (IsaETH) { return SAETH; } /** * @dev External function to return the total amount of ETH submitted * @return The total amount of ETH submitted */ function submitted() external view returns (uint256) { return submitted_; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "../library/TransferHelper.sol"; /** * @title Aspida's WithdrawalQueue model * @dev This contract implements a withdrawal queue for users to withdraw their funds in a fair manner. * Users can withdraw their funds immediately if there are enough funds available, otherwise they will be added to the queue. * The queue is processed in a first-in-first-out (FIFO) manner. * Users can claim their funds from the queue at any time. * @author Aspida engineer */ abstract contract WithdrawalQueue { using EnumerableSet for EnumerableSet.UintSet; using TransferHelper for address; uint256 internal totalWithdrawn_; // Total amount of funds withdrawn uint256 internal totalClaimed_; // Total amount of funds claimed uint256 internal pendingClaimAmount_; // Total amount of funds in the queue uint256 internal lastQueueId_; // The last queue ID mapping(address => EnumerableSet.UintSet) internal userQueueIds_; // Mapping of user addresses to their queue IDs mapping(uint256 => uint256) internal claimAccumulated_; // Mapping of queue IDs to their accumulated claim amounts /** * @dev Emitted when the total amount of funds in the queue is updated. */ event UpdatePendingClaim(uint256 pendingClaimAmount); /** * @dev Emitted when the total amount of funds claimed is updated. */ event UpdateTotalClaimed(uint256 totalClaimed); /** * @dev Emitted when a user is added to the withdrawal queue. */ event EnterWithdrawalQueue( address sender, address recipient, uint256 queueId, uint256 claimAmount, uint256 accumulated ); /** * @dev Emitted when a user is removed from the withdrawal queue. */ event ExitWithdrawalQueue(address sender, address recipient, uint256 queueId, uint256 claimAmount); /** * @dev Emitted when funds are withdrawn from the contract. */ event Withdrawn(address sender, address recipient, uint256 amount); /** * @dev Emitted when funds are claimed from the queue. */ event Claimed(address sender, address recipient, uint256 amount); /** * @dev Updates the total amount of funds in the queue. * @param _pendingClaimAmount The new total amount of funds in the queue. */ function _updatePendingClaim(uint256 _pendingClaimAmount) internal { pendingClaimAmount_ = _pendingClaimAmount; emit UpdatePendingClaim(_pendingClaimAmount); } /** * @dev Updates the total amount of funds claimed. * @param _totalClaimed The new total amount of funds claimed. */ function _updateTotalClaimed(uint256 _totalClaimed) internal { totalClaimed_ = _totalClaimed; emit UpdateTotalClaimed(_totalClaimed); } /** * @dev Adds the user to the withdrawal queue. * @param _receiver The address of the user to add to the queue. * @param _amount The amount of funds to add to the queue. */ function _withdrawalQueue(address _receiver, uint256 _amount) internal { uint256 _queueId = lastQueueId_; uint256 _accumulated = claimAccumulated_[_queueId]; _queueId += 1; userQueueIds_[_receiver].add(_queueId); uint256 _claimAccumulated = _accumulated + _amount; claimAccumulated_[_queueId] = _claimAccumulated; lastQueueId_ = _queueId; _updatePendingClaim(pendingClaimAmount_ + _amount); emit EnterWithdrawalQueue(msg.sender, _receiver, _queueId, _amount, _claimAccumulated); } /** * @dev Withdraws funds from the contract. * @param _sender The address of the user withdrawing the funds. * @param _receiver The address of the user receiving the funds. * @param _amount The amount of funds to withdraw. */ function _withdraw(address _sender, address _receiver, uint256 _amount) internal virtual { require(_amount > 0, "_withdraw: withdraw amount cannot be 0"); if (_withdrawableAmount() < _amount) { _withdrawalQueue(_receiver, _amount); return; } totalWithdrawn_ += _amount; _receiver.safeTransferETH(_amount); emit Withdrawn(_sender, _receiver, _amount); } /** * @dev Claims funds from the queue for a specific user. * @param _sender The address of the user claiming the funds. * @param _receiver The address of the user receiving the funds. */ function _claimByAddress(address _sender, address _receiver) internal virtual { EnumerableSet.UintSet storage _userQueueIds = userQueueIds_[_sender]; _claimByQueueId(_sender, _receiver, _userQueueIds.values(), _userQueueIds); } /** * @dev Claims funds from the queue for a specific user and queue IDs. * @param _sender The address of the user claiming the funds. * @param _receiver The address of the user receiving the funds. * @param _queueIds The list of queue IDs to claim from. * @param _userQueueIds The user's queue IDs. */ function _claimByQueueId( address _sender, address _receiver, uint256[] memory _queueIds, EnumerableSet.UintSet storage _userQueueIds ) internal virtual { require(_queueIds.length > 0, "_claimByQueueId: Queue list cannot be empty"); uint256 _availableBalance = _claimableAmount(); uint256 _claimAmount; for (uint256 i = 0; i < _queueIds.length; i++) { uint256 _amount = _getClaimAmount(_queueIds[i], _availableBalance); if (_amount == 0) continue; require(_userQueueIds.remove(_queueIds[i]), "_claimByQueueId: Queue id does not exist"); emit ExitWithdrawalQueue(_sender, _receiver, _queueIds[i], _amount); _claimAmount += _amount; } require(_claimAmount > 0, "_claimByQueueId: No claim amount"); _updatePendingClaim(pendingClaimAmount_ - _claimAmount); _updateTotalClaimed(totalClaimed_ + _claimAmount); _receiver.safeTransferETH(_claimAmount); emit Claimed(_sender, _receiver, _claimAmount); } /** * @dev Returns the amount of funds that can be withdrawn. * @return _availableAmount The available amount of funds that can be withdrawn. */ function _withdrawableAmount() internal view virtual returns (uint256 _availableAmount) { uint256 _balance = address(this).balance; uint256 _locked = pendingClaimAmount_; if (_balance > _locked) _availableAmount = _balance - _locked; } /** * @dev Returns the amount of funds that can be claimed. * @return _claimableAmount The claimable amount of funds. */ function _claimableAmount() internal view virtual returns (uint256) { return address(this).balance + totalClaimed_; } /** * @dev Returns the claim amount and accumulated claim amount for a specific queue ID. * @param _queueId The queue ID. * @return _claimAmount The claim amount for the queue ID. * @return _claimAccumulated The accumulated claim amount for the queue ID. */ function _claimDataByQueueId( uint256 _queueId ) internal view returns (uint256 _claimAmount, uint256 _claimAccumulated) { _claimAccumulated = claimAccumulated_[_queueId]; if (_claimAccumulated > 0) _claimAmount = _claimAccumulated - claimAccumulated_[_queueId - 1]; } /** * @dev Returns the claim amount for a specific queue ID. * @param _queueId The queue ID. * @param _claimable The claimable amount of funds. * @return _claimAmount The claim amount for the queue ID. */ function _getClaimAmount(uint256 _queueId, uint256 _claimable) internal view returns (uint256 _claimAmount) { uint256 _accumulated; (_claimAmount, _accumulated) = _claimDataByQueueId(_queueId); if (_claimable < _accumulated) _claimAmount = 0; } /** * @dev Allows a user to withdraw funds. * @param _amount The amount of funds to withdraw. */ function withdraw(uint256 _amount) external { _withdraw(msg.sender, msg.sender, _amount); } /** * @dev Allows a user to withdraw funds and specify a receiver address. * @param _amount The amount of funds to withdraw. * @param _receiver The address of the receiver. */ function withdraw(uint256 _amount, address _receiver) external { _withdraw(msg.sender, _receiver, _amount); } /** * @dev Allows a user to claim their funds from the queue. */ function claim() external { _claimByAddress(msg.sender, msg.sender); } /** * @dev Allows a user to claim their funds from the queue and specify a receiver address. * @param _receiver The address of the receiver. */ function claim(address _receiver) external { _claimByAddress(msg.sender, _receiver); } /** * @dev Allows a user to claim their funds from the queue using specific queue IDs. * @param _queueIds The list of queue IDs to claim from. */ function claim(uint256[] memory _queueIds) external { _claimByQueueId(msg.sender, msg.sender, _queueIds, userQueueIds_[msg.sender]); } /** * @dev Allows a user to claim their funds from the queue using specific queue IDs and specify a receiver address. * @param _receiver The address of the receiver. * @param _queueIds The list of queue IDs to claim from. */ function claim(address _receiver, uint256[] memory _queueIds) external { _claimByQueueId(msg.sender, _receiver, _queueIds, userQueueIds_[msg.sender]); } /** * @dev Returns the total amount of funds withdrawn. * @return The total amount of funds withdrawn. */ function totalWithdrawn() external view returns (uint256) { return totalWithdrawn_; } /** * @dev Returns the total amount of funds claimed. * @return The total amount of funds claimed. */ function totalClaimed() external view returns (uint256) { return totalClaimed_; } /** * @dev Returns the total amount of funds in the queue. * @return The total amount of funds in the queue. */ function pendingClaimAmount() external view returns (uint256) { return pendingClaimAmount_; } /** * @dev Returns the last queue ID. * @return The last queue ID. */ function lastQueueId() external view returns (uint256) { return lastQueueId_; } /** * @dev Returns the accumulated amount of funds in the queue. * @return The accumulated amount of funds in the queue. */ function accumulated() external view returns (uint256) { return claimAccumulated_[lastQueueId_]; } /** * @dev Returns the amount of funds that can be withdrawn. * @return The amount of funds that can be withdrawn. */ function withdrawableAmount() external view returns (uint256) { return _withdrawableAmount(); } /** * @dev Returns the amount of funds that can be claimed. * @return The amount of funds that can be claimed. */ function claimableAmount() external view returns (uint256) { return _claimableAmount(); } /** * @dev Returns the claim amount and accumulated claim amount for a specific queue ID. * @param _queueId The queue ID to get claim data for. * @return _claimAmount The claim amount for the queue ID. * @return _claimAccumulated The accumulated claim amount for the queue ID. */ function claimDataByQueueId( uint256 _queueId ) external view returns (uint256 _claimAmount, uint256 _claimAccumulated) { (_claimAmount, _claimAccumulated) = _claimDataByQueueId(_queueId); } /** * @dev Returns the claim data for a specific address. * @param _account The address to get claim data for. * @return _ids The IDs of the claims. * @return _claimAmounts The amounts of the claims. * @return _claimStatuses The statuses of the claims. */ function claimDataByAddress( address _account ) external view returns (uint256[] memory _ids, uint256[] memory _claimAmounts, bool[] memory _claimStatuses) { _ids = userQueueIds_[_account].values(); _claimAmounts = new uint256[](_ids.length); _claimStatuses = new bool[](_ids.length); uint256 _claimable = _claimableAmount(); uint256 _accumulated; for (uint256 i = 0; i < _ids.length; i++) { (_claimAmounts[i], _accumulated) = _claimDataByQueueId(_ids[i]); _claimStatuses[i] = _claimable >= _accumulated; } } /** * @dev Returns the user's queue IDs, claim amounts, and accumulated claim amounts. * @param _account The address of the user. * @return _ids The IDs of the user's claims. * @return _claimAmounts The amounts of the user's claims. * @return _accumulations The accumulated amounts of the user's claims. */ function userQueueIds( address _account ) external view returns (uint256[] memory _ids, uint256[] memory _claimAmounts, uint256[] memory _accumulations) { _ids = userQueueIds_[_account].values(); _claimAmounts = new uint256[](_ids.length); _accumulations = new uint256[](_ids.length); for (uint256 i = 0; i < _accumulations.length; i++) { (_claimAmounts[i], _accumulations[i]) = _claimDataByQueueId(_ids[i]); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol"; interface IaETH is IERC20Upgradeable, IERC20PermitUpgradeable { function mint(address _receiver, uint256 _amount) external; function burn(uint256 _amount) external; function burnFrom(address _account, uint256 _amount) external; function minterMint(address _receiver, uint256 _amount) external; function minterBurn(uint256 _amount) external; function mintCap(address _minter) external view returns (uint256); function mintAmount(address _minter) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; interface IDepositContract { function get_deposit_root() external view returns (bytes32 rootHash); function deposit( bytes calldata pubkey, // 48 bytes bytes calldata withdrawal_credentials, // 32 bytes bytes calldata signature, // 96 bytes bytes32 deposit_data_root ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; interface IRewardOracle { function core() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; interface IsaETH { function deposit(uint256 _assets, address _receiver) external returns (uint256 _shares); function withdraw(uint256 _assets, address _receiver, address _owner) external returns (uint256 _shares); function redeem(uint256 _shares, address _receiver, address _owner) external returns (uint256 _assets); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; interface IStrategy { function strategyReceive() external payable returns (uint256); function aETH() external view returns (address); function core() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; /** * @title Aspida's manager module * @author Aspida engineer */ abstract contract Manable { using EnumerableSet for EnumerableSet.AddressSet; /// @dev EnumerableSet of managers EnumerableSet.AddressSet internal managers_; /** * @dev Emitted when `manager` is added as `managers`. */ event ManagerAdded(address manager); /** * @dev Emitted when `manager` is removed from `managers`. */ event ManagerRemoved(address manager); /** * @dev Throws if called by any account other than the managers. */ modifier onlyManager() { require(managers_.contains(msg.sender), "onlyManager: caller is not manager"); _; } /** * @notice Add `manager` into managers. * If `manager` have not been a manager, emits a `ManagerAdded` event. * * @param _manager The manager to add */ function _addManagerInternal(address _manager) internal virtual { require(_manager != address(0), "_addManagerInternal: _manager the zero address"); require(managers_.add(_manager), "_addManagerInternal: _manager has been added"); emit ManagerAdded(_manager); } /** * @notice Remove `manager` from managers. * If `manager` is a manager, emits a `ManagerRemoved` event. * * @param _manager The manager to remove */ function _removeManagerInternal(address _manager) internal virtual { require(managers_.remove(_manager), "_removeManagerInternal: _manager has been removed"); emit ManagerRemoved(_manager); } /** * @notice Return all managers * @return _managers The list of manager addresses */ function managers() public view returns (address[] memory _managers) { _managers = managers_.values(); } /** * @dev Check if address is manager * @param _manager The address to check * @return Is manager boolean, true: is the manager; false: not the manager */ function isManager(address _manager) public view returns (bool) { return managers_.contains(_manager); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; /** * @title Aspida's PauseGuardian module * @author Aspida engineer */ abstract contract PauseGuardian is PausableUpgradeable { using EnumerableSet for EnumerableSet.AddressSet; /// @dev EnumerableSet of pauseGuardians EnumerableSet.AddressSet internal pauseGuardians_; /** * @dev Emitted when `pauseGuardian` is added as `pauseGuardian`. */ event PauseGuardianAdded(address pauseGuardian); /** * @dev Emitted when `pauseGuardian` is removed from `pauseGuardians`. */ event PauseGuardianRemoved(address pauseGuardian); /** * @dev Throws if called by any account other than pauseGuardian. */ modifier onlyPauseGuardian() { require(isPauseGuardian(msg.sender), "onlyPauseGuardian: caller is not pauseGuardian"); _; } /** * @notice Add `pauseGuardian` into pauseGuardians. * If `pauseGuardian` have not been a pauseGuardian, emits a `PauseGuardianAdded` event. * * @param _pauseGuardian The pauseGuardian to add */ function _addPauseGuardianInternal(address _pauseGuardian) internal virtual { require(_pauseGuardian != address(0), "_addPauseGuardianInternal: _pauseGuardian the zero address"); require(pauseGuardians_.add(_pauseGuardian), "_addPauseGuardianInternal: _pauseGuardian has been added"); emit PauseGuardianAdded(_pauseGuardian); } /** * @notice Remove `pauseGuardian` from pauseGuardians. * If `pauseGuardian` is a pauseGuardian, emits a `PauseGuardianRemoved` event. * * @param _pauseGuardian The pauseGuardian to remove */ function _removePauseGuardianInternal(address _pauseGuardian) internal virtual { require( pauseGuardians_.remove(_pauseGuardian), "_removePauseGuardianInternal: _pauseGuardian has been removed" ); emit PauseGuardianRemoved(_pauseGuardian); } /** * @notice Return all pauseGuardians * @return _pauseGuardians The list of pauseGuardian addresses */ function pauseGuardians() public view returns (address[] memory _pauseGuardians) { _pauseGuardians = pauseGuardians_.values(); } /** * @dev Check if address is pauseGuardian * @param _pauseGuardian The address to check * @return Is pauseGuardian boolean, true: is the pauseGuardian; false: not the pauseGuardian */ function isPauseGuardian(address _pauseGuardian) public view virtual returns (bool) { return pauseGuardians_.contains(_pauseGuardian); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Library for safely executing transfers and approvals of ERC20 tokens and ETH. */ library TransferHelper { /** * @dev Safely approves `value` tokens for `to` by calling the `approve` function on `token`. * @param token The address of the ERC20 token. * @param to The address to approve tokens for. * @param value The number of tokens to approve. */ function safeApprove(address token, address to, uint value) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: APPROVE_FAILED"); } /** * @dev Safely transfers `value` tokens to `to` by calling the `transfer` function on `token`. * @param token The address of the ERC20 token. * @param to The address to transfer tokens to. * @param value The number of tokens to transfer. */ function safeTransfer(address token, address to, uint value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: TRANSFER_FAILED"); } /** * @dev Safely transfers `value` tokens from `from` to `to` by calling the `transferFrom` function on `token`. * @param token The address of the ERC20 token. * @param from The address to transfer tokens from. * @param to The address to transfer tokens to. * @param value The number of tokens to transfer. */ function safeTransferFrom(address token, address from, address to, uint value) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: TRANSFER_FROM_FAILED"); } /** * @dev Safely transfers `value` ETH to `to`. * @param to The address to transfer ETH to. * @param value The amount of ETH to transfer. */ function safeTransferETH(address to, uint value) internal { (bool success, ) = to.call{ value: value }(new bytes(0)); require(success, "TransferHelper: ETH_TRANSFER_FAILED"); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IDepositContract","name":"_depositContract","type":"address"},{"internalType":"contract IaETH","name":"_aETH","type":"address"},{"internalType":"contract IsaETH","name":"_saETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"depositValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"validatorCount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"strategy","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositToStrategy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"queueId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claimAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"accumulated","type":"uint256"}],"name":"EnterWithdrawalQueue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"queueId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claimAmount","type":"uint256"}],"name":"ExitWithdrawalQueue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"manager","type":"address"}],"name":"ManagerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"manager","type":"address"}],"name":"ManagerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","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":"pauseGuardian","type":"address"}],"name":"PauseGuardianAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pauseGuardian","type":"address"}],"name":"PauseGuardianRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"strategy","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReceiveFromStrategy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_ethValue","type":"uint256"}],"name":"Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reserveRatio","type":"uint256"}],"name":"SetReserveRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"rewardOracle","type":"address"}],"name":"SetRewardOracle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"treasury","type":"address"}],"name":"SetTreasury","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"treasuryRatio","type":"uint256"}],"name":"SetTreasuryRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"withdrawalCredential","type":"bytes"}],"name":"SetWithdrawalCredentials","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"strategy","type":"address"}],"name":"StrategyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"strategy","type":"address"}],"name":"StrategyRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"ethValue","type":"uint256"}],"name":"Submitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"pendingClaimAmount","type":"uint256"}],"name":"UpdatePendingClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"strategyReserve","type":"uint256"}],"name":"UpdateStrategyReserve","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalClaimed","type":"uint256"}],"name":"UpdateTotalClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bytes","name":"pubKey","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"signature","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"withdrawalCredential","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"depositDataRoot","type":"bytes32"}],"name":"ValidatorDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"_addManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pauseGuardian","type":"address"}],"name":"_addPauseGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"}],"name":"_addStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_close","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"uint256","name":"_ethAmount","type":"uint256"}],"name":"_depositIntoStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_disableRewardOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_open","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_loss","type":"uint256"}],"name":"_recapLoss","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_releaseAmount","type":"uint256"}],"name":"_releaseStrategyReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"_removeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pauseGuardian","type":"address"}],"name":"_removePauseGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"}],"name":"_removeStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reserveRatio","type":"uint256"}],"name":"_setReserveRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardOracle","type":"address"}],"name":"_setRewardOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"_setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_treasuryRatio","type":"uint256"}],"name":"_setTreasuryRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"aETH","outputs":[{"internalType":"contract IaETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"accumulated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256[]","name":"_queueIds","type":"uint256[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_queueIds","type":"uint256[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"claimDataByAddress","outputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"},{"internalType":"uint256[]","name":"_claimAmounts","type":"uint256[]"},{"internalType":"bool[]","name":"_claimStatuses","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_queueId","type":"uint256"}],"name":"claimDataByQueueId","outputs":[{"internalType":"uint256","name":"_claimAmount","type":"uint256"},{"internalType":"uint256","name":"_claimAccumulated","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimableAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"pubKey","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct StakingModel.Validator[]","name":"_validators","type":"tuple[]"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"pubKey","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct StakingModel.Validator[]","name":"_validators","type":"tuple[]"},{"internalType":"bytes32","name":"_depositRoot","type":"bytes32"}],"name":"depositCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositContract","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositStrategy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"isManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pauseGuardian","type":"address"}],"name":"isPauseGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastQueueId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managers","outputs":[{"internalType":"address[]","name":"_managers","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseGuardians","outputs":[{"internalType":"address[]","name":"_pauseGuardians","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingClaimAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_pubKey","type":"bytes"}],"name":"pubKeyExpired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"receiveStrategy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"receiveStrategyEarning","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"received","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_saETHAmount","type":"uint256"}],"name":"redeemAndWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"redeemUnderlyingAndWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserveRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"saETH","outputs":[{"internalType":"contract IsaETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_deposited","type":"uint256"},{"internalType":"uint256","name":"_exited","type":"uint256"}],"name":"stakingReward","outputs":[{"internalType":"uint256","name":"_stakingReward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategists","outputs":[{"internalType":"address[]","name":"_strategists","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategyReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"submit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"submit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"submitAndStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"submitted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"supplyReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalWithdrawn","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":[],"name":"treasuryRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"userQueueIds","outputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"},{"internalType":"uint256[]","name":"_claimAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"_accumulations","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"bool","name":"_approveMax","type":"bool"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"withdrawWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawableAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalCredentials","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60e06040523480156200001157600080fd5b5060405162004ed638038062004ed683398101604081905262000034916200013a565b6001600160a01b0380831660805280821660a052831660c0526200005762000060565b5050506200018e565b600054610100900460ff1615620000cd5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200011f576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b03811681146200013757600080fd5b50565b6000806000606084860312156200015057600080fd5b83516200015d8162000121565b6020850151909350620001708162000121565b6040850151909250620001838162000121565b809150509250925092565b60805160a05160c051614cb66200022060003960008181610ba6015281816123870152612be6015260008181610b1f01528181610da701528181610fde015281816116f3015281816117b7015261189301526000818161097601528181610f540152818161100d015281816113170152818161172101528181611aca01528181611e730152613bae0152614cb66000f3fe6080604052600436106103fd5760003560e01c806379ba509711610213578063bdf78bb411610123578063de5bc882116100ab578063ecc3cc391161007a578063ecc3cc3914610bca578063ece40c2e14610bdf578063f2fde38b14610bff578063f3ae241514610c1f578063f9263a4b14610c3f57600080fd5b8063de5bc88214610b43578063e30c397814610b59578063e325a9e414610b77578063e94ad65b14610b9757600080fd5b8063c4f7b384116100f2578063c4f7b38414610a9a578063c8339b6714610aba578063d54ad2a114610ada578063da5fa89014610af0578063de4a8a0814610b1057600080fd5b8063bdf78bb414610a15578063bfb793ee14610a44578063c08ed1d414610a5a578063c4d75dd014610a7a57600080fd5b80638da5cb5b116101a65780639c8460b2116101755780639c8460b2146109af578063a1903eab146109cf578063a556f846146109e2578063ba681c4d146109f7578063bdae2f0c14610a0d57600080fd5b80638da5cb5b146109295780638f636a131461094757806392f63d2e14610967578063951303f51461099a57600080fd5b80638348741e116101e25780638348741e146108ca57806383a6deb5146108ea578063870ba746146109005780638b623f601461091657600080fd5b806379ba5097146108655780637a0443231461087a5780637f4e3076146108a05780638129fc1c146108b557600080fd5b806348f6cc0a1161030e5780635e4c9af8116102a15780636c071269116102705780636c071269146107f05780637026436f14610805578063708ddf7b14610825578063715018a61461083b578063723117051461085057600080fd5b80635e4c9af81461077c57806361d027b31461079c57806369e51d7f146107ba5780636ba4c138146107d057600080fd5b806359d614da116102dd57806359d614da146107175780635bcb2fc61461072d5780635c975abb146107355780635e1c6c3f1461074d57600080fd5b806348f6cc0a146106aa5780634b319713146106ca5780634cd79e0a146106e05780634e71d92d1461070257600080fd5b80632dad786a1161039157806338c653c51161036057806338c653c5146105e55780633baa4885146106055780633d97e2871461063a5780634261f4d81461065a578063457182781461068a57600080fd5b80632dad786a1461055d5780632e1a7d4d14610572578063357b992f1461059257806338329fbc146105c557600080fd5b80631e83409a116103cd5780631e83409a146104dd5780631f4c50cb146104fd57806327ad7e1b1461051d5780632a08922c1461053d57600080fd5b8062f714ce1461045457806303ead348146104765780630c7d5cd81461049657806314647655146104bb57600080fd5b3661044f5734610111600082825461041591906142a6565b90915550506040513481527fa8142743f8f70a4c26f3691cf4ed59718381fb2f18070ec52be1f1022d8555579060200160405180910390a1005b600080fd5b34801561046057600080fd5b5061047461046f3660046142d3565b610c5f565b005b34801561048257600080fd5b50610474610491366004614303565b610c6e565b3480156104a257600080fd5b50610101545b6040519081526020015b60405180910390f35b3480156104c757600080fd5b506104d0610c82565b6040516104b2919061431c565b3480156104e957600080fd5b506104746104f8366004614369565b610c93565b34801561050957600080fd5b50610474610518366004614369565b610c9d565b34801561052957600080fd5b506104746105383660046143d1565b610cae565b34801561054957600080fd5b50610474610558366004614369565b610d59565b34801561056957600080fd5b506104d0610d6a565b34801561057e57600080fd5b5061047461058d366004614303565b610d77565b34801561059e57600080fd5b50610110546001600160a01b03165b6040516001600160a01b0390911681526020016104b2565b3480156105d157600080fd5b506104746105e0366004614303565b610d82565b3480156105f157600080fd5b50610474610600366004614303565b610e28565b34801561061157600080fd5b50610625610620366004614303565b610e39565b604080519283526020830191909152016104b2565b34801561064657600080fd5b50610474610655366004614303565b610e4f565b34801561066657600080fd5b5061067a610675366004614369565b61106f565b60405190151581526020016104b2565b34801561069657600080fd5b506104746106a53660046144d7565b611098565b3480156106b657600080fd5b506104746106c5366004614369565b6110b6565b3480156106d657600080fd5b5061010a546104a8565b3480156106ec57600080fd5b506106f56110c7565b6040516104b2919061457e565b34801561070e57600080fd5b5061047461115a565b34801561072357600080fd5b5061010d546104a8565b610474611166565b34801561074157600080fd5b5060975460ff1661067a565b34801561075957600080fd5b5061076d610768366004614369565b61116f565b6040516104b2939291906145cc565b34801561078857600080fd5b50610474610797366004614645565b6112c3565b3480156107a857600080fd5b5060ff546001600160a01b03166105ad565b3480156107c657600080fd5b5061010c546104a8565b3480156107dc57600080fd5b506104746107eb3660046146bc565b611390565b3480156107fc57600080fd5b506104746113ae565b34801561081157600080fd5b50610474610820366004614369565b611422565b34801561083157600080fd5b50610107546104a8565b34801561084757600080fd5b50610474611433565b34801561085c57600080fd5b506104d0611445565b34801561087157600080fd5b50610474611451565b34801561088657600080fd5b5061010d54600090815261010f60205260409020546104a8565b3480156108ac57600080fd5b506104746114c8565b3480156108c157600080fd5b506104746114d8565b3480156108d657600080fd5b506104746108e53660046146f8565b611630565b3480156108f657600080fd5b50610111546104a8565b34801561090c57600080fd5b50610103546104a8565b610474610924366004614369565b6116d3565b34801561093557600080fd5b506033546001600160a01b03166105ad565b34801561095357600080fd5b50610474610962366004614303565b61186b565b34801561097357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006105ad565b3480156109a657600080fd5b506104a8611915565b3480156109bb57600080fd5b506104746109ca366004614369565b61191f565b6104746109dd366004614369565b611930565b3480156109ee57600080fd5b506104a8611939565b348015610a0357600080fd5b50610100546104a8565b610474611943565b348015610a2157600080fd5b50610a35610a30366004614369565b61194c565b6040516104b293929190614743565b348015610a5057600080fd5b50610102546104a8565b348015610a6657600080fd5b50610474610a75366004614369565b611a76565b348015610a8657600080fd5b50610474610a9536600461477c565b611a87565b348015610aa657600080fd5b50610474610ab5366004614303565b611a99565b348015610ac657600080fd5b50610474610ad5366004614369565b611b2b565b348015610ae657600080fd5b5061010b546104a8565b348015610afc57600080fd5b50610474610b0b366004614369565b611c77565b348015610b1c57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006105ad565b348015610b4f57600080fd5b50610104546104a8565b348015610b6557600080fd5b506065546001600160a01b03166105ad565b348015610b8357600080fd5b506104a8610b923660046147a8565b611c88565b348015610ba357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006105ad565b348015610bd657600080fd5b50610474611d32565b348015610beb57600080fd5b5061067a610bfa3660046147ca565b611d82565b348015610c0b57600080fd5b50610474610c1a366004614369565b611dae565b348015610c2b57600080fd5b5061067a610c3a366004614369565b611e1f565b348015610c4b57600080fd5b50610474610c5a366004614303565b611e2c565b610c6a338284611e3d565b5050565b610c76611ee4565b610c7f81611f3e565b50565b6060610c8e60c9611f55565b905090565b610c7f3382611f69565b610ca5611ee4565b610c7f81611f96565b610cb661204c565b610cbe612092565b610cc960fd336120ec565b610cee5760405162461bcd60e51b8152600401610ce59061485e565b60405180910390fd5b8181818190506801bc16d674ec80000061010c546101025447610d1191906148a0565b610d1b91906148a0565b610d2591906148b7565b1015610d435760405162461bcd60e51b8152600401610ce5906148d9565b610d4d848461210d565b5050610c6a600160cb55565b610d61611ee4565b610c7f81612615565b6060610c8e610105611f55565b610c7f333383611e3d565b604051632d182be560e21b8152600481018290523060248201523360448201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b460af94906064016020604051808303816000875af1158015610df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1c919061491c565b50610c6a308284611e3d565b610e30611ee4565b610c7f816126e4565b600080610e45836127fd565b9094909350915050565b610e5761204c565b610110546001600160a01b03163314610ecb5760405162461bcd60e51b815260206004820152603060248201527f6f6e6c795265776172644f7261636c653a2063616c6c6572206973206e6f742060448201526f746865207265776172644f7261636c6560801b6064820152608401610ce5565b80610f185760405162461bcd60e51b815260206004820181905260248201527f737570706c795265776172643a20416d6f756e742063616e6e6f7420626520306044820152606401610ce5565b6000610f2382612845565b90508015610fb35760ff546040516340c10f1960e01b81526001600160a01b039182166004820152602481018390527f0000000000000000000000000000000000000000000000000000000000000000909116906340c10f1990604401600060405180830381600087803b158015610f9a57600080fd5b505af1158015610fae573d6000803e3d6000fd5b505050505b6000610fbf82846148a0565b9050801561106a576040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390527f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990604401600060405180830381600087803b15801561105157600080fd5b505af1158015611065573d6000803e3d6000fd5b505050505b505050565b600061107a82612869565b8061109257506033546001600160a01b038381169116145b92915050565b33600081815261010e60205260409020610c6a919084908490612876565b6110be611ee4565b610c7f816128a2565b606061010880546110d790614935565b80601f016020809104026020016040519081016040528092919081815260200182805461110390614935565b80156111505780601f1061112557610100808354040283529160200191611150565b820191906000526020600020905b81548152906001019060200180831161113357829003601f168201915b5050505050905090565b6111643333611f69565b565b6111643361294c565b6001600160a01b038116600090815261010e602052604090206060908190819061119890611f55565b925082516001600160401b038111156111b3576111b3614412565b6040519080825280602002602001820160405280156111dc578160200160208202803683370190505b50915082516001600160401b038111156111f8576111f8614412565b604051908082528060200260200182016040528015611221578160200160208202803683370190505b509050600061122e612978565b90506000805b85518110156112b95761125f86828151811061125257611252614970565b60200260200101516127fd565b86838151811061127157611271614970565b602002602001018194508281525050508183101584828151811061129757611297614970565b91151560209283029190910190910152806112b181614986565b915050611234565b5050509193909250565b6000846112d057876112d4565b6000195b60405163d505accf60e01b8152336004820152306024820152604481018290526064810188905260ff8616608482015260a4810185905260c481018490529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d505accf9060e401600060405180830381600087803b15801561136357600080fd5b505af1158015611377573d6000803e3d6000fd5b5050505061138633888a611e3d565b5050505050505050565b33600081815261010e60205260409020610c7f919081908490612876565b6113b73361106f565b61141a5760405162461bcd60e51b815260206004820152602e60248201527f6f6e6c795061757365477561726469616e3a2063616c6c6572206973206e6f7460448201526d103830bab9b2a3bab0b93234b0b760911b6064820152608401610ce5565b611164612997565b61142a611ee4565b610c7f816129ec565b61143b611ee4565b6111646000612a98565b6060610c8e60fd611f55565b60655433906001600160a01b031681146114bf5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610ce5565b610c7f81612a98565b6114d0611ee4565b611164612ab1565b600054610100900460ff16158080156114f85750600054600160ff909116105b806115125750303b158015611512575060005460ff166001145b6115755760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610ce5565b6000805460ff191660011790558015611598576000805461ff0019166101001790555b6115a0612aea565b6115ba6115b56033546001600160a01b031690565b612615565b60408051600160f81b3017602080830191909152825180830390910181529082019091526115e790612b19565b8015610c7f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a150565b61163861204c565b611640612092565b61164b60fd336120ec565b6116675760405162461bcd60e51b8152600401610ce59061485e565b8282818190506801bc16d674ec80000061010c54610102544761168a91906148a0565b61169491906148a0565b61169e91906148b7565b10156116bc5760405162461bcd60e51b8152600401610ce5906148d9565b6116c7858585612be4565b505061106a600160cb55565b6116dc3061294c565b60405163095ea7b360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301523460248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af115801561176a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178e91906149a1565b50604051636e553f6560e01b81523460048201526001600160a01b0382811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690636e553f65906044016020604051808303816000875af1158015611802573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611826919061491c565b11610c7f5760405162461bcd60e51b8152602060048201526015602482015274139bc81cd8515512081dd85cc81c995d1d5c9b9959605a1b6044820152606401610ce5565b604051635d043b2960e11b8152600481018290523060248201523360448201819052906000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ba087652906064016020604051808303816000875af11580156118e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611908919061491c565b905061106a308383611e3d565b6000610c8e612cce565b611927611ee4565b610c7f81612d02565b610c7f8161294c565b6000610c8e612978565b61116433612e34565b6001600160a01b038116600090815261010e602052604090206060908190819061197590611f55565b925082516001600160401b0381111561199057611990614412565b6040519080825280602002602001820160405280156119b9578160200160208202803683370190505b50915082516001600160401b038111156119d5576119d5614412565b6040519080825280602002602001820160405280156119fe578160200160208202803683370190505b50905060005b8151811015611a6e57611a2284828151811061125257611252614970565b848381518110611a3457611a34614970565b60200260200101848481518110611a4d57611a4d614970565b60209081029190910101919091525280611a6681614986565b915050611a04565b509193909250565b611a7e611ee4565b610c7f81612ebe565b611a8f611ee4565b610c6a8282613052565b611aa1611ee4565b60ff5460405163079cc67960e41b81526001600160a01b039182166004820152602481018390527f0000000000000000000000000000000000000000000000000000000000000000909116906379cc679090604401600060405180830381600087803b158015611b1057600080fd5b505af1158015611b24573d6000803e3d6000fd5b5050505050565b611b33611ee4565b610110546001600160a01b03828116911614801590611bc45750306001600160a01b0316816001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb991906149be565b6001600160a01b0316145b611c285760405162461bcd60e51b815260206004820152602f60248201527f5f7365745265776172644f7261636c653a20496e76616c69642072657761726460448201526e206f7261636c65206164647265737360881b6064820152608401610ce5565b61011080546001600160a01b0319166001600160a01b0383169081179091556040519081527f30da13f0963a005974ddb16864f563178e1dc990a1ca4f5e1cc0b3e0addd9ea590602001611625565b611c7f611ee4565b610c7f81613143565b600080611c9e6801bc16d674ec800000856149db565b6101035461010b5461010a54611cb490476142a6565b611cbe91906142a6565b611cc891906142a6565b611cd291906142a6565b90506000611ce96801bc16d674ec800000856149db565b610104546101115461010754611cff91906142a6565b611d0991906142a6565b611d1391906142a6565b905080821115611d2a57611d2781836148a0565b92505b505092915050565b611d3a611ee4565b61011080546001600160a01b0319169055604051600081527f30da13f0963a005974ddb16864f563178e1dc990a1ca4f5e1cc0b3e0addd9ea5906020015b60405180910390a1565b600061010982604051611d9591906149fa565b9081526040519081900360200190205460ff1692915050565b611db6611ee4565b606580546001600160a01b0383166001600160a01b03199091168117909155611de76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600061109260fd836120ec565b611e34611ee4565b610c7f81613255565b611e4561204c565b611e4d612092565b60405163079cc67960e41b81526001600160a01b038481166004830152602482018390527f000000000000000000000000000000000000000000000000000000000000000016906379cc679090604401600060405180830381600087803b158015611eb757600080fd5b505af1158015611ecb573d6000803e3d6000fd5b50505050611eda83838361336b565b61106a600160cb55565b6033546001600160a01b031633146111645760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ce5565b610c7f8161010254611f5091906148a0565b613457565b60606000611f628361348d565b9392505050565b6001600160a01b038216600090815261010e6020526040902061106a8383611f9084611f55565b84612876565b611fa160c9826134e9565b6120135760405162461bcd60e51b815260206004820152603d60248201527f5f72656d6f76655061757365477561726469616e496e7465726e616c3a205f7060448201527f61757365477561726469616e20686173206265656e2072656d6f7665640000006064820152608401610ce5565b6040516001600160a01b03821681527ff0833dc70126c53eb99fc93b161125acd71f7d141f81f41da6cf3668e0fcc7cc90602001611625565b60975460ff16156111645760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ce5565b600260cb5414156120e55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce5565b600260cb55565b6001600160a01b031660009081526001919091016020526040902054151590565b8061215a5760405162461bcd60e51b815260206004820152601e60248201527f5f6465706f7369743a204465706f736974203020697320696e76616c696400006044820152606401610ce5565b6000610108805461216a90614935565b80601f016020809104026020016040519081016040528092919081815260200182805461219690614935565b80156121e35780601f106121b8576101008083540402835291602001916121e3565b820191906000526020600020905b8154815290600101906020018083116121c657829003601f168201915b5050505050905060005b828110156125c35761010984848381811061220a5761220a614970565b905060200281019061221c9190614a16565b61222a906020810190614a2c565b604051612238929190614a72565b9081526040519081900360200190205460ff16156122a75760405162461bcd60e51b815260206004820152602660248201527f5f6465706f7369743a20496e76616c69642076616c696461746f72207075626c6044820152656963206b657960d01b6064820152608401610ce5565b60006123838585848181106122be576122be614970565b90506020028101906122d09190614a16565b6122de906020810190614a2c565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525089925088915086905081811061232757612327614970565b90506020028101906123399190614a16565b612347906040810190614a2c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508892506134fe915050565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663228951186801bc16d674ec8000008787868181106123d0576123d0614970565b90506020028101906123e29190614a16565b6123f0906020810190614a2c565b878a8a8981811061240357612403614970565b90506020028101906124159190614a16565b612423906040810190614a2c565b886040518863ffffffff1660e01b815260040161244596959493929190614aab565b6000604051808303818588803b15801561245e57600080fd5b505af1158015612472573d6000803e3d6000fd5b5050505050600161010986868581811061248e5761248e614970565b90506020028101906124a09190614a16565b6124ae906020810190614a2c565b6040516124bc929190614a72565b908152604051908190036020019020805491151560ff199092169190911790557f887b1d3d2a3c4bcd07ba76bd8be8a3ad106431448d8a21a8102fd8a961c61ec185858481811061250f5761250f614970565b90506020028101906125219190614a16565b61252f906020810190614369565b86868581811061254157612541614970565b90506020028101906125539190614a16565b612561906020810190614a2c565b88888781811061257357612573614970565b90506020028101906125859190614a16565b612593906040810190614a2c565b88876040516125a89796959493929190614afa565b60405180910390a150806125bb81614986565b9150506121ed565b507fa3af609bf46297028ce551832669030f9effef2b02606d02cbbcc40fe6b47c556125f86801bc16d674ec800000846149db565b6040805191825260208201859052015b60405180910390a1505050565b6001600160a01b0381161580159061263b575060ff546001600160a01b03828116911614155b6126965760405162461bcd60e51b815260206004820152602660248201527f5f7365745472656173757279496e7465726e616c3a20496e76616c696420747260448201526565617375727960d01b6064820152608401610ce5565b60ff80546001600160a01b0319166001600160a01b0383169081179091556040519081527fcb7ef3e545f5cdb893f5c568ba710fe08f336375a2d9fd66e161033f8fc09ef390602001611625565b670de0b6b3a76400008111156127575760405162461bcd60e51b815260206004820152603260248201527f5f7365745472656173757279526174696f496e7465726e616c3a205472656173604482015271757279526174696f20746f6f206c6172676560701b6064820152608401610ce5565b610100548114156127c75760405162461bcd60e51b815260206004820152603460248201527f5f7365745472656173757279526174696f496e7465726e616c3a2043616e6e6f6044820152737420736574207468652073616d652076616c756560601b6064820152608401610ce5565b6101008190556040518181527fb4b966f8bcf60846d459594008002153c57d34cfcb8508c9ebea69316d9318c790602001611625565b600081815261010f602052604081205480156128405761010f60006128236001866148a0565b8152602001908152602001600020548161283d91906148a0565b91505b915091565b6000670de0b6b3a7640000610100548361285f91906149db565b61109291906148b7565b600061109260c9836120ec565b61287e61204c565b612886612092565b61289284848484613840565b61289c600160cb55565b50505050565b6128ad60fd826134e9565b6129135760405162461bcd60e51b815260206004820152603160248201527f5f72656d6f76654d616e61676572496e7465726e616c3a205f6d616e61676572604482015270081a185cc81899595b881c995b5bdd9959607a1b6064820152608401610ce5565b6040516001600160a01b03821681527fef69f7d97228658c92417be1b16b19058315de71fecb435d07b7d23728b6bd3190602001611625565b61295461204c565b61295c612092565b61296534613af8565b61296e81613b22565b610c7f600160cb55565b600061010b54610102544761298d91906148a0565b610c8e91906142a6565b61299f61204c565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586129d43390565b6040516001600160a01b039091168152602001611d78565b6129f8610105826134e9565b612a5f5760405162461bcd60e51b815260206004820152603260248201527f5f72656d6f76655374726174656779496e7465726e616c3a20537472617465676044820152711e481a185cc81899595b881c995b5bdd995960721b6064820152608401610ce5565b6040516001600160a01b03821681527f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea490602001611625565b606580546001600160a01b0319169055610c7f81613c58565b612ab9613caa565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336129d4565b600054610100900460ff16612b115760405162461bcd60e51b8152600401610ce590614b5b565b611164613cf3565b8051602014612ba05760405162461bcd60e51b815260206004820152604760248201527f5f7365745769746864726177616c43726564656e7469616c73496e7465726e6160448201527f6c3a20496e76616c6964207769746864726177616c43726564656e7469616c73606482015266040d8cadccee8d60cb1b608482015260a401610ce5565b8051612bb4906101089060208401906141f7565b507f3022649204514734559f042fcb9f5876604a0f08e1775754fee1a618bc7dfec981604051611625919061457e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c5f2892f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c66919061491c565b8114612cc45760405162461bcd60e51b815260206004820152602760248201527f5f6465706f736974436865636b3a204465706f73697420726f6f74206861732060448201526618da185b99d95960ca1b6064820152608401610ce5565b61106a838361210d565b6101025461010c5460009147918391612ce6916142a6565b905080821115612cfd57612cfa81836148a0565b92505b505090565b6001600160a01b038116612d7e5760405162461bcd60e51b815260206004820152603a60248201527f5f6164645061757365477561726469616e496e7465726e616c3a205f7061757360448201527f65477561726469616e20746865207a65726f20616464726573730000000000006064820152608401610ce5565b612d8960c982613d23565b612dfb5760405162461bcd60e51b815260206004820152603860248201527f5f6164645061757365477561726469616e496e7465726e616c3a205f7061757360448201527f65477561726469616e20686173206265656e20616464656400000000000000006064820152608401610ce5565b6040516001600160a01b03821681527fc7eb4f7ea192fd1c93e0613101988e33fa679dd68ffbb33a1040ef4d1747f2cd90602001611625565b80612e41610105826120ec565b612e5d5760405162461bcd60e51b8152600401610ce590614ba6565b34612e6781613d38565b806101046000828254612e7a91906142a6565b9091555050604080516001600160a01b0385168152602081018390527f7faf370a097fbb34b849fc972aaf1817e85129d2c1b46304902212900cf129159101612608565b6001600160a01b03811615801590612f485750306001600160a01b0316816001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f3d91906149be565b6001600160a01b0316145b612fab5760405162461bcd60e51b815260206004820152602e60248201527f5f6164645374726174656779496e7465726e616c3a20696e76616c696420737460448201526d726174656779206164647265737360901b6064820152608401610ce5565b612fb761010582613d23565b6130195760405162461bcd60e51b815260206004820152602d60248201527f5f6164645374726174656779496e7465726e616c3a205374726174656779206860448201526c185cc81899595b881859191959609a1b6064820152608401610ce5565b6040516001600160a01b03821681527f3f008fd510eae7a9e7bee13513d7b83bef8003d488b5a3d0b0da4de71d6846f190602001611625565b8161305f610105826120ec565b61307b5760405162461bcd60e51b8152600401610ce590614ba6565b61308482611f3e565b81610103600082825461309791906142a6565b92505081905550826001600160a01b0316639d3bbaf6836040518263ffffffff1660e01b815260040160206040518083038185885af11580156130de573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613103919061491c565b50604080516001600160a01b0385168152602081018490527f8125d05f0839eec6c1f6b1674833e01f11ab362bd9c60eb2e3b274fa3b47e4f49101612608565b6001600160a01b0381166131b05760405162461bcd60e51b815260206004820152602e60248201527f5f6164644d616e61676572496e7465726e616c3a205f6d616e6167657220746860448201526d65207a65726f206164647265737360901b6064820152608401610ce5565b6131bb60fd82613d23565b61321c5760405162461bcd60e51b815260206004820152602c60248201527f5f6164644d616e61676572496e7465726e616c3a205f6d616e6167657220686160448201526b1cc81899595b88185919195960a21b6064820152608401610ce5565b6040516001600160a01b03821681527f3b4a40cccf2058c593542587329dd385be4f0b588db5471fbd9598e56dd7093a90602001611625565b670de0b6b3a76400008111156132c65760405162461bcd60e51b815260206004820152603060248201527f5f73657452657365727665526174696f496e7465726e616c3a2052657365727660448201526f65526174696f20746f6f206c6172676560801b6064820152608401610ce5565b610101548114156133355760405162461bcd60e51b815260206004820152603360248201527f5f73657452657365727665526174696f496e7465726e616c3a2043616e6e6f7460448201527220736574207468652073616d652076616c756560681b6064820152608401610ce5565b6101018190556040518181527f53010711698e5dbf2a05de8cd22b034a7c0972d110c1fd3fa95ee2eefc88ae9b90602001611625565b600081116133ca5760405162461bcd60e51b815260206004820152602660248201527f5f77697468647261773a20776974686472617720616d6f756e742063616e6e6f60448201526507420626520360d41b6064820152608401610ce5565b806133d3612cce565b10156133e35761106a8282613d4a565b8061010a60008282546133f691906142a6565b9091555061340f90506001600160a01b03831682613e28565b604080516001600160a01b038086168252841660208201529081018290527fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb90606001612608565b6101028190556040518181527f064a6eddb1d5ef0b05d467753b4ec9677d94224577c854f2bb7c6c0504775ff690602001611625565b6060816000018054806020026020016040519081016040528092919081815260200182805480156134dd57602002820191906000526020600020905b8154815260200190600101908083116134c9575b50505050509050919050565b6000611f62836001600160a01b038416613ef1565b600080600285600060801b60405160200161351a929190614bea565b60408051601f1981840301815290829052613534916149fa565b602060405180830381855afa158015613551573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190613574919061491c565b905060006002806135888760006040613feb565b60405160200161359891906149fa565b60408051601f19818403018152908290526135b2916149fa565b602060405180830381855afa1580156135cf573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906135f2919061491c565b60026136018860406020613feb565b6040516136149190600090602001614c22565b60408051601f198184030181529082905261362e916149fa565b602060405180830381855afa15801561364b573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061366e919061491c565b60408051602081019390935282015260600160408051601f198184030181529082905261369a916149fa565b602060405180830381855afa1580156136b7573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906136da919061491c565b905060028083866040516020016136f2929190614c44565b60408051601f198184030181529082905261370c916149fa565b602060405180830381855afa158015613729573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061374c919061491c565b60408051634059730760d81b60208201526000602882015290810184905260029060600160408051601f198184030181529082905261378a916149fa565b602060405180830381855afa1580156137a7573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906137ca919061491c565b60408051602081019390935282015260600160408051601f19818403018152908290526137f6916149fa565b602060405180830381855afa158015613813573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190613836919061491c565b9695505050505050565b60008251116138a55760405162461bcd60e51b815260206004820152602b60248201527f5f636c61696d4279517565756549643a205175657565206c6973742063616e6e60448201526a6f7420626520656d70747960a81b6064820152608401610ce5565b60006138af612978565b90506000805b8451811015613a135760006138e38683815181106138d5576138d5614970565b602002602001015185614101565b9050806138f05750613a01565b61391c86838151811061390557613905614970565b60200260200101518661412490919063ffffffff16565b6139795760405162461bcd60e51b815260206004820152602860248201527f5f636c61696d4279517565756549643a20517565756520696420646f6573206e6044820152671bdd08195e1a5cdd60c21b6064820152608401610ce5565b7ffcdf2346933a63444be3a43932dc03282174211c25bb16b9f202ed7b3c01c48e88888885815181106139ae576139ae614970565b6020026020010151846040516139eb94939291906001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b60405180910390a16139fd81846142a6565b9250505b80613a0b81614986565b9150506138b5565b5060008111613a645760405162461bcd60e51b815260206004820181905260248201527f5f636c61696d4279517565756549643a204e6f20636c61696d20616d6f756e746044820152606401610ce5565b613a7b8161010c54613a7691906148a0565b614130565b613a928161010b54613a8d91906142a6565b614166565b613aa56001600160a01b03861682613e28565b604080516001600160a01b038089168252871660208201529081018290527ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd39926839060600160405180910390a1505050505050565b610c7f670de0b6b3a76400006101015483613b1391906149db565b613b1d91906148b7565b613d38565b3480613b705760405162461bcd60e51b815260206004820152601860248201527f5f7375626d69743a204554482063616e6e6f74206265203000000000000000006044820152606401610ce5565b806101076000828254613b8391906142a6565b90915550506040516340c10f1960e01b81526001600160a01b038381166004830152602482018390527f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990604401600060405180830381600087803b158015613bf257600080fd5b505af1158015613c06573d6000803e3d6000fd5b5050604080513381526001600160a01b03861660208201529081018490527fc960f3456d7f4d44ac94a2d643da2516ec1fd12ddaf65f7ce5070a45898072949250606001905060405180910390a15050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60975460ff166111645760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610ce5565b600054610100900460ff16613d1a5760405162461bcd60e51b8152600401610ce590614b5b565b61116433612a98565b6000611f62836001600160a01b03841661419c565b610c7f8161010254611f5091906142a6565b61010d54600081815261010f6020526040902054613d696001836142a6565b6001600160a01b038516600090815261010e60205260409020909250613d8f90836141eb565b506000613d9c84836142a6565b600084815261010f6020526040902081905561010d84905561010c54909150613dca90613a769086906142a6565b604080513381526001600160a01b038716602082015290810184905260608101859052608081018290527fb51f063b97a509a8abdbe3eef791e7342e9c61ef1519cf74c3a4a6b4331d86fa9060a00160405180910390a15050505050565b604080516000808252602082019092526001600160a01b038416908390604051613e5291906149fa565b60006040518083038185875af1925050503d8060008114613e8f576040519150601f19603f3d011682016040523d82523d6000602084013e613e94565b606091505b505090508061106a5760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608401610ce5565b60008181526001830160205260408120548015613fda576000613f156001836148a0565b8554909150600090613f29906001906148a0565b9050818114613f8e576000866000018281548110613f4957613f49614970565b9060005260206000200154905080876000018481548110613f6c57613f6c614970565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613f9f57613f9f614c6a565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611092565b6000915050611092565b5092915050565b8251606090613ffa83856142a6565b11156140485760405162461bcd60e51b815260206004820152601e60248201527f5f6279746573536c6963653a20536c69636520706172616d206572726f7200006044820152606401610ce5565b816001600160401b0381111561406057614060614412565b6040519080825280601f01601f19166020018201604052801561408a576020820181803683370190505b50905060005b828110156140f957846140a385836142a6565b815181106140b3576140b3614970565b602001015160f81c60f81b8282815181106140d0576140d0614970565b60200101906001600160f81b031916908160001a905350806140f181614986565b915050614090565b509392505050565b60008061410d846127fd565b909250905080831015613fe4575060009392505050565b6000611f628383613ef1565b61010c8190556040518181527f104d0584aa9e9d5db30e252ea72c7635a0523beb1e3a44036626c1ffa831543990602001611625565b61010b8190556040518181527ffc100561a5b3a15d243d29373ad1eecc28836fdb7fa37cb3039a95af23c921ba90602001611625565b60008181526001830160205260408120546141e357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611092565b506000611092565b6000611f62838361419c565b82805461420390614935565b90600052602060002090601f016020900481019282614225576000855561426b565b82601f1061423e57805160ff191683800117855561426b565b8280016001018555821561426b579182015b8281111561426b578251825591602001919060010190614250565b5061427792915061427b565b5090565b5b80821115614277576000815560010161427c565b634e487b7160e01b600052601160045260246000fd5b600082198211156142b9576142b9614290565b500190565b6001600160a01b0381168114610c7f57600080fd5b600080604083850312156142e657600080fd5b8235915060208301356142f8816142be565b809150509250929050565b60006020828403121561431557600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561435d5783516001600160a01b031683529284019291840191600101614338565b50909695505050505050565b60006020828403121561437b57600080fd5b8135611f62816142be565b60008083601f84011261439857600080fd5b5081356001600160401b038111156143af57600080fd5b6020830191508360208260051b85010111156143ca57600080fd5b9250929050565b600080602083850312156143e457600080fd5b82356001600160401b038111156143fa57600080fd5b61440685828601614386565b90969095509350505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561445057614450614412565b604052919050565b600082601f83011261446957600080fd5b813560206001600160401b0382111561448457614484614412565b8160051b614493828201614428565b92835284810182019282810190878511156144ad57600080fd5b83870192505b848310156144cc578235825291830191908301906144b3565b979650505050505050565b600080604083850312156144ea57600080fd5b82356144f5816142be565b915060208301356001600160401b0381111561451057600080fd5b61451c85828601614458565b9150509250929050565b60005b83811015614541578181015183820152602001614529565b8381111561289c5750506000910152565b6000815180845261456a816020860160208601614526565b601f01601f19169290920160200192915050565b602081526000611f626020830184614552565b600081518084526020808501945080840160005b838110156145c1578151875295820195908201906001016145a5565b509495945050505050565b6060815260006145df6060830186614591565b6020838203818501526145f28287614591565b8481036040860152855180825282870193509082019060005b8181101561462957845115158352938301939183019160010161460b565b509098975050505050505050565b8015158114610c7f57600080fd5b600080600080600080600060e0888a03121561466057600080fd5b873596506020880135614672816142be565b955060408801359450606088013561468981614637565b9350608088013560ff8116811461469f57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000602082840312156146ce57600080fd5b81356001600160401b038111156146e457600080fd5b6146f084828501614458565b949350505050565b60008060006040848603121561470d57600080fd5b83356001600160401b0381111561472357600080fd5b61472f86828701614386565b909790965060209590950135949350505050565b6060815260006147566060830186614591565b82810360208401526147688186614591565b905082810360408401526138368185614591565b6000806040838503121561478f57600080fd5b823561479a816142be565b946020939093013593505050565b600080604083850312156147bb57600080fd5b50508035926020909101359150565b600060208083850312156147dd57600080fd5b82356001600160401b03808211156147f457600080fd5b818501915085601f83011261480857600080fd5b81358181111561481a5761481a614412565b61482c601f8201601f19168501614428565b9150808252868482850101111561484257600080fd5b8084840185840137600090820190930192909252509392505050565b60208082526022908201527f6f6e6c794d616e616765723a2063616c6c6572206973206e6f74206d616e616760408201526132b960f11b606082015260800190565b6000828210156148b2576148b2614290565b500390565b6000826148d457634e487b7160e01b600052601260045260246000fd5b500490565b60208082526023908201527f6465706f73697442616c616e6365436865636b3a204e6f7420656e6f7567682060408201526208aa8960eb1b606082015260800190565b60006020828403121561492e57600080fd5b5051919050565b600181811c9082168061494957607f821691505b6020821081141561496a57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b600060001982141561499a5761499a614290565b5060010190565b6000602082840312156149b357600080fd5b8151611f6281614637565b6000602082840312156149d057600080fd5b8151611f62816142be565b60008160001904831182151516156149f5576149f5614290565b500290565b60008251614a0c818460208701614526565b9190910192915050565b60008235605e19833603018112614a0c57600080fd5b6000808335601e19843603018112614a4357600080fd5b8301803591506001600160401b03821115614a5d57600080fd5b6020019150368190038213156143ca57600080fd5b8183823760009101908152919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b608081526000614abf60808301888a614a82565b8281036020840152614ad18188614552565b90508281036040840152614ae6818688614a82565b915050826060830152979650505050505050565b6001600160a01b038816815260a060208201819052600090614b1f908301888a614a82565b8281036040840152614b32818789614a82565b90508281036060840152614b468186614552565b91505082608083015298975050505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526024908201527f697353747261746567793a20696e76616c6964207374726174656779206164646040820152637265737360e01b606082015260800190565b60008351614bfc818460208801614526565b6fffffffffffffffffffffffffffffffff19939093169190920190815260100192915050565b60008351614c34818460208801614526565b9190910191825250602001919050565b82815260008251614c5c816020850160208701614526565b919091016020019392505050565b634e487b7160e01b600052603160045260246000fdfea264697066735822122071d4236c6f5259cc524d64ec6dc3ee93d7332ee9bb83c8f4ae59f6fcdf3079a964736f6c634300080a003300000000000000000000000000000000219ab540356cbb839cbe05303d7705fa000000000000000000000000fc87753df5ef5c368b5fba8d4c5043b77e8c5b39000000000000000000000000f1617882a71467534d14eee865922de1395c9e89
Deployed Bytecode
0x6080604052600436106103fd5760003560e01c806379ba509711610213578063bdf78bb411610123578063de5bc882116100ab578063ecc3cc391161007a578063ecc3cc3914610bca578063ece40c2e14610bdf578063f2fde38b14610bff578063f3ae241514610c1f578063f9263a4b14610c3f57600080fd5b8063de5bc88214610b43578063e30c397814610b59578063e325a9e414610b77578063e94ad65b14610b9757600080fd5b8063c4f7b384116100f2578063c4f7b38414610a9a578063c8339b6714610aba578063d54ad2a114610ada578063da5fa89014610af0578063de4a8a0814610b1057600080fd5b8063bdf78bb414610a15578063bfb793ee14610a44578063c08ed1d414610a5a578063c4d75dd014610a7a57600080fd5b80638da5cb5b116101a65780639c8460b2116101755780639c8460b2146109af578063a1903eab146109cf578063a556f846146109e2578063ba681c4d146109f7578063bdae2f0c14610a0d57600080fd5b80638da5cb5b146109295780638f636a131461094757806392f63d2e14610967578063951303f51461099a57600080fd5b80638348741e116101e25780638348741e146108ca57806383a6deb5146108ea578063870ba746146109005780638b623f601461091657600080fd5b806379ba5097146108655780637a0443231461087a5780637f4e3076146108a05780638129fc1c146108b557600080fd5b806348f6cc0a1161030e5780635e4c9af8116102a15780636c071269116102705780636c071269146107f05780637026436f14610805578063708ddf7b14610825578063715018a61461083b578063723117051461085057600080fd5b80635e4c9af81461077c57806361d027b31461079c57806369e51d7f146107ba5780636ba4c138146107d057600080fd5b806359d614da116102dd57806359d614da146107175780635bcb2fc61461072d5780635c975abb146107355780635e1c6c3f1461074d57600080fd5b806348f6cc0a146106aa5780634b319713146106ca5780634cd79e0a146106e05780634e71d92d1461070257600080fd5b80632dad786a1161039157806338c653c51161036057806338c653c5146105e55780633baa4885146106055780633d97e2871461063a5780634261f4d81461065a578063457182781461068a57600080fd5b80632dad786a1461055d5780632e1a7d4d14610572578063357b992f1461059257806338329fbc146105c557600080fd5b80631e83409a116103cd5780631e83409a146104dd5780631f4c50cb146104fd57806327ad7e1b1461051d5780632a08922c1461053d57600080fd5b8062f714ce1461045457806303ead348146104765780630c7d5cd81461049657806314647655146104bb57600080fd5b3661044f5734610111600082825461041591906142a6565b90915550506040513481527fa8142743f8f70a4c26f3691cf4ed59718381fb2f18070ec52be1f1022d8555579060200160405180910390a1005b600080fd5b34801561046057600080fd5b5061047461046f3660046142d3565b610c5f565b005b34801561048257600080fd5b50610474610491366004614303565b610c6e565b3480156104a257600080fd5b50610101545b6040519081526020015b60405180910390f35b3480156104c757600080fd5b506104d0610c82565b6040516104b2919061431c565b3480156104e957600080fd5b506104746104f8366004614369565b610c93565b34801561050957600080fd5b50610474610518366004614369565b610c9d565b34801561052957600080fd5b506104746105383660046143d1565b610cae565b34801561054957600080fd5b50610474610558366004614369565b610d59565b34801561056957600080fd5b506104d0610d6a565b34801561057e57600080fd5b5061047461058d366004614303565b610d77565b34801561059e57600080fd5b50610110546001600160a01b03165b6040516001600160a01b0390911681526020016104b2565b3480156105d157600080fd5b506104746105e0366004614303565b610d82565b3480156105f157600080fd5b50610474610600366004614303565b610e28565b34801561061157600080fd5b50610625610620366004614303565b610e39565b604080519283526020830191909152016104b2565b34801561064657600080fd5b50610474610655366004614303565b610e4f565b34801561066657600080fd5b5061067a610675366004614369565b61106f565b60405190151581526020016104b2565b34801561069657600080fd5b506104746106a53660046144d7565b611098565b3480156106b657600080fd5b506104746106c5366004614369565b6110b6565b3480156106d657600080fd5b5061010a546104a8565b3480156106ec57600080fd5b506106f56110c7565b6040516104b2919061457e565b34801561070e57600080fd5b5061047461115a565b34801561072357600080fd5b5061010d546104a8565b610474611166565b34801561074157600080fd5b5060975460ff1661067a565b34801561075957600080fd5b5061076d610768366004614369565b61116f565b6040516104b2939291906145cc565b34801561078857600080fd5b50610474610797366004614645565b6112c3565b3480156107a857600080fd5b5060ff546001600160a01b03166105ad565b3480156107c657600080fd5b5061010c546104a8565b3480156107dc57600080fd5b506104746107eb3660046146bc565b611390565b3480156107fc57600080fd5b506104746113ae565b34801561081157600080fd5b50610474610820366004614369565b611422565b34801561083157600080fd5b50610107546104a8565b34801561084757600080fd5b50610474611433565b34801561085c57600080fd5b506104d0611445565b34801561087157600080fd5b50610474611451565b34801561088657600080fd5b5061010d54600090815261010f60205260409020546104a8565b3480156108ac57600080fd5b506104746114c8565b3480156108c157600080fd5b506104746114d8565b3480156108d657600080fd5b506104746108e53660046146f8565b611630565b3480156108f657600080fd5b50610111546104a8565b34801561090c57600080fd5b50610103546104a8565b610474610924366004614369565b6116d3565b34801561093557600080fd5b506033546001600160a01b03166105ad565b34801561095357600080fd5b50610474610962366004614303565b61186b565b34801561097357600080fd5b507f000000000000000000000000fc87753df5ef5c368b5fba8d4c5043b77e8c5b396105ad565b3480156109a657600080fd5b506104a8611915565b3480156109bb57600080fd5b506104746109ca366004614369565b61191f565b6104746109dd366004614369565b611930565b3480156109ee57600080fd5b506104a8611939565b348015610a0357600080fd5b50610100546104a8565b610474611943565b348015610a2157600080fd5b50610a35610a30366004614369565b61194c565b6040516104b293929190614743565b348015610a5057600080fd5b50610102546104a8565b348015610a6657600080fd5b50610474610a75366004614369565b611a76565b348015610a8657600080fd5b50610474610a9536600461477c565b611a87565b348015610aa657600080fd5b50610474610ab5366004614303565b611a99565b348015610ac657600080fd5b50610474610ad5366004614369565b611b2b565b348015610ae657600080fd5b5061010b546104a8565b348015610afc57600080fd5b50610474610b0b366004614369565b611c77565b348015610b1c57600080fd5b507f000000000000000000000000f1617882a71467534d14eee865922de1395c9e896105ad565b348015610b4f57600080fd5b50610104546104a8565b348015610b6557600080fd5b506065546001600160a01b03166105ad565b348015610b8357600080fd5b506104a8610b923660046147a8565b611c88565b348015610ba357600080fd5b507f00000000000000000000000000000000219ab540356cbb839cbe05303d7705fa6105ad565b348015610bd657600080fd5b50610474611d32565b348015610beb57600080fd5b5061067a610bfa3660046147ca565b611d82565b348015610c0b57600080fd5b50610474610c1a366004614369565b611dae565b348015610c2b57600080fd5b5061067a610c3a366004614369565b611e1f565b348015610c4b57600080fd5b50610474610c5a366004614303565b611e2c565b610c6a338284611e3d565b5050565b610c76611ee4565b610c7f81611f3e565b50565b6060610c8e60c9611f55565b905090565b610c7f3382611f69565b610ca5611ee4565b610c7f81611f96565b610cb661204c565b610cbe612092565b610cc960fd336120ec565b610cee5760405162461bcd60e51b8152600401610ce59061485e565b60405180910390fd5b8181818190506801bc16d674ec80000061010c546101025447610d1191906148a0565b610d1b91906148a0565b610d2591906148b7565b1015610d435760405162461bcd60e51b8152600401610ce5906148d9565b610d4d848461210d565b5050610c6a600160cb55565b610d61611ee4565b610c7f81612615565b6060610c8e610105611f55565b610c7f333383611e3d565b604051632d182be560e21b8152600481018290523060248201523360448201819052907f000000000000000000000000f1617882a71467534d14eee865922de1395c9e896001600160a01b03169063b460af94906064016020604051808303816000875af1158015610df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1c919061491c565b50610c6a308284611e3d565b610e30611ee4565b610c7f816126e4565b600080610e45836127fd565b9094909350915050565b610e5761204c565b610110546001600160a01b03163314610ecb5760405162461bcd60e51b815260206004820152603060248201527f6f6e6c795265776172644f7261636c653a2063616c6c6572206973206e6f742060448201526f746865207265776172644f7261636c6560801b6064820152608401610ce5565b80610f185760405162461bcd60e51b815260206004820181905260248201527f737570706c795265776172643a20416d6f756e742063616e6e6f7420626520306044820152606401610ce5565b6000610f2382612845565b90508015610fb35760ff546040516340c10f1960e01b81526001600160a01b039182166004820152602481018390527f000000000000000000000000fc87753df5ef5c368b5fba8d4c5043b77e8c5b39909116906340c10f1990604401600060405180830381600087803b158015610f9a57600080fd5b505af1158015610fae573d6000803e3d6000fd5b505050505b6000610fbf82846148a0565b9050801561106a576040516340c10f1960e01b81526001600160a01b037f000000000000000000000000f1617882a71467534d14eee865922de1395c9e8981166004830152602482018390527f000000000000000000000000fc87753df5ef5c368b5fba8d4c5043b77e8c5b3916906340c10f1990604401600060405180830381600087803b15801561105157600080fd5b505af1158015611065573d6000803e3d6000fd5b505050505b505050565b600061107a82612869565b8061109257506033546001600160a01b038381169116145b92915050565b33600081815261010e60205260409020610c6a919084908490612876565b6110be611ee4565b610c7f816128a2565b606061010880546110d790614935565b80601f016020809104026020016040519081016040528092919081815260200182805461110390614935565b80156111505780601f1061112557610100808354040283529160200191611150565b820191906000526020600020905b81548152906001019060200180831161113357829003601f168201915b5050505050905090565b6111643333611f69565b565b6111643361294c565b6001600160a01b038116600090815261010e602052604090206060908190819061119890611f55565b925082516001600160401b038111156111b3576111b3614412565b6040519080825280602002602001820160405280156111dc578160200160208202803683370190505b50915082516001600160401b038111156111f8576111f8614412565b604051908082528060200260200182016040528015611221578160200160208202803683370190505b509050600061122e612978565b90506000805b85518110156112b95761125f86828151811061125257611252614970565b60200260200101516127fd565b86838151811061127157611271614970565b602002602001018194508281525050508183101584828151811061129757611297614970565b91151560209283029190910190910152806112b181614986565b915050611234565b5050509193909250565b6000846112d057876112d4565b6000195b60405163d505accf60e01b8152336004820152306024820152604481018290526064810188905260ff8616608482015260a4810185905260c481018490529091507f000000000000000000000000fc87753df5ef5c368b5fba8d4c5043b77e8c5b396001600160a01b03169063d505accf9060e401600060405180830381600087803b15801561136357600080fd5b505af1158015611377573d6000803e3d6000fd5b5050505061138633888a611e3d565b5050505050505050565b33600081815261010e60205260409020610c7f919081908490612876565b6113b73361106f565b61141a5760405162461bcd60e51b815260206004820152602e60248201527f6f6e6c795061757365477561726469616e3a2063616c6c6572206973206e6f7460448201526d103830bab9b2a3bab0b93234b0b760911b6064820152608401610ce5565b611164612997565b61142a611ee4565b610c7f816129ec565b61143b611ee4565b6111646000612a98565b6060610c8e60fd611f55565b60655433906001600160a01b031681146114bf5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610ce5565b610c7f81612a98565b6114d0611ee4565b611164612ab1565b600054610100900460ff16158080156114f85750600054600160ff909116105b806115125750303b158015611512575060005460ff166001145b6115755760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610ce5565b6000805460ff191660011790558015611598576000805461ff0019166101001790555b6115a0612aea565b6115ba6115b56033546001600160a01b031690565b612615565b60408051600160f81b3017602080830191909152825180830390910181529082019091526115e790612b19565b8015610c7f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a150565b61163861204c565b611640612092565b61164b60fd336120ec565b6116675760405162461bcd60e51b8152600401610ce59061485e565b8282818190506801bc16d674ec80000061010c54610102544761168a91906148a0565b61169491906148a0565b61169e91906148b7565b10156116bc5760405162461bcd60e51b8152600401610ce5906148d9565b6116c7858585612be4565b505061106a600160cb55565b6116dc3061294c565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000f1617882a71467534d14eee865922de1395c9e89811660048301523460248301527f000000000000000000000000fc87753df5ef5c368b5fba8d4c5043b77e8c5b39169063095ea7b3906044016020604051808303816000875af115801561176a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178e91906149a1565b50604051636e553f6560e01b81523460048201526001600160a01b0382811660248301526000917f000000000000000000000000f1617882a71467534d14eee865922de1395c9e8990911690636e553f65906044016020604051808303816000875af1158015611802573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611826919061491c565b11610c7f5760405162461bcd60e51b8152602060048201526015602482015274139bc81cd8515512081dd85cc81c995d1d5c9b9959605a1b6044820152606401610ce5565b604051635d043b2960e11b8152600481018290523060248201523360448201819052906000907f000000000000000000000000f1617882a71467534d14eee865922de1395c9e896001600160a01b03169063ba087652906064016020604051808303816000875af11580156118e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611908919061491c565b905061106a308383611e3d565b6000610c8e612cce565b611927611ee4565b610c7f81612d02565b610c7f8161294c565b6000610c8e612978565b61116433612e34565b6001600160a01b038116600090815261010e602052604090206060908190819061197590611f55565b925082516001600160401b0381111561199057611990614412565b6040519080825280602002602001820160405280156119b9578160200160208202803683370190505b50915082516001600160401b038111156119d5576119d5614412565b6040519080825280602002602001820160405280156119fe578160200160208202803683370190505b50905060005b8151811015611a6e57611a2284828151811061125257611252614970565b848381518110611a3457611a34614970565b60200260200101848481518110611a4d57611a4d614970565b60209081029190910101919091525280611a6681614986565b915050611a04565b509193909250565b611a7e611ee4565b610c7f81612ebe565b611a8f611ee4565b610c6a8282613052565b611aa1611ee4565b60ff5460405163079cc67960e41b81526001600160a01b039182166004820152602481018390527f000000000000000000000000fc87753df5ef5c368b5fba8d4c5043b77e8c5b39909116906379cc679090604401600060405180830381600087803b158015611b1057600080fd5b505af1158015611b24573d6000803e3d6000fd5b5050505050565b611b33611ee4565b610110546001600160a01b03828116911614801590611bc45750306001600160a01b0316816001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb991906149be565b6001600160a01b0316145b611c285760405162461bcd60e51b815260206004820152602f60248201527f5f7365745265776172644f7261636c653a20496e76616c69642072657761726460448201526e206f7261636c65206164647265737360881b6064820152608401610ce5565b61011080546001600160a01b0319166001600160a01b0383169081179091556040519081527f30da13f0963a005974ddb16864f563178e1dc990a1ca4f5e1cc0b3e0addd9ea590602001611625565b611c7f611ee4565b610c7f81613143565b600080611c9e6801bc16d674ec800000856149db565b6101035461010b5461010a54611cb490476142a6565b611cbe91906142a6565b611cc891906142a6565b611cd291906142a6565b90506000611ce96801bc16d674ec800000856149db565b610104546101115461010754611cff91906142a6565b611d0991906142a6565b611d1391906142a6565b905080821115611d2a57611d2781836148a0565b92505b505092915050565b611d3a611ee4565b61011080546001600160a01b0319169055604051600081527f30da13f0963a005974ddb16864f563178e1dc990a1ca4f5e1cc0b3e0addd9ea5906020015b60405180910390a1565b600061010982604051611d9591906149fa565b9081526040519081900360200190205460ff1692915050565b611db6611ee4565b606580546001600160a01b0383166001600160a01b03199091168117909155611de76033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600061109260fd836120ec565b611e34611ee4565b610c7f81613255565b611e4561204c565b611e4d612092565b60405163079cc67960e41b81526001600160a01b038481166004830152602482018390527f000000000000000000000000fc87753df5ef5c368b5fba8d4c5043b77e8c5b3916906379cc679090604401600060405180830381600087803b158015611eb757600080fd5b505af1158015611ecb573d6000803e3d6000fd5b50505050611eda83838361336b565b61106a600160cb55565b6033546001600160a01b031633146111645760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ce5565b610c7f8161010254611f5091906148a0565b613457565b60606000611f628361348d565b9392505050565b6001600160a01b038216600090815261010e6020526040902061106a8383611f9084611f55565b84612876565b611fa160c9826134e9565b6120135760405162461bcd60e51b815260206004820152603d60248201527f5f72656d6f76655061757365477561726469616e496e7465726e616c3a205f7060448201527f61757365477561726469616e20686173206265656e2072656d6f7665640000006064820152608401610ce5565b6040516001600160a01b03821681527ff0833dc70126c53eb99fc93b161125acd71f7d141f81f41da6cf3668e0fcc7cc90602001611625565b60975460ff16156111645760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ce5565b600260cb5414156120e55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ce5565b600260cb55565b6001600160a01b031660009081526001919091016020526040902054151590565b8061215a5760405162461bcd60e51b815260206004820152601e60248201527f5f6465706f7369743a204465706f736974203020697320696e76616c696400006044820152606401610ce5565b6000610108805461216a90614935565b80601f016020809104026020016040519081016040528092919081815260200182805461219690614935565b80156121e35780601f106121b8576101008083540402835291602001916121e3565b820191906000526020600020905b8154815290600101906020018083116121c657829003601f168201915b5050505050905060005b828110156125c35761010984848381811061220a5761220a614970565b905060200281019061221c9190614a16565b61222a906020810190614a2c565b604051612238929190614a72565b9081526040519081900360200190205460ff16156122a75760405162461bcd60e51b815260206004820152602660248201527f5f6465706f7369743a20496e76616c69642076616c696461746f72207075626c6044820152656963206b657960d01b6064820152608401610ce5565b60006123838585848181106122be576122be614970565b90506020028101906122d09190614a16565b6122de906020810190614a2c565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525089925088915086905081811061232757612327614970565b90506020028101906123399190614a16565b612347906040810190614a2c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508892506134fe915050565b90507f00000000000000000000000000000000219ab540356cbb839cbe05303d7705fa6001600160a01b031663228951186801bc16d674ec8000008787868181106123d0576123d0614970565b90506020028101906123e29190614a16565b6123f0906020810190614a2c565b878a8a8981811061240357612403614970565b90506020028101906124159190614a16565b612423906040810190614a2c565b886040518863ffffffff1660e01b815260040161244596959493929190614aab565b6000604051808303818588803b15801561245e57600080fd5b505af1158015612472573d6000803e3d6000fd5b5050505050600161010986868581811061248e5761248e614970565b90506020028101906124a09190614a16565b6124ae906020810190614a2c565b6040516124bc929190614a72565b908152604051908190036020019020805491151560ff199092169190911790557f887b1d3d2a3c4bcd07ba76bd8be8a3ad106431448d8a21a8102fd8a961c61ec185858481811061250f5761250f614970565b90506020028101906125219190614a16565b61252f906020810190614369565b86868581811061254157612541614970565b90506020028101906125539190614a16565b612561906020810190614a2c565b88888781811061257357612573614970565b90506020028101906125859190614a16565b612593906040810190614a2c565b88876040516125a89796959493929190614afa565b60405180910390a150806125bb81614986565b9150506121ed565b507fa3af609bf46297028ce551832669030f9effef2b02606d02cbbcc40fe6b47c556125f86801bc16d674ec800000846149db565b6040805191825260208201859052015b60405180910390a1505050565b6001600160a01b0381161580159061263b575060ff546001600160a01b03828116911614155b6126965760405162461bcd60e51b815260206004820152602660248201527f5f7365745472656173757279496e7465726e616c3a20496e76616c696420747260448201526565617375727960d01b6064820152608401610ce5565b60ff80546001600160a01b0319166001600160a01b0383169081179091556040519081527fcb7ef3e545f5cdb893f5c568ba710fe08f336375a2d9fd66e161033f8fc09ef390602001611625565b670de0b6b3a76400008111156127575760405162461bcd60e51b815260206004820152603260248201527f5f7365745472656173757279526174696f496e7465726e616c3a205472656173604482015271757279526174696f20746f6f206c6172676560701b6064820152608401610ce5565b610100548114156127c75760405162461bcd60e51b815260206004820152603460248201527f5f7365745472656173757279526174696f496e7465726e616c3a2043616e6e6f6044820152737420736574207468652073616d652076616c756560601b6064820152608401610ce5565b6101008190556040518181527fb4b966f8bcf60846d459594008002153c57d34cfcb8508c9ebea69316d9318c790602001611625565b600081815261010f602052604081205480156128405761010f60006128236001866148a0565b8152602001908152602001600020548161283d91906148a0565b91505b915091565b6000670de0b6b3a7640000610100548361285f91906149db565b61109291906148b7565b600061109260c9836120ec565b61287e61204c565b612886612092565b61289284848484613840565b61289c600160cb55565b50505050565b6128ad60fd826134e9565b6129135760405162461bcd60e51b815260206004820152603160248201527f5f72656d6f76654d616e61676572496e7465726e616c3a205f6d616e61676572604482015270081a185cc81899595b881c995b5bdd9959607a1b6064820152608401610ce5565b6040516001600160a01b03821681527fef69f7d97228658c92417be1b16b19058315de71fecb435d07b7d23728b6bd3190602001611625565b61295461204c565b61295c612092565b61296534613af8565b61296e81613b22565b610c7f600160cb55565b600061010b54610102544761298d91906148a0565b610c8e91906142a6565b61299f61204c565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586129d43390565b6040516001600160a01b039091168152602001611d78565b6129f8610105826134e9565b612a5f5760405162461bcd60e51b815260206004820152603260248201527f5f72656d6f76655374726174656779496e7465726e616c3a20537472617465676044820152711e481a185cc81899595b881c995b5bdd995960721b6064820152608401610ce5565b6040516001600160a01b03821681527f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea490602001611625565b606580546001600160a01b0319169055610c7f81613c58565b612ab9613caa565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336129d4565b600054610100900460ff16612b115760405162461bcd60e51b8152600401610ce590614b5b565b611164613cf3565b8051602014612ba05760405162461bcd60e51b815260206004820152604760248201527f5f7365745769746864726177616c43726564656e7469616c73496e7465726e6160448201527f6c3a20496e76616c6964207769746864726177616c43726564656e7469616c73606482015266040d8cadccee8d60cb1b608482015260a401610ce5565b8051612bb4906101089060208401906141f7565b507f3022649204514734559f042fcb9f5876604a0f08e1775754fee1a618bc7dfec981604051611625919061457e565b7f00000000000000000000000000000000219ab540356cbb839cbe05303d7705fa6001600160a01b031663c5f2892f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c66919061491c565b8114612cc45760405162461bcd60e51b815260206004820152602760248201527f5f6465706f736974436865636b3a204465706f73697420726f6f74206861732060448201526618da185b99d95960ca1b6064820152608401610ce5565b61106a838361210d565b6101025461010c5460009147918391612ce6916142a6565b905080821115612cfd57612cfa81836148a0565b92505b505090565b6001600160a01b038116612d7e5760405162461bcd60e51b815260206004820152603a60248201527f5f6164645061757365477561726469616e496e7465726e616c3a205f7061757360448201527f65477561726469616e20746865207a65726f20616464726573730000000000006064820152608401610ce5565b612d8960c982613d23565b612dfb5760405162461bcd60e51b815260206004820152603860248201527f5f6164645061757365477561726469616e496e7465726e616c3a205f7061757360448201527f65477561726469616e20686173206265656e20616464656400000000000000006064820152608401610ce5565b6040516001600160a01b03821681527fc7eb4f7ea192fd1c93e0613101988e33fa679dd68ffbb33a1040ef4d1747f2cd90602001611625565b80612e41610105826120ec565b612e5d5760405162461bcd60e51b8152600401610ce590614ba6565b34612e6781613d38565b806101046000828254612e7a91906142a6565b9091555050604080516001600160a01b0385168152602081018390527f7faf370a097fbb34b849fc972aaf1817e85129d2c1b46304902212900cf129159101612608565b6001600160a01b03811615801590612f485750306001600160a01b0316816001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f3d91906149be565b6001600160a01b0316145b612fab5760405162461bcd60e51b815260206004820152602e60248201527f5f6164645374726174656779496e7465726e616c3a20696e76616c696420737460448201526d726174656779206164647265737360901b6064820152608401610ce5565b612fb761010582613d23565b6130195760405162461bcd60e51b815260206004820152602d60248201527f5f6164645374726174656779496e7465726e616c3a205374726174656779206860448201526c185cc81899595b881859191959609a1b6064820152608401610ce5565b6040516001600160a01b03821681527f3f008fd510eae7a9e7bee13513d7b83bef8003d488b5a3d0b0da4de71d6846f190602001611625565b8161305f610105826120ec565b61307b5760405162461bcd60e51b8152600401610ce590614ba6565b61308482611f3e565b81610103600082825461309791906142a6565b92505081905550826001600160a01b0316639d3bbaf6836040518263ffffffff1660e01b815260040160206040518083038185885af11580156130de573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613103919061491c565b50604080516001600160a01b0385168152602081018490527f8125d05f0839eec6c1f6b1674833e01f11ab362bd9c60eb2e3b274fa3b47e4f49101612608565b6001600160a01b0381166131b05760405162461bcd60e51b815260206004820152602e60248201527f5f6164644d616e61676572496e7465726e616c3a205f6d616e6167657220746860448201526d65207a65726f206164647265737360901b6064820152608401610ce5565b6131bb60fd82613d23565b61321c5760405162461bcd60e51b815260206004820152602c60248201527f5f6164644d616e61676572496e7465726e616c3a205f6d616e6167657220686160448201526b1cc81899595b88185919195960a21b6064820152608401610ce5565b6040516001600160a01b03821681527f3b4a40cccf2058c593542587329dd385be4f0b588db5471fbd9598e56dd7093a90602001611625565b670de0b6b3a76400008111156132c65760405162461bcd60e51b815260206004820152603060248201527f5f73657452657365727665526174696f496e7465726e616c3a2052657365727660448201526f65526174696f20746f6f206c6172676560801b6064820152608401610ce5565b610101548114156133355760405162461bcd60e51b815260206004820152603360248201527f5f73657452657365727665526174696f496e7465726e616c3a2043616e6e6f7460448201527220736574207468652073616d652076616c756560681b6064820152608401610ce5565b6101018190556040518181527f53010711698e5dbf2a05de8cd22b034a7c0972d110c1fd3fa95ee2eefc88ae9b90602001611625565b600081116133ca5760405162461bcd60e51b815260206004820152602660248201527f5f77697468647261773a20776974686472617720616d6f756e742063616e6e6f60448201526507420626520360d41b6064820152608401610ce5565b806133d3612cce565b10156133e35761106a8282613d4a565b8061010a60008282546133f691906142a6565b9091555061340f90506001600160a01b03831682613e28565b604080516001600160a01b038086168252841660208201529081018290527fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb90606001612608565b6101028190556040518181527f064a6eddb1d5ef0b05d467753b4ec9677d94224577c854f2bb7c6c0504775ff690602001611625565b6060816000018054806020026020016040519081016040528092919081815260200182805480156134dd57602002820191906000526020600020905b8154815260200190600101908083116134c9575b50505050509050919050565b6000611f62836001600160a01b038416613ef1565b600080600285600060801b60405160200161351a929190614bea565b60408051601f1981840301815290829052613534916149fa565b602060405180830381855afa158015613551573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190613574919061491c565b905060006002806135888760006040613feb565b60405160200161359891906149fa565b60408051601f19818403018152908290526135b2916149fa565b602060405180830381855afa1580156135cf573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906135f2919061491c565b60026136018860406020613feb565b6040516136149190600090602001614c22565b60408051601f198184030181529082905261362e916149fa565b602060405180830381855afa15801561364b573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061366e919061491c565b60408051602081019390935282015260600160408051601f198184030181529082905261369a916149fa565b602060405180830381855afa1580156136b7573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906136da919061491c565b905060028083866040516020016136f2929190614c44565b60408051601f198184030181529082905261370c916149fa565b602060405180830381855afa158015613729573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061374c919061491c565b60408051634059730760d81b60208201526000602882015290810184905260029060600160408051601f198184030181529082905261378a916149fa565b602060405180830381855afa1580156137a7573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906137ca919061491c565b60408051602081019390935282015260600160408051601f19818403018152908290526137f6916149fa565b602060405180830381855afa158015613813573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190613836919061491c565b9695505050505050565b60008251116138a55760405162461bcd60e51b815260206004820152602b60248201527f5f636c61696d4279517565756549643a205175657565206c6973742063616e6e60448201526a6f7420626520656d70747960a81b6064820152608401610ce5565b60006138af612978565b90506000805b8451811015613a135760006138e38683815181106138d5576138d5614970565b602002602001015185614101565b9050806138f05750613a01565b61391c86838151811061390557613905614970565b60200260200101518661412490919063ffffffff16565b6139795760405162461bcd60e51b815260206004820152602860248201527f5f636c61696d4279517565756549643a20517565756520696420646f6573206e6044820152671bdd08195e1a5cdd60c21b6064820152608401610ce5565b7ffcdf2346933a63444be3a43932dc03282174211c25bb16b9f202ed7b3c01c48e88888885815181106139ae576139ae614970565b6020026020010151846040516139eb94939291906001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b60405180910390a16139fd81846142a6565b9250505b80613a0b81614986565b9150506138b5565b5060008111613a645760405162461bcd60e51b815260206004820181905260248201527f5f636c61696d4279517565756549643a204e6f20636c61696d20616d6f756e746044820152606401610ce5565b613a7b8161010c54613a7691906148a0565b614130565b613a928161010b54613a8d91906142a6565b614166565b613aa56001600160a01b03861682613e28565b604080516001600160a01b038089168252871660208201529081018290527ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd39926839060600160405180910390a1505050505050565b610c7f670de0b6b3a76400006101015483613b1391906149db565b613b1d91906148b7565b613d38565b3480613b705760405162461bcd60e51b815260206004820152601860248201527f5f7375626d69743a204554482063616e6e6f74206265203000000000000000006044820152606401610ce5565b806101076000828254613b8391906142a6565b90915550506040516340c10f1960e01b81526001600160a01b038381166004830152602482018390527f000000000000000000000000fc87753df5ef5c368b5fba8d4c5043b77e8c5b3916906340c10f1990604401600060405180830381600087803b158015613bf257600080fd5b505af1158015613c06573d6000803e3d6000fd5b5050604080513381526001600160a01b03861660208201529081018490527fc960f3456d7f4d44ac94a2d643da2516ec1fd12ddaf65f7ce5070a45898072949250606001905060405180910390a15050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60975460ff166111645760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610ce5565b600054610100900460ff16613d1a5760405162461bcd60e51b8152600401610ce590614b5b565b61116433612a98565b6000611f62836001600160a01b03841661419c565b610c7f8161010254611f5091906142a6565b61010d54600081815261010f6020526040902054613d696001836142a6565b6001600160a01b038516600090815261010e60205260409020909250613d8f90836141eb565b506000613d9c84836142a6565b600084815261010f6020526040902081905561010d84905561010c54909150613dca90613a769086906142a6565b604080513381526001600160a01b038716602082015290810184905260608101859052608081018290527fb51f063b97a509a8abdbe3eef791e7342e9c61ef1519cf74c3a4a6b4331d86fa9060a00160405180910390a15050505050565b604080516000808252602082019092526001600160a01b038416908390604051613e5291906149fa565b60006040518083038185875af1925050503d8060008114613e8f576040519150601f19603f3d011682016040523d82523d6000602084013e613e94565b606091505b505090508061106a5760405162461bcd60e51b815260206004820152602360248201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960448201526213115160ea1b6064820152608401610ce5565b60008181526001830160205260408120548015613fda576000613f156001836148a0565b8554909150600090613f29906001906148a0565b9050818114613f8e576000866000018281548110613f4957613f49614970565b9060005260206000200154905080876000018481548110613f6c57613f6c614970565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613f9f57613f9f614c6a565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611092565b6000915050611092565b5092915050565b8251606090613ffa83856142a6565b11156140485760405162461bcd60e51b815260206004820152601e60248201527f5f6279746573536c6963653a20536c69636520706172616d206572726f7200006044820152606401610ce5565b816001600160401b0381111561406057614060614412565b6040519080825280601f01601f19166020018201604052801561408a576020820181803683370190505b50905060005b828110156140f957846140a385836142a6565b815181106140b3576140b3614970565b602001015160f81c60f81b8282815181106140d0576140d0614970565b60200101906001600160f81b031916908160001a905350806140f181614986565b915050614090565b509392505050565b60008061410d846127fd565b909250905080831015613fe4575060009392505050565b6000611f628383613ef1565b61010c8190556040518181527f104d0584aa9e9d5db30e252ea72c7635a0523beb1e3a44036626c1ffa831543990602001611625565b61010b8190556040518181527ffc100561a5b3a15d243d29373ad1eecc28836fdb7fa37cb3039a95af23c921ba90602001611625565b60008181526001830160205260408120546141e357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611092565b506000611092565b6000611f62838361419c565b82805461420390614935565b90600052602060002090601f016020900481019282614225576000855561426b565b82601f1061423e57805160ff191683800117855561426b565b8280016001018555821561426b579182015b8281111561426b578251825591602001919060010190614250565b5061427792915061427b565b5090565b5b80821115614277576000815560010161427c565b634e487b7160e01b600052601160045260246000fd5b600082198211156142b9576142b9614290565b500190565b6001600160a01b0381168114610c7f57600080fd5b600080604083850312156142e657600080fd5b8235915060208301356142f8816142be565b809150509250929050565b60006020828403121561431557600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561435d5783516001600160a01b031683529284019291840191600101614338565b50909695505050505050565b60006020828403121561437b57600080fd5b8135611f62816142be565b60008083601f84011261439857600080fd5b5081356001600160401b038111156143af57600080fd5b6020830191508360208260051b85010111156143ca57600080fd5b9250929050565b600080602083850312156143e457600080fd5b82356001600160401b038111156143fa57600080fd5b61440685828601614386565b90969095509350505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561445057614450614412565b604052919050565b600082601f83011261446957600080fd5b813560206001600160401b0382111561448457614484614412565b8160051b614493828201614428565b92835284810182019282810190878511156144ad57600080fd5b83870192505b848310156144cc578235825291830191908301906144b3565b979650505050505050565b600080604083850312156144ea57600080fd5b82356144f5816142be565b915060208301356001600160401b0381111561451057600080fd5b61451c85828601614458565b9150509250929050565b60005b83811015614541578181015183820152602001614529565b8381111561289c5750506000910152565b6000815180845261456a816020860160208601614526565b601f01601f19169290920160200192915050565b602081526000611f626020830184614552565b600081518084526020808501945080840160005b838110156145c1578151875295820195908201906001016145a5565b509495945050505050565b6060815260006145df6060830186614591565b6020838203818501526145f28287614591565b8481036040860152855180825282870193509082019060005b8181101561462957845115158352938301939183019160010161460b565b509098975050505050505050565b8015158114610c7f57600080fd5b600080600080600080600060e0888a03121561466057600080fd5b873596506020880135614672816142be565b955060408801359450606088013561468981614637565b9350608088013560ff8116811461469f57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000602082840312156146ce57600080fd5b81356001600160401b038111156146e457600080fd5b6146f084828501614458565b949350505050565b60008060006040848603121561470d57600080fd5b83356001600160401b0381111561472357600080fd5b61472f86828701614386565b909790965060209590950135949350505050565b6060815260006147566060830186614591565b82810360208401526147688186614591565b905082810360408401526138368185614591565b6000806040838503121561478f57600080fd5b823561479a816142be565b946020939093013593505050565b600080604083850312156147bb57600080fd5b50508035926020909101359150565b600060208083850312156147dd57600080fd5b82356001600160401b03808211156147f457600080fd5b818501915085601f83011261480857600080fd5b81358181111561481a5761481a614412565b61482c601f8201601f19168501614428565b9150808252868482850101111561484257600080fd5b8084840185840137600090820190930192909252509392505050565b60208082526022908201527f6f6e6c794d616e616765723a2063616c6c6572206973206e6f74206d616e616760408201526132b960f11b606082015260800190565b6000828210156148b2576148b2614290565b500390565b6000826148d457634e487b7160e01b600052601260045260246000fd5b500490565b60208082526023908201527f6465706f73697442616c616e6365436865636b3a204e6f7420656e6f7567682060408201526208aa8960eb1b606082015260800190565b60006020828403121561492e57600080fd5b5051919050565b600181811c9082168061494957607f821691505b6020821081141561496a57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b600060001982141561499a5761499a614290565b5060010190565b6000602082840312156149b357600080fd5b8151611f6281614637565b6000602082840312156149d057600080fd5b8151611f62816142be565b60008160001904831182151516156149f5576149f5614290565b500290565b60008251614a0c818460208701614526565b9190910192915050565b60008235605e19833603018112614a0c57600080fd5b6000808335601e19843603018112614a4357600080fd5b8301803591506001600160401b03821115614a5d57600080fd5b6020019150368190038213156143ca57600080fd5b8183823760009101908152919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b608081526000614abf60808301888a614a82565b8281036020840152614ad18188614552565b90508281036040840152614ae6818688614a82565b915050826060830152979650505050505050565b6001600160a01b038816815260a060208201819052600090614b1f908301888a614a82565b8281036040840152614b32818789614a82565b90508281036060840152614b468186614552565b91505082608083015298975050505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526024908201527f697353747261746567793a20696e76616c6964207374726174656779206164646040820152637265737360e01b606082015260800190565b60008351614bfc818460208801614526565b6fffffffffffffffffffffffffffffffff19939093169190920190815260100192915050565b60008351614c34818460208801614526565b9190910191825250602001919050565b82815260008251614c5c816020850160208701614526565b919091016020019392505050565b634e487b7160e01b600052603160045260246000fdfea264697066735822122071d4236c6f5259cc524d64ec6dc3ee93d7332ee9bb83c8f4ae59f6fcdf3079a964736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000219ab540356cbb839cbe05303d7705fa000000000000000000000000fc87753df5ef5c368b5fba8d4c5043b77e8c5b39000000000000000000000000f1617882a71467534d14eee865922de1395c9e89
-----Decoded View---------------
Arg [0] : _depositContract (address): 0x00000000219ab540356cBB839Cbe05303d7705Fa
Arg [1] : _aETH (address): 0xFC87753Df5Ef5C368b5FBA8D4C5043b77e8C5b39
Arg [2] : _saETH (address): 0xF1617882A71467534D14EEe865922de1395c9E89
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000219ab540356cbb839cbe05303d7705fa
Arg [1] : 000000000000000000000000fc87753df5ef5c368b5fba8d4c5043b77e8c5b39
Arg [2] : 000000000000000000000000f1617882a71467534d14eee865922de1395c9e89
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.