More Info
Private Name Tags
ContractCreator
Latest 6 from a total of 6 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Grant Role | 19615790 | 82 days ago | IN | 0 ETH | 0.00103004 | ||||
Grant Role | 19615788 | 82 days ago | IN | 0 ETH | 0.0010226 | ||||
Set Zunami Pool | 19615687 | 82 days ago | IN | 0 ETH | 0.0009498 | ||||
Set Token Conver... | 19615684 | 82 days ago | IN | 0 ETH | 0.0009498 | ||||
Set Price Oracle | 19615683 | 82 days ago | IN | 0 ETH | 0.00094826 | ||||
0x61012060 | 19615682 | 82 days ago | IN | Create: ZunEthFrxEthApsStakeDaoCurveStrat | 0 ETH | 0.0508198 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
ZunEthFrxEthApsStakeDaoCurveStrat
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import '../../../../../utils/Constants.sol'; import './FrxEthApsStakeDaoCurveStratBase.sol'; contract ZunEthFrxEthApsStakeDaoCurveStrat is FrxEthApsStakeDaoCurveStratBase { constructor() FrxEthApsStakeDaoCurveStratBase( [ IERC20(Constants.zunETH_ADDRESS), IERC20(address(0)), IERC20(address(0)), IERC20(address(0)), IERC20(address(0)) ], [uint256(1), 0, 0, 0, 0], Constants.SDT_zunETH_frxETH_VAULT_ADDRESS, Constants.CRV_zunETH_frxETH_ADDRESS, Constants.CRV_zunETH_frxETH_LP_ADDRESS, Constants.zunETH_CONTROLLER_ADDRESS, Constants.zunETH_ADDRESS ) {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) 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 FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; interface IController { function deposit(uint256[5] memory amounts, address receiver) external returns (uint256 shares); function withdraw(uint256 shares, uint256[5] memory minTokenAmounts, address receiver) external; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import './ICurvePoolPricable.sol'; interface ICurvePool2 is ICurvePoolPricable { function coins(uint256 i) external view returns (address); function add_liquidity( uint256[2] memory amounts, uint256 min_mint_amount ) external returns (uint256); function remove_liquidity( uint256 burn_amount, uint256[2] memory min_amounts ) external returns (uint256[2] memory); function remove_liquidity_imbalance( uint256[2] memory amounts, uint256 max_burn_amount ) external returns (uint256); function remove_liquidity_one_coin( uint256 burn_amount, int128 i, uint256 min_received ) external returns (uint256); function exchange( int128 i, int128 j, uint256 input, uint256 min_output ) external returns (uint256); function exchange_underlying(int128 i, int128 j, uint256 input, uint256 min_output) external; function calc_token_amount( uint256[2] memory amounts, bool is_deposit ) external view returns (uint256); function calc_token_amount( uint256[2] memory amounts, bool is_deposit, bool previous ) external view returns (uint256); function calc_withdraw_one_coin(uint256 burn_amount, int128 i) external view returns (uint256); function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import './ICurvePoolPricable.sol'; interface ICurvePoolN is ICurvePoolPricable { function coins(uint256 i) external view returns (address); function add_liquidity( uint256[] memory amounts, uint256 min_mint_amount ) external returns (uint256); function remove_liquidity( uint256 burn_amount, uint256[] memory min_amounts ) external returns (uint256[] memory); function remove_liquidity_imbalance( uint256[] memory amounts, uint256 max_burn_amount ) external returns (uint256); function remove_liquidity_one_coin( uint256 burn_amount, int128 i, uint256 min_received ) external returns (uint256); function exchange( int128 i, int128 j, uint256 input, uint256 min_output ) external returns (uint256); function exchange_underlying(int128 i, int128 j, uint256 input, uint256 min_output) external; function calc_token_amount( uint256[] memory amounts, bool is_deposit ) external view returns (uint256); function calc_token_amount( uint256[] memory amounts, bool is_deposit, bool previous ) external view returns (uint256); function calc_withdraw_one_coin(uint256 burn_amount, int128 i) external view returns (uint256); function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; interface ICurvePoolPricable { function get_virtual_price() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import { IStrategy } from './IStrategy.sol'; interface IPool is IERC20 { error WrongDeposit(uint256 sid, uint256[5] amounts); error AbsentStrategy(uint256 sid); error NotStartedStrategy(uint256 sid); error DisabledStrategy(uint256 sid); error WrongAmount(); error WrongWithdrawParams(uint256 sid); error WrongRatio(); error ZeroAddress(); error DuplicatedStrategy(); error IncorrectArguments(); error WrongWithdrawPercent(); error WrongReceiver(); error IncorrectSid(); error WrongTokens(); error WrongDecimalMultipliers(); struct StrategyInfo { IStrategy strategy; uint256 startTime; uint256 minted; bool enabled; } event Deposited( address indexed depositor, uint256 deposited, uint256[5] amounts, uint256 indexed sid ); event Withdrawn(address indexed withdrawer, uint256 withdrawn, uint256 indexed sid); event FailedWithdrawal(address indexed withdrawer, uint256[5] amounts, uint256 withdrawn); event AddedStrategy(uint256 indexed sid, address indexed strategyAddr, uint256 startTime); event ClaimedRewards(address indexed receiver, IERC20[] rewardTokens); event ClaimedExtraGains(address indexed receiver, uint256 amount); event EnabledStrategy(address indexed pool); event DisableStrategy(address indexed pool); event UpdatedToken( uint256 indexed tid, address indexed token, uint256 tokenDecimalMultiplier, address tokenOld ); function tokens() external view returns (IERC20[5] memory); function token(uint256 tid) external view returns (IERC20); function tokenDecimalsMultipliers() external view returns (uint256[5] memory); function strategyInfo(uint256 sid) external view returns (StrategyInfo memory); function claimRewards(address receiver, IERC20[] memory rewardTokens) external; function totalHoldings() external view returns (uint256); function strategyCount() external view returns (uint256); function deposit( uint256 sid, uint256[5] memory amounts, address receiver ) external returns (uint256); function depositStrategy(uint256 sid, uint256[5] memory amounts) external returns (uint256); function withdraw( uint256 sid, uint256 stableAmount, uint256[5] memory minTokenAmounts, address receiver ) external; function mintAndClaimExtraGains(address receiver) external; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; interface IStableConverter { function handle(address from, address to, uint256 amount, uint256 slippage) external; function valuate(address from, address to, uint256 amount) external view returns (uint256); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; interface IStakeDaoGauge is IERC20 { function claimable_reward(address _user, address _reward_token) external view returns (uint256); function claim_rewards() external; function withdraw(uint256 _value, address _addr, bool _claim_rewards) external; function reward_tokens(uint256 id) external view returns (address); function reward_count() external view returns (uint256); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import './IStakeDaoGauge.sol'; interface IStakeDaoVault is IERC20 { function liquidityGauge() external view returns (IStakeDaoGauge); function withdraw(uint256 amount) external; function deposit(address staker, uint256 amount, bool earn) external; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; interface IStrategy { function deposit(uint256[5] memory amounts) external returns (uint256); function withdraw( address receiver, uint256 userDepositRatio, // multiplied by 1e18 uint256[5] memory minTokenAmounts ) external returns (bool); function withdrawAll(uint256[5] memory minTokenAmounts) external; function totalHoldings() external view returns (uint256); function claimRewards(address receiver, IERC20[] memory rewardTokens) external; function calcTokenAmount( uint256[5] memory tokenAmounts, bool isDeposit ) external view returns (uint256 sharesAmount); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; interface ITokenConverter { function handle( address tokenIn, address tokenOut, uint256 amount, uint256 minAmountOut ) external returns (uint256); function valuate( address tokenIn_, address tokenOut_, uint256 amountIn_ ) external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.23; interface IOracle { /// @notice returns the price in USD of symbol. function getUSDPrice(address token) external view returns (uint256); /// @notice returns if the given token is supported for pricing. function isTokenSupported(address token) external view returns (bool); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import '../../interfaces/ICurvePoolN.sol'; import '../ZunamiStratBase.sol'; abstract contract CurveNStratBase is ZunamiStratBase { using SafeERC20 for IERC20; ICurvePoolN public immutable pool; IERC20 public immutable poolToken; constructor( IERC20[POOL_ASSETS] memory tokens_, uint256[POOL_ASSETS] memory tokenDecimalsMultipliers_, address poolAddr, address poolTokenAddr ) ZunamiStratBase(tokens_, tokenDecimalsMultipliers_) { if (poolAddr == address(0)) revert ZeroAddress(); pool = ICurvePoolN(poolAddr); if (poolTokenAddr == address(0)) revert ZeroAddress(); poolToken = IERC20(poolTokenAddr); } function convertCurvePoolTokenAmounts( uint256[POOL_ASSETS] memory amounts ) internal view virtual returns (uint256[] memory); function depositLiquidity( uint256[POOL_ASSETS] memory amounts ) internal override returns (uint256 poolTokenAmount) { uint256[] memory amountsN = convertAndApproveTokens(address(pool), amounts); poolTokenAmount = depositCurve(amountsN); depositBooster(poolTokenAmount); } function convertAndApproveTokens( address pool, uint256[POOL_ASSETS] memory amounts ) internal virtual returns (uint256[] memory amountsN); function depositCurve(uint256[] memory amountsN) internal virtual returns (uint256 deposited) { return pool.add_liquidity(amountsN, 0); } function depositBooster(uint256 amount) internal virtual; function getLiquidityTokenPrice() internal view virtual override returns (uint256) { return getTokenPrice(address(poolToken)); } function calcTokenAmount( uint256[POOL_ASSETS] memory tokenAmounts, bool isDeposit ) public view override returns (uint256 sharesAmount) { return pool.calc_token_amount(convertCurvePoolTokenAmounts(tokenAmounts), isDeposit); } function getCurveRemovingTokenIndex() internal view virtual returns (int128); function getZunamiRemovingTokenIndex() internal view virtual returns (uint256); function removeLiquidity( uint256 amount, uint256[POOL_ASSETS] memory minTokenAmounts, bool ) internal virtual override { int128 curveTokenIndex = getCurveRemovingTokenIndex(); uint256 removedAmount = pool.remove_liquidity_one_coin( amount, curveTokenIndex, minTokenAmounts[getZunamiRemovingTokenIndex()] ); convertRemovedAmount(removedAmount); } function convertRemovedAmount(uint256 receivedAmount) internal virtual {} }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import '../StakeDaoCurveNStratBase.sol'; abstract contract EmergencyAdminStakeDaoCurveNStratBase is StakeDaoCurveNStratBase { bytes32 public constant EMERGENCY_ADMIN_ROLE = keccak256('EMERGENCY_ADMIN_ROLE'); constructor( IERC20[POOL_ASSETS] memory _tokens, uint256[POOL_ASSETS] memory _tokenDecimalsMultipliers, address _vaultAddr, address _poolAddr, address _poolTokenAddr ) StakeDaoCurveNStratBase( _tokens, _tokenDecimalsMultipliers, _vaultAddr, _poolAddr, _poolTokenAddr ) { _grantRole(EMERGENCY_ADMIN_ROLE, msg.sender); } function inflate( uint256 ratioOfCrvLps, uint256 minInflatedAmount ) external onlyRole(EMERGENCY_ADMIN_ROLE) { _inflate(ratioOfCrvLps, minInflatedAmount); } function _inflate(uint256 ratioOfCrvLps, uint256 minInflatedAmount) internal virtual; function deflate( uint256 ratioOfCrvLps, uint256 minDeflateAmount ) external onlyRole(EMERGENCY_ADMIN_ROLE) { _deflate(ratioOfCrvLps, minDeflateAmount); } function _deflate(uint256 ratioOfCrvLps, uint256 minDeflateAmount) internal virtual; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import '../../../../../utils/Constants.sol'; import '../../../../../interfaces/IController.sol'; import '../../../../../interfaces/IStableConverter.sol'; import '../EmergencyAdminStakeDaoCurveNStratBase.sol'; import '../../../../../interfaces/ICurvePool2.sol'; import '../../../../../interfaces/ITokenConverter.sol'; contract FrxEthApsStakeDaoCurveStratBase is EmergencyAdminStakeDaoCurveNStratBase { using SafeERC20 for IERC20; error InsufficientAmount(); uint256 constant ZUNAMI_STABLE_TOKEN_ID = 0; uint128 public constant FRXETH_TOKEN_POOL_FRXETH_ID = 1; int128 public constant FRXETH_TOKEN_POOL_FRXETH_ID_INT = int128(FRXETH_TOKEN_POOL_FRXETH_ID); uint128 public constant FRXETH_TOKEN_POOL_TOKEN_ID = 0; int128 public constant FRXETH_TOKEN_POOL_TOKEN_ID_INT = int128(FRXETH_TOKEN_POOL_TOKEN_ID); IERC20 wEth = IERC20(Constants.WETH_ADDRESS); IERC20 frxEth = IERC20(Constants.FRX_ETH_ADDRESS); IController public immutable zunamiController; IERC20 public immutable zunamiStable; ITokenConverter public converter; event SetTokenConverter(address tokenConverter); constructor( IERC20[POOL_ASSETS] memory _tokens, uint256[POOL_ASSETS] memory _tokenDecimalsMultipliers, address _vaultAddr, address _poolAddr, address _poolTokenAddr, address _zunamiControllerAddr, address _zunamiStableAddr ) EmergencyAdminStakeDaoCurveNStratBase( _tokens, _tokenDecimalsMultipliers, _vaultAddr, _poolAddr, _poolTokenAddr ) { if (_zunamiControllerAddr == address(0)) revert ZeroAddress(); zunamiController = IController(_zunamiControllerAddr); if (_zunamiStableAddr == address(0)) revert ZeroAddress(); zunamiStable = IERC20(_zunamiStableAddr); } function setTokenConverter(address converterAddr) external onlyRole(DEFAULT_ADMIN_ROLE) { if (address(converterAddr) == address(0)) revert ZeroAddress(); converter = ITokenConverter(converterAddr); emit SetTokenConverter(converterAddr); } function getTokenPrice(address token) internal view override returns (uint256) { return (oracle.getUSDPrice(token) * 1e18) / oracle.getUSDPrice(Constants.CHAINLINK_FEED_REGISTRY_ETH_ADDRESS); } function convertCurvePoolTokenAmounts( uint256[POOL_ASSETS] memory amounts ) internal pure override returns (uint256[] memory) { uint256[] memory amountsN = new uint256[](8); amountsN[FRXETH_TOKEN_POOL_TOKEN_ID] = amounts[ZUNAMI_STABLE_TOKEN_ID]; return amountsN; } function convertAndApproveTokens( address pool, uint256[POOL_ASSETS] memory amounts ) internal override returns (uint256[] memory) { uint256[] memory amountsN = new uint256[](8); amountsN[FRXETH_TOKEN_POOL_TOKEN_ID] = amounts[ZUNAMI_STABLE_TOKEN_ID]; zunamiStable.safeIncreaseAllowance(pool, amountsN[FRXETH_TOKEN_POOL_TOKEN_ID]); return amountsN; } function getCurveRemovingTokenIndex() internal pure override returns (int128) { return FRXETH_TOKEN_POOL_TOKEN_ID_INT; } function getZunamiRemovingTokenIndex() internal pure override returns (uint256) { return ZUNAMI_STABLE_TOKEN_ID; } function _inflate(uint256 ratioOfCrvLps, uint256 minInflatedAmount) internal override { uint256 removingCrvLps = getLiquidityAmountByRatio(ratioOfCrvLps); depositedLiquidity -= removingCrvLps; vault.withdraw(removingCrvLps); uint256 frxEthAmount = pool.remove_liquidity_one_coin( removingCrvLps, FRXETH_TOKEN_POOL_FRXETH_ID_INT, 0 ); frxEth.safeIncreaseAllowance(address(zunamiController), frxEthAmount); uint256 zunStableAmount = zunamiController.deposit( [0, frxEthAmount, 0, 0, 0], address(this) ); if (zunStableAmount < minInflatedAmount) { revert InsufficientAmount(); } uint256[] memory amountsN = new uint256[](8); amountsN[FRXETH_TOKEN_POOL_TOKEN_ID] = zunStableAmount; zunamiStable.safeIncreaseAllowance(address(pool), zunStableAmount); uint256 poolTokenAmount = depositCurve(amountsN); depositedLiquidity += poolTokenAmount; depositBooster(poolTokenAmount); } function _deflate(uint256 ratioOfCrvLps, uint256 minDeflateAmount) internal override { uint256 removingCrvLps = getLiquidityAmountByRatio(ratioOfCrvLps); depositedLiquidity -= removingCrvLps; vault.withdraw(removingCrvLps); uint256 tokenAmount = pool.remove_liquidity_one_coin( removingCrvLps, FRXETH_TOKEN_POOL_TOKEN_ID_INT, 0 ); zunamiStable.safeIncreaseAllowance(address(zunamiController), tokenAmount); zunamiController.withdraw(tokenAmount, [uint256(0), 0, 0, 0, 0], address(this)); uint256 wEthBalance = wEth.balanceOf(address(this)); if (wEthBalance > 0) { wEth.safeTransfer(address(converter), wEthBalance); converter.handle( address(wEth), address(frxEth), wEthBalance, applySlippage(wEthBalance) ); } uint256 frxEthAmount = frxEth.balanceOf(address(this)); if (frxEthAmount < minDeflateAmount) { revert InsufficientAmount(); } uint256[] memory amountsN = new uint256[](8); amountsN[FRXETH_TOKEN_POOL_FRXETH_ID] = frxEthAmount; frxEth.safeIncreaseAllowance(address(pool), frxEthAmount); uint256 poolTokenAmount = depositCurve(amountsN); depositedLiquidity += poolTokenAmount; depositBooster(poolTokenAmount); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import '../CurveNStratBase.sol'; import '../../../interfaces/IStakeDaoVault.sol'; abstract contract StakeDaoCurveNStratBase is CurveNStratBase { using SafeERC20 for IERC20; IStakeDaoVault public immutable vault; constructor( IERC20[POOL_ASSETS] memory _tokens, uint256[POOL_ASSETS] memory _tokenDecimalsMultipliers, address _vaultAddr, address _poolAddr, address _poolTokenAddr ) CurveNStratBase(_tokens, _tokenDecimalsMultipliers, _poolAddr, _poolTokenAddr) { if (_vaultAddr == address(0)) revert ZeroAddress(); vault = IStakeDaoVault(_vaultAddr); } function depositBooster(uint256 amount) internal override { poolToken.safeIncreaseAllowance(address(vault), amount); vault.deposit(address(this), amount, true); } function removeLiquidity( uint256 amount, uint256[POOL_ASSETS] memory minTokenAmounts, bool removeAll ) internal virtual override { vault.withdraw(amount); super.removeLiquidity(amount, minTokenAmounts, removeAll); } function claimCollectedRewards() internal virtual override { vault.liquidityGauge().claim_rewards(); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import '@openzeppelin/contracts/access/AccessControl.sol'; import '../interfaces/IPool.sol'; contract ZunamiPoolAccessControl is AccessControl { error MustBeCalledByZunamiPool(); error ZeroAddress(); error ZeroValue(); error MustHaveOwner(); IPool public zunamiPool; event ZunamiPoolSet(address zunamiPoolAddr); modifier onlyZunamiPool() { if (_msgSender() != address(zunamiPool)) revert MustBeCalledByZunamiPool(); _; } constructor() { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); } function setZunamiPool(address zunamiAddr) external onlyRole(DEFAULT_ADMIN_ROLE) { if (zunamiAddr == address(0)) revert ZeroAddress(); zunamiPool = IPool(zunamiAddr); emit ZunamiPoolSet(zunamiAddr); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import '../lib/Oracle/interfaces/IOracle.sol'; import '../interfaces/IStrategy.sol'; import './ZunamiPoolAccessControl.sol'; abstract contract ZunamiStratBase is IStrategy, ZunamiPoolAccessControl { using SafeERC20 for IERC20; error WrongTokens(); error WrongDecimalMultipliers(); error DepositLiquidityValueTooLow(); uint8 public constant POOL_ASSETS = 5; uint256 public constant RATIO_MULTIPLIER = 1e18; uint256 public constant PRICE_DENOMINATOR = 1e18; uint256 public constant SLIPPAGE_DENOMINATOR = 10000; uint256 public slippage = 50; // 0.50% IERC20[POOL_ASSETS] public tokens; uint256[POOL_ASSETS] public tokenDecimalsMultipliers; IOracle public oracle; uint256 public depositedLiquidity; event SlippageSet(uint256 oldSlippage, uint256 newSlippage); event PriceOracleSet(address oracleAddr); constructor( IERC20[POOL_ASSETS] memory tokens_, uint256[POOL_ASSETS] memory tokenDecimalsMultipliers_ ) { bool otherZeros = false; for (uint256 i = 0; i < POOL_ASSETS; i++) { if (otherZeros && address(tokens_[i]) != address(0)) revert WrongTokens(); if (address(tokens_[i]) == address(0)) otherZeros = true; if ( (address(tokens_[i]) != address(0) && tokenDecimalsMultipliers_[i] == 0) || (address(tokens_[i]) == address(0) && tokenDecimalsMultipliers_[i] != 0) ) revert WrongDecimalMultipliers(); } tokens = tokens_; tokenDecimalsMultipliers = tokenDecimalsMultipliers_; } function setPriceOracle(address oracleAddr) public onlyRole(DEFAULT_ADMIN_ROLE) { if (oracleAddr == address(0)) revert ZeroAddress(); oracle = IOracle(oracleAddr); emit PriceOracleSet(oracleAddr); } function setSlippage(uint256 _slippage) external onlyRole(DEFAULT_ADMIN_ROLE) { require(_slippage > 0 && _slippage <= SLIPPAGE_DENOMINATOR, 'Wrong slippage number!'); emit SlippageSet(slippage, _slippage); slippage = _slippage; } function applySlippage(uint256 amount) internal view returns (uint256) { return (amount * (SLIPPAGE_DENOMINATOR - slippage)) / SLIPPAGE_DENOMINATOR; } function calcTokenAmount( uint256[POOL_ASSETS] memory tokenAmounts, bool isDeposit ) public view virtual returns (uint256 sharesAmount); function calcLiquidityValue(uint256 tokenAmount) internal view returns (uint256) { return (tokenAmount * getLiquidityTokenPrice()) / PRICE_DENOMINATOR; } function getLiquidityTokenPrice() internal view virtual returns (uint256); function getTokenPrice(address token) internal view virtual returns (uint256) { return oracle.getUSDPrice(token); } function totalHoldings() public view virtual returns (uint256) { return calcLiquidityValue(getLiquidityBalance()); } function getLiquidityBalance() internal view virtual returns (uint256) { return depositedLiquidity; } function deposit( uint256[POOL_ASSETS] memory amounts ) external onlyZunamiPool returns (uint256 liquidityValue) { uint256 depositValue = valuateDeposit(amounts); uint256 liquidity = depositLiquidity(amounts); depositedLiquidity += liquidity; liquidityValue = calcLiquidityValue(liquidity); if (liquidityValue < applySlippage(depositValue)) revert DepositLiquidityValueTooLow(); } function valuateDeposit( uint256[POOL_ASSETS] memory amounts ) internal view virtual returns (uint256 value) { for (uint256 i = 0; i < POOL_ASSETS; i++) { value += (getTokenPrice(address(tokens[i])) * amounts[i] * tokenDecimalsMultipliers[i]) / PRICE_DENOMINATOR; } return value; } function depositLiquidity( uint256[POOL_ASSETS] memory amounts ) internal virtual returns (uint256); function getLiquidityAmountByRatio( uint256 poolTokenRatio // multiplied by 1e18 ) internal view returns (uint256) { require(poolTokenRatio > 0 && poolTokenRatio <= RATIO_MULTIPLIER, 'Wrong PoolToken Ratio'); return (getLiquidityBalance() * poolTokenRatio) / RATIO_MULTIPLIER; } function withdraw( address receiver, uint256 poolTokenRatio, // multiplied by 1e18 uint256[POOL_ASSETS] memory tokenAmounts ) external virtual onlyZunamiPool returns (bool) { uint256 liquidityAmount = getLiquidityAmountByRatio(poolTokenRatio); if (liquidityAmount < calcTokenAmount(tokenAmounts, false)) { return false; } uint256[] memory prevBalances = new uint256[](POOL_ASSETS); for (uint256 i = 0; i < POOL_ASSETS; i++) { if (address(tokens[i]) == address(0)) break; prevBalances[i] = tokens[i].balanceOf(address(this)); } depositedLiquidity -= liquidityAmount; removeLiquidity(liquidityAmount, tokenAmounts, false); transferTokensOut(convertTokensToDynamic(tokens), receiver, prevBalances); return true; } function removeLiquidity( uint256 amount, uint256[POOL_ASSETS] memory minTokenAmounts, bool removeAll ) internal virtual; function claimRewards( address receiver, IERC20[] memory rewardTokens ) public virtual onlyZunamiPool { claimCollectedRewards(); transferTokensOut(rewardTokens, receiver, fillArrayN(0, rewardTokens.length)); } function claimCollectedRewards() internal virtual {} function withdrawAll( uint256[POOL_ASSETS] memory minTokenAmounts ) external virtual onlyZunamiPool { removeLiquidity(depositedLiquidity, minTokenAmounts, true); depositedLiquidity = 0; transferTokensOut(convertTokensToDynamic(tokens), _msgSender(), fillArrayN(0, POOL_ASSETS)); } function transferTokensOut( IERC20[] memory transferringTokens, address receiver, uint256[] memory prevBalances ) internal { uint256 transferAmount; IERC20 token_; for (uint256 i = 0; i < transferringTokens.length; i++) { token_ = transferringTokens[i]; if (address(token_) == address(0)) break; transferAmount = token_.balanceOf(address(this)) - prevBalances[i]; if (transferAmount > 0) { token_.safeTransfer(receiver, transferAmount); } } } function convertTokensToDynamic( IERC20[POOL_ASSETS] memory _tokens ) internal pure returns (IERC20[] memory tokesDynamic) { tokesDynamic = new IERC20[](POOL_ASSETS); for (uint256 i = 0; i < _tokens.length; i++) { tokesDynamic[i] = _tokens[i]; } } function fillArrayN( uint256 _value, uint256 _count ) internal pure returns (uint256[] memory values) { values = new uint256[](_count); for (uint256 i = 0; i < _count; i++) { values[i] = _value; } } function withdrawStuckToken(IERC20 _token) external onlyRole(DEFAULT_ADMIN_ROLE) { uint256 tokenBalance = _token.balanceOf(address(this)); if (tokenBalance > 0) { _token.safeTransfer(_msgSender(), tokenBalance); } } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.23; library Constants { address internal constant CRVUSD_ADDRESS = 0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E; address internal constant USDC_ADDRESS = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; address internal constant USDT_ADDRESS = 0xdAC17F958D2ee523a2206206994597C13D831ec7; address internal constant DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F; address internal constant FRX_ETH_ADDRESS = 0x5E8422345238F34275888049021821E8E08CAa1f; address internal constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address internal constant CVX_ADDRESS = 0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B; address internal constant CRV_ADDRESS = 0xD533a949740bb3306d119CC777fa900bA034cd52; address internal constant FXS_ADDRESS = 0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0; address internal constant SPELL_ADDRESS = 0x090185f2135308BaD17527004364eBcC2D37e5F6; address internal constant SDT_ADDRESS = 0x73968b9a57c6E53d41345FD57a6E6ae27d6CDB2F; address internal constant SFRXETH_ADDRESS = 0xac3E018457B222d93114458476f3E3416Abbe38F; // Will be added after deployment of zunUSD v2 pool address internal constant ZUNUSD_ADDRESS = 0x8C0D76C9B18779665475F3E212D9Ca1Ed6A1A0e6; // Will be added after deployment of zunUSD v2 pool controller address internal constant zunUSD_CONTROLLER_ADDRESS = 0x618eee502CDF6b46A2199C21D1411f3F6065c940; // Will be added after deployment of zunETH v2 pool address internal constant zunETH_ADDRESS = 0xc2e660C62F72c2ad35AcE6DB78a616215E2F2222; address internal constant zunETH_CONTROLLER_ADDRESS = 0x54A00DA65c79DDCe24E7fe4691737FD70F7797DF; address public constant CHAINLINK_FEED_REGISTRY_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address internal constant CRV_3POOL_ADDRESS = 0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7; address internal constant CRV_3POOL_LP_ADDRESS = 0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490; address internal constant CRV_TRICRYPTO2_ADDRESS = 0xD51a44d3FaE010294C616388b506AcdA1bfAAE46; address internal constant ETH_frxETH_ADDRESS = 0xa1F8A6807c402E4A15ef4EBa36528A3FED24E577; address internal constant ETH_frxETH_LP_ADDRESS = 0xf43211935C781D5ca1a41d2041F397B8A7366C7A; address internal constant WETH_frxETH_ADDRESS = 0x9c3B46C0Ceb5B9e304FCd6D88Fc50f7DD24B31Bc; address internal constant WETH_frxETH_LP_ADDRESS = 0x9c3B46C0Ceb5B9e304FCd6D88Fc50f7DD24B31Bc; address internal constant CRV_FRAX_USDC_POOL_ADDRESS = 0xDcEF968d416a41Cdac0ED8702fAC8128A64241A2; address internal constant CRV_FRAX_USDC_POOL_LP_ADDRESS = 0x3175Df0976dFA876431C2E9eE6Bc45b65d3473CC; address internal constant SDT_CRVUSD_USDT_VAULT_ADDRESS = 0x37b24ac19504C0c6FC1ADc8deb5D24f5C4F6A2f2; address internal constant CRV_CRVUSD_USDT_LP_ADDRESS = 0x390f3595bCa2Df7d23783dFd126427CCeb997BF4; address internal constant CRV_CRVUSD_USDT_ADDRESS = 0x390f3595bCa2Df7d23783dFd126427CCeb997BF4; address internal constant SDT_CRVUSD_USDC_VAULT_ADDRESS = 0xb618EA40cb1F5b08839Ba228C8dd58AC3DCA12F3; address internal constant CRV_CRVUSD_USDC_LP_ADDRESS = 0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E; address internal constant CRV_CRVUSD_USDC_ADDRESS = 0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E; address internal constant CRV_BOOSTER_ADDRESS = 0xF403C135812408BFbE8713b5A23a04b3D48AAE31; address internal constant CRV_ETH_stETH_ADDRESS = 0x21E27a5E5513D6e65C4f830167390997aA84843a; address internal constant CRV_ETH_stETH_LP_ADDRESS = 0x21E27a5E5513D6e65C4f830167390997aA84843a; address internal constant CVX_ETH_stETH_REWARDS_ADDRESS = 0x6B27D7BC63F1999D14fF9bA900069ee516669ee8; uint256 internal constant CVX_ETH_stETH_PID = 177; address internal constant CRV_zunUSD_crvUSD_ADDRESS = 0x8C24b3213FD851db80245FCCc42c40B94Ac9a745; address internal constant CRV_zunUSD_crvUSD_LP_ADDRESS = 0x8C24b3213FD851db80245FCCc42c40B94Ac9a745; address internal constant CVX_zunUSD_crvUSD_REWARDS_ADDRESS = 0xB0408d1477554268Ece9b0a40290C345196fBf1B; uint256 internal constant CVX_zunUSD_crvUSD_PID = 309; address internal constant CRV_USDT_crvUSD_ADDRESS = 0x390f3595bCa2Df7d23783dFd126427CCeb997BF4; address internal constant LLAMALEND_CRVUSD_ADDRESS = 0xCeA18a8752bb7e7817F9AE7565328FE415C0f2cA; address internal constant CVX_LLAMALEND_CRVUSD_REWARDS_ADDRESS = 0x4bf2d8484474170bff8a8c34475be3d87dFF28cA; uint256 internal constant CVX_LLAMALEND_CRVUSD_PID = 325; address internal constant CRV_zunETH_frxETH_ADDRESS = 0x3A65cbaebBFecbeA5D0CB523ab56fDbda7fF9aAA; address internal constant CRV_zunETH_frxETH_LP_ADDRESS = 0x3A65cbaebBFecbeA5D0CB523ab56fDbda7fF9aAA; address internal constant CVX_zunETH_frxETH_REWARDS_ADDRESS = 0x756d67A10974Fa0e0cE63F82AF4E7ef0d46d452D; uint256 internal constant CVX_zunETH_frxETH_PID = 330; address internal constant SDT_zunETH_frxETH_VAULT_ADDRESS = 0xAaE1Ae12d4C8b811DDa1188b01be23b4ab7C62D2; address internal constant SDT_LLAMALEND_CRVUSD_VAULT_ADDRESS = 0xfa6D40573082D797CB3cC378c0837fB90eB043e5; // Will be added after deployment of zunUSD v2 pool and curve pool for zunUSD address internal constant CRV_zunUSD_crvFRAX_ADDRESS = address(0); address internal constant CRV_zunUSD_crvFRAX_LP_ADDRESS = address(0); address internal constant CVX_zunUSD_crvFRAX_REWARDS_ADDRESS = address(0); uint256 internal constant CVX_zunUSD_crvFRAX_PID = 0; }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "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":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"DepositLiquidityValueTooLow","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InsufficientAmount","type":"error"},{"inputs":[],"name":"MustBeCalledByZunamiPool","type":"error"},{"inputs":[],"name":"MustHaveOwner","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"WrongDecimalMultipliers","type":"error"},{"inputs":[],"name":"WrongTokens","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oracleAddr","type":"address"}],"name":"PriceOracleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenConverter","type":"address"}],"name":"SetTokenConverter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldSlippage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSlippage","type":"uint256"}],"name":"SlippageSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"zunamiPoolAddr","type":"address"}],"name":"ZunamiPoolSet","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMERGENCY_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRXETH_TOKEN_POOL_FRXETH_ID","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRXETH_TOKEN_POOL_FRXETH_ID_INT","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRXETH_TOKEN_POOL_TOKEN_ID","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRXETH_TOKEN_POOL_TOKEN_ID_INT","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_ASSETS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RATIO_MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SLIPPAGE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[5]","name":"tokenAmounts","type":"uint256[5]"},{"internalType":"bool","name":"isDeposit","type":"bool"}],"name":"calcTokenAmount","outputs":[{"internalType":"uint256","name":"sharesAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"contract IERC20[]","name":"rewardTokens","type":"address[]"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"converter","outputs":[{"internalType":"contract ITokenConverter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ratioOfCrvLps","type":"uint256"},{"internalType":"uint256","name":"minDeflateAmount","type":"uint256"}],"name":"deflate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[5]","name":"amounts","type":"uint256[5]"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"liquidityValue","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositedLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ratioOfCrvLps","type":"uint256"},{"internalType":"uint256","name":"minInflatedAmount","type":"uint256"}],"name":"inflate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract ICurvePoolN","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"oracleAddr","type":"address"}],"name":"setPriceOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_slippage","type":"uint256"}],"name":"setSlippage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"converterAddr","type":"address"}],"name":"setTokenConverter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"zunamiAddr","type":"address"}],"name":"setZunamiPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slippage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenDecimalsMultipliers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokens","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalHoldings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IStakeDaoVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"poolTokenRatio","type":"uint256"},{"internalType":"uint256[5]","name":"tokenAmounts","type":"uint256[5]"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[5]","name":"minTokenAmounts","type":"uint256[5]"}],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"}],"name":"withdrawStuckToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"zunamiController","outputs":[{"internalType":"contract IController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zunamiPool","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zunamiStable","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101206040526032600255600f80546001600160a01b031990811673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21790915560108054909116735e8422345238f34275888049021821e8e08caa1f1790553480156200005f57600080fd5b506040518060a0016040528073c2e660c62f72c2ad35ace6db78a616215e2f22226001600160a01b03166001600160a01b0316815260200160006001600160a01b03166001600160a01b0316815260200160006001600160a01b03166001600160a01b0316815260200160006001600160a01b03166001600160a01b0316815260200160006001600160a01b03166001600160a01b03168152506040518060a0016040528060018152602001600081526020016000815260200160008152602001600081525073aae1ae12d4c8b811dda1188b01be23b4ab7c62d2733a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa807354a00da65c79ddce24e7fe4691737fd70f7797df73c2e660c62f72c2ad35ace6db78a616215e2f2222868686868684848484848484838383836200019f6000801b336200045660201b60201c565b506000805b6005811015620002f357818015620001df57506000848260058110620001ce57620001ce620005aa565b60200201516001600160a01b031614155b15620001fe57604051631d37a6fd60e11b815260040160405180910390fd5b6000848260058110620002155762000215620005aa565b60200201516001600160a01b0316036200022e57600191505b6000848260058110620002455762000245620005aa565b60200201516001600160a01b031614158015620002795750828160058110620002725762000272620005aa565b6020020151155b80620002cb57506000848260058110620002975762000297620005aa565b60200201516001600160a01b0316148015620002cb5750828160058110620002c357620002c3620005aa565b602002015115155b15620002ea5760405163bfa45dc560e01b815260040160405180910390fd5b600101620001a4565b5062000303600384600562000505565b5062000313600883600562000562565b5050506001600160a01b0383169050620003405760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0380831660805281166200036e5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0390811660a05286169250620003a19150505760405163d92e233d60e01b815260040160405180910390fd5b50506001600160a01b031660c05250620003de90507f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a633362000456565b5050506001600160a01b03851692506200040e9150505760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0380831660e05281166200043c5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b03166101005250620005c0945050505050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16620004fb576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620004b23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001620004ff565b5060005b92915050565b826005810192821562000550579160200282015b828111156200055057825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019062000519565b506200055e92915062000593565b5090565b826005810192821562000550579160200282015b828111156200055057825182559160200191906001019062000576565b5b808211156200055e576000815560010162000594565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e0516101005161296b620006a6600039600081816103ef015281816112460152818161186a015261218d01526000818161059a01528181611268015281816112cb0152818161170b01526117340152600081816105c101528181610eaf01528181611137015281816115f601528181611a7f01528181611eb40152611efc01526000818161054501528181611e9201526121cb0152600081816102b101528181610ba5015281816111c10152818161155f015281816116800152818161188c01528181611c5e01528181611e0b0152611f68015261296b6000f3fe608060405234801561001057600080fd5b50600436106102535760003560e01c80636c1516e111610146578063b5326170116100c3578063d547741f11610087578063d547741f14610567578063d5f651a41461043f578063e9ec2e991461057a578063f0fa55a914610582578063f459fff414610595578063fbfa77cf146105bc57600080fd5b8063b5326170146104ff578063b67d611d14610507578063bd38837b1461051a578063c56aa1661461052d578063cbdf382c1461054057600080fd5b806381a7b8941161010a57806381a7b894146104b557806391d14854146104c85780639d57b9a6146104db578063a217fddf146104ee578063ac905114146104f657600080fd5b80636c1516e11461043f5780636d9164c61461044e5780636e76fc8f1461046157806375451b4f146104885780637dc0d1d0146104a257600080fd5b80632e7f237f116101d4578063530e784f11610198578063530e784f146103d7578063550f5c98146103ea57806356edb3161461041157806359615983146104245780636524ee901461043757600080fd5b80632e7f237f1461037a5780632f2ff15d1461039557806336568abe146103a85780633e032a3b146103bb5780634f64b2be146103c457600080fd5b8063213c79d81161021b578063213c79d8146102fe578063248a9ca3146103115780632512226414610334578063258a5f29146103475780632a9383421461036757600080fd5b806301ffc9a714610258578063068acf6c1461028057806310c231c71461029557806316f0115b146102ac5780632026ffa3146102eb575b600080fd5b61026b610266366004612457565b6105e3565b60405190151581526020015b60405180910390f35b61029361028e366004612496565b61061a565b005b61029e600e5481565b604051908152602001610277565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610277565b6102936102f93660046124fa565b6106b1565b6001546102d3906001600160a01b031681565b61029e61031f3660046125c1565b60009081526020819052604090206001015490565b6102936103423660046125da565b610707565b61034f600081565b6040516001600160801b039091168152602001610277565b6102936103753660046125da565b61073b565b610382600081565b604051600f9190910b8152602001610277565b6102936103a33660046125fc565b61076f565b6102936103b63660046125fc565b61079a565b61029e60025481565b6102d36103d23660046125c1565b6107cd565b6102936103e5366004612496565b6107ed565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b61029e61041f3660046125c1565b610875565b610293610432366004612496565b61088c565b61034f600181565b61029e670de0b6b3a764000081565b61026b61045c36600461269a565b61090c565b61029e7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a6381565b610490600581565b60405160ff9091168152602001610277565b600d546102d3906001600160a01b031681565b6102936104c33660046126d9565b610ae2565b61026b6104d63660046125fc565b610b78565b61029e6104e9366004612703565b610ba1565b61029e600081565b61029e61271081565b610382600181565b61029e6105153660046126d9565b610c3a565b6011546102d3906001600160a01b031681565b61029361053b366004612496565b610cde565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6102936105753660046125fc565b610d5e565b61029e610d83565b6102936105903660046125c1565b610d9b565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b03198216637965db0b60e01b148061061457506301ffc9a760e01b6001600160e01b03198316145b92915050565b600061062581610e44565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561066c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106909190612730565b905080156106ac576106ac6001600160a01b0384163383610e4e565b505050565b6001546001600160a01b0316336001600160a01b0316146106e5576040516304d6e46b60e31b815260040160405180910390fd5b6106ed610ead565b61070381836106fe60008551610f7d565b610ffc565b5050565b7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a6361073181610e44565b6106ac83836110fd565b7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a6361076581610e44565b6106ac83836115bc565b60008281526020819052604090206001015461078a81610e44565b61079483836118e8565b50505050565b6001600160a01b03811633146107c35760405163334bd91960e11b815260040160405180910390fd5b6106ac828261197a565b600381600581106107dd57600080fd5b01546001600160a01b0316905081565b60006107f881610e44565b6001600160a01b03821661081f5760405163d92e233d60e01b815260040160405180910390fd5b600d80546001600160a01b0319166001600160a01b0384169081179091556040519081527f6536690106168bdf4ba72c128a053d817999b1db90cae23f139b293bf862cb75906020015b60405180910390a15050565b6008816005811061088557600080fd5b0154905081565b600061089781610e44565b6001600160a01b0382166108be5760405163d92e233d60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384169081179091556040519081527ffa639b2012458fd129b4bf30b2a98c9b56cc3a9ba0606013b8d1f9232cb4498a90602001610869565b6001546000906001600160a01b0316336001600160a01b031614610943576040516304d6e46b60e31b815260040160405180910390fd5b600061094e846119e5565b905061095b836000610ba1565b81101561096c576000915050610adb565b60408051600580825260c082019092526000916020820160a08036833701905050905060005b6005811015610a63576000600382600581106109b0576109b0612749565b01546001600160a01b031614610a6357600381600581106109d3576109d3612749565b01546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e9190612730565b828281518110610a5057610a50612749565b6020908102919091010152600101610992565b5081600e6000828254610a769190612775565b90915550610a88905082856000611a69565b6040805160a0810191829052610ad491610acd919060039060059082845b81546001600160a01b03168152600190910190602001808311610aa6575050505050611aee565b8783610ffc565b6001925050505b9392505050565b6001546001600160a01b0316336001600160a01b031614610b16576040516304d6e46b60e31b815260040160405180910390fd5b610b24600e54826001611a69565b6000600e556040805160a0810191829052600380546001600160a01b03168252610b7592610b68929190600590600460208501808311610aa6575050505050611aee565b336106fe60006005610f7d565b50565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633db06dd8610bdb85611b6c565b846040518363ffffffff1660e01b8152600401610bf99291906127c4565b602060405180830381865afa158015610c16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610adb9190612730565b6001546000906001600160a01b0316336001600160a01b031614610c71576040516304d6e46b60e31b815260040160405180910390fd5b6000610c7c83611bbc565b90506000610c8984611c56565b905080600e6000828254610c9d91906127e8565b90915550610cac905081611c99565b9250610cb782611cb6565b831015610cd757604051630224f5df60e11b815260040160405180910390fd5b5050919050565b6000610ce981610e44565b6001600160a01b038216610d105760405163d92e233d60e01b815260040160405180910390fd5b601180546001600160a01b0319166001600160a01b0384169081179091556040519081527f18f0ece2d6ea55163aef7a7c841762e706a96c532ed665e8abefaa00d1767fb890602001610869565b600082815260208190526040902060010154610d7981610e44565b610794838361197a565b6000610d96610d91600e5490565b611c99565b905090565b6000610da681610e44565b600082118015610db857506127108211155b610e025760405162461bcd60e51b815260206004820152601660248201527557726f6e6720736c697070616765206e756d6265722160501b60448201526064015b60405180910390fd5b60025460408051918252602082018490527f785f467195f308c252d89e7e85c95a6b7646506ba4774a1dc54e0eedc08e3d43910160405180910390a150600255565b610b758133611ccb565b6040516001600160a01b038381166024830152604482018390526106ac91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611d04565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f9a0be686040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2f91906127fb565b6001600160a01b031663e6f1daf26040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610f6957600080fd5b505af1158015610794573d6000803e3d6000fd5b60608167ffffffffffffffff811115610f9857610f986124b3565b604051908082528060200260200182016040528015610fc1578160200160208202803683370190505b50905060005b82811015610ff55783828281518110610fe257610fe2612749565b6020908102919091010152600101610fc7565b5092915050565b60008060005b85518110156110f55785818151811061101d5761101d612749565b6020026020010151915060006001600160a01b0316826001600160a01b031603156110f55783818151811061105457611054612749565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa1580156110a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c79190612730565b6110d19190612775565b925082156110ed576110ed6001600160a01b0383168685610e4e565b600101611002565b505050505050565b6000611108836119e5565b905080600e600082825461111c9190612775565b9091555050604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561118357600080fd5b505af1158015611197573d6000803e3d6000fd5b5050604051630d2680e960e11b8152600481018490526000602482018190526044820181905292507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169150631a4d01d2906064016020604051808303816000875af1158015611213573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112379190612730565b905061128d6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000083611d67565b6040805160a081018252600080825260208201819052818301819052606082018190526080820152905163ca54be3b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163ca54be3b91611302918591309060040161283b565b600060405180830381600087803b15801561131c57600080fd5b505af1158015611330573d6000803e3d6000fd5b5050600f546040516370a0823160e01b8152306004820152600093506001600160a01b0390911691506370a0823190602401602060405180830381865afa15801561137f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a39190612730565b9050801561147057601154600f546113c8916001600160a01b03918216911683610e4e565b601154600f546010546001600160a01b0392831692631a378db79281169116846113f181611cb6565b6040516001600160e01b031960e087901b1681526001600160a01b039485166004820152939092166024840152604483015260648201526084016020604051808303816000875af115801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e9190612730565b505b6010546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156114b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114dd9190612730565b90508481101561150057604051632ca2f52b60e11b815260040160405180910390fd5b60408051600880825261012082019092526000916020820161010080368337019050509050818160016001600160801b03168151811061154257611542612749565b6020908102919091010152601054611584906001600160a01b03167f000000000000000000000000000000000000000000000000000000000000000084611d67565b600061158f82611df1565b905080600e60008282546115a391906127e8565b909155506115b2905081611e85565b5050505050505050565b60006115c7836119e5565b905080600e60008282546115db9190612775565b9091555050604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561164257600080fd5b505af1158015611656573d6000803e3d6000fd5b5050604051630d2680e960e11b8152600481018490526001602482015260006044820181905292507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169150631a4d01d2906064016020604051808303816000875af11580156116d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f69190612730565b601054909150611730906001600160a01b03167f000000000000000000000000000000000000000000000000000000000000000083611d67565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632d62af2f6040518060a001604052806000815260200185815260200160008152602001600081526020016000815250306040518363ffffffff1660e01b81526004016117aa929190612868565b6020604051808303816000875af11580156117c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ed9190612730565b90508381101561181057604051632ca2f52b60e11b815260040160405180910390fd5b60408051600880825261012082019092526000916020820161010080368337019050509050818160006001600160801b03168151811061185257611852612749565b60209081029190910101526118b16001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000084611d67565b60006118bc82611df1565b905080600e60008282546118d091906127e8565b909155506118df905081611e85565b50505050505050565b60006118f48383610b78565b611972576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561192a3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610614565b506000610614565b60006119868383610b78565b15611972576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610614565b600080821180156119fe5750670de0b6b3a76400008211155b611a425760405162461bcd60e51b815260206004820152601560248201527457726f6e6720506f6f6c546f6b656e20526174696f60581b6044820152606401610df9565b670de0b6b3a764000082611a55600e5490565b611a5f919061288e565b61061491906128a5565b604051632e1a7d4d60e01b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015611acb57600080fd5b505af1158015611adf573d6000803e3d6000fd5b505050506106ac838383611f63565b60408051600580825260c082019092526060916020820160a08036833701905050905060005b6005811015611b6657828160058110611b2f57611b2f612749565b6020020151828281518110611b4657611b46612749565b6001600160a01b0390921660209283029190910190910152600101611b14565b50919050565b604080516008808252610120820190925260609160009190602082016101008036833750508451825192935091839150600090611bab57611bab612749565b602090810291909101015292915050565b6000805b6005811015611b6657670de0b6b3a764000060088260058110611be557611be5612749565b0154848360058110611bf957611bf9612749565b6020020151611c2460038560058110611c1457611c14612749565b01546001600160a01b0316612017565b611c2e919061288e565b611c38919061288e565b611c4291906128a5565b611c4c90836127e8565b9150600101611bc0565b600080611c837f000000000000000000000000000000000000000000000000000000000000000084612118565b9050611c8e81611df1565b9150611b6682611e85565b6000670de0b6b3a7640000611cac6121c4565b611a5f908461288e565b6000612710600254612710611cac9190612775565b611cd58282610b78565b6107035760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610df9565b6000611d196001600160a01b038416836121ef565b90508051600014158015611d3e575080806020019051810190611d3c91906128c7565b155b156106ac57604051635274afe760e01b81526001600160a01b0384166004820152602401610df9565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015611db7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ddb9190612730565b90506107948484611dec85856127e8565b6121fd565b604051635b96faef60e11b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b72df5de90611e4290859085906004016128e4565b6020604051808303816000875af1158015611e61573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106149190612730565b611ed96001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000083611d67565b6040516307dba22560e31b815230600482015260248101829052600160448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633edd112890606401600060405180830381600087803b158015611f4857600080fd5b505af1158015611f5c573d6000803e3d6000fd5b5050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631a4d01d28683878160200201516040516001600160e01b031960e086901b1681526004810193909352600f9190910b602483015260448201526064016020604051808303816000875af1158015611fec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120109190612730565b9050611f5c565b600d54604051638b2f0f4f60e01b815273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60048201526000916001600160a01b031690638b2f0f4f90602401602060405180830381865afa158015612074573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120989190612730565b600d54604051638b2f0f4f60e01b81526001600160a01b03858116600483015290911690638b2f0f4f90602401602060405180830381865afa1580156120e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121069190612730565b611a5f90670de0b6b3a764000061288e565b60408051600880825261012082019092526060916000919060208201610100803683375050845182519293509183915060009061215757612157612749565b602002602001018181525050610adb848260006001600160801b03168151811061218357612183612749565b60200260200101517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611d679092919063ffffffff16565b6000610d967f0000000000000000000000000000000000000000000000000000000000000000612017565b6060610adb8383600061228d565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261224e848261232a565b610794576040516001600160a01b0384811660248301526000604483015261228391869182169063095ea7b390606401610e7b565b6107948482611d04565b6060814710156122b25760405163cd78605960e01b8152306004820152602401610df9565b600080856001600160a01b031684866040516122ce9190612906565b60006040518083038185875af1925050503d806000811461230b576040519150601f19603f3d011682016040523d82523d6000602084013e612310565b606091505b50915091506123208683836123d2565b9695505050505050565b6000806000846001600160a01b0316846040516123479190612906565b6000604051808303816000865af19150503d8060008114612384576040519150601f19603f3d011682016040523d82523d6000602084013e612389565b606091505b50915091508180156123b35750805115806123b35750808060200190518101906123b391906128c7565b80156123c957506000856001600160a01b03163b115b95945050505050565b6060826123e7576123e28261242e565b610adb565b81511580156123fe57506001600160a01b0384163b155b1561242757604051639996b31560e01b81526001600160a01b0385166004820152602401610df9565b5080610adb565b80511561243e5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60006020828403121561246957600080fd5b81356001600160e01b031981168114610adb57600080fd5b6001600160a01b0381168114610b7557600080fd5b6000602082840312156124a857600080fd5b8135610adb81612481565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156124f2576124f26124b3565b604052919050565b6000806040838503121561250d57600080fd5b823561251881612481565b915060208381013567ffffffffffffffff8082111561253657600080fd5b818601915086601f83011261254a57600080fd5b81358181111561255c5761255c6124b3565b8060051b915061256d8483016124c9565b818152918301840191848101908984111561258757600080fd5b938501935b838510156125b157843592506125a183612481565b828252938501939085019061258c565b8096505050505050509250929050565b6000602082840312156125d357600080fd5b5035919050565b600080604083850312156125ed57600080fd5b50508035926020909101359150565b6000806040838503121561260f57600080fd5b82359150602083013561262181612481565b809150509250929050565b600082601f83011261263d57600080fd5b60405160a0810181811067ffffffffffffffff82111715612660576126606124b3565b6040528060a084018581111561267557600080fd5b845b8181101561268f578035835260209283019201612677565b509195945050505050565b600080600060e084860312156126af57600080fd5b83356126ba81612481565b9250602084013591506126d0856040860161262c565b90509250925092565b600060a082840312156126eb57600080fd5b610adb838361262c565b8015158114610b7557600080fd5b60008060c0838503121561271657600080fd5b612720848461262c565b915060a0830135612621816126f5565b60006020828403121561274257600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156106145761061461275f565b60008151808452602080850194506020840160005b838110156127b95781518752958201959082019060010161279d565b509495945050505050565b6040815260006127d76040830185612788565b905082151560208301529392505050565b808201808211156106145761061461275f565b60006020828403121561280d57600080fd5b8151610adb81612481565b8060005b600581101561079457815184526020938401939091019060010161281c565b83815260e0810161284f6020830185612818565b6001600160a01b039290921660c0919091015292915050565b60c081016128768285612818565b6001600160a01b039290921660a09190910152919050565b80820281158282048414176106145761061461275f565b6000826128c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156128d957600080fd5b8151610adb816126f5565b6040815260006128f76040830185612788565b90508260208301529392505050565b6000825160005b81811015612927576020818601810151858301520161290d565b50600092019182525091905056fea2646970667358221220927a93806e9adc76c8246fe64aaff67e62f6da633a0bfbdef32b3002e942a97f64736f6c63430008170033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102535760003560e01c80636c1516e111610146578063b5326170116100c3578063d547741f11610087578063d547741f14610567578063d5f651a41461043f578063e9ec2e991461057a578063f0fa55a914610582578063f459fff414610595578063fbfa77cf146105bc57600080fd5b8063b5326170146104ff578063b67d611d14610507578063bd38837b1461051a578063c56aa1661461052d578063cbdf382c1461054057600080fd5b806381a7b8941161010a57806381a7b894146104b557806391d14854146104c85780639d57b9a6146104db578063a217fddf146104ee578063ac905114146104f657600080fd5b80636c1516e11461043f5780636d9164c61461044e5780636e76fc8f1461046157806375451b4f146104885780637dc0d1d0146104a257600080fd5b80632e7f237f116101d4578063530e784f11610198578063530e784f146103d7578063550f5c98146103ea57806356edb3161461041157806359615983146104245780636524ee901461043757600080fd5b80632e7f237f1461037a5780632f2ff15d1461039557806336568abe146103a85780633e032a3b146103bb5780634f64b2be146103c457600080fd5b8063213c79d81161021b578063213c79d8146102fe578063248a9ca3146103115780632512226414610334578063258a5f29146103475780632a9383421461036757600080fd5b806301ffc9a714610258578063068acf6c1461028057806310c231c71461029557806316f0115b146102ac5780632026ffa3146102eb575b600080fd5b61026b610266366004612457565b6105e3565b60405190151581526020015b60405180910390f35b61029361028e366004612496565b61061a565b005b61029e600e5481565b604051908152602001610277565b6102d37f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa81565b6040516001600160a01b039091168152602001610277565b6102936102f93660046124fa565b6106b1565b6001546102d3906001600160a01b031681565b61029e61031f3660046125c1565b60009081526020819052604090206001015490565b6102936103423660046125da565b610707565b61034f600081565b6040516001600160801b039091168152602001610277565b6102936103753660046125da565b61073b565b610382600081565b604051600f9190910b8152602001610277565b6102936103a33660046125fc565b61076f565b6102936103b63660046125fc565b61079a565b61029e60025481565b6102d36103d23660046125c1565b6107cd565b6102936103e5366004612496565b6107ed565b6102d37f000000000000000000000000c2e660c62f72c2ad35ace6db78a616215e2f222281565b61029e61041f3660046125c1565b610875565b610293610432366004612496565b61088c565b61034f600181565b61029e670de0b6b3a764000081565b61026b61045c36600461269a565b61090c565b61029e7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a6381565b610490600581565b60405160ff9091168152602001610277565b600d546102d3906001600160a01b031681565b6102936104c33660046126d9565b610ae2565b61026b6104d63660046125fc565b610b78565b61029e6104e9366004612703565b610ba1565b61029e600081565b61029e61271081565b610382600181565b61029e6105153660046126d9565b610c3a565b6011546102d3906001600160a01b031681565b61029361053b366004612496565b610cde565b6102d37f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa81565b6102936105753660046125fc565b610d5e565b61029e610d83565b6102936105903660046125c1565b610d9b565b6102d37f00000000000000000000000054a00da65c79ddce24e7fe4691737fd70f7797df81565b6102d37f000000000000000000000000aae1ae12d4c8b811dda1188b01be23b4ab7c62d281565b60006001600160e01b03198216637965db0b60e01b148061061457506301ffc9a760e01b6001600160e01b03198316145b92915050565b600061062581610e44565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561066c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106909190612730565b905080156106ac576106ac6001600160a01b0384163383610e4e565b505050565b6001546001600160a01b0316336001600160a01b0316146106e5576040516304d6e46b60e31b815260040160405180910390fd5b6106ed610ead565b61070381836106fe60008551610f7d565b610ffc565b5050565b7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a6361073181610e44565b6106ac83836110fd565b7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a6361076581610e44565b6106ac83836115bc565b60008281526020819052604090206001015461078a81610e44565b61079483836118e8565b50505050565b6001600160a01b03811633146107c35760405163334bd91960e11b815260040160405180910390fd5b6106ac828261197a565b600381600581106107dd57600080fd5b01546001600160a01b0316905081565b60006107f881610e44565b6001600160a01b03821661081f5760405163d92e233d60e01b815260040160405180910390fd5b600d80546001600160a01b0319166001600160a01b0384169081179091556040519081527f6536690106168bdf4ba72c128a053d817999b1db90cae23f139b293bf862cb75906020015b60405180910390a15050565b6008816005811061088557600080fd5b0154905081565b600061089781610e44565b6001600160a01b0382166108be5760405163d92e233d60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384169081179091556040519081527ffa639b2012458fd129b4bf30b2a98c9b56cc3a9ba0606013b8d1f9232cb4498a90602001610869565b6001546000906001600160a01b0316336001600160a01b031614610943576040516304d6e46b60e31b815260040160405180910390fd5b600061094e846119e5565b905061095b836000610ba1565b81101561096c576000915050610adb565b60408051600580825260c082019092526000916020820160a08036833701905050905060005b6005811015610a63576000600382600581106109b0576109b0612749565b01546001600160a01b031614610a6357600381600581106109d3576109d3612749565b01546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e9190612730565b828281518110610a5057610a50612749565b6020908102919091010152600101610992565b5081600e6000828254610a769190612775565b90915550610a88905082856000611a69565b6040805160a0810191829052610ad491610acd919060039060059082845b81546001600160a01b03168152600190910190602001808311610aa6575050505050611aee565b8783610ffc565b6001925050505b9392505050565b6001546001600160a01b0316336001600160a01b031614610b16576040516304d6e46b60e31b815260040160405180910390fd5b610b24600e54826001611a69565b6000600e556040805160a0810191829052600380546001600160a01b03168252610b7592610b68929190600590600460208501808311610aa6575050505050611aee565b336106fe60006005610f7d565b50565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60007f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa6001600160a01b0316633db06dd8610bdb85611b6c565b846040518363ffffffff1660e01b8152600401610bf99291906127c4565b602060405180830381865afa158015610c16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610adb9190612730565b6001546000906001600160a01b0316336001600160a01b031614610c71576040516304d6e46b60e31b815260040160405180910390fd5b6000610c7c83611bbc565b90506000610c8984611c56565b905080600e6000828254610c9d91906127e8565b90915550610cac905081611c99565b9250610cb782611cb6565b831015610cd757604051630224f5df60e11b815260040160405180910390fd5b5050919050565b6000610ce981610e44565b6001600160a01b038216610d105760405163d92e233d60e01b815260040160405180910390fd5b601180546001600160a01b0319166001600160a01b0384169081179091556040519081527f18f0ece2d6ea55163aef7a7c841762e706a96c532ed665e8abefaa00d1767fb890602001610869565b600082815260208190526040902060010154610d7981610e44565b610794838361197a565b6000610d96610d91600e5490565b611c99565b905090565b6000610da681610e44565b600082118015610db857506127108211155b610e025760405162461bcd60e51b815260206004820152601660248201527557726f6e6720736c697070616765206e756d6265722160501b60448201526064015b60405180910390fd5b60025460408051918252602082018490527f785f467195f308c252d89e7e85c95a6b7646506ba4774a1dc54e0eedc08e3d43910160405180910390a150600255565b610b758133611ccb565b6040516001600160a01b038381166024830152604482018390526106ac91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611d04565b7f000000000000000000000000aae1ae12d4c8b811dda1188b01be23b4ab7c62d26001600160a01b031663f9a0be686040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2f91906127fb565b6001600160a01b031663e6f1daf26040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610f6957600080fd5b505af1158015610794573d6000803e3d6000fd5b60608167ffffffffffffffff811115610f9857610f986124b3565b604051908082528060200260200182016040528015610fc1578160200160208202803683370190505b50905060005b82811015610ff55783828281518110610fe257610fe2612749565b6020908102919091010152600101610fc7565b5092915050565b60008060005b85518110156110f55785818151811061101d5761101d612749565b6020026020010151915060006001600160a01b0316826001600160a01b031603156110f55783818151811061105457611054612749565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa1580156110a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c79190612730565b6110d19190612775565b925082156110ed576110ed6001600160a01b0383168685610e4e565b600101611002565b505050505050565b6000611108836119e5565b905080600e600082825461111c9190612775565b9091555050604051632e1a7d4d60e01b8152600481018290527f000000000000000000000000aae1ae12d4c8b811dda1188b01be23b4ab7c62d26001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561118357600080fd5b505af1158015611197573d6000803e3d6000fd5b5050604051630d2680e960e11b8152600481018490526000602482018190526044820181905292507f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa6001600160a01b03169150631a4d01d2906064016020604051808303816000875af1158015611213573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112379190612730565b905061128d6001600160a01b037f000000000000000000000000c2e660c62f72c2ad35ace6db78a616215e2f2222167f00000000000000000000000054a00da65c79ddce24e7fe4691737fd70f7797df83611d67565b6040805160a081018252600080825260208201819052818301819052606082018190526080820152905163ca54be3b60e01b81526001600160a01b037f00000000000000000000000054a00da65c79ddce24e7fe4691737fd70f7797df169163ca54be3b91611302918591309060040161283b565b600060405180830381600087803b15801561131c57600080fd5b505af1158015611330573d6000803e3d6000fd5b5050600f546040516370a0823160e01b8152306004820152600093506001600160a01b0390911691506370a0823190602401602060405180830381865afa15801561137f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a39190612730565b9050801561147057601154600f546113c8916001600160a01b03918216911683610e4e565b601154600f546010546001600160a01b0392831692631a378db79281169116846113f181611cb6565b6040516001600160e01b031960e087901b1681526001600160a01b039485166004820152939092166024840152604483015260648201526084016020604051808303816000875af115801561144a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146e9190612730565b505b6010546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156114b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114dd9190612730565b90508481101561150057604051632ca2f52b60e11b815260040160405180910390fd5b60408051600880825261012082019092526000916020820161010080368337019050509050818160016001600160801b03168151811061154257611542612749565b6020908102919091010152601054611584906001600160a01b03167f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa84611d67565b600061158f82611df1565b905080600e60008282546115a391906127e8565b909155506115b2905081611e85565b5050505050505050565b60006115c7836119e5565b905080600e60008282546115db9190612775565b9091555050604051632e1a7d4d60e01b8152600481018290527f000000000000000000000000aae1ae12d4c8b811dda1188b01be23b4ab7c62d26001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561164257600080fd5b505af1158015611656573d6000803e3d6000fd5b5050604051630d2680e960e11b8152600481018490526001602482015260006044820181905292507f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa6001600160a01b03169150631a4d01d2906064016020604051808303816000875af11580156116d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f69190612730565b601054909150611730906001600160a01b03167f00000000000000000000000054a00da65c79ddce24e7fe4691737fd70f7797df83611d67565b60007f00000000000000000000000054a00da65c79ddce24e7fe4691737fd70f7797df6001600160a01b0316632d62af2f6040518060a001604052806000815260200185815260200160008152602001600081526020016000815250306040518363ffffffff1660e01b81526004016117aa929190612868565b6020604051808303816000875af11580156117c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ed9190612730565b90508381101561181057604051632ca2f52b60e11b815260040160405180910390fd5b60408051600880825261012082019092526000916020820161010080368337019050509050818160006001600160801b03168151811061185257611852612749565b60209081029190910101526118b16001600160a01b037f000000000000000000000000c2e660c62f72c2ad35ace6db78a616215e2f2222167f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa84611d67565b60006118bc82611df1565b905080600e60008282546118d091906127e8565b909155506118df905081611e85565b50505050505050565b60006118f48383610b78565b611972576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561192a3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610614565b506000610614565b60006119868383610b78565b15611972576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610614565b600080821180156119fe5750670de0b6b3a76400008211155b611a425760405162461bcd60e51b815260206004820152601560248201527457726f6e6720506f6f6c546f6b656e20526174696f60581b6044820152606401610df9565b670de0b6b3a764000082611a55600e5490565b611a5f919061288e565b61061491906128a5565b604051632e1a7d4d60e01b8152600481018490527f000000000000000000000000aae1ae12d4c8b811dda1188b01be23b4ab7c62d26001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015611acb57600080fd5b505af1158015611adf573d6000803e3d6000fd5b505050506106ac838383611f63565b60408051600580825260c082019092526060916020820160a08036833701905050905060005b6005811015611b6657828160058110611b2f57611b2f612749565b6020020151828281518110611b4657611b46612749565b6001600160a01b0390921660209283029190910190910152600101611b14565b50919050565b604080516008808252610120820190925260609160009190602082016101008036833750508451825192935091839150600090611bab57611bab612749565b602090810291909101015292915050565b6000805b6005811015611b6657670de0b6b3a764000060088260058110611be557611be5612749565b0154848360058110611bf957611bf9612749565b6020020151611c2460038560058110611c1457611c14612749565b01546001600160a01b0316612017565b611c2e919061288e565b611c38919061288e565b611c4291906128a5565b611c4c90836127e8565b9150600101611bc0565b600080611c837f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa84612118565b9050611c8e81611df1565b9150611b6682611e85565b6000670de0b6b3a7640000611cac6121c4565b611a5f908461288e565b6000612710600254612710611cac9190612775565b611cd58282610b78565b6107035760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610df9565b6000611d196001600160a01b038416836121ef565b90508051600014158015611d3e575080806020019051810190611d3c91906128c7565b155b156106ac57604051635274afe760e01b81526001600160a01b0384166004820152602401610df9565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015611db7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ddb9190612730565b90506107948484611dec85856127e8565b6121fd565b604051635b96faef60e11b81526000906001600160a01b037f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa169063b72df5de90611e4290859085906004016128e4565b6020604051808303816000875af1158015611e61573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106149190612730565b611ed96001600160a01b037f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa167f000000000000000000000000aae1ae12d4c8b811dda1188b01be23b4ab7c62d283611d67565b6040516307dba22560e31b815230600482015260248101829052600160448201527f000000000000000000000000aae1ae12d4c8b811dda1188b01be23b4ab7c62d26001600160a01b031690633edd112890606401600060405180830381600087803b158015611f4857600080fd5b505af1158015611f5c573d6000803e3d6000fd5b5050505050565b6000807f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa6001600160a01b0316631a4d01d28683878160200201516040516001600160e01b031960e086901b1681526004810193909352600f9190910b602483015260448201526064016020604051808303816000875af1158015611fec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120109190612730565b9050611f5c565b600d54604051638b2f0f4f60e01b815273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60048201526000916001600160a01b031690638b2f0f4f90602401602060405180830381865afa158015612074573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120989190612730565b600d54604051638b2f0f4f60e01b81526001600160a01b03858116600483015290911690638b2f0f4f90602401602060405180830381865afa1580156120e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121069190612730565b611a5f90670de0b6b3a764000061288e565b60408051600880825261012082019092526060916000919060208201610100803683375050845182519293509183915060009061215757612157612749565b602002602001018181525050610adb848260006001600160801b03168151811061218357612183612749565b60200260200101517f000000000000000000000000c2e660c62f72c2ad35ace6db78a616215e2f22226001600160a01b0316611d679092919063ffffffff16565b6000610d967f0000000000000000000000003a65cbaebbfecbea5d0cb523ab56fdbda7ff9aaa612017565b6060610adb8383600061228d565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261224e848261232a565b610794576040516001600160a01b0384811660248301526000604483015261228391869182169063095ea7b390606401610e7b565b6107948482611d04565b6060814710156122b25760405163cd78605960e01b8152306004820152602401610df9565b600080856001600160a01b031684866040516122ce9190612906565b60006040518083038185875af1925050503d806000811461230b576040519150601f19603f3d011682016040523d82523d6000602084013e612310565b606091505b50915091506123208683836123d2565b9695505050505050565b6000806000846001600160a01b0316846040516123479190612906565b6000604051808303816000865af19150503d8060008114612384576040519150601f19603f3d011682016040523d82523d6000602084013e612389565b606091505b50915091508180156123b35750805115806123b35750808060200190518101906123b391906128c7565b80156123c957506000856001600160a01b03163b115b95945050505050565b6060826123e7576123e28261242e565b610adb565b81511580156123fe57506001600160a01b0384163b155b1561242757604051639996b31560e01b81526001600160a01b0385166004820152602401610df9565b5080610adb565b80511561243e5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60006020828403121561246957600080fd5b81356001600160e01b031981168114610adb57600080fd5b6001600160a01b0381168114610b7557600080fd5b6000602082840312156124a857600080fd5b8135610adb81612481565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156124f2576124f26124b3565b604052919050565b6000806040838503121561250d57600080fd5b823561251881612481565b915060208381013567ffffffffffffffff8082111561253657600080fd5b818601915086601f83011261254a57600080fd5b81358181111561255c5761255c6124b3565b8060051b915061256d8483016124c9565b818152918301840191848101908984111561258757600080fd5b938501935b838510156125b157843592506125a183612481565b828252938501939085019061258c565b8096505050505050509250929050565b6000602082840312156125d357600080fd5b5035919050565b600080604083850312156125ed57600080fd5b50508035926020909101359150565b6000806040838503121561260f57600080fd5b82359150602083013561262181612481565b809150509250929050565b600082601f83011261263d57600080fd5b60405160a0810181811067ffffffffffffffff82111715612660576126606124b3565b6040528060a084018581111561267557600080fd5b845b8181101561268f578035835260209283019201612677565b509195945050505050565b600080600060e084860312156126af57600080fd5b83356126ba81612481565b9250602084013591506126d0856040860161262c565b90509250925092565b600060a082840312156126eb57600080fd5b610adb838361262c565b8015158114610b7557600080fd5b60008060c0838503121561271657600080fd5b612720848461262c565b915060a0830135612621816126f5565b60006020828403121561274257600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156106145761061461275f565b60008151808452602080850194506020840160005b838110156127b95781518752958201959082019060010161279d565b509495945050505050565b6040815260006127d76040830185612788565b905082151560208301529392505050565b808201808211156106145761061461275f565b60006020828403121561280d57600080fd5b8151610adb81612481565b8060005b600581101561079457815184526020938401939091019060010161281c565b83815260e0810161284f6020830185612818565b6001600160a01b039290921660c0919091015292915050565b60c081016128768285612818565b6001600160a01b039290921660a09190910152919050565b80820281158282048414176106145761061461275f565b6000826128c257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156128d957600080fd5b8151610adb816126f5565b6040815260006128f76040830185612788565b90508260208301529392505050565b6000825160005b81811015612927576020818601810151858301520161290d565b50600092019182525091905056fea2646970667358221220927a93806e9adc76c8246fe64aaff67e62f6da633a0bfbdef32b3002e942a97f64736f6c63430008170033
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.