More Info
Private Name Tags
ContractCreator
TokenTracker
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
MeroTriHopCvx
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-08-12 */ // SPDX-License-Identifier: GPL-3.0-or-later // Sources flattened with hardhat v2.6.1 https://hardhat.org // File @openzeppelin/contracts/token/ERC20/[email protected] // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @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); } // File @openzeppelin/contracts/utils/structs/[email protected] // OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } } // File @openzeppelin/contracts/utils/[email protected] // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File @openzeppelin/contracts/token/ERC20/utils/[email protected] // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; /** * @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; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File libraries/UncheckedMath.sol pragma solidity 0.8.10; library UncheckedMath { function uncheckedInc(uint256 a) internal pure returns (uint256) { unchecked { return a + 1; } } function uncheckedAdd(uint256 a, uint256 b) internal pure returns (uint256) { unchecked { return a + b; } } function uncheckedSub(uint256 a, uint256 b) internal pure returns (uint256) { unchecked { return a - b; } } function uncheckedDiv(uint256 a, uint256 b) internal pure returns (uint256) { unchecked { return a / b; } } } // File contracts/utils/CvxMintAmount.sol pragma solidity 0.8.10; abstract contract CvxMintAmount { using UncheckedMath for uint256; uint256 private constant _CLIFF_SIZE = 100_000e18; //new cliff every 100,000 tokens uint256 private constant _CLIFF_COUNT = 1000; // 1,000 cliffs uint256 private constant _MAX_SUPPLY = 100_000_000e18; //100 mil max supply IERC20 private constant _CVX_TOKEN = IERC20(address(0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B)); // CVX Token function getCvxMintAmount(uint256 crvEarned) public view returns (uint256) { //first get total supply uint256 cvxTotalSupply = _CVX_TOKEN.totalSupply(); //get current cliff uint256 currentCliff = cvxTotalSupply.uncheckedDiv(_CLIFF_SIZE); //if current cliff is under the max if (currentCliff >= _CLIFF_COUNT) return 0; //get remaining cliffs uint256 remaining = _CLIFF_COUNT.uncheckedSub(currentCliff); //multiply ratio of remaining cliffs to total cliffs against amount CRV received uint256 cvxEarned = (crvEarned * remaining) / _CLIFF_COUNT; //double check we have not gone over the max supply uint256 amountTillMax = _MAX_SUPPLY - cvxTotalSupply; if (cvxEarned > amountTillMax) cvxEarned = amountTillMax; return cvxEarned; } } // File interfaces/IRoleManager.sol pragma solidity 0.8.10; interface IRoleManager { event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); function initialize() external; function grantRole(bytes32 role, address account) external; function addGovernor(address newGovernor) external; function renounceGovernance() external; function addGaugeZap(address zap) external; function removeGaugeZap(address zap) external; function revokeRole(bytes32 role, address account) external; function hasRole(bytes32 role, address account) external view returns (bool); function hasAnyRole(bytes32[] memory roles, address account) external view returns (bool); function hasAnyRole( bytes32 role1, bytes32 role2, address account ) external view returns (bool); function hasAnyRole( bytes32 role1, bytes32 role2, bytes32 role3, address account ) external view returns (bool); function getRoleMemberCount(bytes32 role) external view returns (uint256); function getRoleMember(bytes32 role, uint256 index) external view returns (address); } // File libraries/Errors.sol pragma solidity 0.8.10; // solhint-disable private-vars-leading-underscore library Error { string internal constant ADDRESS_WHITELISTED = "address already whitelisted"; string internal constant ADMIN_ALREADY_SET = "admin has already been set once"; string internal constant ADDRESS_NOT_WHITELISTED = "address not whitelisted"; string internal constant ADDRESS_NOT_FOUND = "address not found"; string internal constant CONTRACT_INITIALIZED = "contract can only be initialized once"; string internal constant CONTRACT_PAUSED = "contract is paused"; string internal constant UNAUTHORIZED_PAUSE = "not authorized to pause"; string internal constant INVALID_AMOUNT = "invalid amount"; string internal constant INVALID_INDEX = "invalid index"; string internal constant INVALID_VALUE = "invalid msg.value"; string internal constant INVALID_SENDER = "invalid msg.sender"; string internal constant INVALID_TOKEN = "token address does not match pool's LP token address"; string internal constant INVALID_DECIMALS = "incorrect number of decimals"; string internal constant INVALID_ARGUMENT = "invalid argument"; string internal constant INVALID_PARAMETER_VALUE = "invalid parameter value attempted"; string internal constant INVALID_IMPLEMENTATION = "invalid pool implementation for given coin"; string internal constant INVALID_POOL_IMPLEMENTATION = "invalid pool implementation for given coin"; string internal constant INVALID_LP_TOKEN_IMPLEMENTATION = "invalid LP Token implementation for given coin"; string internal constant INVALID_VAULT_IMPLEMENTATION = "invalid vault implementation for given coin"; string internal constant INVALID_STAKER_VAULT_IMPLEMENTATION = "invalid stakerVault implementation for given coin"; string internal constant INSUFFICIENT_ALLOWANCE = "insufficient allowance"; string internal constant INSUFFICIENT_BALANCE = "insufficient balance"; string internal constant INSUFFICIENT_AMOUNT_OUT = "Amount received less than min amount"; string internal constant PROXY_CALL_FAILED = "proxy call failed"; string internal constant INSUFFICIENT_AMOUNT_IN = "Amount spent more than max amount"; string internal constant ADDRESS_ALREADY_SET = "Address is already set"; string internal constant INSUFFICIENT_STRATEGY_BALANCE = "insufficient strategy balance"; string internal constant INSUFFICIENT_FUNDS_RECEIVED = "insufficient funds received"; string internal constant ADDRESS_DOES_NOT_EXIST = "address does not exist"; string internal constant ADDRESS_FROZEN = "address is frozen"; string internal constant ROLE_EXISTS = "role already exists"; string internal constant CANNOT_REVOKE_ROLE = "cannot revoke role"; string internal constant UNAUTHORIZED_ACCESS = "unauthorized access"; string internal constant SAME_ADDRESS_NOT_ALLOWED = "same address not allowed"; string internal constant SELF_TRANSFER_NOT_ALLOWED = "self-transfer not allowed"; string internal constant ZERO_ADDRESS_NOT_ALLOWED = "zero address not allowed"; string internal constant ZERO_TRANSFER_NOT_ALLOWED = "zero transfer not allowed"; string internal constant THRESHOLD_TOO_HIGH = "threshold is too high, must be under 10"; string internal constant INSUFFICIENT_THRESHOLD = "insufficient threshold"; string internal constant NO_POSITION_EXISTS = "no position exists"; string internal constant POSITION_ALREADY_EXISTS = "position already exists"; string internal constant CANNOT_EXECUTE_IN_SAME_BLOCK = "cannot execute action in same block"; string internal constant PROTOCOL_NOT_FOUND = "protocol not found"; string internal constant TOP_UP_FAILED = "top up failed"; string internal constant SWAP_PATH_NOT_FOUND = "swap path not found"; string internal constant UNDERLYING_NOT_SUPPORTED = "underlying token not supported"; string internal constant NOT_ENOUGH_FUNDS_WITHDRAWN = "not enough funds were withdrawn from the pool"; string internal constant FAILED_TRANSFER = "transfer failed"; string internal constant FAILED_MINT = "mint failed"; string internal constant FAILED_REPAY_BORROW = "repay borrow failed"; string internal constant FAILED_METHOD_CALL = "method call failed"; string internal constant NOTHING_TO_CLAIM = "there is no claimable balance"; string internal constant ERC20_BALANCE_EXCEEDED = "ERC20: transfer amount exceeds balance"; string internal constant INVALID_MINTER = "the minter address of the LP token and the pool address do not match"; string internal constant STAKER_VAULT_EXISTS = "a staker vault already exists for the token"; string internal constant DEADLINE_NOT_ZERO = "deadline must be 0"; string internal constant NOTHING_PENDING = "no pending change to reset"; string internal constant DEADLINE_NOT_SET = "deadline is 0"; string internal constant DEADLINE_NOT_REACHED = "deadline has not been reached yet"; string internal constant DELAY_TOO_SHORT = "delay must be at least 3 days"; string internal constant INSUFFICIENT_UPDATE_BALANCE = "insufficient funds for updating the position"; string internal constant SAME_AS_CURRENT = "value must be different to existing value"; string internal constant NOT_CAPPED = "the pool is not currently capped"; string internal constant ALREADY_CAPPED = "the pool is already capped"; string internal constant ALREADY_SHUTDOWN = "already shutdown"; string internal constant EXCEEDS_DEPOSIT_CAP = "deposit exceeds deposit cap"; string internal constant VALUE_TOO_LOW_FOR_GAS = "value too low to cover gas"; string internal constant NOT_ENOUGH_FUNDS = "not enough funds to withdraw"; string internal constant ESTIMATED_GAS_TOO_HIGH = "too much ETH will be used for gas"; string internal constant GAUGE_KILLED = "gauge killed"; string internal constant INVALID_TARGET = "Invalid Target"; string internal constant DEPOSIT_FAILED = "deposit failed"; string internal constant GAS_TOO_HIGH = "too much ETH used for gas"; string internal constant GAS_BANK_BALANCE_TOO_LOW = "not enough ETH in gas bank to cover gas"; string internal constant INVALID_TOKEN_TO_ADD = "Invalid token to add"; string internal constant INVALID_TOKEN_TO_REMOVE = "token can not be removed"; string internal constant TIME_DELAY_NOT_EXPIRED = "time delay not expired yet"; string internal constant UNDERLYING_NOT_WITHDRAWABLE = "pool does not support additional underlying coins to be withdrawn"; string internal constant STRATEGY_SHUTDOWN = "Strategy is shutdown"; string internal constant POOL_SHUTDOWN = "Pool is shutdown"; string internal constant ACTION_SHUTDOWN = "Action is shutdown"; string internal constant ACTION_PAUSED = "Action is paused"; string internal constant STRATEGY_DOES_NOT_EXIST = "Strategy does not exist"; string internal constant GAUGE_STILL_ACTIVE = "Gauge still active"; string internal constant UNSUPPORTED_UNDERLYING = "Underlying not supported"; string internal constant NO_DEX_SET = "no dex has been set for token"; string internal constant INVALID_TOKEN_PAIR = "invalid token pair"; string internal constant TOKEN_NOT_USABLE = "token not usable for the specific action"; string internal constant ADDRESS_NOT_ACTION = "address is not registered action"; string internal constant ACTION_NOT_ACTIVE = "address is not active action"; string internal constant INVALID_SLIPPAGE_TOLERANCE = "Invalid slippage tolerance"; string internal constant INVALID_MAX_FEE = "invalid max fee"; string internal constant POOL_NOT_PAUSED = "Pool must be paused to withdraw from reserve"; string internal constant INTERACTION_LIMIT = "Max of one deposit and withdraw per block"; string internal constant GAUGE_EXISTS = "Gauge already exists"; string internal constant GAUGE_DOES_NOT_EXIST = "Gauge does not exist"; string internal constant EXCEEDS_MAX_BOOST = "Not allowed to exceed maximum boost on Convex"; string internal constant PREPARED_WITHDRAWAL = "Cannot relock funds when withdrawal is being prepared"; string internal constant ASSET_NOT_SUPPORTED = "Asset not supported"; string internal constant STALE_PRICE = "Price is stale"; string internal constant NEGATIVE_PRICE = "Price is negative"; string internal constant ROUND_NOT_COMPLETE = "Round not complete"; string internal constant NOT_ENOUGH_MERO_STAKED = "Not enough MERO tokens staked"; string internal constant RESERVE_ACCESS_EXCEEDED = "Reserve access exceeded"; } // File libraries/Roles.sol pragma solidity 0.8.10; // solhint-disable private-vars-leading-underscore library Roles { bytes32 internal constant GOVERNANCE = "governance"; bytes32 internal constant ADDRESS_PROVIDER = "address_provider"; bytes32 internal constant POOL_FACTORY = "pool_factory"; bytes32 internal constant CONTROLLER = "controller"; bytes32 internal constant GAUGE_ZAP = "gauge_zap"; bytes32 internal constant MAINTENANCE = "maintenance"; bytes32 internal constant INFLATION_ADMIN = "inflation_admin"; bytes32 internal constant INFLATION_MANAGER = "inflation_manager"; bytes32 internal constant POOL = "pool"; bytes32 internal constant VAULT = "vault"; bytes32 internal constant ACTION = "action"; } // File contracts/access/AuthorizationBase.sol pragma solidity 0.8.10; /** * @notice Provides modifiers for authorization */ abstract contract AuthorizationBase { /** * @notice Only allows a sender with `role` to perform the given action */ modifier onlyRole(bytes32 role) { require(_roleManager().hasRole(role, msg.sender), Error.UNAUTHORIZED_ACCESS); _; } /** * @notice Only allows a sender with GOVERNANCE role to perform the given action */ modifier onlyGovernance() { require(_roleManager().hasRole(Roles.GOVERNANCE, msg.sender), Error.UNAUTHORIZED_ACCESS); _; } /** * @notice Only allows a sender with any of `roles` to perform the given action */ modifier onlyRoles2(bytes32 role1, bytes32 role2) { require(_roleManager().hasAnyRole(role1, role2, msg.sender), Error.UNAUTHORIZED_ACCESS); _; } /** * @notice Only allows a sender with any of `roles` to perform the given action */ modifier onlyRoles3( bytes32 role1, bytes32 role2, bytes32 role3 ) { require( _roleManager().hasAnyRole(role1, role2, role3, msg.sender), Error.UNAUTHORIZED_ACCESS ); _; } function roleManager() external view virtual returns (IRoleManager) { return _roleManager(); } function _roleManager() internal view virtual returns (IRoleManager); } // File contracts/access/Authorization.sol pragma solidity 0.8.10; contract Authorization is AuthorizationBase { IRoleManager internal immutable __roleManager; constructor(IRoleManager roleManager) { __roleManager = roleManager; } function _roleManager() internal view override returns (IRoleManager) { return __roleManager; } } // File libraries/ScaledMath.sol pragma solidity 0.8.10; /* * @dev To use functions of this contract, at least one of the numbers must * be scaled to `DECIMAL_SCALE`. The result will scaled to `DECIMAL_SCALE` * if both numbers are scaled to `DECIMAL_SCALE`, otherwise to the scale * of the number not scaled by `DECIMAL_SCALE` */ library ScaledMath { // solhint-disable-next-line private-vars-leading-underscore uint256 internal constant DECIMAL_SCALE = 1e18; // solhint-disable-next-line private-vars-leading-underscore uint256 internal constant ONE = 1e18; /** * @notice Performs a multiplication between two scaled numbers */ function scaledMul(uint256 a, uint256 b) internal pure returns (uint256) { return (a * b) / DECIMAL_SCALE; } /** * @notice Performs a division between two scaled numbers */ function scaledDiv(uint256 a, uint256 b) internal pure returns (uint256) { return (a * DECIMAL_SCALE) / b; } /** * @notice Performs a division between two numbers, rounding up the result */ function scaledDivRoundUp(uint256 a, uint256 b) internal pure returns (uint256) { return (a * DECIMAL_SCALE + b - 1) / b; } /** * @notice Performs a division between two numbers, ignoring any scaling and rounding up the result */ function divRoundUp(uint256 a, uint256 b) internal pure returns (uint256) { return (a + b - 1) / b; } } // File interfaces/IGasBank.sol pragma solidity 0.8.10; interface IGasBank { event Deposit(address indexed account, uint256 value); event Withdraw(address indexed account, address indexed receiver, uint256 value); function depositFor(address account) external payable; function withdrawUnused(address account) external; function withdrawFrom(address account, uint256 amount) external; function withdrawFrom( address account, address payable to, uint256 amount ) external; function balanceOf(address account) external view returns (uint256); } // File interfaces/IVaultReserve.sol pragma solidity 0.8.10; interface IVaultReserve { event Deposit(address indexed vault, address indexed token, uint256 amount); event Withdraw(address indexed vault, address indexed token, uint256 amount); event VaultListed(address indexed vault); function deposit(address token, uint256 amount) external payable; function withdraw(address token, uint256 amount) external; function getBalance(address vault, address token) external view returns (uint256); function canWithdraw(address vault) external view returns (bool); } // File interfaces/oracles/IOracleProvider.sol pragma solidity 0.8.10; interface IOracleProvider { /// @notice Checks whether the asset is supported /// @param baseAsset the asset of which the price is to be quoted /// @return true if the asset is supported function isAssetSupported(address baseAsset) external view returns (bool); /// @notice Quotes the USD price of `baseAsset` /// @param baseAsset the asset of which the price is to be quoted /// @return the USD price of the asset function getPriceUSD(address baseAsset) external view returns (uint256); /// @notice Quotes the ETH price of `baseAsset` /// @param baseAsset the asset of which the price is to be quoted /// @return the ETH price of the asset function getPriceETH(address baseAsset) external view returns (uint256); } // File interfaces/strategies/IStrategy.sol pragma solidity 0.8.10; interface IStrategy { function deposit() external payable returns (bool); function withdraw(uint256 amount) external returns (bool); function withdrawAll() external returns (uint256); function harvest() external returns (uint256); function shutdown() external; function setCommunityReserve(address _communityReserve) external; function setStrategist(address strategist_) external; function name() external view returns (string memory); function balance() external view returns (uint256); function harvestable() external view returns (uint256); function strategist() external view returns (address); function hasPendingFunds() external view returns (bool); } // File interfaces/IVault.sol pragma solidity 0.8.10; /** * @title Interface for a Vault */ interface IVault { event StrategyActivated(address indexed strategy); event StrategyDeactivated(address indexed strategy); /** * @dev 'netProfit' is the profit after all fees have been deducted */ event Harvest(uint256 indexed netProfit, uint256 indexed loss); function initialize( address _pool, uint256 _debtLimit, uint256 _targetAllocation, uint256 _bound ) external; function withdrawFromStrategyWaitingForRemoval(address strategy) external returns (uint256); function deposit() external payable; function withdraw(uint256 amount) external returns (bool); function withdrawAvailableToPool() external; function initializeStrategy(address strategy_) external; function shutdownStrategy() external; function withdrawFromReserve(uint256 amount) external; function updateStrategy(address newStrategy) external; function activateStrategy() external returns (bool); function deactivateStrategy() external returns (bool); function updatePerformanceFee(uint256 newPerformanceFee) external; function updateStrategistFee(uint256 newStrategistFee) external; function updateDebtLimit(uint256 newDebtLimit) external; function updateTargetAllocation(uint256 newTargetAllocation) external; function updateReserveFee(uint256 newReserveFee) external; function updateBound(uint256 newBound) external; function withdrawFromStrategy(uint256 amount) external returns (bool); function withdrawAllFromStrategy() external returns (bool); function harvest() external returns (bool); function getStrategiesWaitingForRemoval() external view returns (address[] memory); function getAllocatedToStrategyWaitingForRemoval(address strategy) external view returns (uint256); function getTotalUnderlying() external view returns (uint256); function getUnderlying() external view returns (address); function strategy() external view returns (IStrategy); } // File interfaces/IStakerVault.sol pragma solidity 0.8.10; interface IStakerVault { event Staked(address indexed account, uint256 amount); event Unstaked(address indexed account, uint256 amount); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); function initialize(address _token) external; function initializeLpGauge(address _lpGauge) external; function stake(uint256 amount) external; function stakeFor(address account, uint256 amount) external; function unstake(uint256 amount) external; function unstakeFor( address src, address dst, uint256 amount ) external; function approve(address spender, uint256 amount) external; function transfer(address account, uint256 amount) external; function transferFrom( address src, address dst, uint256 amount ) external; function increaseActionLockedBalance(address account, uint256 amount) external; function decreaseActionLockedBalance(address account, uint256 amount) external; function updateLpGauge(address _lpGauge) external; function poolCheckpoint() external returns (bool); function poolCheckpoint(uint256 updateEndTime) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function getToken() external view returns (address); function balanceOf(address account) external view returns (uint256); function stakedAndActionLockedBalanceOf(address account) external view returns (uint256); function actionLockedBalanceOf(address account) external view returns (uint256); function getStakedByActions() external view returns (uint256); function getPoolTotalStaked() external view returns (uint256); function decimals() external view returns (uint8); function lpGauge() external view returns (address); } // File interfaces/pool/ILiquidityPool.sol pragma solidity 0.8.10; interface ILiquidityPool { event Deposit(address indexed minter, uint256 depositAmount, uint256 mintedLpTokens); event DepositFor( address indexed minter, address indexed mintee, uint256 depositAmount, uint256 mintedLpTokens ); event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens); event LpTokenSet(address indexed lpToken); event StakerVaultSet(address indexed stakerVault); event Shutdown(); function redeem(uint256 redeemTokens) external returns (uint256); function redeem(uint256 redeemTokens, uint256 minRedeemAmount) external returns (uint256); function calcRedeem(address account, uint256 underlyingAmount) external returns (uint256); function deposit(uint256 mintAmount) external payable returns (uint256); function deposit(uint256 mintAmount, uint256 minTokenAmount) external payable returns (uint256); function depositAndStake(uint256 depositAmount, uint256 minTokenAmount) external payable returns (uint256); function depositFor(address account, uint256 depositAmount) external payable returns (uint256); function depositFor( address account, uint256 depositAmount, uint256 minTokenAmount ) external payable returns (uint256); function unstakeAndRedeem(uint256 redeemLpTokens, uint256 minRedeemAmount) external returns (uint256); function handleLpTokenTransfer( address from, address to, uint256 amount ) external; function updateVault(address _vault) external; function setLpToken(address _lpToken) external; function setStaker() external; function shutdownPool(bool shutdownStrategy) external; function shutdownStrategy() external; function updateRequiredReserves(uint256 _newRatio) external; function updateReserveDeviation(uint256 newRatio) external; function updateMinWithdrawalFee(uint256 newFee) external; function updateMaxWithdrawalFee(uint256 newFee) external; function updateWithdrawalFeeDecreasePeriod(uint256 newPeriod) external; function rebalanceVault() external; function getNewCurrentFees( uint256 timeToWait, uint256 lastActionTimestamp, uint256 feeRatio ) external view returns (uint256); function vault() external view returns (IVault); function staker() external view returns (IStakerVault); function getUnderlying() external view returns (address); function getLpToken() external view returns (address); function getWithdrawalFee(address account, uint256 amount) external view returns (uint256); function exchangeRate() external view returns (uint256); function totalUnderlying() external view returns (uint256); function name() external view returns (string memory); function isShutdown() external view returns (bool); } // File libraries/AddressProviderMeta.sol pragma solidity 0.8.10; library AddressProviderMeta { struct Meta { bool freezable; bool frozen; } function fromUInt(uint256 value) internal pure returns (Meta memory) { Meta memory meta; meta.freezable = (value & 1) == 1; meta.frozen = ((value >> 1) & 1) == 1; return meta; } function toUInt(Meta memory meta) internal pure returns (uint256) { uint256 value; value |= meta.freezable ? 1 : 0; value |= meta.frozen ? 1 << 1 : 0; return value; } } // File interfaces/IAddressProvider.sol pragma solidity 0.8.10; // solhint-disable ordering interface IAddressProvider { event KnownAddressKeyAdded(bytes32 indexed key); event StakerVaultListed(address indexed stakerVault); event StakerVaultDelisted(address indexed stakerVault); event ActionListed(address indexed action); event ActionShutdown(address indexed action); event PoolListed(address indexed pool); event VaultUpdated(address indexed previousVault, address indexed newVault); event FeeHandlerAdded(address feeHandler); event FeeHandlerRemoved(address feeHandler); /** Key functions */ function getKnownAddressKeys() external view returns (bytes32[] memory); function freezeAddress(bytes32 key) external; /** Pool functions */ function allPools() external view returns (address[] memory); function addPool(address pool) external; function poolsCount() external view returns (uint256); function getPoolAtIndex(uint256 index) external view returns (address); function isPool(address pool) external view returns (bool); function getPoolForToken(address token) external view returns (ILiquidityPool); function safeGetPoolForToken(address token) external view returns (address); /** Vault functions */ function updateVault(address previousVault, address newVault) external; function allVaults() external view returns (address[] memory); function vaultsCount() external view returns (uint256); function getVaultAtIndex(uint256 index) external view returns (address); function isVault(address vault) external view returns (bool); /** Action functions */ function allActions() external view returns (address[] memory); function actionsCount() external view returns (uint256); function getActionAtIndex(uint256 index) external view returns (address); function allActiveActions() external view returns (address[] memory); function addAction(address action) external returns (bool); function shutdownAction(address action) external; function isAction(address action) external view returns (bool); function isActiveAction(address action) external view returns (bool); /** Address functions */ function initialize(address roleManager_, address treasury_) external; function initializeAddress(bytes32 key, address initialAddress) external; function initializeAddress( bytes32 key, address initialAddress, bool frezable ) external; function initializeAndFreezeAddress(bytes32 key, address initialAddress) external; function getAddress(bytes32 key) external view returns (address); function getAddress(bytes32 key, bool checkExists) external view returns (address); function getAddressMeta(bytes32 key) external view returns (AddressProviderMeta.Meta memory); function updateAddress(bytes32 key, address newAddress) external; function initializeInflationManager(address initialAddress) external; /** Staker vault functions */ function allStakerVaults() external view returns (address[] memory); function tryGetStakerVault(address token) external view returns (bool, address); function getStakerVault(address token) external view returns (address); function addStakerVault(address stakerVault) external; function isStakerVault(address stakerVault, address token) external view returns (bool); function isStakerVaultRegistered(address stakerVault) external view returns (bool); function isWhiteListedFeeHandler(address feeHandler) external view returns (bool); /** Fee Handler function */ function addFeeHandler(address feeHandler) external; function removeFeeHandler(address feeHandler) external; } // File interfaces/IFeeBurner.sol pragma solidity 0.8.10; interface IFeeBurner { function burnToTarget(address[] memory tokens, address targetLpToken) external payable returns (uint256); } // File interfaces/tokenomics/IMeroToken.sol pragma solidity 0.8.10; interface IMeroToken is IERC20 { function mint(address account, uint256 amount) external; function cap() external view returns (uint256); } // File interfaces/actions/IAction.sol pragma solidity 0.8.10; interface IAction { event UsableTokenAdded(address token); event UsableTokenRemoved(address token); event Paused(); event Unpaused(); event Shutdown(); function addUsableToken(address token) external; function removeUsableToken(address token) external; function updateActionFee(uint256 actionFee) external; function updateFeeHandler(address feeHandler) external; function shutdownAction() external; function pause() external; function unpause() external; function getEthRequiredForGas(address payer) external view returns (uint256); function getUsableTokens() external view returns (address[] memory); function isUsable(address token) external view returns (bool); function feeHandler() external view returns (address); function isShutdown() external view returns (bool); function isPaused() external view returns (bool); } // File interfaces/tokenomics/IInflationManager.sol pragma solidity 0.8.10; interface IInflationManager { event KeeperGaugeListed(address indexed pool, address indexed keeperGauge); event AmmGaugeListed(address indexed token, address indexed ammGauge); event KeeperGaugeDelisted(address indexed pool, address indexed keeperGauge); event AmmGaugeDelisted(address indexed token, address indexed ammGauge); /** Pool functions */ function setKeeperGauge(address pool, address _keeperGauge) external returns (bool); function setAmmGauge(address token, address _ammGauge) external returns (bool); function setMinter(address _minter) external; function advanceKeeperGaugeEpoch(address pool) external; function whitelistGauge(address gauge) external; function removeStakerVaultFromInflation(address lpToken) external; function removeAmmGauge(address token) external returns (bool); function addGaugeForVault(address lpToken) external; function checkpointAllGauges(uint256 updateEndTime) external; function mintRewards(address beneficiary, uint256 amount) external; function checkPointInflation() external; function removeKeeperGauge(address pool) external; function getAllAmmGauges() external view returns (address[] memory); function getLpRateForStakerVault(address stakerVault) external view returns (uint256); function getKeeperRateForPool(address pool) external view returns (uint256); function getAmmRateForToken(address token) external view returns (uint256); function getLpPoolWeight(address pool) external view returns (uint256); function getKeeperGaugeForPool(address pool) external view returns (address); function getAmmGaugeForToken(address token) external view returns (address); function gauges(address lpToken) external view returns (bool); function ammWeights(address gauge) external view returns (uint256); function lpPoolWeights(address gauge) external view returns (uint256); function keeperPoolWeights(address gauge) external view returns (uint256); function minter() external view returns (address); function weightBasedKeeperDistributionDeactivated() external view returns (bool); function totalKeeperPoolWeight() external view returns (uint256); function totalLpPoolWeight() external view returns (uint256); function totalAmmTokenWeight() external view returns (uint256); /** Weight setter functions **/ function updateLpPoolWeight(address lpToken, uint256 newPoolWeight) external; function updateAmmTokenWeight(address token, uint256 newTokenWeight) external; function updateKeeperPoolWeight(address pool, uint256 newPoolWeight) external; function batchUpdateLpPoolWeights(address[] calldata lpTokens, uint256[] calldata weights) external; function batchUpdateAmmTokenWeights(address[] calldata tokens, uint256[] calldata weights) external; function batchUpdateKeeperPoolWeights(address[] calldata pools, uint256[] calldata weights) external; function deactivateWeightBasedKeeperDistribution() external; } // File interfaces/IController.sol pragma solidity 0.8.10; // solhint-disable ordering interface IController { function addressProvider() external view returns (IAddressProvider); function addStakerVault(address stakerVault) external; function shutdownPool(ILiquidityPool pool, bool shutdownStrategy) external returns (bool); function shutdownAction(IAction action) external; /** Keeper functions */ function updateKeeperRequiredStakedMERO(uint256 amount) external; function canKeeperExecuteAction(address keeper) external view returns (bool); function keeperRequireStakedMero() external view returns (uint256); /** Miscellaneous functions */ function getTotalEthRequiredForGas(address payer) external view returns (uint256); } // File interfaces/ISwapperRouter.sol pragma solidity 0.8.10; interface ISwapperRouter { function swapAll(address fromToken, address toToken) external payable returns (uint256); function setSlippageTolerance(uint256 slippageTolerance_) external; function setCurvePool(address token_, address curvePool_) external; function swap( address fromToken, address toToken, uint256 amountIn ) external payable returns (uint256); function getAmountOut( address fromToken, address toToken, uint256 amountIn ) external view returns (uint256 amountOut); } // File libraries/AddressProviderKeys.sol pragma solidity 0.8.10; library AddressProviderKeys { bytes32 internal constant _TREASURY_KEY = "treasury"; bytes32 internal constant _REWARD_HANDLER_KEY = "rewardHandler"; bytes32 internal constant _GAS_BANK_KEY = "gasBank"; bytes32 internal constant _VAULT_RESERVE_KEY = "vaultReserve"; bytes32 internal constant _ORACLE_PROVIDER_KEY = "oracleProvider"; bytes32 internal constant _POOL_FACTORY_KEY = "poolFactory"; bytes32 internal constant _CONTROLLER_KEY = "controller"; bytes32 internal constant _MERO_LOCKER_KEY = "meroLocker"; bytes32 internal constant _INFLATION_MANAGER_KEY = "inflationManager"; bytes32 internal constant _FEE_BURNER_KEY = "feeBurner"; bytes32 internal constant _ROLE_MANAGER_KEY = "roleManager"; bytes32 internal constant _SWAPPER_ROUTER_KEY = "swapperRouter"; } // File libraries/AddressProviderHelpers.sol pragma solidity 0.8.10; library AddressProviderHelpers { /** * @return The address of the treasury. */ function getTreasury(IAddressProvider provider) internal view returns (address) { return provider.getAddress(AddressProviderKeys._TREASURY_KEY); } /** * @return The address of the reward handler. */ function getRewardHandler(IAddressProvider provider) internal view returns (address) { return provider.getAddress(AddressProviderKeys._REWARD_HANDLER_KEY); } /** * @dev Returns zero address if no reward handler is set. * @return The address of the reward handler. */ function getSafeRewardHandler(IAddressProvider provider) internal view returns (address) { return provider.getAddress(AddressProviderKeys._REWARD_HANDLER_KEY, false); } /** * @return The address of the fee burner. */ function getFeeBurner(IAddressProvider provider) internal view returns (IFeeBurner) { return IFeeBurner(provider.getAddress(AddressProviderKeys._FEE_BURNER_KEY)); } /** * @return The gas bank. */ function getGasBank(IAddressProvider provider) internal view returns (IGasBank) { return IGasBank(provider.getAddress(AddressProviderKeys._GAS_BANK_KEY)); } /** * @return The address of the vault reserve. */ function getVaultReserve(IAddressProvider provider) internal view returns (IVaultReserve) { return IVaultReserve(provider.getAddress(AddressProviderKeys._VAULT_RESERVE_KEY)); } /** * @return The oracleProvider. */ function getOracleProvider(IAddressProvider provider) internal view returns (IOracleProvider) { return IOracleProvider(provider.getAddress(AddressProviderKeys._ORACLE_PROVIDER_KEY)); } /** * @return the address of the MERO locker */ function getMEROLocker(IAddressProvider provider) internal view returns (address) { return provider.getAddress(AddressProviderKeys._MERO_LOCKER_KEY); } /** * @return the address of the MERO locker */ function getRoleManager(IAddressProvider provider) internal view returns (IRoleManager) { return IRoleManager(provider.getAddress(AddressProviderKeys._ROLE_MANAGER_KEY)); } /** * @return the controller */ function getController(IAddressProvider provider) internal view returns (IController) { return IController(provider.getAddress(AddressProviderKeys._CONTROLLER_KEY)); } /** * @return the inflation manager */ function getInflationManager(IAddressProvider provider) internal view returns (IInflationManager) { return IInflationManager(provider.getAddress(AddressProviderKeys._INFLATION_MANAGER_KEY)); } /** * @return the inflation manager or `address(0)` if it does not exist */ function safeGetInflationManager(IAddressProvider provider) internal view returns (IInflationManager) { return IInflationManager( provider.getAddress(AddressProviderKeys._INFLATION_MANAGER_KEY, false) ); } /** * @return the swapper router */ function getSwapperRouter(IAddressProvider provider) internal view returns (ISwapperRouter) { return ISwapperRouter(provider.getAddress(AddressProviderKeys._SWAPPER_ROUTER_KEY)); } } // File libraries/EnumerableMapping.sol pragma solidity 0.8.10; library EnumerableMapping { using EnumerableSet for EnumerableSet.Bytes32Set; // Code take from contracts/utils/structs/EnumerableMap.sol // because the helper functions are private // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Map type with // bytes32 keys and values. // The Map implementation uses private functions, and user-facing // implementations (such as Uint256ToAddressMap) are just wrappers around // the underlying Map. // This means that we can only create new EnumerableMaps for types that fit // in bytes32. struct Map { // Storage of keys EnumerableSet.Bytes32Set _keys; mapping(bytes32 => bytes32) _values; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function _set( Map storage map, bytes32 key, bytes32 value ) private returns (bool) { map._values[key] = value; return map._keys.add(key); } /** * @dev Removes a key-value pair from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function _remove(Map storage map, bytes32 key) private returns (bool) { delete map._values[key]; return map._keys.remove(key); } /** * @dev Returns true if the key is in the map. O(1). */ function _contains(Map storage map, bytes32 key) private view returns (bool) { return map._keys.contains(key); } /** * @dev Returns the number of key-value pairs in the map. O(1). */ function _length(Map storage map) private view returns (uint256) { return map._keys.length(); } /** * @dev Returns the key-value pair stored at position `index` in the map. O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) { bytes32 key = map._keys.at(index); return (key, map._values[key]); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) { bytes32 value = map._values[key]; if (value == bytes32(0)) { return (_contains(map, key), bytes32(0)); } else { return (true, value); } } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function _get(Map storage map, bytes32 key) private view returns (bytes32) { bytes32 value = map._values[key]; require(value != 0 || _contains(map, key), "EnumerableMap: nonexistent key"); return value; } // AddressToAddressMap struct AddressToAddressMap { Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( AddressToAddressMap storage map, address key, address value ) internal returns (bool) { return _set(map._inner, bytes32(uint256(uint160(key))), bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToAddressMap storage map, address key) internal returns (bool) { return _remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToAddressMap storage map, address key) internal view returns (bool) { return _contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToAddressMap storage map) internal view returns (uint256) { return _length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressToAddressMap storage map, uint256 index) internal view returns (address, address) { (bytes32 key, bytes32 value) = _at(map._inner, index); return (address(uint160(uint256(key))), address(uint160(uint256(value)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. * * _Available since v3.4._ */ function tryGet(AddressToAddressMap storage map, address key) internal view returns (bool, address) { (bool success, bytes32 value) = _tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, address(uint160(uint256(value)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToAddressMap storage map, address key) internal view returns (address) { return address(uint160(uint256(_get(map._inner, bytes32(uint256(uint160(key))))))); } // AddressToUintMap struct AddressToUintMap { Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( AddressToUintMap storage map, address key, uint256 value ) internal returns (bool) { return _set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToUintMap storage map, address key) internal returns (bool) { return _remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToUintMap storage map, address key) internal view returns (bool) { return _contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToUintMap storage map) internal view returns (uint256) { return _length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { (bytes32 key, bytes32 value) = _at(map._inner, index); return (address(uint160(uint256(key))), uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. * * _Available since v3.4._ */ function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { (bool success, bytes32 value) = _tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToUintMap storage map, address key) internal view returns (uint256) { return uint256(_get(map._inner, bytes32(uint256(uint160(key))))); } // Bytes32ToUIntMap struct Bytes32ToUIntMap { Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( Bytes32ToUIntMap storage map, bytes32 key, uint256 value ) internal returns (bool) { return _set(map._inner, key, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToUIntMap storage map, bytes32 key) internal returns (bool) { return _remove(map._inner, key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToUIntMap storage map, bytes32 key) internal view returns (bool) { return _contains(map._inner, key); } /** * @dev Returns the number of elements in the map. O(1). */ function length(Bytes32ToUIntMap storage map) internal view returns (uint256) { return _length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToUIntMap storage map, uint256 index) internal view returns (bytes32, uint256) { (bytes32 key, bytes32 value) = _at(map._inner, index); return (key, uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. * * _Available since v3.4._ */ function tryGet(Bytes32ToUIntMap storage map, bytes32 key) internal view returns (bool, uint256) { (bool success, bytes32 value) = _tryGet(map._inner, key); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToUIntMap storage map, bytes32 key) internal view returns (uint256) { return uint256(_get(map._inner, key)); } } // File libraries/EnumerableExtensions.sol pragma solidity 0.8.10; library EnumerableExtensions { using EnumerableSet for EnumerableSet.AddressSet; using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableMapping for EnumerableMapping.AddressToAddressMap; using EnumerableMapping for EnumerableMapping.AddressToUintMap; using EnumerableMapping for EnumerableMapping.Bytes32ToUIntMap; function toArray(EnumerableSet.AddressSet storage addresses) internal view returns (address[] memory) { uint256 len = addresses.length(); address[] memory result = new address[](len); for (uint256 i; i < len; ) { result[i] = addresses.at(i); unchecked { ++i; } } return result; } function toArray(EnumerableSet.Bytes32Set storage values) internal view returns (bytes32[] memory) { uint256 len = values.length(); bytes32[] memory result = new bytes32[](len); for (uint256 i; i < len; ) { result[i] = values.at(i); unchecked { ++i; } } return result; } function keyAt(EnumerableMapping.AddressToAddressMap storage map, uint256 index) internal view returns (address) { (address key, ) = map.at(index); return key; } function valueAt(EnumerableMapping.AddressToAddressMap storage map, uint256 index) internal view returns (address) { (, address value) = map.at(index); return value; } function keyAt(EnumerableMapping.AddressToUintMap storage map, uint256 index) internal view returns (address) { (address key, ) = map.at(index); return key; } function keyAt(EnumerableMapping.Bytes32ToUIntMap storage map, uint256 index) internal view returns (bytes32) { (bytes32 key, ) = map.at(index); return key; } function valueAt(EnumerableMapping.AddressToUintMap storage map, uint256 index) internal view returns (uint256) { (, uint256 value) = map.at(index); return value; } function keysArray(EnumerableMapping.AddressToAddressMap storage map) internal view returns (address[] memory) { uint256 len = map.length(); address[] memory result = new address[](len); for (uint256 i; i < len; ) { result[i] = keyAt(map, i); unchecked { ++i; } } return result; } function valuesArray(EnumerableMapping.AddressToAddressMap storage map) internal view returns (address[] memory) { uint256 len = map.length(); address[] memory result = new address[](len); for (uint256 i; i < len; ) { result[i] = valueAt(map, i); unchecked { ++i; } } return result; } function keysArray(EnumerableMapping.AddressToUintMap storage map) internal view returns (address[] memory) { uint256 len = map.length(); address[] memory result = new address[](len); for (uint256 i; i < len; ) { result[i] = keyAt(map, i); unchecked { ++i; } } return result; } function keysArray(EnumerableMapping.Bytes32ToUIntMap storage map) internal view returns (bytes32[] memory) { uint256 len = map.length(); bytes32[] memory result = new bytes32[](len); for (uint256 i; i < len; ) { result[i] = keyAt(map, i); unchecked { ++i; } } return result; } } // File interfaces/strategies/IConvexStrategyBase.sol pragma solidity 0.8.10; interface IConvexStrategyBase is IStrategy { function setCrvCommunityReserveShare(uint256 crvCommunityReserveShare_) external; function setCvxCommunityReserveShare(uint256 cvxCommunityReserveShare_) external; function setImbalanceToleranceIn(uint256 imbalanceToleranceIn_) external; function setImbalanceToleranceOut(uint256 imbalanceToleranceOut_) external; function addRewardToken(address token_) external returns (bool); function removeRewardToken(address token_) external returns (bool); function rewardTokens() external view returns (address[] memory); } // File interfaces/vendor/IBooster.sol pragma solidity 0.8.10; interface IBooster { /** * @dev `_pid` is the ID of the Convex for a specific Curve LP token. */ function deposit( uint256 _pid, uint256 _amount, bool _stake ) external returns (bool); function withdraw(uint256 _pid, uint256 _amount) external returns (bool); function withdrawAll(uint256 _pid) external returns (bool); function withdrawTo( uint256 _pid, uint256 _amount, address _to ) external returns (bool); function depositAll(uint256 _pid, bool _stake) external returns (bool); function poolInfo(uint256 pid) external view returns ( address lpToken, address token, address gauge, address crvRewards, address stash, bool shutdown ); } // File interfaces/vendor/IRewardStaking.sol pragma solidity 0.8.10; interface IRewardStaking { function stakeFor(address, uint256) external; function stake(uint256) external; function stakeAll() external returns (bool); function withdraw(uint256 amount, bool claim) external returns (bool); function withdrawAndUnwrap(uint256 amount, bool claim) external returns (bool); function earned(address account) external view returns (uint256); function getReward() external; function getReward(address _account, bool _claimExtras) external; function extraRewardsLength() external view returns (uint256); function extraRewards(uint256 _pid) external view returns (address); function rewardToken() external view returns (address); function balanceOf(address account) external view returns (uint256); } // File interfaces/vendor/ICurveSwapEth.sol pragma solidity 0.8.10; interface ICurveSwapEth { function get_virtual_price() external view returns (uint256); function add_liquidity(uint256[2] calldata amounts, uint256 min_mint_amount) external payable; function add_liquidity(uint256[3] calldata amounts, uint256 min_mint_amount) external payable; function remove_liquidity_imbalance(uint256[3] calldata amounts, uint256 max_burn_amount) external; function remove_liquidity_imbalance(uint256[2] calldata amounts, uint256 max_burn_amount) external; function remove_liquidity(uint256 _amount, uint256[3] calldata min_amounts) external; function exchange( uint256 i, uint256 j, uint256 dx, uint256 min_dy ) external payable; function coins(uint256 i) external view returns (address); function get_dy( uint256 i, uint256 j, uint256 dx ) external view returns (uint256); function calc_token_amount(uint256[3] calldata amounts, bool deposit) external view returns (uint256); function calc_token_amount(uint256[2] calldata amounts, bool deposit) external view returns (uint256); function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external view returns (uint256); function remove_liquidity_one_coin( uint256 _token_amount, int128 i, uint256 min_amount ) external; } // File interfaces/vendor/ICurveRegistry.sol pragma solidity 0.8.10; interface ICurveRegistry { function get_A(address curvePool_) external view returns (uint256); } // File contracts/strategies/ConvexStrategyBase.sol pragma solidity 0.8.10; abstract contract ConvexStrategyBase is IConvexStrategyBase, Authorization, CvxMintAmount { using ScaledMath for uint256; using UncheckedMath for uint256; using SafeERC20 for IERC20; using EnumerableSet for EnumerableSet.AddressSet; using EnumerableExtensions for EnumerableSet.AddressSet; using AddressProviderHelpers for IAddressProvider; IBooster internal constant _BOOSTER = IBooster(0xF403C135812408BFbE8713b5A23a04b3D48AAE31); // Convex Booster Contract IERC20 internal constant _CRV = IERC20(0xD533a949740bb3306d119CC777fa900bA034cd52); // CRV IERC20 internal constant _CVX = IERC20(0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B); // CVX IERC20 internal constant _WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); // WETH ICurveRegistry internal constant _CURVE_REGISTRY = ICurveRegistry(0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5); // Curve Registry Contract address internal constant _CURVE_ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); // Null Address used for Curve ETH pools IAddressProvider internal immutable _addressProvider; // Address Provider, used for getting Swapper Router address internal _strategist; // The strategist for the strategy EnumerableSet.AddressSet internal _rewardTokens; // List of additional reward tokens when claiming rewards on Convex IERC20 public underlying; // Strategy Underlying bool public isShutdown; // If the strategy is shutdown, stops all deposits address public communityReserve; // Address for sending CVX & CRV Community Reserve share address public immutable vault; // Mero Vault uint256 public crvCommunityReserveShare; // Share of CRV sent to Community Reserve uint256 public cvxCommunityReserveShare; // Share of CVX sent to Community Reserve uint256 public imbalanceToleranceIn; // Maximum allowed slippage from Curve Pool Imbalance for depositing uint256 public imbalanceToleranceOut; // Maximum allowed slippage from Curve Pool Imbalance for withdrawing IRewardStaking public rewards; // Rewards Contract for claiming Convex Rewards IERC20 public lp; // Curve Pool LP Token ICurveSwapEth public curvePool; // Curve Pool uint256 public convexPid; // Index of Convex Pool in Booster Contract uint256 public curveIndex; // Underlying index in Curve Pool event Deposit(); // Emitted after a successfull deposit event Withdraw(uint256 amount); // Emitted after a successful withdrawal event WithdrawAll(uint256 amount); // Emitted after successfully withdrwaing all event Shutdown(); // Emitted after a successful shutdown event SetCommunityReserve(address reserve); // Emitted after a successful setting of reserve event SetCrvCommunityReserveShare(uint256 value); // Emitted after a successful setting of CRV Community Reserve Share event SetCvxCommunityReserveShare(uint256 value); // Emitted after a successful setting of CVX Community Reserve Share event SetImbalanceToleranceIn(uint256 value); // Emitted after a successful setting of imbalance tolerance in event SetImbalanceToleranceOut(uint256 value); // Emitted after a successful setting of imbalance tolerance out event SetStrategist(address strategist); // Emitted after a successful setting of strategist event AddRewardToken(address token); // Emitted after successfully adding a new reward token event RemoveRewardToken(address token); // Emitted after successfully removing a reward token event Harvest(uint256 amount); // Emitted after a successful harvest modifier onlyVault() { require(msg.sender == vault, Error.UNAUTHORIZED_ACCESS); _; } constructor( address vault_, address strategist_, uint256 convexPid_, address curvePool_, uint256 curveIndex_, IAddressProvider addressProvider_ ) Authorization(addressProvider_.getRoleManager()) { // Getting data from supporting contracts _validateCurvePool(curvePool_); (address lp_, , , address rewards_, , bool shutdown_) = _BOOSTER.poolInfo(convexPid_); require(!shutdown_, Error.POOL_SHUTDOWN); lp = IERC20(lp_); rewards = IRewardStaking(rewards_); curvePool = ICurveSwapEth(curvePool_); address underlying_ = ICurveSwapEth(curvePool_).coins(curveIndex_); if (underlying_ == _CURVE_ETH_ADDRESS) underlying_ = address(0); underlying = IERC20(underlying_); // Setting inputs vault = vault_; _strategist = strategist_; convexPid = convexPid_; curveIndex = curveIndex_; _addressProvider = addressProvider_; ISwapperRouter swapperRouter_ = addressProvider_.getSwapperRouter(); // Approvals _CRV.safeApprove(address(swapperRouter_), type(uint256).max); _CVX.safeApprove(address(swapperRouter_), type(uint256).max); _WETH.safeApprove(address(swapperRouter_), type(uint256).max); } /** * @notice Deposit all available underlying into Convex pool. * @return True if successful deposit. */ function deposit() external payable override onlyVault returns (bool) { require(!isShutdown, Error.STRATEGY_SHUTDOWN); if (!_deposit()) return false; emit Deposit(); } /** * @notice Withdraw an amount of underlying to the vault. * @dev This can only be called by the vault. * If the amount is not available, it will be made liquid. * @param amount_ Amount of underlying to withdraw. * @return True if successful withdrawal. */ function withdraw(uint256 amount_) external override onlyVault returns (bool) { if (amount_ == 0) return false; _withdraw(amount_); emit Withdraw(amount_); return true; } /** * @notice Withdraw all underlying. * @dev This does not liquidate reward tokens and only considers * idle underlying, idle lp tokens and staked lp tokens. * @return Amount of underlying withdrawn */ function withdrawAll() external override returns (uint256) { require(msg.sender == vault, Error.UNAUTHORIZED_ACCESS); uint256 amountWithdrawn_ = _withdrawAll(); if (amountWithdrawn_ == 0) return 0; emit WithdrawAll(amountWithdrawn_); return amountWithdrawn_; } /** * @notice Harvests reward tokens and sells these for the underlying. * @dev Any underlying harvested is not redeposited by this method. * @return Amount of underlying harvested. */ function harvest() external override onlyVault returns (uint256) { return _harvest(); } /** * @notice Shuts down the strategy, disabling deposits. */ function shutdown() external override onlyVault { require(!isShutdown, Error.STRATEGY_SHUTDOWN); isShutdown = true; emit Shutdown(); } /** * @notice Set the address of the community reserve. * @dev CRV & CVX will be taxed and allocated to the reserve, * such that Mero can participate in governance. * @param _communityReserve Address of the community reserve. */ function setCommunityReserve(address _communityReserve) external override onlyGovernance { require(_communityReserve != address(0), Error.ZERO_ADDRESS_NOT_ALLOWED); communityReserve = _communityReserve; emit SetCommunityReserve(_communityReserve); } /** * @notice Set the share of CRV to send to the Community Reserve. * @param crvCommunityReserveShare_ New fee charged on CRV rewards for governance. */ function setCrvCommunityReserveShare(uint256 crvCommunityReserveShare_) external override onlyGovernance { require(crvCommunityReserveShare_ <= ScaledMath.ONE, Error.INVALID_AMOUNT); require(communityReserve != address(0), "Community reserve must be set"); crvCommunityReserveShare = crvCommunityReserveShare_; emit SetCrvCommunityReserveShare(crvCommunityReserveShare_); } /** * @notice Set the share of CVX to send to the Community Reserve. * @param cvxCommunityReserveShare_ New fee charged on CVX rewards for governance. */ function setCvxCommunityReserveShare(uint256 cvxCommunityReserveShare_) external override onlyGovernance { require(cvxCommunityReserveShare_ <= ScaledMath.ONE, Error.INVALID_AMOUNT); require(communityReserve != address(0), "Community reserve must be set"); cvxCommunityReserveShare = cvxCommunityReserveShare_; emit SetCvxCommunityReserveShare(cvxCommunityReserveShare_); } /** * @notice Set imbalance tolerance for Curve Pool deposits. * @dev Stored as a percent, e.g. 1% would be set as 0.01 * @param imbalanceToleranceIn_ New imbalance tolerance in. */ function setImbalanceToleranceIn(uint256 imbalanceToleranceIn_) external override onlyGovernance { imbalanceToleranceIn = imbalanceToleranceIn_; emit SetImbalanceToleranceIn(imbalanceToleranceIn_); } /** * @notice Set imbalance tolerance for Curve Pool withdrawals. * @dev Stored as a percent, e.g. 1% would be set as 0.01 * @param imbalanceToleranceOut_ New imbalance tolerance out. */ function setImbalanceToleranceOut(uint256 imbalanceToleranceOut_) external override onlyGovernance { imbalanceToleranceOut = imbalanceToleranceOut_; emit SetImbalanceToleranceOut(imbalanceToleranceOut_); } /** * @notice Set strategist. * @dev Can only be set by current strategist. * @param strategist_ Address of new strategist. */ function setStrategist(address strategist_) external override { require(msg.sender == _strategist, Error.UNAUTHORIZED_ACCESS); _strategist = strategist_; emit SetStrategist(strategist_); } /** * @notice Add a reward token to list of extra reward tokens. * @dev These are tokens that are not the main assets of the strategy. For instance, temporary incentives. * @param token_ Address of token to add to reward token list. * @return True if successfully added. */ function addRewardToken(address token_) external override onlyGovernance returns (bool) { require( token_ != address(_CVX) && token_ != address(underlying) && token_ != address(_CRV), Error.INVALID_TOKEN_TO_ADD ); if (_rewardTokens.contains(token_)) return false; _rewardTokens.add(token_); address swapperRouter_ = address(_swapperRouter()); IERC20(token_).safeApprove(swapperRouter_, 0); IERC20(token_).safeApprove(swapperRouter_, type(uint256).max); emit AddRewardToken(token_); return true; } /** * @notice Remove a reward token. * @param token_ Address of token to remove from reward token list. * @return True if successfully removed. */ function removeRewardToken(address token_) external override onlyGovernance returns (bool) { if (!_rewardTokens.remove(token_)) return false; emit RemoveRewardToken(token_); return true; } /** * @notice Amount of rewards that can be harvested in the underlying. * @dev Includes rewards for CRV, CVX & Extra Rewards. * @return Estimated amount of underlying available to harvest. */ function harvestable() external view override returns (uint256) { IRewardStaking rewards_ = rewards; uint256 crvAmount_ = rewards_.earned(address(this)); if (crvAmount_ == 0) return 0; uint256 harvestable_ = _underlyingAmountOut( address(_CRV), crvAmount_.scaledMul(ScaledMath.ONE - crvCommunityReserveShare) ) + _underlyingAmountOut( address(_CVX), getCvxMintAmount(crvAmount_).scaledMul(ScaledMath.ONE - cvxCommunityReserveShare) ); uint256 length_ = _rewardTokens.length(); for (uint256 i; i < length_; i = i.uncheckedInc()) { IRewardStaking extraRewards_ = IRewardStaking(rewards_.extraRewards(i)); address rewardToken_ = extraRewards_.rewardToken(); if (!_rewardTokens.contains(rewardToken_)) continue; harvestable_ += _underlyingAmountOut(rewardToken_, extraRewards_.earned(address(this))); } return harvestable_; } /** * @notice Returns the address of the strategist. * @return The the address of the strategist. */ function strategist() external view override returns (address) { return _strategist; } /** * @notice Returns the list of reward tokens supported by the strategy. * @return The list of reward tokens supported by the strategy. */ function rewardTokens() external view override returns (address[] memory) { return _rewardTokens.toArray(); } /** * @notice Get the total underlying balance of the strategy. * @return Underlying balance of strategy. */ function balance() external view virtual override returns (uint256); /** * @notice Returns the name of the strategy. * @return The name of the strategy. */ function name() external view virtual override returns (string memory); /** * @dev Contract does not stash tokens. */ function hasPendingFunds() external pure override returns (bool) { return false; } function _deposit() internal virtual returns (bool); function _withdraw(uint256 amount_) internal virtual; function _withdrawAll() internal virtual returns (uint256); function _harvest() internal returns (uint256) { uint256 initialBalance_ = _underlyingBalance(); // Claim Convex rewards rewards.getReward(); // Sending share to Community Reserve _sendCommunityReserveShare(); // Swap CVX for WETH ISwapperRouter swapperRouter_ = _swapperRouter(); swapperRouter_.swapAll(address(_CVX), address(_WETH)); // Swap CRV for WETH swapperRouter_.swapAll(address(_CRV), address(_WETH)); // Swap Extra Rewards for WETH uint256 length_ = _rewardTokens.length(); for (uint256 i; i < length_; i = i.uncheckedInc()) { swapperRouter_.swapAll(_rewardTokens.at(i), address(_WETH)); } // Swap WETH for underlying swapperRouter_.swapAll(address(_WETH), address(underlying)); uint256 harvested_ = _underlyingBalance() - initialBalance_; emit Harvest(harvested_); return harvested_; } /** * @notice Sends a share of the current balance of CRV and CVX to the Community Reserve. */ function _sendCommunityReserveShare() internal { address communityReserve_ = communityReserve; if (communityReserve_ == address(0)) return; uint256 cvxCommunityReserveShare_ = cvxCommunityReserveShare; if (cvxCommunityReserveShare_ > 0) { IERC20 cvx_ = _CVX; uint256 cvxBalance_ = cvx_.balanceOf(address(this)); if (cvxBalance_ > 0) { cvx_.safeTransfer( communityReserve_, cvxBalance_.scaledMul(cvxCommunityReserveShare_) ); } } uint256 crvCommunityReserveShare_ = crvCommunityReserveShare; if (crvCommunityReserveShare_ > 0) { IERC20 crv_ = _CRV; uint256 crvBalance_ = crv_.balanceOf(address(this)); if (crvBalance_ > 0) { crv_.safeTransfer( communityReserve_, crvBalance_.scaledMul(crvCommunityReserveShare_) ); } } } /** * @dev Get the balance of the underlying. */ function _underlyingBalance() internal view virtual returns (uint256); /** * @dev Get the balance of the lp. */ function _lpBalance() internal view returns (uint256) { return lp.balanceOf(address(this)); } /** * @dev Get the balance of the underlying staked in the Curve pool. */ function _stakedBalance() internal view returns (uint256) { return rewards.balanceOf(address(this)); } function _underlyingAmountOut(address token_, uint256 amount_) internal view returns (uint256) { return _swapperRouter().getAmountOut(token_, address(underlying), amount_); } /** * @dev Reverts if it is not a valid Curve Pool. */ function _validateCurvePool(address curvePool_) internal view { _CURVE_REGISTRY.get_A(curvePool_); } /** * @dev Gets the Swapper Router, used for swapping tokens. */ function _swapperRouter() internal view returns (ISwapperRouter) { return _addressProvider.getSwapperRouter(); } } // File interfaces/IERC20Full.sol pragma solidity 0.8.10; /// @notice This is the ERC20 interface including optional getter functions /// The interface is used in the frontend through the generated typechain wrapper interface IERC20Full is IERC20 { function symbol() external view returns (string memory); function name() external view returns (string memory); function decimals() external view returns (uint8); } // File interfaces/strategies/IMeroTriHopCvx.sol pragma solidity 0.8.10; interface IMeroTriHopCvx { function setHopImbalanceToleranceIn(uint256 _hopImbalanceToleranceIn) external; function setHopImbalanceToleranceOut(uint256 _hopImbalanceToleranceOut) external; function changeConvexPool( uint256 convexPid_, address curvePool_, uint256 curveIndex_ ) external; } // File contracts/strategies/MeroTriHopCvx.sol pragma solidity 0.8.10; /** * This is the MeroTriHopCvx strategy, which is designed to be used by a Mero ERC20 Vault. * The strategy holds a given ERC20 underlying and allocates liquidity to Convex via a given Curve Pool. * The Curve Pools used are Meta Pools which first require getting an LP Token from another Curve Pool. * The strategy does a 'Hop' when depositing and withdrawing, by first getting the required LP Token, and then the final LP Token for Convex. * Rewards received on Convex (CVX, CRV), are sold in part for the underlying. * A share of earned CVX & CRV are retained on behalf of the Mero community to participate in governance. */ contract MeroTriHopCvx is ConvexStrategyBase, IMeroTriHopCvx { using ScaledMath for uint256; using UncheckedMath for uint256; using SafeERC20 for IERC20; ICurveSwapEth public immutable curveHopPool; // Curve Pool to use for Hops IERC20 public immutable hopLp; // Curve Hop Pool LP Token uint256 public immutable curveHopIndex; // Underlying index in Curve Pool uint256 public hopImbalanceToleranceIn; // Maximum allowed slippage from Curve Hop Pool Imbalance for depositing uint256 public hopImbalanceToleranceOut; // Maximum allowed slippage from Curve Hop Pool Imbalance for withdrawing uint256 public decimalMultiplier; // Used for converting between underlying and LP event SetHopImbalanceToleranceIn(uint256 value); // Emitted after a successful setting of hop imbalance tolerance in event SetHopImbalanceToleranceOut(uint256 value); // Emitted after a successful setting of hop imbalance tolerance out constructor( address vault_, address strategist_, uint256 convexPid_, address curvePool_, uint256 curveIndex_, address curveHopPool_, uint256 curveHopIndex_, IAddressProvider addressProvider_ ) ConvexStrategyBase( vault_, strategist_, convexPid_, curvePool_, curveIndex_, addressProvider_ ) { // Getting data from supporting contracts _validateCurvePool(curveHopPool_); (address lp_, , , , , bool shutdown) = _BOOSTER.poolInfo(convexPid_); require(!shutdown, Error.POOL_SHUTDOWN); address hopLp_ = ICurveSwapEth(curvePool_).coins(curveIndex_); hopLp = IERC20(hopLp_); curveHopPool = ICurveSwapEth(curveHopPool_); address underlying_ = ICurveSwapEth(curveHopPool_).coins(curveHopIndex_); underlying = IERC20(underlying_); decimalMultiplier = 10**(18 - IERC20Full(underlying_).decimals()); // Setting inputs curveHopIndex = curveHopIndex_; // Setting default values imbalanceToleranceIn = 0.001e18; imbalanceToleranceOut = 0.048e18; hopImbalanceToleranceIn = 0.001e18; hopImbalanceToleranceOut = 0.0015e18; // Approvals IERC20(underlying_).safeApprove(curveHopPool_, type(uint256).max); IERC20(hopLp_).safeApprove(curvePool_, type(uint256).max); IERC20(lp_).safeApprove(address(_BOOSTER), type(uint256).max); } /** * @notice Set hop imbalance tolerance for Curve Hop Pool deposits. * @dev Stored as a percent, e.g. 1% would be set as 0.01 * @param _hopImbalanceToleranceIn New hop imbalance tolerance in. */ function setHopImbalanceToleranceIn(uint256 _hopImbalanceToleranceIn) external override onlyGovernance { hopImbalanceToleranceIn = _hopImbalanceToleranceIn; emit SetHopImbalanceToleranceIn(_hopImbalanceToleranceIn); } /** * @notice Set hop imbalance tolerance for Curve Hop Pool withdrawals. * @dev Stored as a percent, e.g. 1% would be set as 0.01 * @param _hopImbalanceToleranceOut New hop imbalance tolerance out. */ function setHopImbalanceToleranceOut(uint256 _hopImbalanceToleranceOut) external override onlyGovernance { hopImbalanceToleranceOut = _hopImbalanceToleranceOut; emit SetHopImbalanceToleranceOut(_hopImbalanceToleranceOut); } /** * @notice Changes the Convex Pool used for farming yield, e.g. from FRAX to MIM. * @dev First withdraws all funds, then harvests any rewards, then changes pool, then deposits again. * @param convexPid_ The PID for the new Convex Pool. * @param curvePool_ The Curve Pool to deposit into to get the required LP Token for Convex staking. * @param curveIndex_ The index of the new Convex Pool Token in the new Curve Pool. */ function changeConvexPool( uint256 convexPid_, address curvePool_, uint256 curveIndex_ ) external override onlyGovernance { _validateCurvePool(curvePool_); _harvest(); _withdrawAllToHopLp(); convexPid = convexPid_; curveIndex = curveIndex_; (address lp_, , , address rewards_, , bool shutdown) = _BOOSTER.poolInfo(convexPid_); require(!shutdown, Error.POOL_SHUTDOWN); lp = IERC20(lp_); rewards = IRewardStaking(rewards_); curvePool = ICurveSwapEth(curvePool_); IERC20(hopLp).safeApprove(curvePool_, 0); IERC20(hopLp).safeApprove(curvePool_, type(uint256).max); IERC20(lp_).safeApprove(address(_BOOSTER), 0); IERC20(lp_).safeApprove(address(_BOOSTER), type(uint256).max); require(_deposit(), Error.DEPOSIT_FAILED); } function balance() public view override returns (uint256) { return _underlyingBalance() + _hopLpToUnderlying(_lpToHopLp(_stakedBalance() + _lpBalance()) + _hopLpBalance()); } function name() public pure override returns (string memory) { return "MeroTriHopCvx"; } function _deposit() internal override returns (bool) { require(msg.value == 0, Error.INVALID_VALUE); // Depositing into Curve Hop Pool uint256 underlyingBalance = _underlyingBalance(); if (underlyingBalance > 0) { uint256[3] memory hopAmounts; hopAmounts[curveHopIndex] = underlyingBalance; curveHopPool.add_liquidity(hopAmounts, _minHopLpAcceptedFromDeposit(underlyingBalance)); } // Depositing into Curve Pool uint256 hopLpBalance = _hopLpBalance(); if (hopLpBalance > 0) { uint256[2] memory amounts; amounts[curveIndex] = hopLpBalance; curvePool.add_liquidity(amounts, _minLpAccepted(hopLpBalance)); } // Depositing into Convex and Staking if (_lpBalance() == 0) return false; if (!_BOOSTER.depositAll(convexPid, true)) return false; return true; } function _withdraw(uint256 amount) internal override { // Transferring from idle balance if enough uint256 underlyingBalance = _underlyingBalance(); if (underlyingBalance >= amount) { underlying.safeTransfer(vault, amount); emit Withdraw(amount); return; } // Calculating needed amount of LP to withdraw uint256 requiredUnderlyingAmount = amount.uncheckedSub(underlyingBalance); uint256 maxHopLpBurned = _maxHopLpBurned(requiredUnderlyingAmount); uint256 requiredHopLpAmount = maxHopLpBurned - _hopLpBalance(); uint256 maxLpBurned = _maxLpBurned(requiredHopLpAmount); uint256 requiredLpAmount = maxLpBurned - _lpBalance(); // Unstaking needed LP Tokens from Convex if (!rewards.withdrawAndUnwrap(requiredLpAmount, false)) return; // Removing needed liquidity from Curve Pool uint256[2] memory amounts; amounts[curveIndex] = requiredHopLpAmount; curvePool.remove_liquidity_imbalance(amounts, maxLpBurned); // Removing needed liquidity from Curve Hop Pool uint256[3] memory hopAmounts; hopAmounts[curveHopIndex] = requiredUnderlyingAmount; curveHopPool.remove_liquidity_imbalance(hopAmounts, maxHopLpBurned); // Sending underlying to vault underlying.safeTransfer(vault, amount); } function _withdrawAll() internal override returns (uint256) { // Withdrawing all from Convex and converting to Hop LP Token _withdrawAllToHopLp(); // Removing liquidity from Curve Hop Pool uint256 hopLpBalance = _hopLpBalance(); if (hopLpBalance > 0) { curveHopPool.remove_liquidity_one_coin( hopLpBalance, int128(uint128(curveHopIndex)), _minUnderlyingAccepted(hopLpBalance) ); } // Transferring underlying to vault uint256 underlyingBalance = _underlyingBalance(); if (underlyingBalance == 0) return 0; underlying.safeTransfer(vault, underlyingBalance); return underlyingBalance; } function _underlyingBalance() internal view override returns (uint256) { return underlying.balanceOf(address(this)); } /** * @dev Get the balance of the hop lp. */ function _hopLpBalance() internal view returns (uint256) { return hopLp.balanceOf(address(this)); } /** * @notice Calculates the minimum LP to accept when depositing underlying into Curve Pool. * @param _hopLpAmount Amount of Hop LP that is being deposited into Curve Pool. * @return The minimum LP balance to accept. */ function _minLpAccepted(uint256 _hopLpAmount) internal view returns (uint256) { return _hopLpToLp(_hopLpAmount).scaledMul(ScaledMath.ONE - imbalanceToleranceIn); } /** * @notice Calculates the maximum LP to accept burning when withdrawing amount from Curve Pool. * @param _hopLpAmount Amount of Hop LP that is being withdrawn from Curve Pool. * @return The maximum LP balance to accept burning. */ function _maxLpBurned(uint256 _hopLpAmount) internal view returns (uint256) { return _hopLpToLp(_hopLpAmount).scaledMul(ScaledMath.ONE + imbalanceToleranceOut); } /** * @notice Calculates the minimum Hop LP to accept when burning LP tokens to withdraw from Curve Pool. * @param _lpAmount Amount of LP tokens being burned to withdraw from Curve Pool. * @return The minimum Hop LP balance to accept. */ function _minHopLpAcceptedFromWithdraw(uint256 _lpAmount) internal view returns (uint256) { return _lpToHopLp(_lpAmount).scaledMul(ScaledMath.ONE - imbalanceToleranceOut); } /** * @notice Calculates the minimum Hop LP to accept when depositing underlying into Curve Hop Pool. * @param _underlyingAmount Amount of underlying that is being deposited into Curve Hop Pool. * @return The minimum Hop LP balance to accept. */ function _minHopLpAcceptedFromDeposit(uint256 _underlyingAmount) internal view returns (uint256) { return _underlyingToHopLp(_underlyingAmount).scaledMul( ScaledMath.ONE - hopImbalanceToleranceIn ); } /** * @notice Calculates the maximum Hop LP to accept burning when withdrawing amount from Curve Hop Pool. * @param _underlyingAmount Amount of underlying that is being withdrawn from Curve Hop Pool. * @return The maximum Hop LP balance to accept burning. */ function _maxHopLpBurned(uint256 _underlyingAmount) internal view returns (uint256) { return _underlyingToHopLp(_underlyingAmount).scaledMul( ScaledMath.ONE + hopImbalanceToleranceOut ); } /** * @notice Calculates the minimum underlying to accept when burning Hop LP tokens to withdraw from Curve Hop Pool. * @param _hopLpAmount Amount of Hop LP tokens being burned to withdraw from Curve Hop Pool. * @return The minimum underlying balance to accept. */ function _minUnderlyingAccepted(uint256 _hopLpAmount) internal view returns (uint256) { return _hopLpToUnderlying(_hopLpAmount).scaledMul(ScaledMath.ONE - hopImbalanceToleranceOut); } /** * @notice Converts an amount of underlying into their estimated Hop LP value. * @dev Uses get_virtual_price which is less susceptible to manipulation. * But is also less accurate to how much could be withdrawn. * @param _underlyingAmount Amount of underlying to convert. * @return The estimated value in the Hop LP. */ function _underlyingToHopLp(uint256 _underlyingAmount) internal view returns (uint256) { return (_underlyingAmount * decimalMultiplier).scaledDiv(curveHopPool.get_virtual_price()); } /** * @notice Converts an amount of Hop LP into their estimated underlying value. * @dev Uses get_virtual_price which is less susceptible to manipulation. * But is also less accurate to how much could be withdrawn. * @param _hopLpAmount Amount of Hop LP to convert. * @return The estimated value in the underlying. */ function _hopLpToUnderlying(uint256 _hopLpAmount) internal view returns (uint256) { return (_hopLpAmount / decimalMultiplier).scaledMul(curveHopPool.get_virtual_price()); } /** * @notice Converts an amount of LP into their estimated Hop LP value. * @dev Uses get_virtual_price which is less susceptible to manipulation. * But is also less accurate to how much could be withdrawn. * @param _lpAmount Amount of underlying to convert. * @return The estimated value in the Hop LP. */ function _lpToHopLp(uint256 _lpAmount) internal view returns (uint256) { return _lpAmount.scaledMul(curvePool.get_virtual_price()).scaledDiv( curveHopPool.get_virtual_price() ); } /** * @notice Converts an amount of Hop LP into their estimated LP value. * @dev Uses get_virtual_price which is less susceptible to manipulation. * But is also less accurate to how much could be withdrawn. * @param _hopLpAmount Amount of Hop LP to convert. * @return The estimated value in the LP. */ function _hopLpToLp(uint256 _hopLpAmount) internal view returns (uint256) { return _hopLpAmount.scaledMul(curveHopPool.get_virtual_price()).scaledDiv( curvePool.get_virtual_price() ); } /** * @dev Withdraw all underlying and convert to the Hop LP Token. */ function _withdrawAllToHopLp() private { // Unstaking and withdrawing from Convex pool uint256 stakedBalance = _stakedBalance(); if (stakedBalance > 0) { rewards.withdrawAndUnwrap(stakedBalance, false); } // Removing liquidity from Curve Pool uint256 lpBalance = _lpBalance(); if (lpBalance > 0) { curvePool.remove_liquidity_one_coin( lpBalance, int128(uint128(curveIndex)), _minHopLpAcceptedFromWithdraw(lpBalance) ); } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"vault_","type":"address"},{"internalType":"address","name":"strategist_","type":"address"},{"internalType":"uint256","name":"convexPid_","type":"uint256"},{"internalType":"address","name":"curvePool_","type":"address"},{"internalType":"uint256","name":"curveIndex_","type":"uint256"},{"internalType":"address","name":"curveHopPool_","type":"address"},{"internalType":"uint256","name":"curveHopIndex_","type":"uint256"},{"internalType":"contract IAddressProvider","name":"addressProvider_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"AddRewardToken","type":"event"},{"anonymous":false,"inputs":[],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Harvest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"RemoveRewardToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"reserve","type":"address"}],"name":"SetCommunityReserve","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"SetCrvCommunityReserveShare","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"SetCvxCommunityReserveShare","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"SetHopImbalanceToleranceIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"SetHopImbalanceToleranceOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"SetImbalanceToleranceIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"SetImbalanceToleranceOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"strategist","type":"address"}],"name":"SetStrategist","type":"event"},{"anonymous":false,"inputs":[],"name":"Shutdown","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawAll","type":"event"},{"inputs":[{"internalType":"address","name":"token_","type":"address"}],"name":"addRewardToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"balance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"convexPid_","type":"uint256"},{"internalType":"address","name":"curvePool_","type":"address"},{"internalType":"uint256","name":"curveIndex_","type":"uint256"}],"name":"changeConvexPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"communityReserve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"convexPid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"crvCommunityReserveShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveHopIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveHopPool","outputs":[{"internalType":"contract ICurveSwapEth","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curveIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curvePool","outputs":[{"internalType":"contract ICurveSwapEth","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cvxCommunityReserveShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"crvEarned","type":"uint256"}],"name":"getCvxMintAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasPendingFunds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"hopImbalanceToleranceIn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hopImbalanceToleranceOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hopLp","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"imbalanceToleranceIn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"imbalanceToleranceOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isShutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lp","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"}],"name":"removeRewardToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewards","outputs":[{"internalType":"contract IRewardStaking","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"roleManager","outputs":[{"internalType":"contract IRoleManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_communityReserve","type":"address"}],"name":"setCommunityReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"crvCommunityReserveShare_","type":"uint256"}],"name":"setCrvCommunityReserveShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"cvxCommunityReserveShare_","type":"uint256"}],"name":"setCvxCommunityReserveShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_hopImbalanceToleranceIn","type":"uint256"}],"name":"setHopImbalanceToleranceIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_hopImbalanceToleranceOut","type":"uint256"}],"name":"setHopImbalanceToleranceOut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"imbalanceToleranceIn_","type":"uint256"}],"name":"setImbalanceToleranceIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"imbalanceToleranceOut_","type":"uint256"}],"name":"setImbalanceToleranceOut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"strategist_","type":"address"}],"name":"setStrategist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101406040523480156200001257600080fd5b5060405162004e4238038062004e42833981016040819052620000359162000b70565b8787878787856200005a816001600160a01b03166200064f60201b6200205d1760201c565b6001600160a01b03166080526200007183620006d2565b604051631526fe2760e01b8152600481018590526000908190819073f403c135812408bfbe8713b5a23a04b3d48aae3190631526fe279060240160c060405180830381865afa158015620000c9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ef919062000c23565b95505094505050925080156040518060400160405280601081526020016f2837b7b61034b99039b43aba3237bbb760811b815250906200014d5760405162461bcd60e51b815260040162000144919062000ce5565b60405180910390fd5b50600a80546001600160a01b038581166001600160a01b03199283161790925560098054858416908316179055600b8054928916929091168217905560405163c661065760e01b8152600481018790526000919063c661065790602401602060405180830381865afa158015620001c8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ee919062000d1a565b90506001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156200021a575060005b600380546001600160a01b03199081166001600160a01b03848116919091179092558b821660c052600080549091168b8316178155600c8a9055600d88905590861660a0819052620002789062000755602090811b620020dd17901c565b9050620002a973d533a949740bb3306d119cc777fa900ba034cd528260001962000795602090811b6200211c17901c565b620002d8734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b8260001962000795602090811b6200211c17901c565b6200030773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28260001962000795602090811b6200211c17901c565b50505050505050505050506200032383620006d260201b60201c565b604051631526fe2760e01b815260048101879052600090819073f403c135812408bfbe8713b5a23a04b3d48aae3190631526fe279060240160c060405180830381865afa15801562000379573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200039f919062000c23565b955050505050915080156040518060400160405280601081526020016f2837b7b61034b99039b43aba3237bbb760811b81525090620003f35760405162461bcd60e51b815260040162000144919062000ce5565b5060405163c661065760e01b8152600481018790526000906001600160a01b0389169063c661065790602401602060405180830381865afa1580156200043d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000463919062000d1a565b6001600160a01b0381811661010052871660e081905260405163c661065760e01b81526004810188905291925060009163c661065790602401602060405180830381865afa158015620004ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004e0919062000d1a565b905080600360006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000548573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200056e919062000d3a565b6200057b90601262000d75565b6200058890600a62000e98565b60105561012086905266038d7ea4c68000600781905566aa87bee5380000600855600e556605543df729c000600f55620005db6001600160a01b0382168860001962000795602090811b6200211c17901c565b6200060289600019846001600160a01b03166200079560201b6200211c179092919060201c565b6200063d73f403c135812408bfbe8713b5a23a04b3d48aae31600019866001600160a01b03166200079560201b6200211c179092919060201c565b50505050505050505050505062000eff565b6040516321f8a72160e01b81526a3937b632a6b0b730b3b2b960a91b60048201526000906001600160a01b038316906321f8a721906024015b602060405180830381865afa158015620006a6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006cc919062000d1a565b92915050565b6040516355b30b1960e01b81526001600160a01b03821660048201527390e00ace148ca3b23ac1bc8c240c2a7dd9c2d7f5906355b30b1990602401602060405180830381865afa1580156200072b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000751919062000ea9565b5050565b6040516321f8a72160e01b81526c39bbb0b83832b92937baba32b960991b60048201526000906001600160a01b038316906321f8a7219060240162000688565b801580620008135750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015620007eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000811919062000ea9565b155b620008875760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606482015260840162000144565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620008df918591620008e416565b505050565b600062000940826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620009c260201b62002269179092919060201c565b805190915015620008df578080602001905181019062000961919062000ec3565b620008df5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000144565b6060620009d38484600085620009dd565b90505b9392505050565b60608247101562000a405760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000144565b6001600160a01b0385163b62000a995760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000144565b600080866001600160a01b0316858760405162000ab7919062000ee1565b60006040518083038185875af1925050503d806000811462000af6576040519150601f19603f3d011682016040523d82523d6000602084013e62000afb565b606091505b50909250905062000b0e82828662000b19565b979650505050505050565b6060831562000b2a575081620009d6565b82511562000b3b5782518084602001fd5b8160405162461bcd60e51b815260040162000144919062000ce5565b6001600160a01b038116811462000b6d57600080fd5b50565b600080600080600080600080610100898b03121562000b8e57600080fd5b885162000b9b8162000b57565b60208a015190985062000bae8162000b57565b60408a015160608b0151919850965062000bc88162000b57565b60808a015160a08b0151919650945062000be28162000b57565b60c08a015160e08b0151919450925062000bfc8162000b57565b809150509295985092959890939650565b8051801515811462000c1e57600080fd5b919050565b60008060008060008060c0878903121562000c3d57600080fd5b865162000c4a8162000b57565b602088015190965062000c5d8162000b57565b604088015190955062000c708162000b57565b606088015190945062000c838162000b57565b608088015190935062000c968162000b57565b915062000ca660a0880162000c0d565b90509295509295509295565b60005b8381101562000ccf57818101518382015260200162000cb5565b8381111562000cdf576000848401525b50505050565b602081526000825180602084015262000d0681604085016020870162000cb2565b601f01601f19169190910160400192915050565b60006020828403121562000d2d57600080fd5b8151620009d68162000b57565b60006020828403121562000d4d57600080fd5b815160ff81168114620009d657600080fd5b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff84168082101562000d925762000d9262000d5f565b90039392505050565b600181815b8085111562000ddc57816000190482111562000dc05762000dc062000d5f565b8085161562000dce57918102915b93841c939080029062000da0565b509250929050565b60008262000df557506001620006cc565b8162000e0457506000620006cc565b816001811462000e1d576002811462000e285762000e48565b6001915050620006cc565b60ff84111562000e3c5762000e3c62000d5f565b50506001821b620006cc565b5060208310610133831016604e8410600b841016171562000e6d575081810a620006cc565b62000e79838362000d9b565b806000190482111562000e905762000e9062000d5f565b029392505050565b6000620009d660ff84168362000de4565b60006020828403121562000ebc57600080fd5b5051919050565b60006020828403121562000ed657600080fd5b620009d68262000c0d565b6000825162000ef581846020870162000cb2565b9190910192915050565b60805160a05160c05160e0516101005161012051613e1a620010286000396000818161050b015281816124a90152818161297c0152612e1b01526000818161045601528181611b8101528181611bb60152612a6f01526000818161038c015281816124f40152818161294c01528181612b4c01528181612c4f01528181612e5901528181613871015261397f01526000818161076101528181610a4501528181610d2e0152818161107f015281816115ef01528181611f88015281816122f0015281816125700152612a320152600061229e01526000818161026f015281816107cd01528181610bcf01528181610d7701528181610e940152818161111101528181611227015281816113990152818161196f01528181611c8a0152611da00152613e1a6000f3fe60806040526004361061025b5760003560e01c80637bdcdaff11610144578063c2bddf31116100b6578063e9eb50881161007a578063e9eb50881461070f578063ecf8db0a1461072f578063fbfa77cf1461074f578063fc0e74d114610783578063fdc0bfca14610798578063ff0af85b146107ae57600080fd5b8063c2bddf3114610692578063c7b9d530146106b2578063d0e30db0146106d2578063dbbd47d4146106da578063df22a747146106ef57600080fd5b80639ec5a894116101085780639ec5a894146105e4578063aa6a8caf14610604578063b69ef8a814610624578063b6ed67a814610639578063bf86d6901461064f578063c2b18aa01461067057600080fd5b80637bdcdaff1461056d578063853828b61461058357806386993bef14610598578063938511a7146105ae5780639b61a924146105ce57600080fd5b80633778851e116101dd57806356be5f71116101a157806356be5f71146104af57806361240eea146104c5578063621e8fe1146104d957806369cbb00d146104f95780636f307dc31461052d57806370aa17261461054d57600080fd5b80633778851e146104045780633d509c971461042457806344d32ee9146104445780634641257d1461047857806349cabcdf1461048d57600080fd5b8063218751b211610224578063218751b21461035a578063283f3b561461037a5780632e1a7d4d146103ae5780633082538f146103ce578063313c06a0146103e457600080fd5b8062435da51461026057806306fdde03146102ac5780631a55820d146102e85780631c03e6cc1461030c5780631fe4a6861461033c575b600080fd5b34801561026c57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102b857600080fd5b50604080518082018252600d81526c09acae4dea8e4d290dee086ecf609b1b602082015290516102a39190613a71565b3480156102f457600080fd5b506102fe60085481565b6040519081526020016102a3565b34801561031857600080fd5b5061032c610327366004613abc565b6107c9565b60405190151581526020016102a3565b34801561034857600080fd5b506000546001600160a01b031661028f565b34801561036657600080fd5b50600b5461028f906001600160a01b031681565b34801561038657600080fd5b5061028f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103ba57600080fd5b5061032c6103c9366004613ad9565b610a15565b3480156103da57600080fd5b506102fe60105481565b3480156103f057600080fd5b50600a5461028f906001600160a01b031681565b34801561041057600080fd5b506102fe61041f366004613ad9565b610ad6565b34801561043057600080fd5b5061032c61043f366004613abc565b610bcb565b34801561045057600080fd5b5061028f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561048457600080fd5b506102fe610cfe565b34801561049957600080fd5b506104ad6104a8366004613ad9565b610d75565b005b3480156104bb57600080fd5b506102fe60075481565b3480156104d157600080fd5b50600061032c565b3480156104e557600080fd5b5060045461028f906001600160a01b031681565b34801561050557600080fd5b506102fe7f000000000000000000000000000000000000000000000000000000000000000081565b34801561053957600080fd5b5060035461028f906001600160a01b031681565b34801561055957600080fd5b506104ad610568366004613ad9565b610e92565b34801561057957600080fd5b506102fe600d5481565b34801561058f57600080fd5b506102fe61104f565b3480156105a457600080fd5b506102fe600c5481565b3480156105ba57600080fd5b506104ad6105c9366004613ad9565b61110f565b3480156105da57600080fd5b506102fe60065481565b3480156105f057600080fd5b5060095461028f906001600160a01b031681565b34801561061057600080fd5b506104ad61061f366004613ad9565b611225565b34801561063057600080fd5b506102fe61133b565b34801561064557600080fd5b506102fe600e5481565b34801561065b57600080fd5b5060035461032c90600160a01b900460ff1681565b34801561067c57600080fd5b5061068561138b565b6040516102a39190613af2565b34801561069e57600080fd5b506104ad6106ad366004613abc565b611397565b3480156106be57600080fd5b506104ad6106cd366004613abc565b611522565b61032c6115bf565b3480156106e657600080fd5b506102fe6116c4565b3480156106fb57600080fd5b506104ad61070a366004613b3f565b61196d565b34801561071b57600080fd5b506104ad61072a366004613ad9565b611c88565b34801561073b57600080fd5b506104ad61074a366004613ad9565b611d9e565b34801561075b57600080fd5b5061028f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561078f57600080fd5b506104ad611f5b565b3480156107a457600080fd5b506102fe600f5481565b3480156107ba57600080fd5b506102fe60055481565b905090565b60007f0000000000000000000000000000000000000000000000000000000000000000604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108699190613b87565b604051806040016040528060138152602001600080516020613dc5833981519152815250906108b45760405162461bcd60e51b81526004016108ab9190613a71565b60405180910390fd5b506001600160a01b038216734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b148015906108f057506003546001600160a01b03838116911614155b801561091957506001600160a01b03821673d533a949740bb3306d119cc777fa900ba034cd5214155b60405180604001604052806014815260200173125b9d985b1a59081d1bdad95b881d1bc818591960621b815250906109645760405162461bcd60e51b81526004016108ab9190613a71565b506001600160a01b0382166000908152600260205260409020541561098b57506000919050565b610996600183612282565b5060006109a1612297565b90506109b86001600160a01b03841682600061211c565b6109ce6001600160a01b0384168260001961211c565b6040516001600160a01b03841681527f851bbb4304bf0768ed98b97e429b5bd1dcc1f194b36cd1650f40293e951ae3939060200160405180910390a160019150505b919050565b6040805180820190915260138152600080516020613dc58339815191526020820152600090336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a835760405162461bcd60e51b81526004016108ab9190613a71565b5081610a9157506000919050565b610a9a826122cb565b6040518281527f5b6b431d4476a211bb7d41c20d1aab9ae2321deee0d20be3d9fc9b1093fa6e3d906020015b60405180910390a1506001919050565b600080734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4f9190613ba2565b90506000610b678269152d02c7e14af68000006125a0565b90506103e88110610b7c575060009392505050565b6103e881810390600090610b908388613bd1565b610b9a9190613c06565b90506000610bb3856a52b7d2dcc80cd2e4000000613c28565b905080821115610bc1578091505b5095945050505050565b60007f0000000000000000000000000000000000000000000000000000000000000000604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6b9190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090610cad5760405162461bcd60e51b81526004016108ab9190613a71565b50610cb96001836125b9565b610cc557506000919050565b6040516001600160a01b03831681527f36bd04094fa067bb9471a8fbdb0a6e8a43424a2566ad3a740c88973fa40a311890602001610ac6565b6040805180820190915260138152600080516020613dc58339815191526020820152600090336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d6c5760405162461bcd60e51b81526004016108ab9190613a71565b506107c46125ce565b7f0000000000000000000000000000000000000000000000000000000000000000604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610def573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e139190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090610e555760405162461bcd60e51b81526004016108ab9190613a71565b5060078190556040518181527f4ede3e4e9f7997fda6ff4a12d6c43d5c9e1e2055065cbc15f902f504f72dc8c0906020015b60405180910390a150565b7f0000000000000000000000000000000000000000000000000000000000000000604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610f0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f309190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090610f725760405162461bcd60e51b81526004016108ab9190613a71565b5060408051808201909152600e81526d1a5b9d985b1a5908185b5bdd5b9d60921b6020820152670de0b6b3a7640000821115610fc15760405162461bcd60e51b81526004016108ab9190613a71565b506004546001600160a01b031661101a5760405162461bcd60e51b815260206004820152601d60248201527f436f6d6d756e6974792072657365727665206d7573742062652073657400000060448201526064016108ab565b60058190556040518181527f1a8542dffa4956932e66916113e6a123e123956172fbc0e2e59df92b8a87d8e690602001610e87565b6040805180820190915260138152600080516020613dc58339815191526020820152600090336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146110bd5760405162461bcd60e51b81526004016108ab9190613a71565b5060006110c861292e565b9050806110d757600091505090565b6040518181527f3d5a341dc6a12221fcf31279cef3771f8fad757b2d9261f97605ccc17c2574249060200160405180910390a1919050565b7f0000000000000000000000000000000000000000000000000000000000000000604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ad9190613b87565b604051806040016040528060138152602001600080516020613dc5833981519152815250906111ef5760405162461bcd60e51b81526004016108ab9190613a71565b50600e8190556040518181527fe6b4374e594cac6d717f89735f722a01c53affe6a4603ed44e09004666b7a6f390602001610e87565b7f0000000000000000000000000000000000000000000000000000000000000000604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa15801561129f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c39190613b87565b604051806040016040528060138152602001600080516020613dc5833981519152815250906113055760405162461bcd60e51b81526004016108ab9190613a71565b50600f8190556040518181527f8b8ad8032596ef90599a67881aed48dba49c88dd982cd479440bfcee796dcf8b90602001610e87565b6000611379611348612a57565b61136a611353612ae3565b61135b612b14565b6113659190613c3f565b612b45565b6113749190613c3f565b612c48565b611381612cdc565b6107c49190613c3f565b60606107c46001612d0d565b7f0000000000000000000000000000000000000000000000000000000000000000604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611411573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114359190613b87565b604051806040016040528060138152602001600080516020613dc5833981519152815250906114775760405162461bcd60e51b81526004016108ab9190613a71565b5060408051808201909152601881527f7a65726f2061646472657373206e6f7420616c6c6f776564000000000000000060208201526001600160a01b0382166114d35760405162461bcd60e51b81526004016108ab9190613a71565b50600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f17d7ba6682f162782054b119192f8e5b98fe7090b4bec7a55fc7075d9cd859ee90602001610e87565b6000546040805180820190915260138152600080516020613dc58339815191526020820152906001600160a01b031633146115705760405162461bcd60e51b81526004016108ab9190613a71565b50600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f46d58e3fa07bf19b1d27240f0e286b27e9f7c1b0d88933333fe833b60eec541290602001610e87565b6040805180820190915260138152600080516020613dc58339815191526020820152600090336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461162d5760405162461bcd60e51b81526004016108ab9190613a71565b5060035460408051808201909152601481527329ba3930ba32b3bc9034b99039b43aba3237bbb760611b602082015290600160a01b900460ff16156116855760405162461bcd60e51b81526004016108ab9190613a71565b5061168e612db2565b6116985750600090565b6040517fed21248cb703b524cc0029bb8669df941baca560163a3bc6ad184e7e9c26807090600090a190565b6009546040516246613160e11b81523060048201526000916001600160a01b03169082908290628cc26290602401602060405180830381865afa15801561170f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117339190613ba2565b9050806117435760009250505090565b600061178a734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b611785600654670de0b6b3a76400006117769190613c28565b61177f86610ad6565b90613025565b613044565b6117c273d533a949740bb3306d119cc777fa900ba034cd52611785600554670de0b6b3a76400006117bb9190613c28565b8690613025565b6117cc9190613c3f565b905060006117da60016130ca565b905060005b8181101561196357604051632061aa2360e11b8152600481018290526000906001600160a01b038716906340c3544690602401602060405180830381865afa15801561182f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118539190613c57565b90506000816001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015611895573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b99190613c57565b6001600160a01b0381166000908152600260205260409020549091506118e057505061195b565b6040516246613160e11b815230600482015261194c9082906001600160a01b03851690628cc26290602401602060405180830381865afa158015611928573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117859190613ba2565b6119569086613c3f565b945050505b6001016117df565b5090949350505050565b7f0000000000000000000000000000000000000000000000000000000000000000604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa1580156119e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0b9190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090611a4d5760405162461bcd60e51b81526004016108ab9190613a71565b50611a57826130d4565b611a5f6125ce565b50611a68613154565b600c839055600d819055604051631526fe2760e01b8152600481018490526000908190819073f403c135812408bfbe8713b5a23a04b3d48aae3190631526fe279060240160c060405180830381865afa158015611ac9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aed9190613c74565b95505094505050925080156040518060400160405280601081526020016f2837b7b61034b99039b43aba3237bbb760811b81525090611b3f5760405162461bcd60e51b81526004016108ab9190613a71565b50600a80546001600160a01b038086166001600160a01b03199283161790925560098054858416908316179055600b80548884169216919091179055611ba9907f00000000000000000000000000000000000000000000000000000000000000001686600061211c565b611bdf6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168660001961211c565b611c086001600160a01b03841673f403c135812408bfbe8713b5a23a04b3d48aae31600061211c565b611c326001600160a01b03841673f403c135812408bfbe8713b5a23a04b3d48aae3160001961211c565b611c3a612db2565b6040518060400160405280600e81526020016d19195c1bdcda5d0819985a5b195960921b81525090611c7f5760405162461bcd60e51b81526004016108ab9190613a71565b50505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611d02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d269190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090611d685760405162461bcd60e51b81526004016108ab9190613a71565b5060088190556040518181527fb2861fed34a4613f8f25f46553a23408a3364ee9ddc4ef6714f0a81d856e41a790602001610e87565b7f0000000000000000000000000000000000000000000000000000000000000000604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c9190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090611e7e5760405162461bcd60e51b81526004016108ab9190613a71565b5060408051808201909152600e81526d1a5b9d985b1a5908185b5bdd5b9d60921b6020820152670de0b6b3a7640000821115611ecd5760405162461bcd60e51b81526004016108ab9190613a71565b506004546001600160a01b0316611f265760405162461bcd60e51b815260206004820152601d60248201527f436f6d6d756e6974792072657365727665206d7573742062652073657400000060448201526064016108ab565b60068190556040518181527f2c3c7d70a1dfbfaf74447753b8a73e1323aa10b32b9209742db563671e14b13c90602001610e87565b6040805180820190915260138152600080516020613dc58339815191526020820152336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611fc65760405162461bcd60e51b81526004016108ab9190613a71565b5060035460408051808201909152601481527329ba3930ba32b3bc9034b99039b43aba3237bbb760611b602082015290600160a01b900460ff161561201e5760405162461bcd60e51b81526004016108ab9190613a71565b506003805460ff60a01b1916600160a01b1790556040517f4426aa1fb73e391071491fcfe21a88b5c38a0a0333a1f6e77161470439704cf890600090a1565b6040516321f8a72160e01b81526a3937b632a6b0b730b3b2b960a91b60048201526000906001600160a01b038316906321f8a721906024015b602060405180830381865afa1580156120b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d79190613c57565b92915050565b6040516321f8a72160e01b81526c39bbb0b83832b92937baba32b960991b60048201526000906001600160a01b038316906321f8a72190602401612096565b8015806121965750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015612170573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121949190613ba2565b155b6122015760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016108ab565b6040516001600160a01b03831660248201526044810182905261226490849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613278565b505050565b6060612278848460008561334a565b90505b9392505050565b600061227b836001600160a01b03841661347b565b60006107c47f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166120dd565b60006122d5612cdc565b905081811061234c57600354612315906001600160a01b03167f0000000000000000000000000000000000000000000000000000000000000000846134ca565b6040518281527f5b6b431d4476a211bb7d41c20d1aab9ae2321deee0d20be3d9fc9b1093fa6e3d9060200160405180910390a15050565b808203600061235a826134fa565b90506000612366612a57565b6123709083613c28565b9050600061237d8261351e565b90506000612389612ae3565b6123939083613c28565b600954604051636197390160e11b815260048101839052600060248201529192506001600160a01b03169063c32e7202906044016020604051808303816000875af11580156123e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240a9190613b87565b6124175750505050505050565b61241f613a05565b8381600d546002811061243457612434613cf6565b6020020152600b5460405163e310327360e01b81526001600160a01b039091169063e31032739061246b9084908790600401613d0c565b600060405180830381600087803b15801561248557600080fd5b505af1158015612499573d6000803e3d6000fd5b505050506124a5613a23565b86817f0000000000000000000000000000000000000000000000000000000000000000600381106124d8576124d8613cf6565b60200201526040516327f6ba8360e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639fdaea0c9061252b9084908a90600401613d44565b600060405180830381600087803b15801561254557600080fd5b505af1158015612559573d6000803e3d6000fd5b505060035461259592506001600160a01b031690507f00000000000000000000000000000000000000000000000000000000000000008b6134ca565b505050505050505050565b60008183816125b1576125b1613bf0565b049392505050565b600061227b836001600160a01b038416613542565b6000806125d9612cdc565b9050600960009054906101000a90046001600160a01b03166001600160a01b0316633d18b9126040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561262b57600080fd5b505af115801561263f573d6000803e3d6000fd5b5050505061264b613635565b6000612655612297565b604051633ff37e8f60e01b8152734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b600482015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260248201529091506001600160a01b03821690633ff37e8f906044016020604051808303816000875af11580156126cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f09190613ba2565b50604051633ff37e8f60e01b815273d533a949740bb3306d119cc777fa900ba034cd52600482015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260248201526001600160a01b03821690633ff37e8f906044016020604051808303816000875af1158015612765573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127899190613ba2565b50600061279660016130ca565b905060005b8181101561284a576001600160a01b038316633ff37e8f6127bd600184613792565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260248201526044016020604051808303816000875af115801561281d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128419190613ba2565b5060010161279b565b50600354604051633ff37e8f60e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260048201526001600160a01b03918216602482015290831690633ff37e8f906044016020604051808303816000875af11580156128b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d59190613ba2565b506000836128e1612cdc565b6128eb9190613c28565b90507f80f97f878e16410266694f134ddf012f2be424f54f8b5cafa107eccc51d00d588160405161291e91815260200190565b60405180910390a1949350505050565b6000612938613154565b6000612942612a57565b90508015612a06577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631a4d01d2827f00000000000000000000000000000000000000000000000000000000000000006129a48561379e565b6040516001600160e01b031960e086901b1681526004810193909352600f9190910b60248301526044820152606401600060405180830381600087803b1580156129ed57600080fd5b505af1158015612a01573d6000803e3d6000fd5b505050505b6000612a10612cdc565b905080612a205760009250505090565b6003546120d7906001600160a01b03167f0000000000000000000000000000000000000000000000000000000000000000836134ca565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a08231906024015b602060405180830381865afa158015612abf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c49190613ba2565b600a546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401612aa2565b6009546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401612aa2565b60006120d77f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ba8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bcc9190613ba2565b600b5460408051630176f71760e71b81529051612c42926001600160a01b03169163bb7b8b809160048083019260209291908290030181865afa158015612c17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3b9190613ba2565b8590613025565b906137c2565b60006120d77f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ccf9190613ba2565b60105461177f9085613c06565b6003546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401612aa2565b60606000612d1a836130ca565b905060008167ffffffffffffffff811115612d3757612d37613d7c565b604051908082528060200260200182016040528015612d60578160200160208202803683370190505b50905060005b82811015612daa57612d788582613792565b828281518110612d8a57612d8a613cf6565b6001600160a01b0390921660209283029190910190910152600101612d66565b509392505050565b604080518082019091526011815270696e76616c6964206d73672e76616c756560781b60208201526000903415612dfc5760405162461bcd60e51b81526004016108ab9190613a71565b506000612e07612cdc565b90508015612ed957612e17613a23565b81817f000000000000000000000000000000000000000000000000000000000000000060038110612e4a57612e4a613cf6565b60200201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016634515cef382612e88856137d7565b6040518363ffffffff1660e01b8152600401612ea5929190613d44565b600060405180830381600087803b158015612ebf57600080fd5b505af1158015612ed3573d6000803e3d6000fd5b50505050505b6000612ee3612a57565b90508015612f7957612ef3613a05565b8181600d5460028110612f0857612f08613cf6565b6020020152600b546001600160a01b0316630b4c7e4d82612f28856137f2565b6040518363ffffffff1660e01b8152600401612f45929190613d0c565b600060405180830381600087803b158015612f5f57600080fd5b505af1158015612f73573d6000803e3d6000fd5b50505050505b612f81612ae3565b612f8e5760009250505090565b600c5460405163303acfe760e11b815260048101919091526001602482015273f403c135812408bfbe8713b5a23a04b3d48aae31906360759fce906044016020604051808303816000875af1158015612feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300f9190613b87565b61301c5760009250505090565b60019250505090565b6000670de0b6b3a764000061303a8385613bd1565b61227b9190613c06565b600061304e612297565b600354604051632550332960e11b81526001600160a01b038681166004830152918216602482015260448101859052911690634aa0665290606401602060405180830381865afa1580156130a6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227b9190613ba2565b60006120d7825490565b6040516355b30b1960e01b81526001600160a01b03821660048201527390e00ace148ca3b23ac1bc8c240c2a7dd9c2d7f5906355b30b1990602401602060405180830381865afa15801561312c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131509190613ba2565b5050565b600061315e612b14565b905080156131de57600954604051636197390160e11b815260048101839052600060248201526001600160a01b039091169063c32e7202906044016020604051808303816000875af11580156131b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131dc9190613b87565b505b60006131e8612ae3565b9050801561315057600b54600d546001600160a01b0390911690631a4d01d29083906132138261380d565b6040516001600160e01b031960e086901b1681526004810193909352600f9190910b60248301526044820152606401600060405180830381600087803b15801561325c57600080fd5b505af1158015613270573d6000803e3d6000fd5b505050505050565b60006132cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166122699092919063ffffffff16565b80519091501561226457808060200190518101906132eb9190613b87565b6122645760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108ab565b6060824710156133ab5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016108ab565b6001600160a01b0385163b6134025760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108ab565b600080866001600160a01b0316858760405161341e9190613d92565b60006040518083038185875af1925050503d806000811461345b576040519150601f19603f3d011682016040523d82523d6000602084013e613460565b606091505b5091509150613470828286613831565b979650505050505050565b60008181526001830160205260408120546134c2575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556120d7565b5060006120d7565b6040516001600160a01b03831660248201526044810182905261226490849063a9059cbb60e01b9060640161222d565b60006120d7600f54670de0b6b3a76400006135159190613c3f565b61177f8461386a565b60006120d7600854670de0b6b3a76400006135399190613c3f565b61177f846138fe565b6000818152600183016020526040812054801561362b576000613566600183613c28565b855490915060009061357a90600190613c28565b90508181146135df57600086600001828154811061359a5761359a613cf6565b90600052602060002001549050808760000184815481106135bd576135bd613cf6565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806135f0576135f0613dae565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506120d7565b60009150506120d7565b6004546001600160a01b0316806136495750565b60065480156136f4576040516370a0823160e01b8152306004820152734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b9060009082906370a0823190602401602060405180830381865afa1580156136a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ca9190613ba2565b905080156136f1576136f1846136e08386613025565b6001600160a01b03851691906134ca565b50505b6005548015612264576040516370a0823160e01b815230600482015273d533a949740bb3306d119cc777fa900ba034cd529060009082906370a0823190602401602060405180830381865afa158015613751573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137759190613ba2565b9050801561378b5761378b856136e08386613025565b5050505050565b600061227b83836139db565b60006120d7600f54670de0b6b3a76400006137b99190613c28565b61177f84612c48565b60008161303a670de0b6b3a764000085613bd1565b60006120d7600e54670de0b6b3a76400006135159190613c28565b60006120d7600754670de0b6b3a76400006135399190613c28565b60006120d7600854670de0b6b3a76400006138289190613c28565b61177f84612b45565b6060831561384057508161227b565b8251156138505782518084602001fd5b8160405162461bcd60e51b81526004016108ab9190613a71565b60006120d77f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f19190613ba2565b601054612c429085613bd1565b60006120d7600b60009054906101000a90046001600160a01b03166001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015613956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061397a9190613ba2565b612c427f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c17573d6000803e3d6000fd5b60008260000182815481106139f2576139f2613cf6565b9060005260206000200154905092915050565b60405180604001604052806002906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60005b83811015613a5c578181015183820152602001613a44565b83811115613a6b576000848401525b50505050565b6020815260008251806020840152613a90816040850160208701613a41565b601f01601f19169190910160400192915050565b6001600160a01b0381168114613ab957600080fd5b50565b600060208284031215613ace57600080fd5b813561227b81613aa4565b600060208284031215613aeb57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015613b335783516001600160a01b031683529284019291840191600101613b0e565b50909695505050505050565b600080600060608486031215613b5457600080fd5b833592506020840135613b6681613aa4565b929592945050506040919091013590565b80518015158114610a1057600080fd5b600060208284031215613b9957600080fd5b61227b82613b77565b600060208284031215613bb457600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615613beb57613beb613bbb565b500290565b634e487b7160e01b600052601260045260246000fd5b600082613c2357634e487b7160e01b600052601260045260246000fd5b500490565b600082821015613c3a57613c3a613bbb565b500390565b60008219821115613c5257613c52613bbb565b500190565b600060208284031215613c6957600080fd5b815161227b81613aa4565b60008060008060008060c08789031215613c8d57600080fd5b8651613c9881613aa4565b6020880151909650613ca981613aa4565b6040880151909550613cba81613aa4565b6060880151909450613ccb81613aa4565b6080880151909350613cdc81613aa4565b9150613cea60a08801613b77565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b60608101818460005b6002811015613d34578151835260209283019290910190600101613d15565b5050508260408301529392505050565b60808101818460005b6003811015613d6c578151835260209283019290910190600101613d4d565b5050508260608301529392505050565b634e487b7160e01b600052604160045260246000fd5b60008251613da4818460208701613a41565b9190910192915050565b634e487b7160e01b600052603160045260246000fdfe756e617574686f72697a65642061636365737300000000000000000000000000a2646970667358221220bb517ece7b44df8df7518e0672eff8afb20b6b90638a7706435dc05887a68cb164736f6c634300080a00330000000000000000000000001a358b158729596ba25059068569afd2bab55d34000000000000000000000000b0cf1453a14c433d95a1b2eaef9c3bda16d7d32600000000000000000000000000000000000000000000000000000000000000280000000000000000000000005a6a4d54456819380173272a5e8e9b9904bdf41b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c70000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a298d39715ae492e4caf3ccb33cbf57abc5238d7
Deployed Bytecode
0x60806040526004361061025b5760003560e01c80637bdcdaff11610144578063c2bddf31116100b6578063e9eb50881161007a578063e9eb50881461070f578063ecf8db0a1461072f578063fbfa77cf1461074f578063fc0e74d114610783578063fdc0bfca14610798578063ff0af85b146107ae57600080fd5b8063c2bddf3114610692578063c7b9d530146106b2578063d0e30db0146106d2578063dbbd47d4146106da578063df22a747146106ef57600080fd5b80639ec5a894116101085780639ec5a894146105e4578063aa6a8caf14610604578063b69ef8a814610624578063b6ed67a814610639578063bf86d6901461064f578063c2b18aa01461067057600080fd5b80637bdcdaff1461056d578063853828b61461058357806386993bef14610598578063938511a7146105ae5780639b61a924146105ce57600080fd5b80633778851e116101dd57806356be5f71116101a157806356be5f71146104af57806361240eea146104c5578063621e8fe1146104d957806369cbb00d146104f95780636f307dc31461052d57806370aa17261461054d57600080fd5b80633778851e146104045780633d509c971461042457806344d32ee9146104445780634641257d1461047857806349cabcdf1461048d57600080fd5b8063218751b211610224578063218751b21461035a578063283f3b561461037a5780632e1a7d4d146103ae5780633082538f146103ce578063313c06a0146103e457600080fd5b8062435da51461026057806306fdde03146102ac5780631a55820d146102e85780631c03e6cc1461030c5780631fe4a6861461033c575b600080fd5b34801561026c57600080fd5b507f00000000000000000000000046dcde86b25a3f3b61eadd6b7225f4e2721c0e235b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102b857600080fd5b50604080518082018252600d81526c09acae4dea8e4d290dee086ecf609b1b602082015290516102a39190613a71565b3480156102f457600080fd5b506102fe60085481565b6040519081526020016102a3565b34801561031857600080fd5b5061032c610327366004613abc565b6107c9565b60405190151581526020016102a3565b34801561034857600080fd5b506000546001600160a01b031661028f565b34801561036657600080fd5b50600b5461028f906001600160a01b031681565b34801561038657600080fd5b5061028f7f000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c781565b3480156103ba57600080fd5b5061032c6103c9366004613ad9565b610a15565b3480156103da57600080fd5b506102fe60105481565b3480156103f057600080fd5b50600a5461028f906001600160a01b031681565b34801561041057600080fd5b506102fe61041f366004613ad9565b610ad6565b34801561043057600080fd5b5061032c61043f366004613abc565b610bcb565b34801561045057600080fd5b5061028f7f0000000000000000000000006c3f90f043a72fa612cbac8115ee7e52bde6e49081565b34801561048457600080fd5b506102fe610cfe565b34801561049957600080fd5b506104ad6104a8366004613ad9565b610d75565b005b3480156104bb57600080fd5b506102fe60075481565b3480156104d157600080fd5b50600061032c565b3480156104e557600080fd5b5060045461028f906001600160a01b031681565b34801561050557600080fd5b506102fe7f000000000000000000000000000000000000000000000000000000000000000181565b34801561053957600080fd5b5060035461028f906001600160a01b031681565b34801561055957600080fd5b506104ad610568366004613ad9565b610e92565b34801561057957600080fd5b506102fe600d5481565b34801561058f57600080fd5b506102fe61104f565b3480156105a457600080fd5b506102fe600c5481565b3480156105ba57600080fd5b506104ad6105c9366004613ad9565b61110f565b3480156105da57600080fd5b506102fe60065481565b3480156105f057600080fd5b5060095461028f906001600160a01b031681565b34801561061057600080fd5b506104ad61061f366004613ad9565b611225565b34801561063057600080fd5b506102fe61133b565b34801561064557600080fd5b506102fe600e5481565b34801561065b57600080fd5b5060035461032c90600160a01b900460ff1681565b34801561067c57600080fd5b5061068561138b565b6040516102a39190613af2565b34801561069e57600080fd5b506104ad6106ad366004613abc565b611397565b3480156106be57600080fd5b506104ad6106cd366004613abc565b611522565b61032c6115bf565b3480156106e657600080fd5b506102fe6116c4565b3480156106fb57600080fd5b506104ad61070a366004613b3f565b61196d565b34801561071b57600080fd5b506104ad61072a366004613ad9565b611c88565b34801561073b57600080fd5b506104ad61074a366004613ad9565b611d9e565b34801561075b57600080fd5b5061028f7f0000000000000000000000001a358b158729596ba25059068569afd2bab55d3481565b34801561078f57600080fd5b506104ad611f5b565b3480156107a457600080fd5b506102fe600f5481565b3480156107ba57600080fd5b506102fe60055481565b905090565b60007f00000000000000000000000046dcde86b25a3f3b61eadd6b7225f4e2721c0e23604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108699190613b87565b604051806040016040528060138152602001600080516020613dc5833981519152815250906108b45760405162461bcd60e51b81526004016108ab9190613a71565b60405180910390fd5b506001600160a01b038216734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b148015906108f057506003546001600160a01b03838116911614155b801561091957506001600160a01b03821673d533a949740bb3306d119cc777fa900ba034cd5214155b60405180604001604052806014815260200173125b9d985b1a59081d1bdad95b881d1bc818591960621b815250906109645760405162461bcd60e51b81526004016108ab9190613a71565b506001600160a01b0382166000908152600260205260409020541561098b57506000919050565b610996600183612282565b5060006109a1612297565b90506109b86001600160a01b03841682600061211c565b6109ce6001600160a01b0384168260001961211c565b6040516001600160a01b03841681527f851bbb4304bf0768ed98b97e429b5bd1dcc1f194b36cd1650f40293e951ae3939060200160405180910390a160019150505b919050565b6040805180820190915260138152600080516020613dc58339815191526020820152600090336001600160a01b037f0000000000000000000000001a358b158729596ba25059068569afd2bab55d341614610a835760405162461bcd60e51b81526004016108ab9190613a71565b5081610a9157506000919050565b610a9a826122cb565b6040518281527f5b6b431d4476a211bb7d41c20d1aab9ae2321deee0d20be3d9fc9b1093fa6e3d906020015b60405180910390a1506001919050565b600080734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4f9190613ba2565b90506000610b678269152d02c7e14af68000006125a0565b90506103e88110610b7c575060009392505050565b6103e881810390600090610b908388613bd1565b610b9a9190613c06565b90506000610bb3856a52b7d2dcc80cd2e4000000613c28565b905080821115610bc1578091505b5095945050505050565b60007f00000000000000000000000046dcde86b25a3f3b61eadd6b7225f4e2721c0e23604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6b9190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090610cad5760405162461bcd60e51b81526004016108ab9190613a71565b50610cb96001836125b9565b610cc557506000919050565b6040516001600160a01b03831681527f36bd04094fa067bb9471a8fbdb0a6e8a43424a2566ad3a740c88973fa40a311890602001610ac6565b6040805180820190915260138152600080516020613dc58339815191526020820152600090336001600160a01b037f0000000000000000000000001a358b158729596ba25059068569afd2bab55d341614610d6c5760405162461bcd60e51b81526004016108ab9190613a71565b506107c46125ce565b7f00000000000000000000000046dcde86b25a3f3b61eadd6b7225f4e2721c0e23604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610def573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e139190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090610e555760405162461bcd60e51b81526004016108ab9190613a71565b5060078190556040518181527f4ede3e4e9f7997fda6ff4a12d6c43d5c9e1e2055065cbc15f902f504f72dc8c0906020015b60405180910390a150565b7f00000000000000000000000046dcde86b25a3f3b61eadd6b7225f4e2721c0e23604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610f0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f309190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090610f725760405162461bcd60e51b81526004016108ab9190613a71565b5060408051808201909152600e81526d1a5b9d985b1a5908185b5bdd5b9d60921b6020820152670de0b6b3a7640000821115610fc15760405162461bcd60e51b81526004016108ab9190613a71565b506004546001600160a01b031661101a5760405162461bcd60e51b815260206004820152601d60248201527f436f6d6d756e6974792072657365727665206d7573742062652073657400000060448201526064016108ab565b60058190556040518181527f1a8542dffa4956932e66916113e6a123e123956172fbc0e2e59df92b8a87d8e690602001610e87565b6040805180820190915260138152600080516020613dc58339815191526020820152600090336001600160a01b037f0000000000000000000000001a358b158729596ba25059068569afd2bab55d3416146110bd5760405162461bcd60e51b81526004016108ab9190613a71565b5060006110c861292e565b9050806110d757600091505090565b6040518181527f3d5a341dc6a12221fcf31279cef3771f8fad757b2d9261f97605ccc17c2574249060200160405180910390a1919050565b7f00000000000000000000000046dcde86b25a3f3b61eadd6b7225f4e2721c0e23604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ad9190613b87565b604051806040016040528060138152602001600080516020613dc5833981519152815250906111ef5760405162461bcd60e51b81526004016108ab9190613a71565b50600e8190556040518181527fe6b4374e594cac6d717f89735f722a01c53affe6a4603ed44e09004666b7a6f390602001610e87565b7f00000000000000000000000046dcde86b25a3f3b61eadd6b7225f4e2721c0e23604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa15801561129f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c39190613b87565b604051806040016040528060138152602001600080516020613dc5833981519152815250906113055760405162461bcd60e51b81526004016108ab9190613a71565b50600f8190556040518181527f8b8ad8032596ef90599a67881aed48dba49c88dd982cd479440bfcee796dcf8b90602001610e87565b6000611379611348612a57565b61136a611353612ae3565b61135b612b14565b6113659190613c3f565b612b45565b6113749190613c3f565b612c48565b611381612cdc565b6107c49190613c3f565b60606107c46001612d0d565b7f00000000000000000000000046dcde86b25a3f3b61eadd6b7225f4e2721c0e23604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611411573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114359190613b87565b604051806040016040528060138152602001600080516020613dc5833981519152815250906114775760405162461bcd60e51b81526004016108ab9190613a71565b5060408051808201909152601881527f7a65726f2061646472657373206e6f7420616c6c6f776564000000000000000060208201526001600160a01b0382166114d35760405162461bcd60e51b81526004016108ab9190613a71565b50600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f17d7ba6682f162782054b119192f8e5b98fe7090b4bec7a55fc7075d9cd859ee90602001610e87565b6000546040805180820190915260138152600080516020613dc58339815191526020820152906001600160a01b031633146115705760405162461bcd60e51b81526004016108ab9190613a71565b50600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f46d58e3fa07bf19b1d27240f0e286b27e9f7c1b0d88933333fe833b60eec541290602001610e87565b6040805180820190915260138152600080516020613dc58339815191526020820152600090336001600160a01b037f0000000000000000000000001a358b158729596ba25059068569afd2bab55d34161461162d5760405162461bcd60e51b81526004016108ab9190613a71565b5060035460408051808201909152601481527329ba3930ba32b3bc9034b99039b43aba3237bbb760611b602082015290600160a01b900460ff16156116855760405162461bcd60e51b81526004016108ab9190613a71565b5061168e612db2565b6116985750600090565b6040517fed21248cb703b524cc0029bb8669df941baca560163a3bc6ad184e7e9c26807090600090a190565b6009546040516246613160e11b81523060048201526000916001600160a01b03169082908290628cc26290602401602060405180830381865afa15801561170f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117339190613ba2565b9050806117435760009250505090565b600061178a734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b611785600654670de0b6b3a76400006117769190613c28565b61177f86610ad6565b90613025565b613044565b6117c273d533a949740bb3306d119cc777fa900ba034cd52611785600554670de0b6b3a76400006117bb9190613c28565b8690613025565b6117cc9190613c3f565b905060006117da60016130ca565b905060005b8181101561196357604051632061aa2360e11b8152600481018290526000906001600160a01b038716906340c3544690602401602060405180830381865afa15801561182f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118539190613c57565b90506000816001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015611895573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b99190613c57565b6001600160a01b0381166000908152600260205260409020549091506118e057505061195b565b6040516246613160e11b815230600482015261194c9082906001600160a01b03851690628cc26290602401602060405180830381865afa158015611928573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117859190613ba2565b6119569086613c3f565b945050505b6001016117df565b5090949350505050565b7f00000000000000000000000046dcde86b25a3f3b61eadd6b7225f4e2721c0e23604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa1580156119e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0b9190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090611a4d5760405162461bcd60e51b81526004016108ab9190613a71565b50611a57826130d4565b611a5f6125ce565b50611a68613154565b600c839055600d819055604051631526fe2760e01b8152600481018490526000908190819073f403c135812408bfbe8713b5a23a04b3d48aae3190631526fe279060240160c060405180830381865afa158015611ac9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aed9190613c74565b95505094505050925080156040518060400160405280601081526020016f2837b7b61034b99039b43aba3237bbb760811b81525090611b3f5760405162461bcd60e51b81526004016108ab9190613a71565b50600a80546001600160a01b038086166001600160a01b03199283161790925560098054858416908316179055600b80548884169216919091179055611ba9907f0000000000000000000000006c3f90f043a72fa612cbac8115ee7e52bde6e4901686600061211c565b611bdf6001600160a01b037f0000000000000000000000006c3f90f043a72fa612cbac8115ee7e52bde6e490168660001961211c565b611c086001600160a01b03841673f403c135812408bfbe8713b5a23a04b3d48aae31600061211c565b611c326001600160a01b03841673f403c135812408bfbe8713b5a23a04b3d48aae3160001961211c565b611c3a612db2565b6040518060400160405280600e81526020016d19195c1bdcda5d0819985a5b195960921b81525090611c7f5760405162461bcd60e51b81526004016108ab9190613a71565b50505050505050565b7f00000000000000000000000046dcde86b25a3f3b61eadd6b7225f4e2721c0e23604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611d02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d269190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090611d685760405162461bcd60e51b81526004016108ab9190613a71565b5060088190556040518181527fb2861fed34a4613f8f25f46553a23408a3364ee9ddc4ef6714f0a81d856e41a790602001610e87565b7f00000000000000000000000046dcde86b25a3f3b61eadd6b7225f4e2721c0e23604051632474521560e21b815269676f7665726e616e636560b01b60048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c9190613b87565b604051806040016040528060138152602001600080516020613dc583398151915281525090611e7e5760405162461bcd60e51b81526004016108ab9190613a71565b5060408051808201909152600e81526d1a5b9d985b1a5908185b5bdd5b9d60921b6020820152670de0b6b3a7640000821115611ecd5760405162461bcd60e51b81526004016108ab9190613a71565b506004546001600160a01b0316611f265760405162461bcd60e51b815260206004820152601d60248201527f436f6d6d756e6974792072657365727665206d7573742062652073657400000060448201526064016108ab565b60068190556040518181527f2c3c7d70a1dfbfaf74447753b8a73e1323aa10b32b9209742db563671e14b13c90602001610e87565b6040805180820190915260138152600080516020613dc58339815191526020820152336001600160a01b037f0000000000000000000000001a358b158729596ba25059068569afd2bab55d341614611fc65760405162461bcd60e51b81526004016108ab9190613a71565b5060035460408051808201909152601481527329ba3930ba32b3bc9034b99039b43aba3237bbb760611b602082015290600160a01b900460ff161561201e5760405162461bcd60e51b81526004016108ab9190613a71565b506003805460ff60a01b1916600160a01b1790556040517f4426aa1fb73e391071491fcfe21a88b5c38a0a0333a1f6e77161470439704cf890600090a1565b6040516321f8a72160e01b81526a3937b632a6b0b730b3b2b960a91b60048201526000906001600160a01b038316906321f8a721906024015b602060405180830381865afa1580156120b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d79190613c57565b92915050565b6040516321f8a72160e01b81526c39bbb0b83832b92937baba32b960991b60048201526000906001600160a01b038316906321f8a72190602401612096565b8015806121965750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015612170573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121949190613ba2565b155b6122015760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016108ab565b6040516001600160a01b03831660248201526044810182905261226490849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613278565b505050565b6060612278848460008561334a565b90505b9392505050565b600061227b836001600160a01b03841661347b565b60006107c47f000000000000000000000000a298d39715ae492e4caf3ccb33cbf57abc5238d76001600160a01b03166120dd565b60006122d5612cdc565b905081811061234c57600354612315906001600160a01b03167f0000000000000000000000001a358b158729596ba25059068569afd2bab55d34846134ca565b6040518281527f5b6b431d4476a211bb7d41c20d1aab9ae2321deee0d20be3d9fc9b1093fa6e3d9060200160405180910390a15050565b808203600061235a826134fa565b90506000612366612a57565b6123709083613c28565b9050600061237d8261351e565b90506000612389612ae3565b6123939083613c28565b600954604051636197390160e11b815260048101839052600060248201529192506001600160a01b03169063c32e7202906044016020604051808303816000875af11580156123e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240a9190613b87565b6124175750505050505050565b61241f613a05565b8381600d546002811061243457612434613cf6565b6020020152600b5460405163e310327360e01b81526001600160a01b039091169063e31032739061246b9084908790600401613d0c565b600060405180830381600087803b15801561248557600080fd5b505af1158015612499573d6000803e3d6000fd5b505050506124a5613a23565b86817f0000000000000000000000000000000000000000000000000000000000000001600381106124d8576124d8613cf6565b60200201526040516327f6ba8360e21b81526001600160a01b037f000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c71690639fdaea0c9061252b9084908a90600401613d44565b600060405180830381600087803b15801561254557600080fd5b505af1158015612559573d6000803e3d6000fd5b505060035461259592506001600160a01b031690507f0000000000000000000000001a358b158729596ba25059068569afd2bab55d348b6134ca565b505050505050505050565b60008183816125b1576125b1613bf0565b049392505050565b600061227b836001600160a01b038416613542565b6000806125d9612cdc565b9050600960009054906101000a90046001600160a01b03166001600160a01b0316633d18b9126040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561262b57600080fd5b505af115801561263f573d6000803e3d6000fd5b5050505061264b613635565b6000612655612297565b604051633ff37e8f60e01b8152734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b600482015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260248201529091506001600160a01b03821690633ff37e8f906044016020604051808303816000875af11580156126cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f09190613ba2565b50604051633ff37e8f60e01b815273d533a949740bb3306d119cc777fa900ba034cd52600482015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260248201526001600160a01b03821690633ff37e8f906044016020604051808303816000875af1158015612765573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127899190613ba2565b50600061279660016130ca565b905060005b8181101561284a576001600160a01b038316633ff37e8f6127bd600184613792565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260248201526044016020604051808303816000875af115801561281d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128419190613ba2565b5060010161279b565b50600354604051633ff37e8f60e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260048201526001600160a01b03918216602482015290831690633ff37e8f906044016020604051808303816000875af11580156128b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d59190613ba2565b506000836128e1612cdc565b6128eb9190613c28565b90507f80f97f878e16410266694f134ddf012f2be424f54f8b5cafa107eccc51d00d588160405161291e91815260200190565b60405180910390a1949350505050565b6000612938613154565b6000612942612a57565b90508015612a06577f000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c76001600160a01b0316631a4d01d2827f00000000000000000000000000000000000000000000000000000000000000016129a48561379e565b6040516001600160e01b031960e086901b1681526004810193909352600f9190910b60248301526044820152606401600060405180830381600087803b1580156129ed57600080fd5b505af1158015612a01573d6000803e3d6000fd5b505050505b6000612a10612cdc565b905080612a205760009250505090565b6003546120d7906001600160a01b03167f0000000000000000000000001a358b158729596ba25059068569afd2bab55d34836134ca565b6040516370a0823160e01b81523060048201526000907f0000000000000000000000006c3f90f043a72fa612cbac8115ee7e52bde6e4906001600160a01b0316906370a08231906024015b602060405180830381865afa158015612abf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c49190613ba2565b600a546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401612aa2565b6009546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401612aa2565b60006120d77f000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c76001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ba8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bcc9190613ba2565b600b5460408051630176f71760e71b81529051612c42926001600160a01b03169163bb7b8b809160048083019260209291908290030181865afa158015612c17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3b9190613ba2565b8590613025565b906137c2565b60006120d77f000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c76001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ccf9190613ba2565b60105461177f9085613c06565b6003546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401612aa2565b60606000612d1a836130ca565b905060008167ffffffffffffffff811115612d3757612d37613d7c565b604051908082528060200260200182016040528015612d60578160200160208202803683370190505b50905060005b82811015612daa57612d788582613792565b828281518110612d8a57612d8a613cf6565b6001600160a01b0390921660209283029190910190910152600101612d66565b509392505050565b604080518082019091526011815270696e76616c6964206d73672e76616c756560781b60208201526000903415612dfc5760405162461bcd60e51b81526004016108ab9190613a71565b506000612e07612cdc565b90508015612ed957612e17613a23565b81817f000000000000000000000000000000000000000000000000000000000000000160038110612e4a57612e4a613cf6565b60200201526001600160a01b037f000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c716634515cef382612e88856137d7565b6040518363ffffffff1660e01b8152600401612ea5929190613d44565b600060405180830381600087803b158015612ebf57600080fd5b505af1158015612ed3573d6000803e3d6000fd5b50505050505b6000612ee3612a57565b90508015612f7957612ef3613a05565b8181600d5460028110612f0857612f08613cf6565b6020020152600b546001600160a01b0316630b4c7e4d82612f28856137f2565b6040518363ffffffff1660e01b8152600401612f45929190613d0c565b600060405180830381600087803b158015612f5f57600080fd5b505af1158015612f73573d6000803e3d6000fd5b50505050505b612f81612ae3565b612f8e5760009250505090565b600c5460405163303acfe760e11b815260048101919091526001602482015273f403c135812408bfbe8713b5a23a04b3d48aae31906360759fce906044016020604051808303816000875af1158015612feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300f9190613b87565b61301c5760009250505090565b60019250505090565b6000670de0b6b3a764000061303a8385613bd1565b61227b9190613c06565b600061304e612297565b600354604051632550332960e11b81526001600160a01b038681166004830152918216602482015260448101859052911690634aa0665290606401602060405180830381865afa1580156130a6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227b9190613ba2565b60006120d7825490565b6040516355b30b1960e01b81526001600160a01b03821660048201527390e00ace148ca3b23ac1bc8c240c2a7dd9c2d7f5906355b30b1990602401602060405180830381865afa15801561312c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131509190613ba2565b5050565b600061315e612b14565b905080156131de57600954604051636197390160e11b815260048101839052600060248201526001600160a01b039091169063c32e7202906044016020604051808303816000875af11580156131b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131dc9190613b87565b505b60006131e8612ae3565b9050801561315057600b54600d546001600160a01b0390911690631a4d01d29083906132138261380d565b6040516001600160e01b031960e086901b1681526004810193909352600f9190910b60248301526044820152606401600060405180830381600087803b15801561325c57600080fd5b505af1158015613270573d6000803e3d6000fd5b505050505050565b60006132cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166122699092919063ffffffff16565b80519091501561226457808060200190518101906132eb9190613b87565b6122645760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108ab565b6060824710156133ab5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016108ab565b6001600160a01b0385163b6134025760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108ab565b600080866001600160a01b0316858760405161341e9190613d92565b60006040518083038185875af1925050503d806000811461345b576040519150601f19603f3d011682016040523d82523d6000602084013e613460565b606091505b5091509150613470828286613831565b979650505050505050565b60008181526001830160205260408120546134c2575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556120d7565b5060006120d7565b6040516001600160a01b03831660248201526044810182905261226490849063a9059cbb60e01b9060640161222d565b60006120d7600f54670de0b6b3a76400006135159190613c3f565b61177f8461386a565b60006120d7600854670de0b6b3a76400006135399190613c3f565b61177f846138fe565b6000818152600183016020526040812054801561362b576000613566600183613c28565b855490915060009061357a90600190613c28565b90508181146135df57600086600001828154811061359a5761359a613cf6565b90600052602060002001549050808760000184815481106135bd576135bd613cf6565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806135f0576135f0613dae565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506120d7565b60009150506120d7565b6004546001600160a01b0316806136495750565b60065480156136f4576040516370a0823160e01b8152306004820152734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b9060009082906370a0823190602401602060405180830381865afa1580156136a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ca9190613ba2565b905080156136f1576136f1846136e08386613025565b6001600160a01b03851691906134ca565b50505b6005548015612264576040516370a0823160e01b815230600482015273d533a949740bb3306d119cc777fa900ba034cd529060009082906370a0823190602401602060405180830381865afa158015613751573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137759190613ba2565b9050801561378b5761378b856136e08386613025565b5050505050565b600061227b83836139db565b60006120d7600f54670de0b6b3a76400006137b99190613c28565b61177f84612c48565b60008161303a670de0b6b3a764000085613bd1565b60006120d7600e54670de0b6b3a76400006135159190613c28565b60006120d7600754670de0b6b3a76400006135399190613c28565b60006120d7600854670de0b6b3a76400006138289190613c28565b61177f84612b45565b6060831561384057508161227b565b8251156138505782518084602001fd5b8160405162461bcd60e51b81526004016108ab9190613a71565b60006120d77f000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c76001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f19190613ba2565b601054612c429085613bd1565b60006120d7600b60009054906101000a90046001600160a01b03166001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015613956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061397a9190613ba2565b612c427f000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c76001600160a01b031663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c17573d6000803e3d6000fd5b60008260000182815481106139f2576139f2613cf6565b9060005260206000200154905092915050565b60405180604001604052806002906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b60005b83811015613a5c578181015183820152602001613a44565b83811115613a6b576000848401525b50505050565b6020815260008251806020840152613a90816040850160208701613a41565b601f01601f19169190910160400192915050565b6001600160a01b0381168114613ab957600080fd5b50565b600060208284031215613ace57600080fd5b813561227b81613aa4565b600060208284031215613aeb57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015613b335783516001600160a01b031683529284019291840191600101613b0e565b50909695505050505050565b600080600060608486031215613b5457600080fd5b833592506020840135613b6681613aa4565b929592945050506040919091013590565b80518015158114610a1057600080fd5b600060208284031215613b9957600080fd5b61227b82613b77565b600060208284031215613bb457600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615613beb57613beb613bbb565b500290565b634e487b7160e01b600052601260045260246000fd5b600082613c2357634e487b7160e01b600052601260045260246000fd5b500490565b600082821015613c3a57613c3a613bbb565b500390565b60008219821115613c5257613c52613bbb565b500190565b600060208284031215613c6957600080fd5b815161227b81613aa4565b60008060008060008060c08789031215613c8d57600080fd5b8651613c9881613aa4565b6020880151909650613ca981613aa4565b6040880151909550613cba81613aa4565b6060880151909450613ccb81613aa4565b6080880151909350613cdc81613aa4565b9150613cea60a08801613b77565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b60608101818460005b6002811015613d34578151835260209283019290910190600101613d15565b5050508260408301529392505050565b60808101818460005b6003811015613d6c578151835260209283019290910190600101613d4d565b5050508260608301529392505050565b634e487b7160e01b600052604160045260246000fd5b60008251613da4818460208701613a41565b9190910192915050565b634e487b7160e01b600052603160045260246000fdfe756e617574686f72697a65642061636365737300000000000000000000000000a2646970667358221220bb517ece7b44df8df7518e0672eff8afb20b6b90638a7706435dc05887a68cb164736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001a358b158729596ba25059068569afd2bab55d34000000000000000000000000b0cf1453a14c433d95a1b2eaef9c3bda16d7d32600000000000000000000000000000000000000000000000000000000000000280000000000000000000000005a6a4d54456819380173272a5e8e9b9904bdf41b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c70000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a298d39715ae492e4caf3ccb33cbf57abc5238d7
-----Decoded View---------------
Arg [0] : vault_ (address): 0x1a358b158729596bA25059068569aFd2bAb55D34
Arg [1] : strategist_ (address): 0xb0Cf1453A14c433d95a1b2eAEf9c3BDA16d7d326
Arg [2] : convexPid_ (uint256): 40
Arg [3] : curvePool_ (address): 0x5a6A4D54456819380173272A5E8E9B9904BdF41B
Arg [4] : curveIndex_ (uint256): 1
Arg [5] : curveHopPool_ (address): 0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7
Arg [6] : curveHopIndex_ (uint256): 1
Arg [7] : addressProvider_ (address): 0xa298d39715AE492e4CAF3Ccb33cBF57abC5238d7
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000001a358b158729596ba25059068569afd2bab55d34
Arg [1] : 000000000000000000000000b0cf1453a14c433d95a1b2eaef9c3bda16d7d326
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000028
Arg [3] : 0000000000000000000000005a6a4d54456819380173272a5e8e9b9904bdf41b
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [5] : 000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c7
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [7] : 000000000000000000000000a298d39715ae492e4caf3ccb33cbf57abc5238d7
Deployed Bytecode Sourcemap
109253:14750:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42425:108;;;;;;;;;;-1:-1:-1;42977:13:0;42425:108;;;-1:-1:-1;;;;;199:32:1;;;181:51;;169:2;154:18;42425:108:0;;;;;;;;114429:102;;;;;;;;;;-1:-1:-1;114501:22:0;;;;;;;;;;;-1:-1:-1;;;114501:22:0;;;;114429:102;;;;114501:22;114429:102;:::i;92162:36::-;;;;;;;;;;;;;;;;;;;1040:25:1;;;1028:2;1013:18;92162:36:0;894:177:1;100761:608:0;;;;;;;;;;-1:-1:-1;100761:608:0;;;;;:::i;:::-;;:::i;:::-;;;1629:14:1;;1622:22;1604:41;;1592:2;1577:18;100761:608:0;1464:187:1;103180:100:0;;;;;;;;;;-1:-1:-1;103234:7:0;103261:11;-1:-1:-1;;;;;103261:11:0;103180:100;;92405:30;;;;;;;;;;-1:-1:-1;92405:30:0;;;;-1:-1:-1;;;;;92405:30:0;;;109429:43;;;;;;;;;;;;;;;95935:211;;;;;;;;;;-1:-1:-1;95935:211:0;;;;;:::i;:::-;;:::i;109891:32::-;;;;;;;;;;;;;;;;92359:16;;;;;;;;;;-1:-1:-1;92359:16:0;;;;-1:-1:-1;;;;;92359:16:0;;;29290:867;;;;;;;;;;-1:-1:-1;29290:867:0;;;;;:::i;:::-;;:::i;101553:220::-;;;;;;;;;;-1:-1:-1;101553:220:0;;;;;:::i;:::-;;:::i;109509:29::-;;;;;;;;;;;;;;;96929:101;;;;;;;;;;;;;:::i;99322:254::-;;;;;;;;;;-1:-1:-1;99322:254:0;;;;;:::i;:::-;;:::i;:::-;;92051:35;;;;;;;;;;;;;;;;104043:96;;;;;;;;;;-1:-1:-1;104102:4:0;104043:96;;91729:31;;;;;;;;;;-1:-1:-1;91729:31:0;;;;-1:-1:-1;;;;;91729:31:0;;;109572:38;;;;;;;;;;;;;;;91595:24;;;;;;;;;;-1:-1:-1;91595:24:0;;;;-1:-1:-1;;;;;91595:24:0;;;98026:446;;;;;;;;;;-1:-1:-1;98026:446:0;;;;;:::i;:::-;;:::i;92531:25::-;;;;;;;;;;;;;;;;96397:310;;;;;;;;;;;;;:::i;92456:24::-;;;;;;;;;;;;;;;;112049:272;;;;;;;;;;-1:-1:-1;112049:272:0;;;;;:::i;:::-;;:::i;91963:39::-;;;;;;;;;;;;;;;;92275:29;;;;;;;;;;-1:-1:-1;92275:29:0;;;;-1:-1:-1;;;;;92275:29:0;;;112560:278;;;;;;;;;;-1:-1:-1;112560:278:0;;;;;:::i;:::-;;:::i;114207:214::-;;;;;;;;;;;;;:::i;109653:38::-;;;;;;;;;;;;;;;;91649:22;;;;;;;;;;-1:-1:-1;91649:22:0;;;;-1:-1:-1;;;91649:22:0;;;;;;103452:123;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;97560:281::-;;;;;;;;;;-1:-1:-1;97560:281:0;;;;;:::i;:::-;;:::i;100224:220::-;;;;;;;;;;-1:-1:-1;100224:220:0;;;;;:::i;:::-;;:::i;95423:199::-;;;:::i;102003:1045::-;;;;;;;;;;;;;:::i;113312:887::-;;;;;;;;;;-1:-1:-1;113312:887:0;;;;;:::i;:::-;;:::i;99800:260::-;;;;;;;;;;-1:-1:-1;99800:260:0;;;;;:::i;:::-;;:::i;98657:446::-;;;;;;;;;;-1:-1:-1;98657:446:0;;;;;:::i;:::-;;:::i;91824:30::-;;;;;;;;;;;;;;;97117:166;;;;;;;;;;;;;:::i;109771:39::-;;;;;;;;;;;;;;;;91875;;;;;;;;;;;;;;;;42511:14;42504:21;;42425:108;:::o;100761:608::-;100843:4;42977:13;41666:52;;-1:-1:-1;;;41666:52:0;;-1:-1:-1;;;41666:52:0;;;3956:25:1;41707:10:0;3997:18:1;;;3990:60;-1:-1:-1;;;;;41666:22:0;;;;;;;3929:18:1;;41666:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41720:25;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41720:25:0;;;41658:88;;;;;-1:-1:-1;;;41658:88:0;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;;;;;100882:23:0;::::1;90825:42;100882:23;::::0;::::1;::::0;:56:::1;;-1:-1:-1::0;100927:10:0::1;::::0;-1:-1:-1;;;;;100909:29:0;;::::1;100927:10:::0;::::1;100909:29;;100882:56;:83;;;;-1:-1:-1::0;;;;;;100942:23:0;::::1;90729:42;100942:23;;100882:83;100980:26;;;;;;;;;;;;;-1:-1:-1::0;;;100980:26:0::1;;::::0;100860:157:::1;;;;;-1:-1:-1::0;;;100860:157:0::1;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;;11577:23:0;;11523:4;6979:19;;;:12;:19;;;;;;:24;101028:48:::1;;-1:-1:-1::0;101071:5:0::1;100761:608:::0;;;:::o;101028:48::-:1;101087:25;:13;101105:6:::0;101087:17:::1;:25::i;:::-;;101123:22;101156:16;:14;:16::i;:::-;101123:50:::0;-1:-1:-1;101184:45:0::1;-1:-1:-1::0;;;;;101184:26:0;::::1;101123:50:::0;101227:1:::1;101184:26;:45::i;:::-;101240:61;-1:-1:-1::0;;;;;101240:26:0;::::1;101267:14:::0;-1:-1:-1;;101240:26:0::1;:61::i;:::-;101317:22;::::0;-1:-1:-1;;;;;199:32:1;;181:51;;101317:22:0::1;::::0;169:2:1;154:18;101317:22:0::1;;;;;;;101357:4;101350:11;;;41757:1;100761:608:::0;;;:::o;95935:211::-;93896:25;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;93896:25:0;;;;96007:4;;93875:10;-1:-1:-1;;;;;93889:5:0;93875:19;;93867:55;;;;-1:-1:-1;;;93867:55:0;;;;;;;;:::i;:::-;-1:-1:-1;96028:12:0;96024:30:::1;;-1:-1:-1::0;96049:5:0::1;100761:608:::0;;;:::o;96024:30::-:1;96065:18;96075:7;96065:9;:18::i;:::-;96099:17;::::0;1040:25:1;;;96099:17:0::1;::::0;1028:2:1;1013:18;96099:17:0::1;;;;;;;;-1:-1:-1::0;96134:4:0::1;95935:211:::0;;;:::o;29290:867::-;29356:7;29410:22;29224:42;-1:-1:-1;;;;;29435:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29410:49;-1:-1:-1;29501:20:0;29524:40;29410:49;28965:10;29524:27;:40::i;:::-;29501:63;;29055:4;29626:12;:28;29622:42;;-1:-1:-1;29663:1:0;;29290:867;-1:-1:-1;;;29290:867:0:o;29622:42::-;29055:4;28589:5;;;;29709:17;;29892:21;28589:5;29892:9;:21;:::i;:::-;29891:38;;;;:::i;:::-;29871:58;-1:-1:-1;30003:21:0;30027:28;30041:14;29121;30027:28;:::i;:::-;30003:52;;30082:13;30070:9;:25;30066:56;;;30109:13;30097:25;;30066:56;-1:-1:-1;30140:9:0;29290:867;-1:-1:-1;;;;;29290:867:0:o;101553:220::-;101638:4;42977:13;41666:52;;-1:-1:-1;;;41666:52:0;;-1:-1:-1;;;41666:52:0;;;3956:25:1;41707:10:0;3997:18:1;;;3990:60;-1:-1:-1;;;;;41666:22:0;;;;;;;3929:18:1;;41666:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41720:25;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41720:25:0;;;41658:88;;;;;-1:-1:-1;;;41658:88:0;;;;;;;;:::i;:::-;-1:-1:-1;101660:28:0::1;:13;101681:6:::0;101660:20:::1;:28::i;:::-;101655:47;;-1:-1:-1::0;101697:5:0::1;100761:608:::0;;;:::o;101655:47::-:1;101718:25;::::0;-1:-1:-1;;;;;199:32:1;;181:51;;101718:25:0::1;::::0;169:2:1;154:18;101718:25:0::1;14:224:1::0;96929:101:0;93896:25;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;93896:25:0;;;;96985:7;;93875:10;-1:-1:-1;;;;;93889:5:0;93875:19;;93867:55;;;;-1:-1:-1;;;93867:55:0;;;;;;;;:::i;:::-;;97012:10:::1;:8;:10::i;99322:254::-:0;42977:13;41666:52;;-1:-1:-1;;;41666:52:0;;-1:-1:-1;;;41666:52:0;;;3956:25:1;41707:10:0;3997:18:1;;;3990:60;-1:-1:-1;;;;;41666:22:0;;;;;;;3929:18:1;;41666:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41720:25;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41720:25:0;;;41658:88;;;;;-1:-1:-1;;;41658:88:0;;;;;;;;:::i;:::-;-1:-1:-1;99462:20:0::1;:44:::0;;;99522:46:::1;::::0;1040:25:1;;;99522:46:0::1;::::0;1028:2:1;1013:18;99522:46:0::1;;;;;;;;99322:254:::0;:::o;98026:446::-;42977:13;41666:52;;-1:-1:-1;;;41666:52:0;;-1:-1:-1;;;41666:52:0;;;3956:25:1;41707:10:0;3997:18:1;;;3990:60;-1:-1:-1;;;;;41666:22:0;;;;;;;3929:18:1;;41666:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41720:25;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41720:25:0;;;41658:88;;;;;-1:-1:-1;;;41658:88:0;;;;;;;;:::i;:::-;-1:-1:-1;98227:20:0::1;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;98227:20:0::1;::::0;::::1;::::0;43597:4:::1;98182:43:::0;::::1;;98174:74;;;;-1:-1:-1::0;;;98174:74:0::1;;;;;;;;:::i;:::-;-1:-1:-1::0;98267:16:0::1;::::0;-1:-1:-1;;;;;98267:16:0::1;98259:72;;;::::0;-1:-1:-1;;;98259:72:0;;5617:2:1;98259:72:0::1;::::0;::::1;5599:21:1::0;5656:2;5636:18;;;5629:30;5695:31;5675:18;;;5668:59;5744:18;;98259:72:0::1;5415:353:1::0;98259:72:0::1;98342:24;:52:::0;;;98410:54:::1;::::0;1040:25:1;;;98410:54:0::1;::::0;1028:2:1;1013:18;98410:54:0::1;894:177:1::0;96397:310:0;96496:25;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;96496:25:0;;;;96447:7;;96475:10;-1:-1:-1;;;;;96489:5:0;96475:19;;96467:55;;;;-1:-1:-1;;;96467:55:0;;;;;;;;:::i;:::-;;96533:24;96560:14;:12;:14::i;:::-;96533:41;-1:-1:-1;96589:21:0;96585:35;;96619:1;96612:8;;;96397:310;:::o;96585:35::-;96636:29;;1040:25:1;;;96636:29:0;;1028:2:1;1013:18;96636:29:0;;;;;;;96683:16;96397:310;-1:-1:-1;96397:310:0:o;112049:272::-;42977:13;41666:52;;-1:-1:-1;;;41666:52:0;;-1:-1:-1;;;41666:52:0;;;3956:25:1;41707:10:0;3997:18:1;;;3990:60;-1:-1:-1;;;;;41666:22:0;;;;;;;3929:18:1;;41666:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41720:25;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41720:25:0;;;41658:88;;;;;-1:-1:-1;;;41658:88:0;;;;;;;;:::i;:::-;-1:-1:-1;112195:23:0::1;:50:::0;;;112261:52:::1;::::0;1040:25:1;;;112261:52:0::1;::::0;1028:2:1;1013:18;112261:52:0::1;894:177:1::0;112560:278:0;42977:13;41666:52;;-1:-1:-1;;;41666:52:0;;-1:-1:-1;;;41666:52:0;;;3956:25:1;41707:10:0;3997:18:1;;;3990:60;-1:-1:-1;;;;;41666:22:0;;;;;;;3929:18:1;;41666:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41720:25;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41720:25:0;;;41658:88;;;;;-1:-1:-1;;;41658:88:0;;;;;;;;:::i;:::-;-1:-1:-1;112708:24:0::1;:52:::0;;;112776:54:::1;::::0;1040:25:1;;;112776:54:0::1;::::0;1028:2:1;1013:18;112776:54:0::1;894:177:1::0;114207:214:0;114256:7;114332:81;114397:15;:13;:15::i;:::-;114351:43;114381:12;:10;:12::i;:::-;114362:16;:14;:16::i;:::-;:31;;;;:::i;:::-;114351:10;:43::i;:::-;:61;;;;:::i;:::-;114332:18;:81::i;:::-;114296:20;:18;:20::i;:::-;:117;;;;:::i;103452:123::-;103508:16;103544:23;:13;:21;:23::i;97560:281::-;42977:13;41666:52;;-1:-1:-1;;;41666:52:0;;-1:-1:-1;;;41666:52:0;;;3956:25:1;41707:10:0;3997:18:1;;;3990:60;-1:-1:-1;;;;;41666:22:0;;;;;;;3929:18:1;;41666:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41720:25;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41720:25:0;;;41658:88;;;;;-1:-1:-1;;;41658:88:0;;;;;;;;:::i;:::-;-1:-1:-1;97701:30:0::1;::::0;;;;::::1;::::0;;;::::1;::::0;;::::1;;::::0;::::1;::::0;-1:-1:-1;;;;;97668:31:0;::::1;97660:72;;;;-1:-1:-1::0;;;97660:72:0::1;;;;;;;;:::i;:::-;-1:-1:-1::0;97743:16:0::1;:36:::0;;-1:-1:-1;;;;;;97743:36:0::1;-1:-1:-1::0;;;;;97743:36:0;::::1;::::0;;::::1;::::0;;;97795:38:::1;::::0;181:51:1;;;97795:38:0::1;::::0;169:2:1;154:18;97795:38:0::1;14:224:1::0;100224:220:0;100319:11;;100332:25;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;100332:25:0;;;;;-1:-1:-1;;;;;100319:11:0;100305:10;:25;100297:61;;;;-1:-1:-1;;;100297:61:0;;;;;;;;:::i;:::-;-1:-1:-1;100369:11:0;:25;;-1:-1:-1;;;;;;100369:25:0;-1:-1:-1;;;;;100369:25:0;;;;;;;;100410:26;;181:51:1;;;100410:26:0;;169:2:1;154:18;100410:26:0;14:224:1;95423:199:0;93896:25;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;93896:25:0;;;;95487:4;;93875:10;-1:-1:-1;;;;;93889:5:0;93875:19;;93867:55;;;;-1:-1:-1;;;93867:55:0;;;;;;;;:::i;:::-;-1:-1:-1;95513:10:0::1;::::0;95525:23:::1;::::0;;;;::::1;::::0;;;95513:10:::1;95525:23:::0;;-1:-1:-1;;;95525:23:0::1;::::0;::::1;::::0;;-1:-1:-1;;;95513:10:0;::::1;;;95512:11;95504:45;;;;-1:-1:-1::0;;;95504:45:0::1;;;;;;;;:::i;:::-;;95565:10;:8;:10::i;:::-;95560:29;;-1:-1:-1::0;95584:5:0::1;96929:101:::0;:::o;95560:29::-:1;95605:9;::::0;::::1;::::0;;;::::1;95423:199:::0;:::o;102003:1045::-;102104:7;;102143:30;;-1:-1:-1;;;102143:30:0;;102167:4;102143:30;;;181:51:1;102058:7:0;;-1:-1:-1;;;;;102104:7:0;;102058;;102104;;102143:15;;154:18:1;;102143:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102122:51;-1:-1:-1;102188:15:0;102184:29;;102212:1;102205:8;;;;102003:1045;:::o;102184:29::-;102224:20;102400:167;90825:42;102471:81;102527:24;;43597:4;102510:41;;;;:::i;:::-;102471:28;102488:10;102471:16;:28::i;:::-;:38;;:81::i;:::-;102400:20;:167::i;:::-;102247:137;90729:42;102310:63;102348:24;;43597:4;102331:41;;;;:::i;:::-;102310:10;;:20;:63::i;102247:137::-;:320;;;;:::i;:::-;102224:343;;102578:15;102596:22;:13;:20;:22::i;:::-;102578:40;;102634:9;102629:382;102649:7;102645:1;:11;102629:382;;;102741:24;;-1:-1:-1;;;102741:24:0;;;;;1040:25:1;;;102695:28:0;;-1:-1:-1;;;;;102741:21:0;;;;;1013:18:1;;102741:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102695:71;;102781:20;102804:13;-1:-1:-1;;;;;102804:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11577:23:0;;11523:4;6979:19;;;:12;:19;;;;;;102781:50;;-1:-1:-1;102846:51:0;;102889:8;;;;102846:51;102963:35;;-1:-1:-1;;;102963:35:0;;102992:4;102963:35;;;181:51:1;102928:71:0;;102949:12;;-1:-1:-1;;;;;102963:20:0;;;;;154:18:1;;102963:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;102928:71::-;102912:87;;;;:::i;:::-;;;102680:331;;102629:382;28291:1;28287:5;102629:382;;;-1:-1:-1;103028:12:0;;102003:1045;-1:-1:-1;;;;102003:1045:0:o;113312:887::-;42977:13;41666:52;;-1:-1:-1;;;41666:52:0;;-1:-1:-1;;;41666:52:0;;;3956:25:1;41707:10:0;3997:18:1;;;3990:60;-1:-1:-1;;;;;41666:22:0;;;;;;;3929:18:1;;41666:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41720:25;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41720:25:0;;;41658:88;;;;;-1:-1:-1;;;41658:88:0;;;;;;;;:::i;:::-;;113477:30:::1;113496:10;113477:18;:30::i;:::-;113518:10;:8;:10::i;:::-;;113539:21;:19;:21::i;:::-;113571:9;:22:::0;;;113604:10:::1;:24:::0;;;113694:29:::1;::::0;-1:-1:-1;;;113694:29:0;;::::1;::::0;::::1;1040:25:1::0;;;-1:-1:-1;;;;;;90613:42:0::1;::::0;113694:17:::1;::::0;1013:18:1;;113694:29:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;113639:84;;;;;;;;;113743:8;113742:9;113753:19;;;;;;;;;;;;;-1:-1:-1::0;;;113753:19:0::1;;::::0;113734:39:::1;;;;;-1:-1:-1::0;;;113734:39:0::1;;;;;;;;:::i;:::-;-1:-1:-1::0;113784:2:0::1;:16:::0;;-1:-1:-1;;;;;113784:16:0;;::::1;-1:-1:-1::0;;;;;;113784:16:0;;::::1;;::::0;;;113811:7:::1;:34:::0;;;;::::1;::::0;;::::1;;::::0;;113856:9:::1;:37:::0;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;113904:40:::1;::::0;113911:5:::1;113904:25;113882:10:::0;113784:2:::1;113904:25;:40::i;:::-;113955:56;-1:-1:-1::0;;;;;113962:5:0::1;113955:25;113981:10:::0;-1:-1:-1;;113955:25:0::1;:56::i;:::-;114022:45;-1:-1:-1::0;;;;;114022:23:0;::::1;90613:42;114065:1;114022:23;:45::i;:::-;114078:61;-1:-1:-1::0;;;;;114078:23:0;::::1;90613:42;-1:-1:-1::0;;114078:23:0::1;:61::i;:::-;114158:10;:8;:10::i;:::-;114170:20;;;;;;;;;;;;;-1:-1:-1::0;;;114170:20:0::1;;::::0;114150:41:::1;;;;;-1:-1:-1::0;;;114150:41:0::1;;;;;;;;:::i;:::-;;113466:733;;;113312:887:::0;;;:::o;99800:260::-;42977:13;41666:52;;-1:-1:-1;;;41666:52:0;;-1:-1:-1;;;41666:52:0;;;3956:25:1;41707:10:0;3997:18:1;;;3990:60;-1:-1:-1;;;;;41666:22:0;;;;;;;3929:18:1;;41666:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41720:25;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41720:25:0;;;41658:88;;;;;-1:-1:-1;;;41658:88:0;;;;;;;;:::i;:::-;-1:-1:-1;99942:21:0::1;:46:::0;;;100004:48:::1;::::0;1040:25:1;;;100004:48:0::1;::::0;1028:2:1;1013:18;100004:48:0::1;894:177:1::0;98657:446:0;42977:13;41666:52;;-1:-1:-1;;;41666:52:0;;-1:-1:-1;;;41666:52:0;;;3956:25:1;41707:10:0;3997:18:1;;;3990:60;-1:-1:-1;;;;;41666:22:0;;;;;;;3929:18:1;;41666:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41720:25;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;41720:25:0;;;41658:88;;;;;-1:-1:-1;;;41658:88:0;;;;;;;;:::i;:::-;-1:-1:-1;98858:20:0::1;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;98858:20:0::1;::::0;::::1;::::0;43597:4:::1;98813:43:::0;::::1;;98805:74;;;;-1:-1:-1::0;;;98805:74:0::1;;;;;;;;:::i;:::-;-1:-1:-1::0;98898:16:0::1;::::0;-1:-1:-1;;;;;98898:16:0::1;98890:72;;;::::0;-1:-1:-1;;;98890:72:0;;5617:2:1;98890:72:0::1;::::0;::::1;5599:21:1::0;5656:2;5636:18;;;5629:30;5695:31;5675:18;;;5668:59;5744:18;;98890:72:0::1;5415:353:1::0;98890:72:0::1;98973:24;:52:::0;;;99041:54:::1;::::0;1040:25:1;;;99041:54:0::1;::::0;1028:2:1;1013:18;99041:54:0::1;894:177:1::0;97117:166:0;93896:25;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;93896:25:0;;;;93875:10;-1:-1:-1;;;;;93889:5:0;93875:19;;93867:55;;;;-1:-1:-1;;;93867:55:0;;;;;;;;:::i;:::-;-1:-1:-1;97185:10:0::1;::::0;97197:23:::1;::::0;;;;::::1;::::0;;;97185:10:::1;97197:23:::0;;-1:-1:-1;;;97197:23:0::1;::::0;::::1;::::0;;-1:-1:-1;;;97185:10:0;::::1;;;97184:11;97176:45;;;;-1:-1:-1::0;;;97176:45:0::1;;;;;;;;:::i;:::-;-1:-1:-1::0;97232:10:0::1;:17:::0;;-1:-1:-1;;;;97232:17:0::1;-1:-1:-1::0;;;97232:17:0::1;::::0;;97265:10:::1;::::0;::::1;::::0;97232:17;;97265:10:::1;97117:166::o:0;68709:186::-;68828:58;;-1:-1:-1;;;68828:58:0;;-1:-1:-1;;;68828:58:0;;;1040:25:1;68783:12:0;;-1:-1:-1;;;;;68828:19:0;;;;;1013:18:1;;68828:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68808:79;68709:186;-1:-1:-1;;68709:186:0:o;69891:194::-;70016:60;;-1:-1:-1;;;70016:60:0;;-1:-1:-1;;;70016:60:0;;;1040:25:1;69967:14:0;;-1:-1:-1;;;;;70016:19:0;;;;;1013:18:1;;70016:60:0;894:177:1;25522:616:0;25886:10;;;25885:62;;-1:-1:-1;25902:39:0;;-1:-1:-1;;;25902:39:0;;25926:4;25902:39;;;7430:34:1;-1:-1:-1;;;;;7500:15:1;;;7480:18;;;7473:43;25902:15:0;;;;;7365:18:1;;25902:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;25885:62;25863:166;;;;-1:-1:-1;;;25863:166:0;;7729:2:1;25863:166:0;;;7711:21:1;7768:2;7748:18;;;7741:30;7807:34;7787:18;;;7780:62;-1:-1:-1;;;7858:18:1;;;7851:52;7920:19;;25863:166:0;7527:418:1;25863:166:0;26067:62;;-1:-1:-1;;;;;8142:32:1;;26067:62:0;;;8124:51:1;8191:18;;;8184:34;;;26040:90:0;;26060:5;;-1:-1:-1;;;26090:22:0;8097:18:1;;26067:62:0;;;;-1:-1:-1;;26067:62:0;;;;;;;;;;;;;;-1:-1:-1;;;;;26067:62:0;-1:-1:-1;;;;;;26067:62:0;;;;;;;;;;26040:19;:90::i;:::-;25522:616;;;:::o;19560:229::-;19697:12;19729:52;19751:6;19759:4;19765:1;19768:12;19729:21;:52::i;:::-;19722:59;;19560:229;;;;;;:::o;10871:152::-;10941:4;10965:50;10970:3;-1:-1:-1;;;;;10990:23:0;;10965:4;:50::i;107519:126::-;107568:14;107602:35;:16;-1:-1:-1;;;;;107602:33:0;;:35::i;115504:1431::-;115621:25;115649:20;:18;:20::i;:::-;115621:48;;115705:6;115684:17;:27;115680:155;;115728:10;;:38;;-1:-1:-1;;;;;115728:10:0;115752:5;115759:6;115728:23;:38::i;:::-;115786:16;;1040:25:1;;;115786:16:0;;1028:2:1;1013:18;115786:16:0;;;;;;;115817:7;115504:1431;:::o;115680:155::-;28589:5;;;115903:32;116012:41;28589:5;116012:15;:41::i;:::-;115987:66;;116064:27;116111:15;:13;:15::i;:::-;116094:32;;:14;:32;:::i;:::-;116064:62;;116137:19;116159:33;116172:19;116159:12;:33::i;:::-;116137:55;;116203:24;116244:12;:10;:12::i;:::-;116230:26;;:11;:26;:::i;:::-;116325:7;;:50;;-1:-1:-1;;;116325:50:0;;;;;8397:25:1;;;116325:7:0;8438:18:1;;;8431:50;116203:53:0;;-1:-1:-1;;;;;;116325:7:0;;:25;;8370:18:1;;116325:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116320:64;;116377:7;;;;;;115504:1431;:::o;116320:64::-;116450:25;;:::i;:::-;116508:19;116486:7;116494:10;;116486:19;;;;;;;:::i;:::-;;;;:41;116538:9;;:58;;-1:-1:-1;;;116538:58:0;;-1:-1:-1;;;;;116538:9:0;;;;:36;;:58;;116575:7;;116584:11;;116538:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;116667:28;;:::i;:::-;116734:24;116706:10;116717:13;116706:25;;;;;;;:::i;:::-;;;;:52;116769:67;;-1:-1:-1;;;116769:67:0;;-1:-1:-1;;;;;116769:12:0;:39;;;;:67;;116809:10;;116821:14;;116769:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;116889:10:0;;:38;;-1:-1:-1;;;;;;116889:10:0;;-1:-1:-1;116913:5:0;116920:6;116889:23;:38::i;:::-;115557:1378;;;;;;;;115504:1431;:::o;28621:143::-;28688:7;28744:1;28740;:5;;;;;:::i;:::-;;;28621:143;-1:-1:-1;;;28621:143:0:o;11199:158::-;11272:4;11296:53;11304:3;-1:-1:-1;;;;;11324:23:0;;11296:7;:53::i;104335:1000::-;104373:7;104393:23;104419:20;:18;:20::i;:::-;104393:46;;104485:7;;;;;;;;;-1:-1:-1;;;;;104485:7:0;-1:-1:-1;;;;;104485:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;104564:28;:26;:28::i;:::-;104635:29;104667:16;:14;:16::i;:::-;104694:53;;-1:-1:-1;;;104694:53:0;;90825:42;104694:53;;;7430:34:1;90922:42:0;7480:18:1;;;7473:43;104635:48:0;;-1:-1:-1;;;;;;104694:22:0;;;;;7365:18:1;;104694:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;104790:53:0;;-1:-1:-1;;;104790:53:0;;90729:42;104790:53;;;7430:34:1;90922:42:0;7480:18:1;;;7473:43;-1:-1:-1;;;;;104790:22:0;;;;;7365:18:1;;104790:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;104896:15;104914:22;:13;:20;:22::i;:::-;104896:40;;104952:9;104947:137;104967:7;104963:1;:11;104947:137;;;-1:-1:-1;;;;;105013:22:0;;;105036:19;:13;105053:1;105036:16;:19::i;:::-;105013:59;;-1:-1:-1;;;;;;105013:59:0;;;;;;;-1:-1:-1;;;;;7448:15:1;;;105013:59:0;;;7430:34:1;90922:42:0;7480:18:1;;;7473:43;7365:18;;105013:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;28291:1:0;28287:5;104947:137;;;-1:-1:-1;105180:10:0;;105133:59;;-1:-1:-1;;;105133:59:0;;90922:42;105133:59;;;7430:34:1;-1:-1:-1;;;;;105180:10:0;;;7480:18:1;;;7473:43;105133:22:0;;;;;;7365:18:1;;105133:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;105205:18;105249:15;105226:20;:18;:20::i;:::-;:38;;;;:::i;:::-;105205:59;;105280:19;105288:10;105280:19;;;;1040:25:1;;1028:2;1013:18;;894:177;105280:19:0;;;;;;;;105317:10;104335:1000;-1:-1:-1;;;;104335:1000:0:o;116943:768::-;116994:7;117085:21;:19;:21::i;:::-;117170:20;117193:15;:13;:15::i;:::-;117170:38;-1:-1:-1;117223:16:0;;117219:237;;117256:12;-1:-1:-1;;;;;117256:38:0;;117313:12;117359:13;117393:36;117416:12;117393:22;:36::i;:::-;117256:188;;-1:-1:-1;;;;;;117256:188:0;;;;;;;;;;9965:25:1;;;;10037:2;10026:22;;;;10006:18;;;9999:50;10065:18;;;10058:34;9938:18;;117256:188:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;117219:237;117513:25;117541:20;:18;:20::i;:::-;117513:48;-1:-1:-1;117576:22:0;117572:36;;117607:1;117600:8;;;;116943:768;:::o;117572:36::-;117619:10;;:49;;-1:-1:-1;;;;;117619:10:0;117643:5;117650:17;117619:23;:49::i;117921:113::-;117996:30;;-1:-1:-1;;;117996:30:0;;118020:4;117996:30;;;181:51:1;117969:7:0;;117996:5;-1:-1:-1;;;;;117996:15:0;;;;154:18:1;;117996:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;106717:107::-;106789:2;;:27;;-1:-1:-1;;;106789:27:0;;106810:4;106789:27;;;181:51:1;106762:7:0;;-1:-1:-1;;;;;106789:2:0;;:12;;154:18:1;;106789:27:0;14:224:1;106923:116:0;106999:7;;:32;;-1:-1:-1;;;106999:32:0;;107025:4;106999:32;;;181:51:1;106972:7:0;;-1:-1:-1;;;;;106999:7:0;;:17;;154:18:1;;106999:32:0;14:224:1;122483:236:0;122545:7;122585:126;122664:12;-1:-1:-1;;;;;122664:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;122605:9;;:29;;;-1:-1:-1;;;122605:29:0;;;;122585:50;;-1:-1:-1;;;;;122605:9:0;;:27;;:29;;;;;;;;;;;;;;:9;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;122585:9;;:19;:50::i;:::-;:60;;:126::i;121940:186::-;122013:7;122040:78;122085:12;-1:-1:-1;;;;;122085:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;122056:17;;122041:32;;:12;:32;:::i;117719:132::-;117808:10;;:35;;-1:-1:-1;;;117808:35:0;;117837:4;117808:35;;;181:51:1;117781:7:0;;-1:-1:-1;;;;;117808:10:0;;:20;;154:18:1;;117808:35:0;14:224:1;82128:417:0;82239:16;82273:11;82287:18;:9;:16;:18::i;:::-;82273:32;;82316:23;82356:3;82342:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;82342:18:0;;82316:44;;82376:9;82371:143;82391:3;82387:1;:7;82371:143;;;82425:15;:9;82438:1;82425:12;:15::i;:::-;82413:6;82420:1;82413:9;;;;;;;;:::i;:::-;-1:-1:-1;;;;;82413:27:0;;;:9;;;;;;;;;;;:27;82484:3;;82371:143;;;-1:-1:-1;82531:6:0;82128:417;-1:-1:-1;;;82128:417:0:o;114539:957::-;114627:19;;;;;;;;;;;;-1:-1:-1;;;114627:19:0;;;;114586:4;;114611:9;:14;114603:44;;;;-1:-1:-1;;;114603:44:0;;;;;;;;:::i;:::-;;114703:25;114731:20;:18;:20::i;:::-;114703:48;-1:-1:-1;114766:21:0;;114762:244;;114804:28;;:::i;:::-;114875:17;114847:10;114858:13;114847:25;;;;;;;:::i;:::-;;;;:45;-1:-1:-1;;;;;114907:12:0;:26;;114934:10;114946:47;114975:17;114946:28;:47::i;:::-;114907:87;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;114789:217;114762:244;115057:20;115080:15;:13;:15::i;:::-;115057:38;-1:-1:-1;115110:16:0;;115106:200;;115143:25;;:::i;:::-;115205:12;115183:7;115191:10;;115183:19;;;;;;;:::i;:::-;;;;:34;115232:9;;-1:-1:-1;;;;;115232:9:0;:23;115256:7;115265:28;115280:12;115265:14;:28::i;:::-;115232:62;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;115128:178;115106:200;115369:12;:10;:12::i;:::-;115365:35;;115395:5;115388:12;;;;114539:957;:::o;115365:35::-;115436:9;;115416:36;;-1:-1:-1;;;115416:36:0;;;;;8397:25:1;;;;115447:4:0;8438:18:1;;;8431:50;90613:42:0;;115416:19;;8370:18:1;;115416:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;115411:55;;115461:5;115454:12;;;;114539:957;:::o;115411:55::-;115484:4;115477:11;;;;114539:957;:::o;43697:122::-;43761:7;43488:4;43789:5;43793:1;43789;:5;:::i;:::-;43788:23;;;;:::i;107047:188::-;107133:7;107160:16;:14;:16::i;:::-;107206:10;;107160:67;;-1:-1:-1;;;107160:67:0;;-1:-1:-1;;;;;10493:15:1;;;107160:67:0;;;10475:34:1;107206:10:0;;;10525:18:1;;;10518:43;10577:18;;;10570:34;;;107160:29:0;;;;;10410:18:1;;107160:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;11696:117::-;11759:7;11786:19;11794:3;7180:18;;7097:109;107315:114;107388:33;;-1:-1:-1;;;107388:33:0;;-1:-1:-1;;;;;199:32:1;;107388:33:0;;;181:51:1;91055:42:0;;107388:21;;154:18:1;;107388:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;107315:114;:::o;123409:591::-;123514:21;123538:16;:14;:16::i;:::-;123514:40;-1:-1:-1;123569:17:0;;123565:97;;123603:7;;:47;;-1:-1:-1;;;123603:47:0;;;;;8397:25:1;;;123603:7:0;8438:18:1;;;8431:50;-1:-1:-1;;;;;123603:7:0;;;;:25;;8370:18:1;;123603:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;123565:97;123721:17;123741:12;:10;:12::i;:::-;123721:32;-1:-1:-1;123768:13:0;;123764:229;;123798:9;;123895:10;;-1:-1:-1;;;;;123798:9:0;;;;:35;;123852:9;;123926:40;123852:9;123926:29;:40::i;:::-;123798:183;;-1:-1:-1;;;;;;123798:183:0;;;;;;;;;;9965:25:1;;;;10037:2;10026:22;;;;10006:18;;;9999:50;10065:18;;;10058:34;9938:18;;123798:183:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123448:552;;123409:591::o;27359:716::-;27783:23;27809:69;27837:4;27809:69;;;;;;;;;;;;;;;;;27817:5;-1:-1:-1;;;;;27809:27:0;;;:69;;;;;:::i;:::-;27893:17;;27783:95;;-1:-1:-1;27893:21:0;27889:179;;27990:10;27979:30;;;;;;;;;;;;:::i;:::-;27971:85;;;;-1:-1:-1;;;27971:85:0;;10817:2:1;27971:85:0;;;10799:21:1;10856:2;10836:18;;;10829:30;10895:34;10875:18;;;10868:62;-1:-1:-1;;;10946:18:1;;;10939:40;10996:19;;27971:85:0;10615:406:1;20680:510:0;20850:12;20908:5;20883:21;:30;;20875:81;;;;-1:-1:-1;;;20875:81:0;;11228:2:1;20875:81:0;;;11210:21:1;11267:2;11247:18;;;11240:30;11306:34;11286:18;;;11279:62;-1:-1:-1;;;11357:18:1;;;11350:36;11403:19;;20875:81:0;11026:402:1;20875:81:0;-1:-1:-1;;;;;17110:19:0;;;20967:60;;;;-1:-1:-1;;;20967:60:0;;11635:2:1;20967:60:0;;;11617:21:1;11674:2;11654:18;;;11647:30;11713:31;11693:18;;;11686:59;11762:18;;20967:60:0;11433:353:1;20967:60:0;21041:12;21055:23;21082:6;-1:-1:-1;;;;;21082:11:0;21101:5;21108:4;21082:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21040:73;;;;21131:51;21148:7;21157:10;21169:12;21131:16;:51::i;:::-;21124:58;20680:510;-1:-1:-1;;;;;;;20680:510:0:o;4786:414::-;4849:4;6979:19;;;:12;;;:19;;;;;;4866:327;;-1:-1:-1;4909:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;5092:18;;5070:19;;;:12;;;:19;;;;;;:40;;;;5125:11;;4866:327;-1:-1:-1;5176:5:0;5169:12;;24786:211;24930:58;;-1:-1:-1;;;;;8142:32:1;;24930:58:0;;;8124:51:1;8191:18;;;8184:34;;;24903:86:0;;24923:5;;-1:-1:-1;;;24953:23:0;8097:18:1;;24930:58:0;7950:274:1;120246:245:0;120321:7;120361:122;120444:24;;43597:4;120427:41;;;;:::i;:::-;120361:37;120380:17;120361:18;:37::i;118740:176::-;118807:7;118834:74;118886:21;;43597:4;118869:38;;;;:::i;:::-;118834:24;118845:12;118834:10;:24::i;5376:1420::-;5442:4;5581:19;;;:12;;;:19;;;;;;5617:15;;5613:1176;;5992:21;6016:14;6029:1;6016:10;:14;:::i;:::-;6065:18;;5992:38;;-1:-1:-1;6045:17:0;;6065:22;;6086:1;;6065:22;:::i;:::-;6045:42;;6121:13;6108:9;:26;6104:405;;6155:17;6175:3;:11;;6187:9;6175:22;;;;;;;;:::i;:::-;;;;;;;;;6155:42;;6329:9;6300:3;:11;;6312:13;6300:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;6414:23;;;:12;;;:23;;;;;:36;;;6104:405;6590:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;6685:3;:12;;:19;6698:5;6685:19;;;;;;;;;;;6678:26;;;6728:4;6721:11;;;;;;;5613:1176;6772:5;6765:12;;;;;105455:1052;105541:16;;-1:-1:-1;;;;;105541:16:0;105572:31;105568:44;;105605:7;105455:1052::o;105568:44::-;105658:24;;105697:29;;105693:363;;105798:29;;-1:-1:-1;;;105798:29:0;;105821:4;105798:29;;;181:51:1;90825:42:0;;105743:11;;90825:42;;105798:14;;154:18:1;;105798:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;105776:51;-1:-1:-1;105846:15:0;;105842:203;;105882:147;105922:17;105962:48;:11;105984:25;105962:21;:48::i;:::-;-1:-1:-1;;;;;105882:17:0;;;:147;:17;:147::i;:::-;105728:328;;105693:363;106102:24;;106141:29;;106137:363;;106242:29;;-1:-1:-1;;;106242:29:0;;106265:4;106242:29;;;181:51:1;90729:42:0;;106187:11;;90729:42;;106242:14;;154:18:1;;106242:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;106220:51;-1:-1:-1;106290:15:0;;106286:203;;106326:147;106366:17;106406:48;:11;106428:25;106406:21;:48::i;106326:147::-;106172:328;;105502:1005;;;105455:1052::o;12167:158::-;12241:7;12292:22;12296:3;12308:5;12292:3;:22::i;120793:210::-;120870:7;120910:85;120970:24;;43597:4;120953:41;;;;:::i;:::-;120910:32;120929:12;120910:18;:32::i;43908:122::-;43972:7;44021:1;44000:17;43488:4;44000:1;:17;:::i;119661:289::-;119776:7;119821:121;119904:23;;43597:4;119887:40;;;;:::i;118292:177::-;118361:7;118388:73;118440:20;;43597:4;118423:37;;;;:::i;119191:187::-;119272:7;119299:71;119348:21;;43597:4;119331:38;;;;:::i;:::-;119299:21;119310:9;119299:10;:21::i;23366:712::-;23516:12;23545:7;23541:530;;;-1:-1:-1;23576:10:0;23569:17;;23541:530;23690:17;;:21;23686:374;;23888:10;23882:17;23949:15;23936:10;23932:2;23928:19;23921:44;23686:374;24031:12;24024:20;;-1:-1:-1;;;24024:20:0;;;;;;;;:::i;121376:196::-;121454:7;121481:83;121531:12;-1:-1:-1;;;;;121531:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;121502:17;;121482:37;;:17;:37;:::i;123071:242::-;123136:7;123176:129;123261:9;;;;;;;;;-1:-1:-1;;;;;123261:9:0;-1:-1:-1;;;;;123261:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123176:56;123199:12;-1:-1:-1;;;;;123199:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7560:120;7627:7;7654:3;:11;;7666:5;7654:18;;;;;;;;:::i;:::-;;;;;;;;;7647:25;;7560:120;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;243:258:1:-;315:1;325:113;339:6;336:1;333:13;325:113;;;415:11;;;409:18;396:11;;;389:39;361:2;354:10;325:113;;;456:6;453:1;450:13;447:48;;;491:1;482:6;477:3;473:16;466:27;447:48;;243:258;;;:::o;506:383::-;655:2;644:9;637:21;618:4;687:6;681:13;730:6;725:2;714:9;710:18;703:34;746:66;805:6;800:2;789:9;785:18;780:2;772:6;768:15;746:66;:::i;:::-;873:2;852:15;-1:-1:-1;;848:29:1;833:45;;;;880:2;829:54;;506:383;-1:-1:-1;;506:383:1:o;1076:131::-;-1:-1:-1;;;;;1151:31:1;;1141:42;;1131:70;;1197:1;1194;1187:12;1131:70;1076:131;:::o;1212:247::-;1271:6;1324:2;1312:9;1303:7;1299:23;1295:32;1292:52;;;1340:1;1337;1330:12;1292:52;1379:9;1366:23;1398:31;1423:5;1398:31;:::i;2094:180::-;2153:6;2206:2;2194:9;2185:7;2181:23;2177:32;2174:52;;;2222:1;2219;2212:12;2174:52;-1:-1:-1;2245:23:1;;2094:180;-1:-1:-1;2094:180:1:o;2731:658::-;2902:2;2954:21;;;3024:13;;2927:18;;;3046:22;;;2873:4;;2902:2;3125:15;;;;3099:2;3084:18;;;2873:4;3168:195;3182:6;3179:1;3176:13;3168:195;;;3247:13;;-1:-1:-1;;;;;3243:39:1;3231:52;;3338:15;;;;3303:12;;;;3279:1;3197:9;3168:195;;;-1:-1:-1;3380:3:1;;2731:658;-1:-1:-1;;;;;;2731:658:1:o;3394:383::-;3471:6;3479;3487;3540:2;3528:9;3519:7;3515:23;3511:32;3508:52;;;3556:1;3553;3546:12;3508:52;3592:9;3579:23;3569:33;;3652:2;3641:9;3637:18;3624:32;3665:31;3690:5;3665:31;:::i;:::-;3394:383;;3715:5;;-1:-1:-1;;;3767:2:1;3752:18;;;;3739:32;;3394:383::o;4061:164::-;4137:13;;4186;;4179:21;4169:32;;4159:60;;4215:1;4212;4205:12;4230:202;4297:6;4350:2;4338:9;4329:7;4325:23;4321:32;4318:52;;;4366:1;4363;4356:12;4318:52;4389:37;4416:9;4389:37;:::i;4437:184::-;4507:6;4560:2;4548:9;4539:7;4535:23;4531:32;4528:52;;;4576:1;4573;4566:12;4528:52;-1:-1:-1;4599:16:1;;4437:184;-1:-1:-1;4437:184:1:o;4626:127::-;4687:10;4682:3;4678:20;4675:1;4668:31;4718:4;4715:1;4708:15;4742:4;4739:1;4732:15;4758:168;4798:7;4864:1;4860;4856:6;4852:14;4849:1;4846:21;4841:1;4834:9;4827:17;4823:45;4820:71;;;4871:18;;:::i;:::-;-1:-1:-1;4911:9:1;;4758:168::o;4931:127::-;4992:10;4987:3;4983:20;4980:1;4973:31;5023:4;5020:1;5013:15;5047:4;5044:1;5037:15;5063:217;5103:1;5129;5119:132;;5173:10;5168:3;5164:20;5161:1;5154:31;5208:4;5205:1;5198:15;5236:4;5233:1;5226:15;5119:132;-1:-1:-1;5265:9:1;;5063:217::o;5285:125::-;5325:4;5353:1;5350;5347:8;5344:34;;;5358:18;;:::i;:::-;-1:-1:-1;5395:9:1;;5285:125::o;5773:128::-;5813:3;5844:1;5840:6;5837:1;5834:13;5831:39;;;5850:18;;:::i;:::-;-1:-1:-1;5886:9:1;;5773:128::o;5906:251::-;5976:6;6029:2;6017:9;6008:7;6004:23;6000:32;5997:52;;;6045:1;6042;6035:12;5997:52;6077:9;6071:16;6096:31;6121:5;6096:31;:::i;6162:869::-;6274:6;6282;6290;6298;6306;6314;6367:3;6355:9;6346:7;6342:23;6338:33;6335:53;;;6384:1;6381;6374:12;6335:53;6416:9;6410:16;6435:31;6460:5;6435:31;:::i;:::-;6535:2;6520:18;;6514:25;6485:5;;-1:-1:-1;6548:33:1;6514:25;6548:33;:::i;:::-;6652:2;6637:18;;6631:25;6600:7;;-1:-1:-1;6665:33:1;6631:25;6665:33;:::i;:::-;6769:2;6754:18;;6748:25;6717:7;;-1:-1:-1;6782:33:1;6748:25;6782:33;:::i;:::-;6886:3;6871:19;;6865:26;6834:7;;-1:-1:-1;6900:33:1;6865:26;6900:33;:::i;:::-;6952:7;-1:-1:-1;6978:47:1;7020:3;7005:19;;6978:47;:::i;:::-;6968:57;;6162:869;;;;;;;;:::o;8492:127::-;8553:10;8548:3;8544:20;8541:1;8534:31;8584:4;8581:1;8574:15;8608:4;8605:1;8598:15;8624:565;8832:2;8817:18;;8821:9;8912:6;8790:4;8946:194;8960:4;8957:1;8954:11;8946:194;;;9019:13;;9007:26;;9056:4;9080:12;;;;9115:15;;;;8980:1;8973:9;8946:194;;;8950:3;;;9176:6;9171:2;9160:9;9156:18;9149:34;8624:565;;;;;:::o;9194:566::-;9402:3;9387:19;;9391:9;9483:6;9360:4;9517:194;9531:4;9528:1;9525:11;9517:194;;;9590:13;;9578:26;;9627:4;9651:12;;;;9686:15;;;;9551:1;9544:9;9517:194;;;9521:3;;;9747:6;9742:2;9731:9;9727:18;9720:34;9194:566;;;;;:::o;10103:127::-;10164:10;10159:3;10155:20;10152:1;10145:31;10195:4;10192:1;10185:15;10219:4;10216:1;10209:15;11791:274;11920:3;11958:6;11952:13;11974:53;12020:6;12015:3;12008:4;12000:6;11996:17;11974:53;:::i;:::-;12043:16;;;;;11791:274;-1:-1:-1;;11791:274:1:o;12070:127::-;12131:10;12126:3;12122:20;12119:1;12112:31;12162:4;12159:1;12152:15;12186:4;12183:1;12176:15
Swarm Source
ipfs://bb517ece7b44df8df7518e0672eff8afb20b6b90638a7706435dc05887a68cb1
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.