More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
GenericCompoundV3
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-11-28 */ // File: .deps/Comp.sol pragma solidity >=0.6.12; pragma experimental ABIEncoderV2; // File: Address.sol /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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"); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: IERC20.sol /** * @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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, 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: IGenericLender.sol interface IGenericLender { function lenderName() external view returns (string memory); function nav() external view returns (uint256); function strategy() external view returns (address); function apr() external view returns (uint256); function weightedApr() external view returns (uint256); function withdraw(uint256 amount) external returns (uint256); function emergencyWithdraw(uint256 amount) external; function deposit() external; function withdrawAll() external returns (bool); function hasAssets() external view returns (bool); function aprAfterDeposit(uint256 amount) external view returns (uint256); function setDust(uint256 _dust) external; function sweep(address _token) external; } // File: ITradeFactory.sol // Feel free to change the license, but this is what we use interface ITradeFactory { function enable(address, address) external; function disable(address, address) external; } // File: IUniswapV3SwapCallback.sol /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; } // File: SafeMath.sol /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: CompoundV3.sol library CometStructs { struct AssetInfo { uint8 offset; address asset; address priceFeed; uint64 scale; uint64 borrowCollateralFactor; uint64 liquidateCollateralFactor; uint64 liquidationFactor; uint128 supplyCap; } struct UserBasic { int104 principal; uint64 baseTrackingIndex; uint64 baseTrackingAccrued; uint16 assetsIn; uint8 _reserved; } struct TotalsBasic { uint64 baseSupplyIndex; uint64 baseBorrowIndex; uint64 trackingSupplyIndex; uint64 trackingBorrowIndex; uint104 totalSupplyBase; uint104 totalBorrowBase; uint40 lastAccrualTime; uint8 pauseFlags; } struct UserCollateral { uint128 balance; uint128 _reserved; } struct RewardOwed { address token; uint owed; } struct TotalsCollateral { uint128 totalSupplyAsset; uint128 _reserved; } struct RewardConfig { address token; uint64 rescaleFactor; bool shouldUpscale; } } interface Comet is IERC20 { function baseScale() external view returns (uint); function supply(address asset, uint amount) external; function withdraw(address asset, uint amount) external; function getSupplyRate(uint utilization) external view returns (uint); function getBorrowRate(uint utilization) external view returns (uint); function getAssetInfoByAddress(address asset) external view returns (CometStructs.AssetInfo memory); function getAssetInfo(uint8 i) external view returns (CometStructs.AssetInfo memory); function getPrice(address priceFeed) external view returns (uint128); function userBasic(address) external view returns (CometStructs.UserBasic memory); function totalsBasic() external view returns (CometStructs.TotalsBasic memory); function userCollateral(address, address) external view returns (CometStructs.UserCollateral memory); function baseTokenPriceFeed() external view returns (address); function numAssets() external view returns (uint8); function getUtilization() external view returns (uint); function baseTrackingSupplySpeed() external view returns (uint); function baseTrackingBorrowSpeed() external view returns (uint); function totalSupply() override external view returns (uint256); function totalBorrow() external view returns (uint256); function baseIndexScale() external pure returns (uint64); function baseTrackingAccrued(address account) external view returns (uint64); function totalsCollateral(address asset) external view returns (CometStructs.TotalsCollateral memory); function baseMinForRewards() external view returns (uint256); function baseToken() external view returns (address); function accrueAccount(address account) external; } interface CometRewards { function getRewardOwed(address comet, address account) external returns (CometStructs.RewardOwed memory); function claim(address comet, address src, bool shouldAccrue) external; function rewardsClaimed(address comet, address account) external view returns(uint256); function rewardConfig(address comet) external view returns (CometStructs.RewardConfig memory); } // File: ISwapRouter.sol /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface ISwapRouter is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); // Taken from https://soliditydeveloper.com/uniswap3 // Manually added to the interface function refundETH() external payable; } // File: SafeERC20.sol /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; 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' // solhint-disable-next-line max-line-length 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).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _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 // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: BaseStrategy.sol struct StrategyParams { uint256 performanceFee; uint256 activation; uint256 debtRatio; uint256 minDebtPerHarvest; uint256 maxDebtPerHarvest; uint256 lastReport; uint256 totalDebt; uint256 totalGain; uint256 totalLoss; } interface VaultAPI is IERC20 { function name() external view returns (string calldata); function symbol() external view returns (string calldata); function decimals() external view returns (uint256); function apiVersion() external pure returns (string memory); function permit( address owner, address spender, uint256 amount, uint256 expiry, bytes calldata signature ) external returns (bool); // NOTE: Vyper produces multiple signatures for a given function with "default" args function deposit() external returns (uint256); function deposit(uint256 amount) external returns (uint256); function deposit(uint256 amount, address recipient) external returns (uint256); // NOTE: Vyper produces multiple signatures for a given function with "default" args function withdraw() external returns (uint256); function withdraw(uint256 maxShares) external returns (uint256); function withdraw(uint256 maxShares, address recipient) external returns (uint256); function token() external view returns (address); function strategies(address _strategy) external view returns (StrategyParams memory); function pricePerShare() external view returns (uint256); function totalAssets() external view returns (uint256); function depositLimit() external view returns (uint256); function maxAvailableShares() external view returns (uint256); /** * View how much the Vault would increase this Strategy's borrow limit, * based on its present performance (since its last report). Can be used to * determine expectedReturn in your Strategy. */ function creditAvailable() external view returns (uint256); /** * View how much the Vault would like to pull back from the Strategy, * based on its present performance (since its last report). Can be used to * determine expectedReturn in your Strategy. */ function debtOutstanding() external view returns (uint256); /** * View how much the Vault expect this Strategy to return at the current * block, based on its present performance (since its last report). Can be * used to determine expectedReturn in your Strategy. */ function expectedReturn() external view returns (uint256); /** * This is the main contact point where the Strategy interacts with the * Vault. It is critical that this call is handled as intended by the * Strategy. Therefore, this function will be called by BaseStrategy to * make sure the integration is correct. */ function report( uint256 _gain, uint256 _loss, uint256 _debtPayment ) external returns (uint256); /** * This function should only be used in the scenario where the Strategy is * being retired but no migration of the positions are possible, or in the * extreme scenario that the Strategy needs to be put into "Emergency Exit" * mode in order for it to exit as quickly as possible. The latter scenario * could be for any reason that is considered "critical" that the Strategy * exits its position as fast as possible, such as a sudden change in * market conditions leading to losses, or an imminent failure in an * external dependency. */ function revokeStrategy() external; /** * View the governance address of the Vault to assert privileged functions * can only be called by governance. The Strategy serves the Vault, so it * is subject to governance defined by the Vault. */ function governance() external view returns (address); /** * View the management address of the Vault to assert privileged functions * can only be called by management. The Strategy serves the Vault, so it * is subject to management defined by the Vault. */ function management() external view returns (address); /** * View the guardian address of the Vault to assert privileged functions * can only be called by guardian. The Strategy serves the Vault, so it * is subject to guardian defined by the Vault. */ function guardian() external view returns (address); } /** * This interface is here for the keeper bot to use. */ interface StrategyAPI { function name() external view returns (string memory); function vault() external view returns (address); function want() external view returns (address); function apiVersion() external pure returns (string memory); function keeper() external view returns (address); function isActive() external view returns (bool); function delegatedAssets() external view returns (uint256); function estimatedTotalAssets() external view returns (uint256); function tendTrigger(uint256 callCost) external view returns (bool); function tend() external; function harvestTrigger(uint256 callCost) external view returns (bool); function harvest() external; event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding); } interface HealthCheck { function check( uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding, uint256 totalDebt ) external view returns (bool); } /** * @title Yearn Base Strategy * @author yearn.finance * @notice * BaseStrategy implements all of the required functionality to interoperate * closely with the Vault contract. This contract should be inherited and the * abstract methods implemented to adapt the Strategy to the particular needs * it has to create a return. * * Of special interest is the relationship between `harvest()` and * `vault.report()'. `harvest()` may be called simply because enough time has * elapsed since the last report, and not because any funds need to be moved * or positions adjusted. This is critical so that the Vault may maintain an * accurate picture of the Strategy's performance. See `vault.report()`, * `harvest()`, and `harvestTrigger()` for further details. */ abstract contract BaseStrategy { using SafeMath for uint256; using SafeERC20 for IERC20; string public metadataURI; // health checks bool public doHealthCheck; address public healthCheck; /** * @notice * Used to track which version of `StrategyAPI` this Strategy * implements. * @dev The Strategy's version must match the Vault's `API_VERSION`. * @return A string which holds the current API version of this contract. */ function apiVersion() public pure returns (string memory) { return "0.4.3"; } /** * @notice This Strategy's name. * @dev * You can use this field to manage the "version" of this Strategy, e.g. * `StrategySomethingOrOtherV1`. However, "API Version" is managed by * `apiVersion()` function above. * @return This Strategy's name. */ function name() external view virtual returns (string memory); /** * @notice * The amount (priced in want) of the total assets managed by this strategy should not count * towards Yearn's TVL calculations. * @dev * You can override this field to set it to a non-zero value if some of the assets of this * Strategy is somehow delegated inside another part of of Yearn's ecosystem e.g. another Vault. * Note that this value must be strictly less than or equal to the amount provided by * `estimatedTotalAssets()` below, as the TVL calc will be total assets minus delegated assets. * Also note that this value is used to determine the total assets under management by this * strategy, for the purposes of computing the management fee in `Vault` * @return * The amount of assets this strategy manages that should not be included in Yearn's Total Value * Locked (TVL) calculation across it's ecosystem. */ function delegatedAssets() external view virtual returns (uint256) { return 0; } VaultAPI public vault; address public strategist; address public rewards; address public keeper; IERC20 public want; // So indexers can keep track of this event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding); event UpdatedStrategist(address newStrategist); event UpdatedKeeper(address newKeeper); event UpdatedRewards(address rewards); event UpdatedMinReportDelay(uint256 delay); event UpdatedMaxReportDelay(uint256 delay); event UpdatedProfitFactor(uint256 profitFactor); event UpdatedDebtThreshold(uint256 debtThreshold); event EmergencyExitEnabled(); event UpdatedMetadataURI(string metadataURI); event SetHealthCheck(address); event SetDoHealthCheck(bool); // The minimum number of seconds between harvest calls. See // `setMinReportDelay()` for more details. uint256 public minReportDelay; // The maximum number of seconds between harvest calls. See // `setMaxReportDelay()` for more details. uint256 public maxReportDelay; // The minimum multiple that `callCost` must be above the credit/profit to // be "justifiable". See `setProfitFactor()` for more details. uint256 public profitFactor; // Use this to adjust the threshold at which running a debt causes a // harvest trigger. See `setDebtThreshold()` for more details. uint256 public debtThreshold; // See note on `setEmergencyExit()`. bool public emergencyExit; // modifiers modifier onlyAuthorized() { require(msg.sender == strategist || msg.sender == governance(), "!authorized"); _; } modifier onlyEmergencyAuthorized() { require( msg.sender == strategist || msg.sender == governance() || msg.sender == vault.guardian() || msg.sender == vault.management(), "!authorized" ); _; } modifier onlyStrategist() { require(msg.sender == strategist, "!strategist"); _; } modifier onlyGovernance() { require(msg.sender == governance(), "!authorized"); _; } modifier onlyKeepers() { require( msg.sender == keeper || msg.sender == strategist || msg.sender == governance() || msg.sender == vault.guardian() || msg.sender == vault.management(), "!authorized" ); _; } modifier onlyVaultManagers() { require(msg.sender == vault.management() || msg.sender == governance(), "!authorized"); _; } constructor(address _vault) public { _initialize(_vault, msg.sender, msg.sender, msg.sender); } /** * @notice * Initializes the Strategy, this is called only once, when the * contract is deployed. * @dev `_vault` should implement `VaultAPI`. * @param _vault The address of the Vault responsible for this Strategy. * @param _strategist The address to assign as `strategist`. * The strategist is able to change the reward address * @param _rewards The address to use for pulling rewards. * @param _keeper The adddress of the _keeper. _keeper * can harvest and tend a strategy. */ function _initialize( address _vault, address _strategist, address _rewards, address _keeper ) internal { require(address(want) == address(0), "Strategy already initialized"); vault = VaultAPI(_vault); want = IERC20(vault.token()); want.safeApprove(_vault, uint256(-1)); // Give Vault unlimited access (might save gas) strategist = _strategist; rewards = _rewards; keeper = _keeper; // initialize variables minReportDelay = 0; maxReportDelay = 86400; profitFactor = 100; debtThreshold = 0; vault.approve(rewards, uint256(-1)); // Allow rewards to be pulled } function setHealthCheck(address _healthCheck) external onlyVaultManagers { emit SetHealthCheck(_healthCheck); healthCheck = _healthCheck; } function setDoHealthCheck(bool _doHealthCheck) external onlyVaultManagers { emit SetDoHealthCheck(_doHealthCheck); doHealthCheck = _doHealthCheck; } /** * @notice * Used to change `strategist`. * * This may only be called by governance or the existing strategist. * @param _strategist The new address to assign as `strategist`. */ function setStrategist(address _strategist) external onlyAuthorized { require(_strategist != address(0)); strategist = _strategist; emit UpdatedStrategist(_strategist); } /** * @notice * Used to change `keeper`. * * `keeper` is the only address that may call `tend()` or `harvest()`, * other than `governance()` or `strategist`. However, unlike * `governance()` or `strategist`, `keeper` may *only* call `tend()` * and `harvest()`, and no other authorized functions, following the * principle of least privilege. * * This may only be called by governance or the strategist. * @param _keeper The new address to assign as `keeper`. */ function setKeeper(address _keeper) external onlyAuthorized { require(_keeper != address(0)); keeper = _keeper; emit UpdatedKeeper(_keeper); } /** * @notice * Used to change `rewards`. EOA or smart contract which has the permission * to pull rewards from the vault. * * This may only be called by the strategist. * @param _rewards The address to use for pulling rewards. */ function setRewards(address _rewards) external onlyStrategist { require(_rewards != address(0)); vault.approve(rewards, 0); rewards = _rewards; vault.approve(rewards, uint256(-1)); emit UpdatedRewards(_rewards); } /** * @notice * Used to change `minReportDelay`. `minReportDelay` is the minimum number * of blocks that should pass for `harvest()` to be called. * * For external keepers (such as the Keep3r network), this is the minimum * time between jobs to wait. (see `harvestTrigger()` * for more details.) * * This may only be called by governance or the strategist. * @param _delay The minimum number of seconds to wait between harvests. */ function setMinReportDelay(uint256 _delay) external onlyAuthorized { minReportDelay = _delay; emit UpdatedMinReportDelay(_delay); } /** * @notice * Used to change `maxReportDelay`. `maxReportDelay` is the maximum number * of blocks that should pass for `harvest()` to be called. * * For external keepers (such as the Keep3r network), this is the maximum * time between jobs to wait. (see `harvestTrigger()` * for more details.) * * This may only be called by governance or the strategist. * @param _delay The maximum number of seconds to wait between harvests. */ function setMaxReportDelay(uint256 _delay) external onlyAuthorized { maxReportDelay = _delay; emit UpdatedMaxReportDelay(_delay); } /** * @notice * Used to change `profitFactor`. `profitFactor` is used to determine * if it's worthwhile to harvest, given gas costs. (See `harvestTrigger()` * for more details.) * * This may only be called by governance or the strategist. * @param _profitFactor A ratio to multiply anticipated * `harvest()` gas cost against. */ function setProfitFactor(uint256 _profitFactor) external onlyAuthorized { profitFactor = _profitFactor; emit UpdatedProfitFactor(_profitFactor); } /** * @notice * Sets how far the Strategy can go into loss without a harvest and report * being required. * * By default this is 0, meaning any losses would cause a harvest which * will subsequently report the loss to the Vault for tracking. (See * `harvestTrigger()` for more details.) * * This may only be called by governance or the strategist. * @param _debtThreshold How big of a loss this Strategy may carry without * being required to report to the Vault. */ function setDebtThreshold(uint256 _debtThreshold) external onlyAuthorized { debtThreshold = _debtThreshold; emit UpdatedDebtThreshold(_debtThreshold); } /** * @notice * Used to change `metadataURI`. `metadataURI` is used to store the URI * of the file describing the strategy. * * This may only be called by governance or the strategist. * @param _metadataURI The URI that describe the strategy. */ function setMetadataURI(string calldata _metadataURI) external onlyAuthorized { metadataURI = _metadataURI; emit UpdatedMetadataURI(_metadataURI); } /** * Resolve governance address from Vault contract, used to make assertions * on protected functions in the Strategy. */ function governance() internal view returns (address) { return vault.governance(); } /** * @notice * Provide an accurate conversion from `_amtInWei` (denominated in wei) * to `want` (using the native decimal characteristics of `want`). * @dev * Care must be taken when working with decimals to assure that the conversion * is compatible. As an example: * * given 1e17 wei (0.1 ETH) as input, and want is USDC (6 decimals), * with USDC/ETH = 1800, this should give back 1800000000 (180 USDC) * * @param _amtInWei The amount (in wei/1e-18 ETH) to convert to `want` * @return The amount in `want` of `_amtInEth` converted to `want` **/ function ethToWant(uint256 _amtInWei) public view virtual returns (uint256); /** * @notice * Provide an accurate estimate for the total amount of assets * (principle + return) that this Strategy is currently managing, * denominated in terms of `want` tokens. * * This total should be "realizable" e.g. the total value that could * *actually* be obtained from this Strategy if it were to divest its * entire position based on current on-chain conditions. * @dev * Care must be taken in using this function, since it relies on external * systems, which could be manipulated by the attacker to give an inflated * (or reduced) value produced by this function, based on current on-chain * conditions (e.g. this function is possible to influence through * flashloan attacks, oracle manipulations, or other DeFi attack * mechanisms). * * It is up to governance to use this function to correctly order this * Strategy relative to its peers in the withdrawal queue to minimize * losses for the Vault based on sudden withdrawals. This value should be * higher than the total debt of the Strategy and higher than its expected * value to be "safe". * @return The estimated total assets in this Strategy. */ function estimatedTotalAssets() public view virtual returns (uint256); /* * @notice * Provide an indication of whether this strategy is currently "active" * in that it is managing an active position, or will manage a position in * the future. This should correlate to `harvest()` activity, so that Harvest * events can be tracked externally by indexing agents. * @return True if the strategy is actively managing a position. */ function isActive() public view returns (bool) { return vault.strategies(address(this)).debtRatio > 0 || estimatedTotalAssets() > 0; } /** * Perform any Strategy unwinding or other calls necessary to capture the * "free return" this Strategy has generated since the last time its core * position(s) were adjusted. Examples include unwrapping extra rewards. * This call is only used during "normal operation" of a Strategy, and * should be optimized to minimize losses as much as possible. * * This method returns any realized profits and/or realized losses * incurred, and should return the total amounts of profits/losses/debt * payments (in `want` tokens) for the Vault's accounting (e.g. * `want.balanceOf(this) >= _debtPayment + _profit`). * * `_debtOutstanding` will be 0 if the Strategy is not past the configured * debt limit, otherwise its value will be how far past the debt limit * the Strategy is. The Strategy's debt limit is configured in the Vault. * * NOTE: `_debtPayment` should be less than or equal to `_debtOutstanding`. * It is okay for it to be less than `_debtOutstanding`, as that * should only used as a guide for how much is left to pay back. * Payments should be made to minimize loss from slippage, debt, * withdrawal fees, etc. * * See `vault.debtOutstanding()`. */ function prepareReturn(uint256 _debtOutstanding) internal virtual returns ( uint256 _profit, uint256 _loss, uint256 _debtPayment ); /** * Perform any adjustments to the core position(s) of this Strategy given * what change the Vault made in the "investable capital" available to the * Strategy. Note that all "free capital" in the Strategy after the report * was made is available for reinvestment. Also note that this number * could be 0, and you should handle that scenario accordingly. * * See comments regarding `_debtOutstanding` on `prepareReturn()`. */ function adjustPosition(uint256 _debtOutstanding) internal virtual; /** * Liquidate up to `_amountNeeded` of `want` of this strategy's positions, * irregardless of slippage. Any excess will be re-invested with `adjustPosition()`. * This function should return the amount of `want` tokens made available by the * liquidation. If there is a difference between them, `_loss` indicates whether the * difference is due to a realized loss, or if there is some other sitution at play * (e.g. locked funds) where the amount made available is less than what is needed. * * NOTE: The invariant `_liquidatedAmount + _loss <= _amountNeeded` should always be maintained */ function liquidatePosition(uint256 _amountNeeded) internal virtual returns (uint256 _liquidatedAmount, uint256 _loss); /** * Liquidate everything and returns the amount that got freed. * This function is used during emergency exit instead of `prepareReturn()` to * liquidate all of the Strategy's positions back to the Vault. */ function liquidateAllPositions() internal virtual returns (uint256 _amountFreed); /** * @notice * Provide a signal to the keeper that `tend()` should be called. The * keeper will provide the estimated gas cost that they would pay to call * `tend()`, and this function should use that estimate to make a * determination if calling it is "worth it" for the keeper. This is not * the only consideration into issuing this trigger, for example if the * position would be negatively affected if `tend()` is not called * shortly, then this can return `true` even if the keeper might be * "at a loss" (keepers are always reimbursed by Yearn). * @dev * `callCostInWei` must be priced in terms of `wei` (1e-18 ETH). * * This call and `harvestTrigger()` should never return `true` at the same * time. * @param callCostInWei The keeper's estimated gas cost to call `tend()` (in wei). * @return `true` if `tend()` should be called, `false` otherwise. */ function tendTrigger(uint256 callCostInWei) public view virtual returns (bool) { // We usually don't need tend, but if there are positions that need // active maintainence, overriding this function is how you would // signal for that. // If your implementation uses the cost of the call in want, you can // use uint256 callCost = ethToWant(callCostInWei); return false; } /** * @notice * Adjust the Strategy's position. The purpose of tending isn't to * realize gains, but to maximize yield by reinvesting any returns. * * See comments on `adjustPosition()`. * * This may only be called by governance, the strategist, or the keeper. */ function tend() external onlyKeepers { // Don't take profits with this call, but adjust for better gains adjustPosition(vault.debtOutstanding()); } /** * @notice * Provide a signal to the keeper that `harvest()` should be called. The * keeper will provide the estimated gas cost that they would pay to call * `harvest()`, and this function should use that estimate to make a * determination if calling it is "worth it" for the keeper. This is not * the only consideration into issuing this trigger, for example if the * position would be negatively affected if `harvest()` is not called * shortly, then this can return `true` even if the keeper might be "at a * loss" (keepers are always reimbursed by Yearn). * @dev * `callCostInWei` must be priced in terms of `wei` (1e-18 ETH). * * This call and `tendTrigger` should never return `true` at the * same time. * * See `min/maxReportDelay`, `profitFactor`, `debtThreshold` to adjust the * strategist-controlled parameters that will influence whether this call * returns `true` or not. These parameters will be used in conjunction * with the parameters reported to the Vault (see `params`) to determine * if calling `harvest()` is merited. * * It is expected that an external system will check `harvestTrigger()`. * This could be a script run off a desktop or cloud bot (e.g. * https://github.com/iearn-finance/yearn-vaults/blob/main/scripts/keep.py), * or via an integration with the Keep3r network (e.g. * https://github.com/Macarse/GenericKeep3rV2/blob/master/contracts/keep3r/GenericKeep3rV2.sol). * @param callCostInWei The keeper's estimated gas cost to call `harvest()` (in wei). * @return `true` if `harvest()` should be called, `false` otherwise. */ function harvestTrigger(uint256 callCostInWei) public view virtual returns (bool) { uint256 callCost = ethToWant(callCostInWei); StrategyParams memory params = vault.strategies(address(this)); // Should not trigger if Strategy is not activated if (params.activation == 0) return false; // Should not trigger if we haven't waited long enough since previous harvest if (block.timestamp.sub(params.lastReport) < minReportDelay) return false; // Should trigger if hasn't been called in a while if (block.timestamp.sub(params.lastReport) >= maxReportDelay) return true; // If some amount is owed, pay it back // NOTE: Since debt is based on deposits, it makes sense to guard against large // changes to the value from triggering a harvest directly through user // behavior. This should ensure reasonable resistance to manipulation // from user-initiated withdrawals as the outstanding debt fluctuates. uint256 outstanding = vault.debtOutstanding(); if (outstanding > debtThreshold) return true; // Check for profits and losses uint256 total = estimatedTotalAssets(); // Trigger if we have a loss to report if (total.add(debtThreshold) < params.totalDebt) return true; uint256 profit = 0; if (total > params.totalDebt) profit = total.sub(params.totalDebt); // We've earned a profit! // Otherwise, only trigger if it "makes sense" economically (gas cost // is <N% of value moved) uint256 credit = vault.creditAvailable(); return (profitFactor.mul(callCost) < credit.add(profit)); } /** * @notice * Harvests the Strategy, recognizing any profits or losses and adjusting * the Strategy's position. * * In the rare case the Strategy is in emergency shutdown, this will exit * the Strategy's position. * * This may only be called by governance, the strategist, or the keeper. * @dev * When `harvest()` is called, the Strategy reports to the Vault (via * `vault.report()`), so in some cases `harvest()` must be called in order * to take in profits, to borrow newly available funds from the Vault, or * otherwise adjust its position. In other cases `harvest()` must be * called to report to the Vault on the Strategy's position, especially if * any losses have occurred. */ function harvest() external onlyKeepers { uint256 profit = 0; uint256 loss = 0; uint256 debtOutstanding = vault.debtOutstanding(); uint256 debtPayment = 0; if (emergencyExit) { // Free up as much capital as possible uint256 amountFreed = liquidateAllPositions(); if (amountFreed < debtOutstanding) { loss = debtOutstanding.sub(amountFreed); } else if (amountFreed > debtOutstanding) { profit = amountFreed.sub(debtOutstanding); } debtPayment = debtOutstanding.sub(loss); } else { // Free up returns for Vault to pull (profit, loss, debtPayment) = prepareReturn(debtOutstanding); } // Allow Vault to take up to the "harvested" balance of this contract, // which is the amount it has earned since the last time it reported to // the Vault. uint256 totalDebt = vault.strategies(address(this)).totalDebt; debtOutstanding = vault.report(profit, loss, debtPayment); // Check if free returns are left, and re-invest them adjustPosition(debtOutstanding); // call healthCheck contract if (doHealthCheck && healthCheck != address(0)) { require(HealthCheck(healthCheck).check(profit, loss, debtPayment, debtOutstanding, totalDebt), "!healthcheck"); } else { emit SetDoHealthCheck(true); doHealthCheck = true; } emit Harvested(profit, loss, debtPayment, debtOutstanding); } /** * @notice * Withdraws `_amountNeeded` to `vault`. * * This may only be called by the Vault. * @param _amountNeeded How much `want` to withdraw. * @return _loss Any realized losses */ function withdraw(uint256 _amountNeeded) external returns (uint256 _loss) { require(msg.sender == address(vault), "!vault"); // Liquidate as much as possible to `want`, up to `_amountNeeded` uint256 amountFreed; (amountFreed, _loss) = liquidatePosition(_amountNeeded); // Send it directly back (NOTE: Using `msg.sender` saves some gas here) want.safeTransfer(msg.sender, amountFreed); // NOTE: Reinvest anything leftover on next `tend`/`harvest` } /** * Do anything necessary to prepare this Strategy for migration, such as * transferring any reserve or LP tokens, CDPs, or other tokens or stores of * value. */ function prepareMigration(address _newStrategy) internal virtual; /** * @notice * Transfers all `want` from this Strategy to `_newStrategy`. * * This may only be called by the Vault. * @dev * The new Strategy's Vault must be the same as this Strategy's Vault. * The migration process should be carefully performed to make sure all * the assets are migrated to the new address, which should have never * interacted with the vault before. * @param _newStrategy The Strategy to migrate to. */ function migrate(address _newStrategy) external { require(msg.sender == address(vault)); require(BaseStrategy(_newStrategy).vault() == vault); prepareMigration(_newStrategy); want.safeTransfer(_newStrategy, want.balanceOf(address(this))); } /** * @notice * Activates emergency exit. Once activated, the Strategy will exit its * position upon the next harvest, depositing all funds into the Vault as * quickly as is reasonable given on-chain conditions. * * This may only be called by governance or the strategist. * @dev * See `vault.setEmergencyShutdown()` and `harvest()` for further details. */ function setEmergencyExit() external onlyEmergencyAuthorized { emergencyExit = true; vault.revokeStrategy(); emit EmergencyExitEnabled(); } /** * Override this to add all tokens/tokenized positions this contract * manages on a *persistent* basis (e.g. not just for swapping back to * want ephemerally). * * NOTE: Do *not* include `want`, already included in `sweep` below. * * Example: * ``` * function protectedTokens() internal override view returns (address[] memory) { * address[] memory protected = new address[](3); * protected[0] = tokenA; * protected[1] = tokenB; * protected[2] = tokenC; * return protected; * } * ``` */ function protectedTokens() internal view virtual returns (address[] memory); /** * @notice * Removes tokens from this Strategy that are not the type of tokens * managed by this Strategy. This may be used in case of accidentally * sending the wrong kind of token to this Strategy. * * Tokens will be sent to `governance()`. * * This will fail if an attempt is made to sweep `want`, or any tokens * that are protected by this Strategy. * * This may only be called by governance. * @dev * Implement `protectedTokens()` to specify any additional tokens that * should be protected from sweeping in addition to `want`. * @param _token The token to transfer out of this vault. */ function sweep(address _token) external onlyGovernance { require(_token != address(want), "!want"); require(_token != address(vault), "!shares"); address[] memory _protectedTokens = protectedTokens(); for (uint256 i; i < _protectedTokens.length; i++) require(_token != _protectedTokens[i], "!protected"); IERC20(_token).safeTransfer(governance(), IERC20(_token).balanceOf(address(this))); } } abstract contract BaseStrategyInitializable is BaseStrategy { bool public isOriginal = true; event Cloned(address indexed clone); constructor(address _vault) public BaseStrategy(_vault) {} function initialize( address _vault, address _strategist, address _rewards, address _keeper ) external virtual { _initialize(_vault, _strategist, _rewards, _keeper); } function clone(address _vault) external returns (address) { require(isOriginal, "!clone"); return this.clone(_vault, msg.sender, msg.sender, msg.sender); } function clone( address _vault, address _strategist, address _rewards, address _keeper ) external returns (address newStrategy) { // Copied from https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol bytes20 addressBytes = bytes20(address(this)); assembly { // EIP-1167 bytecode let clone_code := mload(0x40) mstore(clone_code, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) mstore(add(clone_code, 0x14), addressBytes) mstore(add(clone_code, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) newStrategy := create(0, clone_code, 0x37) } BaseStrategyInitializable(newStrategy).initialize(_vault, _strategist, _rewards, _keeper); emit Cloned(newStrategy); } } // File: GenericLenderBase.sol interface IBaseStrategy { function apiVersion() external pure returns (string memory); function name() external pure returns (string memory); function vault() external view returns (address); function keeper() external view returns (address); function tendTrigger(uint256 callCost) external view returns (bool); function tend() external; function harvestTrigger(uint256 callCost) external view returns (bool); function harvest() external; function strategist() external view returns(address); function management() external view returns (address); } abstract contract GenericLenderBase is IGenericLender { using SafeERC20 for IERC20; VaultAPI public vault; address public override strategy; IERC20 public want; string public override lenderName; uint256 public dust; event Cloned(address indexed clone); constructor(address _strategy, string memory _name) public { _initialize(_strategy, _name); } function _initialize(address _strategy, string memory _name) internal { require(address(strategy) == address(0), "Lender already initialized"); strategy = _strategy; vault = VaultAPI(IBaseStrategy(strategy).vault()); want = IERC20(vault.token()); lenderName = _name; dust = 10000; want.safeApprove(_strategy, uint256(-1)); } function initialize(address _strategy, string memory _name) external virtual { _initialize(_strategy, _name); } function _clone(address _strategy, string memory _name) internal returns (address newLender) { // Copied from https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol bytes20 addressBytes = bytes20(address(this)); assembly { // EIP-1167 bytecode let clone_code := mload(0x40) mstore(clone_code, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) mstore(add(clone_code, 0x14), addressBytes) mstore(add(clone_code, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) newLender := create(0, clone_code, 0x37) } GenericLenderBase(newLender).initialize(_strategy, _name); emit Cloned(newLender); } function setDust(uint256 _dust) external virtual override management { dust = _dust; } function sweep(address _token) external virtual override management { address[] memory _protectedTokens = protectedTokens(); for (uint256 i; i < _protectedTokens.length; i++) require(_token != _protectedTokens[i], "!protected"); IERC20(_token).safeTransfer(vault.governance(), IERC20(_token).balanceOf(address(this))); } function protectedTokens() internal view virtual returns (address[] memory); modifier management() { require( msg.sender == address(strategy) || msg.sender == vault.governance() || msg.sender == IBaseStrategy(strategy).strategist(), "!management" ); _; } modifier onlyGovernance() { require(msg.sender == vault.governance(), "!gov"); _; } } // File: GenericCompoundV3.sol /******************** * A lender plugin for LenderYieldOptimiser for any borrowable erc20 asset on compoundV3 (not eth) * Made by @Schlagonia * https://github.com/Schlagonia/Yearn-V2-Generic-Lender/blob/main/contracts/GenericLender/GenericCompoundV3.sol * ********************* */ interface IBaseFee { function isCurrentBaseFeeAcceptable() external view returns (bool); } contract GenericCompoundV3 is GenericLenderBase { using Address for address; using SafeMath for uint256; //For apr calculations uint internal constant DAYS_PER_YEAR = 365; uint internal constant SECONDS_PER_DAY = 60 * 60 * 24; uint internal constant SECONDS_PER_YEAR = 365 days; //Rewards stuff //Uniswap v3 router ISwapRouter internal constant router = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564); //Fees for the V3 pools if the supply is incentivized uint24 public compToEthFee; uint24 public ethToWantFee; address internal constant comp = 0xc00e94Cb662C3520282E6f5717214004A7f26888; address internal constant weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address public tradeFactory; Comet public comet; CometRewards public constant rewardsContract = CometRewards(0x1B0e765F6224C21223AeA2af16c1C46E38885a40); uint internal BASE_MANTISSA; uint internal BASE_INDEX_SCALE; uint256 public minCompToSell; uint256 public minRewardToHarvest; address public keep3r; constructor( address _strategy, string memory name, address _comet ) public GenericLenderBase(_strategy, name) { _initialize(_comet); } function initialize(address _comet) external { _initialize(_comet); } function _initialize(address _comet) internal { require(address(comet) == address(0), "already initialized"); comet = Comet(_comet); require(comet.baseToken() == address(want), "wrong token"); BASE_MANTISSA = comet.baseScale(); BASE_INDEX_SCALE = comet.baseIndexScale(); want.safeApprove(_comet, type(uint256).max); IERC20(comp).safeApprove(address(router), type(uint256).max); minCompToSell = 0.05 ether; minRewardToHarvest = 10 ether; } function cloneCompoundV3Lender( address _strategy, string memory _name, address _comet ) external returns (address newLender) { newLender = _clone(_strategy, _name); GenericCompoundV3(newLender).initialize(_comet); } function setMinRewardAmounts(uint256 _minCompToSell, uint256 _minRewardToHavest) external management { minCompToSell = _minCompToSell; minRewardToHarvest = _minRewardToHavest; } //These will default to 0. //Will need to be manually set if want is incentized before any harvests function setUniFees(uint24 _compToEth, uint24 _ethToWant) external management { compToEthFee = _compToEth; ethToWantFee = _ethToWant; } function setKeep3r(address _keep3r) external management { keep3r = _keep3r; } function nav() external view override returns (uint256) { return _nav(); } function _nav() internal view returns (uint256) { return want.balanceOf(address(this)).add(underlyingBalanceStored()); } function underlyingBalanceStored() public view returns (uint256) { return comet.balanceOf(address(this)); } function apr() external view override returns (uint256) { return _apr(); } function _apr() internal view returns (uint256) { uint utilization = comet.getUtilization(); uint supplyRate = comet.getSupplyRate(utilization).mul(SECONDS_PER_YEAR); uint rewardRate = getRewardAprForSupplyBase(getPriceFeedAddress(comp), 0); return uint256(supplyRate.add(rewardRate)); } /* * Get the current reward for supplying APR in Compound III * @param rewardTokenPriceFeed The address of the reward token (e.g. COMP) price feed * @param newAmount Any amount that will be added to the total supply in a deposit * @return The reward APR in USD as a decimal scaled up by 1e18 */ function getRewardAprForSupplyBase(address rewardTokenPriceFeed, uint newAmount) public view returns (uint) { uint rewardToSuppliersPerDay = comet.baseTrackingSupplySpeed().mul(SECONDS_PER_DAY).mul(BASE_INDEX_SCALE).div(BASE_MANTISSA); if(rewardToSuppliersPerDay == 0) return 0; uint rewardTokenPriceInUsd = getCompoundPrice(rewardTokenPriceFeed); uint wantPriceInUsd = getCompoundPrice(comet.baseTokenPriceFeed()); uint wantTotalSupply = comet.totalSupply().add(newAmount); return (rewardTokenPriceInUsd.mul(rewardToSuppliersPerDay).div((wantTotalSupply.mul(wantPriceInUsd)))).mul(DAYS_PER_YEAR); } function getPriceFeedAddress(address asset) public view returns (address) { return comet.getAssetInfoByAddress(asset).priceFeed; } function getCompoundPrice(address singleAssetPriceFeed) public view returns (uint) { return comet.getPrice(singleAssetPriceFeed); } function weightedApr() external view override returns (uint256) { uint256 a = _apr(); return a.mul(_nav()); } function withdraw(uint256 amount) external override management returns (uint256) { return _withdraw(amount); } //emergency withdraw. sends balance plus amount to governance //Pass in uint256.max to withdraw everything function emergencyWithdraw(uint256 amount) external override onlyGovernance { //dont care about errors here. we want to exit what we can comet.withdraw(address(want), amount); want.safeTransfer(vault.governance(), want.balanceOf(address(this))); } //withdraw an amount including any want balance function _withdraw(uint256 amount) internal returns (uint256) { //Accrue rewards and interest to the lender so all following calls are acurate comet.accrueAccount(address(this)); uint256 balanceUnderlying = underlyingBalanceStored(); uint256 looseBalance = want.balanceOf(address(this)); uint256 total = balanceUnderlying.add(looseBalance); if (amount > total) { //cant withdraw more than we own amount = total; } if (looseBalance >= amount) { want.safeTransfer(address(strategy), amount); return amount; } uint256 liquidity = comet.totalSupply().sub(comet.totalBorrow()); if (liquidity > 1) { uint256 toWithdraw = amount.sub(looseBalance); if (toWithdraw <= liquidity) { //we can take all comet.withdraw(address(want), toWithdraw); } else { //take all we can comet.withdraw(address(want), liquidity); } } looseBalance = want.balanceOf(address(this)); want.safeTransfer(address(strategy), looseBalance); return looseBalance; } function harvest() external keepers { _claimCometRewards(); _disposeOfComp(); uint256 wantBalance = want.balanceOf(address(this)); if(wantBalance > 0) { comet.supply(address(want), wantBalance); } } function harvestTrigger(uint256 /*callCost*/) external view returns(bool) { if(!isBaseFeeAcceptable()) return false; if(getRewardsOwed().add(IERC20(comp).balanceOf(address(this))) > minRewardToHarvest) return true; } /* * Gets the amount of reward tokens due to this contract address */ function getRewardsOwed() public view returns (uint) { CometStructs.RewardConfig memory config = rewardsContract.rewardConfig(address(comet)); uint256 accrued = comet.baseTrackingAccrued(address(this)); if (config.shouldUpscale) { accrued *= config.rescaleFactor; } else { accrued /= config.rescaleFactor; } uint256 claimed = rewardsContract.rewardsClaimed(address(comet), address(this)); return accrued > claimed ? accrued - claimed : 0; } /* * External function that Claims the reward tokens due to this contract address */ function claimCometRewards() external keepers { _claimCometRewards(); } /* * Claims the reward tokens due to this contract address */ function _claimCometRewards() internal { rewardsContract.claim(address(comet), address(this), true); } function _disposeOfComp() internal { //check for Trade Factory implementation or that Uni fees are not set if(tradeFactory != address(0) || compToEthFee == 0) return; uint256 _comp = IERC20(comp).balanceOf(address(this)); if (_comp > minCompToSell) { if(address(want) == weth) { ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams( comp, // tokenIn address(want), // tokenOut compToEthFee, // comp-eth fee address(this), // recipient now, // deadline _comp, // amountIn 0, // amountOut 0 // sqrtPriceLimitX96 ); router.exactInputSingle(params); } else { bytes memory path = abi.encodePacked( comp, // comp-ETH compToEthFee, weth, // ETH-want ethToWantFee, address(want) ); // Proceeds from Comp are not subject to minExpectedSwapPercentage // so they could get sandwiched if we end up in an uncle block router.exactInput( ISwapRouter.ExactInputParams( path, address(this), now, _comp, 0 ) ); } } } function deposit() external override management { uint256 balance = want.balanceOf(address(this)); comet.supply(address(want), balance); } function withdrawAll() external override management returns (bool) { comet.accrueAccount(address(this)); uint256 invested = _nav(); uint256 returned = _withdraw(invested); return returned >= invested; } function hasAssets() external view override returns (bool) { return comet.balanceOf(address(this)) > 0 || want.balanceOf(address(this)) > 0; } function aprAfterDeposit(uint256 amount) external view override returns (uint256) { uint256 borrows = comet.totalBorrow(); uint256 supply = comet.totalSupply(); uint256 newUtilization = borrows.mul(1e18).div(supply.add(amount)); uint256 newSupply = comet.getSupplyRate(newUtilization).mul(SECONDS_PER_YEAR); uint256 newReward = getRewardAprForSupplyBase(getPriceFeedAddress(comp), amount); return newSupply.add(newReward); } function protectedTokens() internal view override returns (address[] memory) { address[] memory protected = new address[](1); protected[0] = address(want); return protected; } modifier keepers() { require( msg.sender == address(keep3r) || msg.sender == address(strategy) || msg.sender == vault.governance() || msg.sender == IBaseStrategy(strategy).strategist(), "!keepers" ); _; } // check if the current baseFee is below our external target function isBaseFeeAcceptable() internal view returns (bool) { return IBaseFee(0xb5e1CAcB567d98faaDB60a1fD4820720141f064F) .isCurrentBaseFeeAcceptable(); } // ---------------------- YSWAPS FUNCTIONS ---------------------- function setTradeFactory(address _tradeFactory) external onlyGovernance { if (tradeFactory != address(0)) { _removeTradeFactoryPermissions(); } ITradeFactory tf = ITradeFactory(_tradeFactory); IERC20(comp).safeApprove(_tradeFactory, type(uint256).max); tf.enable(comp, address(want)); tradeFactory = _tradeFactory; } function removeTradeFactoryPermissions() external management { _removeTradeFactoryPermissions(); } function _removeTradeFactoryPermissions() internal { IERC20(comp).safeApprove(tradeFactory, 0); ITradeFactory(tradeFactory).disable(comp, address(want)); tradeFactory = address(0); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"_comet","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clone","type":"address"}],"name":"Cloned","type":"event"},{"inputs":[],"name":"apr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"aprAfterDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimCometRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_comet","type":"address"}],"name":"cloneCompoundV3Lender","outputs":[{"internalType":"address","name":"newLender","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"comet","outputs":[{"internalType":"contract Comet","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"compToEthFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dust","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ethToWantFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"singleAssetPriceFeed","type":"address"}],"name":"getCompoundPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getPriceFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rewardTokenPriceFeed","type":"address"},{"internalType":"uint256","name":"newAmount","type":"uint256"}],"name":"getRewardAprForSupplyBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardsOwed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"harvestTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasAssets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_comet","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"string","name":"_name","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"keep3r","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lenderName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minCompToSell","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minRewardToHarvest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nav","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"removeTradeFactoryPermissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardsContract","outputs":[{"internalType":"contract CometRewards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_dust","type":"uint256"}],"name":"setDust","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keep3r","type":"address"}],"name":"setKeep3r","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minCompToSell","type":"uint256"},{"internalType":"uint256","name":"_minRewardToHavest","type":"uint256"}],"name":"setMinRewardAmounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tradeFactory","type":"address"}],"name":"setTradeFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"_compToEth","type":"uint24"},{"internalType":"uint24","name":"_ethToWant","type":"uint24"}],"name":"setUniFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tradeFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingBalanceStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract VaultAPI","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"want","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weightedApr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051620050c4380380620050c483398101604081905262000034916200085f565b828262000042828262000059565b506200005090508162000221565b50505062000bb9565b6001546001600160a01b0316156200008e5760405162461bcd60e51b8152600401620000859062000b4f565b60405180910390fd5b600180546001600160a01b0319166001600160a01b0384811691909117918290556040805163fbfa77cf60e01b81529051929091169163fbfa77cf91600480820192602092909190829003018186803b158015620000eb57600080fd5b505afa15801562000100573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200012691906200083a565b600080546001600160a01b0319166001600160a01b03928316179081905560408051637e062a3560e11b81529051919092169163fc0c546a916004808301926020929190829003018186803b1580156200017f57600080fd5b505afa15801562000194573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ba91906200083a565b600280546001600160a01b0319166001600160a01b03929092169190911790558051620001ef90600390602084019062000780565b506127106004556002546200021d906001600160a01b031683600019620004b1602090811b620027c017901c565b5050565b6006546001600160a01b0316156200024d5760405162461bcd60e51b8152600401620000859062000a3a565b600680546001600160a01b0319166001600160a01b0383811691909117918290556002546040805163c55dae6360e01b81529051918316939092169163c55dae63916004808301926020929190829003018186803b158015620002af57600080fd5b505afa158015620002c4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ea91906200083a565b6001600160a01b031614620003135760405162461bcd60e51b8152600401620000859062000a15565b600660009054906101000a90046001600160a01b03166001600160a01b03166344c1e5eb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200036257600080fd5b505afa15801562000377573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200039d91906200094d565b600755600654604080516396e7a9c160e01b815290516001600160a01b03909216916396e7a9c191600480820192602092909190829003018186803b158015620003e657600080fd5b505afa158015620003fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000421919062000966565b6001600160401b031660085560025462000454906001600160a01b031682600019620004b1602090811b620027c017901c565b6200049773c00e94cb662c3520282e6f5717214004a7f2688873e592427a0aece92de3edee1f18e0157c05861564600019620004b1602090811b620027c017901c565b5066b1a2bc2ec50000600955678ac7230489e80000600a55565b801580620005405750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e90620004ea9030908690600401620009ad565b60206040518083038186803b1580156200050357600080fd5b505afa15801562000518573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200053e91906200094d565b155b6200055f5760405162461bcd60e51b8152600401620000859062000af2565b620005ba8363095ea7b360e01b848460405160240162000581929190620009c7565b60408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b0393841617905290620005bf16565b505050565b60606200061b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200065b60201b620028bf179092919060201c565b805190915015620005ba57808060200190518101906200063c91906200092b565b620005ba5760405162461bcd60e51b8152600401620000859062000aa8565b60606200066c848460008562000674565b949350505050565b6060620006818562000746565b620006a05760405162461bcd60e51b8152600401620000859062000a71565b60006060866001600160a01b03168587604051620006bf91906200098f565b60006040518083038185875af1925050503d8060008114620006fe576040519150601f19603f3d011682016040523d82523d6000602084013e62000703565b606091505b50915091508115620007195791506200066c9050565b8051156200072a5780518082602001fd5b8360405162461bcd60e51b8152600401620000859190620009e0565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906200066c575050151592915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620007c357805160ff1916838001178555620007f3565b82800160010185558215620007f3579182015b82811115620007f3578251825591602001919060010190620007d6565b506200080192915062000805565b5090565b5b8082111562000801576000815560010162000806565b80516001600160a01b03811681146200083457600080fd5b92915050565b6000602082840312156200084c578081fd5b6200085883836200081c565b9392505050565b60008060006060848603121562000874578182fd5b6200088085856200081c565b60208501519093506001600160401b03808211156200089d578384fd5b818601915086601f830112620008b1578384fd5b815181811115620008c0578485fd5b604051601f8201601f191681016020018381118282101715620008e1578687fd5b604052818152838201602001891015620008f9578586fd5b6200090c82602083016020870162000b86565b809550505050506200092285604086016200081c565b90509250925092565b6000602082840312156200093d578081fd5b8151801515811462000858578182fd5b6000602082840312156200095f578081fd5b5051919050565b60006020828403121562000978578081fd5b81516001600160401b038116811462000858578182fd5b60008251620009a381846020870162000b86565b9190910192915050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b600060208252825180602084015262000a0181604085016020870162000b86565b601f01601f19169190910160400192915050565b6020808252600b908201526a3bb937b733903a37b5b2b760a91b604082015260600190565b60208082526013908201527f616c726561647920696e697469616c697a656400000000000000000000000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606082015260800190565b6020808252601a908201527f4c656e64657220616c726561647920696e697469616c697a6564000000000000604082015260600190565b60005b8381101562000ba357818101518382015260200162000b89565b8381111562000bb3576000848401525b50505050565b6144fb8062000bc96000396000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c8063974c64721161013b578063c6afba3c116100b8578063ee0ff9371161007c578063ee0ff9371461044b578063f399e22e1461045e578063f7495cac14610471578063fad9aba314610479578063fbfa77cf1461048157610248565b8063c6afba3c14610418578063c97f2ca914610420578063d0e30db014610428578063e5e19b4a14610430578063ed882c2b1461043857610248565b8063ba3e9c12116100ff578063ba3e9c12146103d8578063bb52f70e146103e0578063c1590cd7146103e8578063c4017e76146103f0578063c4d66de81461040557610248565b8063974c64721461038f5780639d457cb9146103a2578063a8c62e76146103aa578063a9702225146103b2578063b21eb1e6146103c557610248565b80635312ea8e116101c95780636d51a20f1161018d5780636d51a20f1461034457806375c3c3a91461034c578063853828b61461035f5780638b2021761461036757806395b0c5071461037c57610248565b80635312ea8e146102f957806357ded9c91461030c5780635be9b2d314610314578063634c7bb514610329578063652109421461033157610248565b8063220cce9711610210578063220cce97146102b05780632e1a7d4d146102b8578063437552c0146102cb5780634641257d146102de5780634cc18e57146102e657610248565b806301681a621461024d57806304324af814610262578063116ac4a314610280578063149a4ae4146102885780631f1fcd511461029b575b600080fd5b61026061025b366004613ce0565b610489565b005b61026a610771565b6040516102779190614454565b60405180910390f35b61026a610777565b61026a610296366004613f6f565b61079c565b6102a36109b1565b6040516102779190614075565b6102a36109c0565b61026a6102c6366004613f6f565b6109d8565b6102606102d9366004613f6f565b610b54565b610260610cc3565b6102606102f4366004613ce0565b610f47565b610260610307366004613f6f565b6110d3565b61026a611309565b61031c611318565b6040516102779190614104565b6102a361142b565b61026061033f366004613ce0565b61143a565b6102606115d9565b6102a361035a366004613d66565b61174d565b61031c6117c1565b61036f6119b2565b604051610277919061410f565b61026061038a366004613f3b565b611a40565b61026a61039d366004613ce0565b611bd9565b61026a611c69565b6102a3611c6f565b6102606103c0366004613f9f565b611c7e565b6102a36103d3366004613ce0565b611df3565b6102a3611e7f565b610260611e8e565b61026a612015565b6103f861201f565b6040516102779190614444565b610260610413366004613ce0565b61202a565b61026a612033565b61026a6120b4565b6102606122d1565b6102a36124f4565b61031c610446366004613f6f565b61250a565b61026a610459366004613dc8565b6125ca565b61026061046c366004613d18565b61278f565b6103f8612799565b61026a6127ab565b6102a36127b1565b6001546001600160a01b0316331480610536575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b1580156104e957600080fd5b505afa1580156104fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105219190613cfc565b6001600160a01b0316336001600160a01b0316145b806105d75750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b15801561058a57600080fd5b505afa15801561059e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c29190613cfc565b6001600160a01b0316336001600160a01b0316145b6105fc5760405162461bcd60e51b81526004016105f390614263565b60405180910390fd5b60606106066128d6565b905060005b81518110156106615781818151811061062057fe5b60200260200101516001600160a01b0316836001600160a01b031614156106595760405162461bcd60e51b81526004016105f3906142d2565b60010161060b565b5060005460408051635aa6e67560e01b8152905161076d926001600160a01b031691635aa6e675916004808301926020929190829003018186803b1580156106a857600080fd5b505afa1580156106bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e09190613cfc565b6040516370a0823160e01b81526001600160a01b038516906370a082319061070c903090600401614075565b60206040518083038186803b15801561072457600080fd5b505afa158015610738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075c9190613f87565b6001600160a01b0385169190612932565b5050565b60095481565b600080610782612951565b905061079661078f612a51565b8290612aa6565b91505090565b600080600660009054906101000a90046001600160a01b03166001600160a01b0316638285ef406040518163ffffffff1660e01b815260040160206040518083038186803b1580156107ed57600080fd5b505afa158015610801573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108259190613f87565b90506000600660009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561087757600080fd5b505afa15801561088b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108af9190613f87565b905060006108d86108c08387612ae7565b6108d285670de0b6b3a7640000612aa6565b90612b0c565b60065460405163d955759d60e01b815291925060009161096e916301e13380916001600160a01b039091169063d955759d90610918908790600401614454565b60206040518083038186803b15801561093057600080fd5b505afa158015610944573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109689190613f87565b90612aa6565b9050600061099861099273c00e94cb662c3520282e6f5717214004a7f26888611df3565b886125ca565b90506109a48282612ae7565b955050505050505b919050565b6002546001600160a01b031681565b731b0e765f6224c21223aea2af16c1c46e38885a4081565b6001546000906001600160a01b0316331480610a88575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015610a3b57600080fd5b505afa158015610a4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a739190613cfc565b6001600160a01b0316336001600160a01b0316145b80610b295750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015610adc57600080fd5b505afa158015610af0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b149190613cfc565b6001600160a01b0316336001600160a01b0316145b610b455760405162461bcd60e51b81526004016105f390614263565b610b4e82612b4e565b92915050565b6001546001600160a01b0316331480610c01575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bb457600080fd5b505afa158015610bc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bec9190613cfc565b6001600160a01b0316336001600160a01b0316145b80610ca25750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015610c5557600080fd5b505afa158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d9190613cfc565b6001600160a01b0316336001600160a01b0316145b610cbe5760405162461bcd60e51b81526004016105f390614263565b600455565b600b546001600160a01b0316331480610ce657506001546001600160a01b031633145b80610d85575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015610d3857600080fd5b505afa158015610d4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d709190613cfc565b6001600160a01b0316336001600160a01b0316145b80610e265750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015610dd957600080fd5b505afa158015610ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e119190613cfc565b6001600160a01b0316336001600160a01b0316145b610e425760405162461bcd60e51b81526004016105f3906141c9565b610e4a612f45565b610e52612fc0565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190610e83903090600401614075565b60206040518083038186803b158015610e9b57600080fd5b505afa158015610eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed39190613f87565b90508015610f4457600654600254604051631e573fb760e31b81526001600160a01b039283169263f2b9fdb892610f119291169085906004016140eb565b600060405180830381600087803b158015610f2b57600080fd5b505af1158015610f3f573d6000803e3d6000fd5b505050505b50565b6001546001600160a01b0316331480610ff4575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015610fa757600080fd5b505afa158015610fbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdf9190613cfc565b6001600160a01b0316336001600160a01b0316145b806110955750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b15801561104857600080fd5b505afa15801561105c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110809190613cfc565b6001600160a01b0316336001600160a01b0316145b6110b15760405162461bcd60e51b81526004016105f390614263565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b60008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561111f57600080fd5b505afa158015611133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111579190613cfc565b6001600160a01b0316336001600160a01b0316146111875760405162461bcd60e51b81526004016105f390614159565b60065460025460405163f3fef3a360e01b81526001600160a01b039283169263f3fef3a3926111bd9291169085906004016140eb565b600060405180830381600087803b1580156111d757600080fd5b505af11580156111eb573d6000803e3d6000fd5b50505050610f4460008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561123e57600080fd5b505afa158015611252573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112769190613cfc565b6002546040516370a0823160e01b81526001600160a01b03909116906370a08231906112a6903090600401614075565b60206040518083038186803b1580156112be57600080fd5b505afa1580156112d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f69190613f87565b6002546001600160a01b03169190612932565b6000611313612951565b905090565b6006546040516370a0823160e01b815260009182916001600160a01b03909116906370a082319061134d903090600401614075565b60206040518083038186803b15801561136557600080fd5b505afa158015611379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139d9190613f87565b118061131357506002546040516370a0823160e01b81526000916001600160a01b0316906370a08231906113d5903090600401614075565b60206040518083038186803b1580156113ed57600080fd5b505afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114259190613f87565b11905090565b600b546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561148657600080fd5b505afa15801561149a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114be9190613cfc565b6001600160a01b0316336001600160a01b0316146114ee5760405162461bcd60e51b81526004016105f390614159565b600554600160301b90046001600160a01b03161561150e5761150e6132c1565b8061153073c00e94cb662c3520282e6f5717214004a7f26888826000196127c0565b600254604051632642a09360e11b81526001600160a01b0380841692634c854126926115769273c00e94cb662c3520282e6f5717214004a7f26888921690600401614089565b600060405180830381600087803b15801561159057600080fd5b505af11580156115a4573d6000803e3d6000fd5b5050600580546001600160a01b03909516600160301b026601000000000000600160d01b031990951694909417909355505050565b6001546001600160a01b0316331480611686575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561163957600080fd5b505afa15801561164d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116719190613cfc565b6001600160a01b0316336001600160a01b0316145b806117275750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b1580156116da57600080fd5b505afa1580156116ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117129190613cfc565b6001600160a01b0316336001600160a01b0316145b6117435760405162461bcd60e51b81526004016105f390614263565b61174b6132c1565b565b60006117598484613391565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890611788908590600401614075565b600060405180830381600087803b1580156117a257600080fd5b505af11580156117b6573d6000803e3d6000fd5b505050509392505050565b6001546000906001600160a01b0316331480611871575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561182457600080fd5b505afa158015611838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185c9190613cfc565b6001600160a01b0316336001600160a01b0316145b806119125750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b1580156118c557600080fd5b505afa1580156118d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118fd9190613cfc565b6001600160a01b0316336001600160a01b0316145b61192e5760405162461bcd60e51b81526004016105f390614263565b60065460405163bfe69c8d60e01b81526001600160a01b039091169063bfe69c8d9061195e903090600401614075565b600060405180830381600087803b15801561197857600080fd5b505af115801561198c573d6000803e3d6000fd5b50505050600061199a612a51565b905060006119a782612b4e565b919091101591505090565b6003805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015611a385780601f10611a0d57610100808354040283529160200191611a38565b820191906000526020600020905b815481529060010190602001808311611a1b57829003601f168201915b505050505081565b6001546001600160a01b0316331480611aed575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015611aa057600080fd5b505afa158015611ab4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad89190613cfc565b6001600160a01b0316336001600160a01b0316145b80611b8e5750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015611b4157600080fd5b505afa158015611b55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b799190613cfc565b6001600160a01b0316336001600160a01b0316145b611baa5760405162461bcd60e51b81526004016105f390614263565b6005805462ffffff92831663010000000265ffffff000000199490931662ffffff199091161792909216179055565b6006546040516341976e0960e01b81526000916001600160a01b0316906341976e0990611c0a908590600401614075565b60206040518083038186803b158015611c2257600080fd5b505afa158015611c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5a9190613f20565b6001600160801b031692915050565b600a5481565b6001546001600160a01b031681565b6001546001600160a01b0316331480611d2b575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015611cde57600080fd5b505afa158015611cf2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d169190613cfc565b6001600160a01b0316336001600160a01b0316145b80611dcc5750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015611d7f57600080fd5b505afa158015611d93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db79190613cfc565b6001600160a01b0316336001600160a01b0316145b611de85760405162461bcd60e51b81526004016105f390614263565b600991909155600a55565b600654604051631d9df61760e11b81526000916001600160a01b031690633b3bec2e90611e24908590600401614075565b6101006040518083038186803b158015611e3d57600080fd5b505afa158015611e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e759190613e13565b6040015192915050565b6006546001600160a01b031681565b600b546001600160a01b0316331480611eb157506001546001600160a01b031633145b80611f50575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015611f0357600080fd5b505afa158015611f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3b9190613cfc565b6001600160a01b0316336001600160a01b0316145b80611ff15750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015611fa457600080fd5b505afa158015611fb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fdc9190613cfc565b6001600160a01b0316336001600160a01b0316145b61200d5760405162461bcd60e51b81526004016105f3906141c9565b61174b612f45565b6000611313612a51565b60055462ffffff1681565b610f4481613478565b6006546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612064903090600401614075565b60206040518083038186803b15801561207c57600080fd5b505afa158015612090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113139190613f87565b60006120be613b33565b60065460405163045136d760e31b8152731b0e765f6224c21223aea2af16c1c46e38885a4091632289b6b891612100916001600160a01b031690600401614075565b60606040518083038186803b15801561211857600080fd5b505afa15801561212c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121509190613ec8565b600654604051632ae6e9fd60e21b81529192506000916001600160a01b039091169063ab9ba7f490612186903090600401614075565b60206040518083038186803b15801561219e57600080fd5b505afa1580156121b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d69190613fc0565b67ffffffffffffffff16905081604001511561220157602082015167ffffffffffffffff160261221c565b816020015167ffffffffffffffff16818161221857fe5b0490505b6006546040516332f091c960e11b8152600091731b0e765f6224c21223aea2af16c1c46e38885a40916365e1239291612265916001600160a01b03909116903090600401614089565b60206040518083038186803b15801561227d57600080fd5b505afa158015612291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b59190613f87565b90508082116122c55760006122c9565b8082035b935050505090565b6001546001600160a01b031633148061237e575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561233157600080fd5b505afa158015612345573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123699190613cfc565b6001600160a01b0316336001600160a01b0316145b8061241f5750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b1580156123d257600080fd5b505afa1580156123e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240a9190613cfc565b6001600160a01b0316336001600160a01b0316145b61243b5760405162461bcd60e51b81526004016105f390614263565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a082319061246c903090600401614075565b60206040518083038186803b15801561248457600080fd5b505afa158015612498573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124bc9190613f87565b600654600254604051631e573fb760e31b81529293506001600160a01b039182169263f2b9fdb892610f1192169085906004016140eb565b600554600160301b90046001600160a01b031681565b60006125146136db565b612520575060006109ac565b600a546040516370a0823160e01b81526125bc9073c00e94cb662c3520282e6f5717214004a7f26888906370a082319061255e903090600401614075565b60206040518083038186803b15801561257657600080fd5b505afa15801561258a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ae9190613f87565b6125b66120b4565b90612ae7565b11156109ac575060016109ac565b60008061262e6007546108d260085461096862015180600660009054906101000a90046001600160a01b03166001600160a01b031663189bb2f16040518163ffffffff1660e01b815260040160206040518083038186803b15801561093057600080fd5b90508061263f576000915050610b4e565b600061264a85611bd9565b905060006126d7600660009054906101000a90046001600160a01b03166001600160a01b031663e7dad6bd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561269f57600080fd5b505afa1580156126b3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039d9190613cfc565b9050600061276586600660009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561272d57600080fd5b505afa158015612741573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b69190613f87565b905061278461016d61096861277a8486612aa6565b6108d28789612aa6565b979650505050505050565b61076d8282613762565b6005546301000000900462ffffff1681565b60045481565b6000546001600160a01b031681565b8015806128485750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906127f69030908690600401614089565b60206040518083038186803b15801561280e57600080fd5b505afa158015612822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128469190613f87565b155b6128645760405162461bcd60e51b81526004016105f3906142f6565b6128ba8363095ea7b360e01b84846040516024016128839291906140eb565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613902565b505050565b60606128ce8484600085613991565b949350505050565b60408051600180825281830190925260609182919060208083019080368337505060025482519293506001600160a01b03169183915060009061291557fe5b6001600160a01b0390921660209283029190910190910152905090565b6128ba8363a9059cbb60e01b84846040516024016128839291906140eb565b600080600660009054906101000a90046001600160a01b03166001600160a01b0316637eb711316040518163ffffffff1660e01b815260040160206040518083038186803b1580156129a257600080fd5b505afa1580156129b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129da9190613f87565b60065460405163d955759d60e01b8152919250600091612a1a916301e13380916001600160a01b039091169063d955759d90610918908790600401614454565b90506000612a45612a3e73c00e94cb662c3520282e6f5717214004a7f26888611df3565b60006125ca565b90506122c98282612ae7565b6000611313612a5e612033565b6002546040516370a0823160e01b81526001600160a01b03909116906370a0823190612a8e903090600401614075565b60206040518083038186803b15801561272d57600080fd5b600082612ab557506000610b4e565b82820282848281612ac257fe5b0414612ae05760405162461bcd60e51b81526004016105f3906141eb565b9392505050565b600082820183811015612ae05760405162461bcd60e51b81526004016105f390614122565b6000612ae083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613a55565b60065460405163bfe69c8d60e01b81526000916001600160a01b03169063bfe69c8d90612b7f903090600401614075565b600060405180830381600087803b158015612b9957600080fd5b505af1158015612bad573d6000803e3d6000fd5b505050506000612bbb612033565b6002546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190612bf1903090600401614075565b60206040518083038186803b158015612c0957600080fd5b505afa158015612c1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c419190613f87565b90506000612c4f8383612ae7565b905080851115612c5d578094505b848210612c8c57600154600254612c81916001600160a01b03918216911687612932565b8493505050506109ac565b6000612da3600660009054906101000a90046001600160a01b03166001600160a01b0316638285ef406040518163ffffffff1660e01b815260040160206040518083038186803b158015612cdf57600080fd5b505afa158015612cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d179190613f87565b600660009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d6557600080fd5b505afa158015612d79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d9d9190613f87565b90613a8c565b90506001811115612e9b576000612dba8785613a8c565b9050818111612e305760065460025460405163f3fef3a360e01b81526001600160a01b039283169263f3fef3a392612df99291169085906004016140eb565b600060405180830381600087803b158015612e1357600080fd5b505af1158015612e27573d6000803e3d6000fd5b50505050612e99565b60065460025460405163f3fef3a360e01b81526001600160a01b039283169263f3fef3a392612e669291169086906004016140eb565b600060405180830381600087803b158015612e8057600080fd5b505af1158015612e94573d6000803e3d6000fd5b505050505b505b6002546040516370a0823160e01b81526001600160a01b03909116906370a0823190612ecb903090600401614075565b60206040518083038186803b158015612ee357600080fd5b505afa158015612ef7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1b9190613f87565b600154600254919450612f3b916001600160a01b03908116911685612932565b5090949350505050565b600654604051635b81a7bf60e11b8152731b0e765f6224c21223aea2af16c1c46e38885a409163b7034f7e91612f8c916001600160a01b03169030906001906004016140a3565b600060405180830381600087803b158015612fa657600080fd5b505af1158015612fba573d6000803e3d6000fd5b50505050565b600554600160301b90046001600160a01b0316151580612fe5575060055462ffffff16155b15612fef5761174b565b6040516370a0823160e01b815260009073c00e94cb662c3520282e6f5717214004a7f26888906370a0823190613029903090600401614075565b60206040518083038186803b15801561304157600080fd5b505afa158015613055573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130799190613f87565b9050600954811115610f44576002546001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc214156131a4576130b4613b53565b50604080516101008101825273c00e94cb662c3520282e6f5717214004a7f2688881526002546001600160a01b0316602082015260055462ffffff168183015230606082015242608082015260a08101839052600060c0820181905260e0820152905163414bf38960e01b815273e592427a0aece92de3edee1f18e0157c058615649063414bf3899061314b9084906004016143db565b602060405180830381600087803b15801561316557600080fd5b505af1158015613179573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061319d9190613f87565b5050610f44565b6005546002546040516060926132089273c00e94cb662c3520282e6f5717214004a7f268889262ffffff8084169373c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2936301000000909104909116916001600160a01b0390911690602001614007565b60408051601f1981840301815260a08301825280835230602084015242838301526060830185905260006080840152905163c04b8d5960e01b815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d599161326f9190600401614383565b602060405180830381600087803b15801561328957600080fd5b505af115801561329d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128ba9190613f87565b6005546132f59073c00e94cb662c3520282e6f5717214004a7f2688890600160301b90046001600160a01b031660006127c0565b600554600254604051639cd38be560e01b8152600160301b9092046001600160a01b0390811692639cd38be5926133479273c00e94cb662c3520282e6f5717214004a7f2688892911690600401614089565b600060405180830381600087803b15801561336157600080fd5b505af1158015613375573d6000803e3d6000fd5b5050600580546601000000000000600160d01b03191690555050565b604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81523060601b601482018190526e5af43d82803e903d91602b57fd5bf360881b602883015260009160378184f06040516379ccf11760e11b81529093506001600160a01b038416915063f399e22e9061340b90879087906004016140c7565b600060405180830381600087803b15801561342557600080fd5b505af1158015613439573d6000803e3d6000fd5b50506040516001600160a01b03851692507f783540fb4221a3238720dc7038937d0d79982bcf895274aa6ad179f82cf0d53c9150600090a25092915050565b6006546001600160a01b0316156134a15760405162461bcd60e51b81526004016105f39061419c565b600680546001600160a01b0319166001600160a01b0383811691909117918290556002546040805163c55dae6360e01b81529051918316939092169163c55dae63916004808301926020929190829003018186803b15801561350257600080fd5b505afa158015613516573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353a9190613cfc565b6001600160a01b0316146135605760405162461bcd60e51b81526004016105f390614177565b600660009054906101000a90046001600160a01b03166001600160a01b03166344c1e5eb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156135ae57600080fd5b505afa1580156135c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135e69190613f87565b600755600654604080516396e7a9c160e01b815290516001600160a01b03909216916396e7a9c191600480820192602092909190829003018186803b15801561362e57600080fd5b505afa158015613642573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136669190613fc0565b67ffffffffffffffff1660085560025461368c906001600160a01b0316826000196127c0565b6136c173c00e94cb662c3520282e6f5717214004a7f2688873e592427a0aece92de3edee1f18e0157c058615646000196127c0565b5066b1a2bc2ec50000600955678ac7230489e80000600a55565b600073b5e1cacb567d98faadb60a1fd4820720141f064f6001600160a01b03166334a9e75c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561372a57600080fd5b505afa15801561373e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113139190613df3565b6001546001600160a01b03161561378b5760405162461bcd60e51b81526004016105f39061434c565b600180546001600160a01b0319166001600160a01b0384811691909117918290556040805163fbfa77cf60e01b81529051929091169163fbfa77cf91600480820192602092909190829003018186803b1580156137e757600080fd5b505afa1580156137fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061381f9190613cfc565b600080546001600160a01b0319166001600160a01b03928316179081905560408051637e062a3560e11b81529051919092169163fc0c546a916004808301926020929190829003018186803b15801561387757600080fd5b505afa15801561388b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138af9190613cfc565b600280546001600160a01b0319166001600160a01b039290921691909117905580516138e2906003906020840190613b97565b5061271060045560025461076d906001600160a01b0316836000196127c0565b6060613957826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166128bf9092919063ffffffff16565b8051909150156128ba57808060200190518101906139759190613df3565b6128ba5760405162461bcd60e51b81526004016105f390614288565b606061399c85613ace565b6139b85760405162461bcd60e51b81526004016105f39061422c565b60006060866001600160a01b031685876040516139d59190614059565b60006040518083038185875af1925050503d8060008114613a12576040519150601f19603f3d011682016040523d82523d6000602084013e613a17565b606091505b50915091508115613a2b5791506128ce9050565b805115613a3b5780518082602001fd5b8360405162461bcd60e51b81526004016105f3919061410f565b60008183613a765760405162461bcd60e51b81526004016105f3919061410f565b506000838581613a8257fe5b0495945050505050565b6000612ae083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613b07565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906128ce575050151592915050565b60008184841115613b2b5760405162461bcd60e51b81526004016105f3919061410f565b505050900390565b604080516060810182526000808252602082018190529181019190915290565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613bd857805160ff1916838001178555613c05565b82800160010185558215613c05579182015b82811115613c05578251825591602001919060010190613bea565b50613c11929150613c15565b5090565b5b80821115613c115760008155600101613c16565b8051610b4e816144b0565b600082601f830112613c45578081fd5b813567ffffffffffffffff811115613c5b578182fd5b613c6e601f8201601f191660200161445d565b9150808252836020828501011115613c8557600080fd5b8060208401602084013760009082016020015292915050565b80516001600160801b0381168114610b4e57600080fd5b803562ffffff81168114610b4e57600080fd5b805167ffffffffffffffff81168114610b4e57600080fd5b600060208284031215613cf1578081fd5b8135612ae0816144b0565b600060208284031215613d0d578081fd5b8151612ae0816144b0565b60008060408385031215613d2a578081fd5b8235613d35816144b0565b9150602083013567ffffffffffffffff811115613d50578182fd5b613d5c85828601613c35565b9150509250929050565b600080600060608486031215613d7a578081fd5b8335613d85816144b0565b9250602084013567ffffffffffffffff811115613da0578182fd5b613dac86828701613c35565b9250506040840135613dbd816144b0565b809150509250925092565b60008060408385031215613dda578182fd5b8235613de5816144b0565b946020939093013593505050565b600060208284031215613e04578081fd5b81518015158114612ae0578182fd5b6000610100808385031215613e26578182fd5b613e2f8161445d565b9050825160ff81168114613e41578283fd5b8152613e508460208501613c2a565b6020820152613e628460408501613c2a565b6040820152613e748460608501613cc8565b6060820152613e868460808501613cc8565b6080820152613e988460a08501613cc8565b60a0820152613eaa8460c08501613cc8565b60c0820152613ebc8460e08501613c9e565b60e08201529392505050565b600060608284031215613ed9578081fd5b613ee3606061445d565b8251613eee816144b0565b8152613efd8460208501613cc8565b602082015260408301518015158114613f14578283fd5b60408201529392505050565b600060208284031215613f31578081fd5b612ae08383613c9e565b60008060408385031215613f4d578182fd5b613f578484613cb5565b9150613f668460208501613cb5565b90509250929050565b600060208284031215613f80578081fd5b5035919050565b600060208284031215613f98578081fd5b5051919050565b60008060408385031215613fb1578081fd5b50508035926020909101359150565b600060208284031215613fd1578081fd5b612ae08383613cc8565b60008151808452613ff3816020860160208601614484565b601f01601f19169290920160200192915050565b6bffffffffffffffffffffffff19606096871b811682526001600160e81b031960e896871b8116601484015294871b811660178301529290941b909216602b840152921b909116602e82015260420190565b6000825161406b818460208701614484565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6001600160a01b03831681526040602082018190526000906128ce90830184613fdb565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b600060208252612ae06020830184613fdb565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526004908201526310b3b7bb60e11b604082015260600190565b6020808252600b908201526a3bb937b733903a37b5b2b760a91b604082015260600190565b602080825260139082015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604082015260600190565b602080825260089082015267216b65657065727360c01b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a085b585b9859d95b595b9d60aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b6020808252601a908201527f4c656e64657220616c726561647920696e697469616c697a6564000000000000604082015260600190565b600060208252825160a0602084015261439f60c0840182613fdb565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b81516001600160a01b03908116825260208084015182169083015260408084015162ffffff16908301526060808401518216908301526080808401519083015260a0838101519083015260c0808401519083015260e09283015116918101919091526101000190565b62ffffff91909116815260200190565b90815260200190565b60405181810167ffffffffffffffff8111828210171561447c57600080fd5b604052919050565b60005b8381101561449f578181015183820152602001614487565b83811115612fba5750506000910152565b6001600160a01b0381168114610f4457600080fdfea264697066735822122082e41f580ac70347c8e45d4a344a166c3ff0f07eaaf408f6a665aa3e210d12e164736f6c634300060c00330000000000000000000000002216e44fa633abd2540db72ad34b42c7f1557cd40000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c3d688b66703497daa19211eedff47f25384cdc3000000000000000000000000000000000000000000000000000000000000000d47656e65726963436f6d70563300000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102485760003560e01c8063974c64721161013b578063c6afba3c116100b8578063ee0ff9371161007c578063ee0ff9371461044b578063f399e22e1461045e578063f7495cac14610471578063fad9aba314610479578063fbfa77cf1461048157610248565b8063c6afba3c14610418578063c97f2ca914610420578063d0e30db014610428578063e5e19b4a14610430578063ed882c2b1461043857610248565b8063ba3e9c12116100ff578063ba3e9c12146103d8578063bb52f70e146103e0578063c1590cd7146103e8578063c4017e76146103f0578063c4d66de81461040557610248565b8063974c64721461038f5780639d457cb9146103a2578063a8c62e76146103aa578063a9702225146103b2578063b21eb1e6146103c557610248565b80635312ea8e116101c95780636d51a20f1161018d5780636d51a20f1461034457806375c3c3a91461034c578063853828b61461035f5780638b2021761461036757806395b0c5071461037c57610248565b80635312ea8e146102f957806357ded9c91461030c5780635be9b2d314610314578063634c7bb514610329578063652109421461033157610248565b8063220cce9711610210578063220cce97146102b05780632e1a7d4d146102b8578063437552c0146102cb5780634641257d146102de5780634cc18e57146102e657610248565b806301681a621461024d57806304324af814610262578063116ac4a314610280578063149a4ae4146102885780631f1fcd511461029b575b600080fd5b61026061025b366004613ce0565b610489565b005b61026a610771565b6040516102779190614454565b60405180910390f35b61026a610777565b61026a610296366004613f6f565b61079c565b6102a36109b1565b6040516102779190614075565b6102a36109c0565b61026a6102c6366004613f6f565b6109d8565b6102606102d9366004613f6f565b610b54565b610260610cc3565b6102606102f4366004613ce0565b610f47565b610260610307366004613f6f565b6110d3565b61026a611309565b61031c611318565b6040516102779190614104565b6102a361142b565b61026061033f366004613ce0565b61143a565b6102606115d9565b6102a361035a366004613d66565b61174d565b61031c6117c1565b61036f6119b2565b604051610277919061410f565b61026061038a366004613f3b565b611a40565b61026a61039d366004613ce0565b611bd9565b61026a611c69565b6102a3611c6f565b6102606103c0366004613f9f565b611c7e565b6102a36103d3366004613ce0565b611df3565b6102a3611e7f565b610260611e8e565b61026a612015565b6103f861201f565b6040516102779190614444565b610260610413366004613ce0565b61202a565b61026a612033565b61026a6120b4565b6102606122d1565b6102a36124f4565b61031c610446366004613f6f565b61250a565b61026a610459366004613dc8565b6125ca565b61026061046c366004613d18565b61278f565b6103f8612799565b61026a6127ab565b6102a36127b1565b6001546001600160a01b0316331480610536575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b1580156104e957600080fd5b505afa1580156104fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105219190613cfc565b6001600160a01b0316336001600160a01b0316145b806105d75750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b15801561058a57600080fd5b505afa15801561059e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c29190613cfc565b6001600160a01b0316336001600160a01b0316145b6105fc5760405162461bcd60e51b81526004016105f390614263565b60405180910390fd5b60606106066128d6565b905060005b81518110156106615781818151811061062057fe5b60200260200101516001600160a01b0316836001600160a01b031614156106595760405162461bcd60e51b81526004016105f3906142d2565b60010161060b565b5060005460408051635aa6e67560e01b8152905161076d926001600160a01b031691635aa6e675916004808301926020929190829003018186803b1580156106a857600080fd5b505afa1580156106bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e09190613cfc565b6040516370a0823160e01b81526001600160a01b038516906370a082319061070c903090600401614075565b60206040518083038186803b15801561072457600080fd5b505afa158015610738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075c9190613f87565b6001600160a01b0385169190612932565b5050565b60095481565b600080610782612951565b905061079661078f612a51565b8290612aa6565b91505090565b600080600660009054906101000a90046001600160a01b03166001600160a01b0316638285ef406040518163ffffffff1660e01b815260040160206040518083038186803b1580156107ed57600080fd5b505afa158015610801573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108259190613f87565b90506000600660009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561087757600080fd5b505afa15801561088b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108af9190613f87565b905060006108d86108c08387612ae7565b6108d285670de0b6b3a7640000612aa6565b90612b0c565b60065460405163d955759d60e01b815291925060009161096e916301e13380916001600160a01b039091169063d955759d90610918908790600401614454565b60206040518083038186803b15801561093057600080fd5b505afa158015610944573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109689190613f87565b90612aa6565b9050600061099861099273c00e94cb662c3520282e6f5717214004a7f26888611df3565b886125ca565b90506109a48282612ae7565b955050505050505b919050565b6002546001600160a01b031681565b731b0e765f6224c21223aea2af16c1c46e38885a4081565b6001546000906001600160a01b0316331480610a88575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015610a3b57600080fd5b505afa158015610a4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a739190613cfc565b6001600160a01b0316336001600160a01b0316145b80610b295750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015610adc57600080fd5b505afa158015610af0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b149190613cfc565b6001600160a01b0316336001600160a01b0316145b610b455760405162461bcd60e51b81526004016105f390614263565b610b4e82612b4e565b92915050565b6001546001600160a01b0316331480610c01575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015610bb457600080fd5b505afa158015610bc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bec9190613cfc565b6001600160a01b0316336001600160a01b0316145b80610ca25750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015610c5557600080fd5b505afa158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d9190613cfc565b6001600160a01b0316336001600160a01b0316145b610cbe5760405162461bcd60e51b81526004016105f390614263565b600455565b600b546001600160a01b0316331480610ce657506001546001600160a01b031633145b80610d85575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015610d3857600080fd5b505afa158015610d4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d709190613cfc565b6001600160a01b0316336001600160a01b0316145b80610e265750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015610dd957600080fd5b505afa158015610ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e119190613cfc565b6001600160a01b0316336001600160a01b0316145b610e425760405162461bcd60e51b81526004016105f3906141c9565b610e4a612f45565b610e52612fc0565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190610e83903090600401614075565b60206040518083038186803b158015610e9b57600080fd5b505afa158015610eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed39190613f87565b90508015610f4457600654600254604051631e573fb760e31b81526001600160a01b039283169263f2b9fdb892610f119291169085906004016140eb565b600060405180830381600087803b158015610f2b57600080fd5b505af1158015610f3f573d6000803e3d6000fd5b505050505b50565b6001546001600160a01b0316331480610ff4575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015610fa757600080fd5b505afa158015610fbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdf9190613cfc565b6001600160a01b0316336001600160a01b0316145b806110955750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b15801561104857600080fd5b505afa15801561105c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110809190613cfc565b6001600160a01b0316336001600160a01b0316145b6110b15760405162461bcd60e51b81526004016105f390614263565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b60008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561111f57600080fd5b505afa158015611133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111579190613cfc565b6001600160a01b0316336001600160a01b0316146111875760405162461bcd60e51b81526004016105f390614159565b60065460025460405163f3fef3a360e01b81526001600160a01b039283169263f3fef3a3926111bd9291169085906004016140eb565b600060405180830381600087803b1580156111d757600080fd5b505af11580156111eb573d6000803e3d6000fd5b50505050610f4460008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561123e57600080fd5b505afa158015611252573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112769190613cfc565b6002546040516370a0823160e01b81526001600160a01b03909116906370a08231906112a6903090600401614075565b60206040518083038186803b1580156112be57600080fd5b505afa1580156112d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f69190613f87565b6002546001600160a01b03169190612932565b6000611313612951565b905090565b6006546040516370a0823160e01b815260009182916001600160a01b03909116906370a082319061134d903090600401614075565b60206040518083038186803b15801561136557600080fd5b505afa158015611379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139d9190613f87565b118061131357506002546040516370a0823160e01b81526000916001600160a01b0316906370a08231906113d5903090600401614075565b60206040518083038186803b1580156113ed57600080fd5b505afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114259190613f87565b11905090565b600b546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561148657600080fd5b505afa15801561149a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114be9190613cfc565b6001600160a01b0316336001600160a01b0316146114ee5760405162461bcd60e51b81526004016105f390614159565b600554600160301b90046001600160a01b03161561150e5761150e6132c1565b8061153073c00e94cb662c3520282e6f5717214004a7f26888826000196127c0565b600254604051632642a09360e11b81526001600160a01b0380841692634c854126926115769273c00e94cb662c3520282e6f5717214004a7f26888921690600401614089565b600060405180830381600087803b15801561159057600080fd5b505af11580156115a4573d6000803e3d6000fd5b5050600580546001600160a01b03909516600160301b026601000000000000600160d01b031990951694909417909355505050565b6001546001600160a01b0316331480611686575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561163957600080fd5b505afa15801561164d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116719190613cfc565b6001600160a01b0316336001600160a01b0316145b806117275750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b1580156116da57600080fd5b505afa1580156116ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117129190613cfc565b6001600160a01b0316336001600160a01b0316145b6117435760405162461bcd60e51b81526004016105f390614263565b61174b6132c1565b565b60006117598484613391565b60405163189acdbd60e31b81529091506001600160a01b0382169063c4d66de890611788908590600401614075565b600060405180830381600087803b1580156117a257600080fd5b505af11580156117b6573d6000803e3d6000fd5b505050509392505050565b6001546000906001600160a01b0316331480611871575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561182457600080fd5b505afa158015611838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185c9190613cfc565b6001600160a01b0316336001600160a01b0316145b806119125750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b1580156118c557600080fd5b505afa1580156118d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118fd9190613cfc565b6001600160a01b0316336001600160a01b0316145b61192e5760405162461bcd60e51b81526004016105f390614263565b60065460405163bfe69c8d60e01b81526001600160a01b039091169063bfe69c8d9061195e903090600401614075565b600060405180830381600087803b15801561197857600080fd5b505af115801561198c573d6000803e3d6000fd5b50505050600061199a612a51565b905060006119a782612b4e565b919091101591505090565b6003805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015611a385780601f10611a0d57610100808354040283529160200191611a38565b820191906000526020600020905b815481529060010190602001808311611a1b57829003601f168201915b505050505081565b6001546001600160a01b0316331480611aed575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015611aa057600080fd5b505afa158015611ab4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad89190613cfc565b6001600160a01b0316336001600160a01b0316145b80611b8e5750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015611b4157600080fd5b505afa158015611b55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b799190613cfc565b6001600160a01b0316336001600160a01b0316145b611baa5760405162461bcd60e51b81526004016105f390614263565b6005805462ffffff92831663010000000265ffffff000000199490931662ffffff199091161792909216179055565b6006546040516341976e0960e01b81526000916001600160a01b0316906341976e0990611c0a908590600401614075565b60206040518083038186803b158015611c2257600080fd5b505afa158015611c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5a9190613f20565b6001600160801b031692915050565b600a5481565b6001546001600160a01b031681565b6001546001600160a01b0316331480611d2b575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015611cde57600080fd5b505afa158015611cf2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d169190613cfc565b6001600160a01b0316336001600160a01b0316145b80611dcc5750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015611d7f57600080fd5b505afa158015611d93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db79190613cfc565b6001600160a01b0316336001600160a01b0316145b611de85760405162461bcd60e51b81526004016105f390614263565b600991909155600a55565b600654604051631d9df61760e11b81526000916001600160a01b031690633b3bec2e90611e24908590600401614075565b6101006040518083038186803b158015611e3d57600080fd5b505afa158015611e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e759190613e13565b6040015192915050565b6006546001600160a01b031681565b600b546001600160a01b0316331480611eb157506001546001600160a01b031633145b80611f50575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b158015611f0357600080fd5b505afa158015611f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3b9190613cfc565b6001600160a01b0316336001600160a01b0316145b80611ff15750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b158015611fa457600080fd5b505afa158015611fb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fdc9190613cfc565b6001600160a01b0316336001600160a01b0316145b61200d5760405162461bcd60e51b81526004016105f3906141c9565b61174b612f45565b6000611313612a51565b60055462ffffff1681565b610f4481613478565b6006546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612064903090600401614075565b60206040518083038186803b15801561207c57600080fd5b505afa158015612090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113139190613f87565b60006120be613b33565b60065460405163045136d760e31b8152731b0e765f6224c21223aea2af16c1c46e38885a4091632289b6b891612100916001600160a01b031690600401614075565b60606040518083038186803b15801561211857600080fd5b505afa15801561212c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121509190613ec8565b600654604051632ae6e9fd60e21b81529192506000916001600160a01b039091169063ab9ba7f490612186903090600401614075565b60206040518083038186803b15801561219e57600080fd5b505afa1580156121b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d69190613fc0565b67ffffffffffffffff16905081604001511561220157602082015167ffffffffffffffff160261221c565b816020015167ffffffffffffffff16818161221857fe5b0490505b6006546040516332f091c960e11b8152600091731b0e765f6224c21223aea2af16c1c46e38885a40916365e1239291612265916001600160a01b03909116903090600401614089565b60206040518083038186803b15801561227d57600080fd5b505afa158015612291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b59190613f87565b90508082116122c55760006122c9565b8082035b935050505090565b6001546001600160a01b031633148061237e575060008054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b15801561233157600080fd5b505afa158015612345573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123699190613cfc565b6001600160a01b0316336001600160a01b0316145b8061241f5750600160009054906101000a90046001600160a01b03166001600160a01b0316631fe4a6866040518163ffffffff1660e01b815260040160206040518083038186803b1580156123d257600080fd5b505afa1580156123e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240a9190613cfc565b6001600160a01b0316336001600160a01b0316145b61243b5760405162461bcd60e51b81526004016105f390614263565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a082319061246c903090600401614075565b60206040518083038186803b15801561248457600080fd5b505afa158015612498573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124bc9190613f87565b600654600254604051631e573fb760e31b81529293506001600160a01b039182169263f2b9fdb892610f1192169085906004016140eb565b600554600160301b90046001600160a01b031681565b60006125146136db565b612520575060006109ac565b600a546040516370a0823160e01b81526125bc9073c00e94cb662c3520282e6f5717214004a7f26888906370a082319061255e903090600401614075565b60206040518083038186803b15801561257657600080fd5b505afa15801561258a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ae9190613f87565b6125b66120b4565b90612ae7565b11156109ac575060016109ac565b60008061262e6007546108d260085461096862015180600660009054906101000a90046001600160a01b03166001600160a01b031663189bb2f16040518163ffffffff1660e01b815260040160206040518083038186803b15801561093057600080fd5b90508061263f576000915050610b4e565b600061264a85611bd9565b905060006126d7600660009054906101000a90046001600160a01b03166001600160a01b031663e7dad6bd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561269f57600080fd5b505afa1580156126b3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039d9190613cfc565b9050600061276586600660009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561272d57600080fd5b505afa158015612741573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b69190613f87565b905061278461016d61096861277a8486612aa6565b6108d28789612aa6565b979650505050505050565b61076d8282613762565b6005546301000000900462ffffff1681565b60045481565b6000546001600160a01b031681565b8015806128485750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906127f69030908690600401614089565b60206040518083038186803b15801561280e57600080fd5b505afa158015612822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128469190613f87565b155b6128645760405162461bcd60e51b81526004016105f3906142f6565b6128ba8363095ea7b360e01b84846040516024016128839291906140eb565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613902565b505050565b60606128ce8484600085613991565b949350505050565b60408051600180825281830190925260609182919060208083019080368337505060025482519293506001600160a01b03169183915060009061291557fe5b6001600160a01b0390921660209283029190910190910152905090565b6128ba8363a9059cbb60e01b84846040516024016128839291906140eb565b600080600660009054906101000a90046001600160a01b03166001600160a01b0316637eb711316040518163ffffffff1660e01b815260040160206040518083038186803b1580156129a257600080fd5b505afa1580156129b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129da9190613f87565b60065460405163d955759d60e01b8152919250600091612a1a916301e13380916001600160a01b039091169063d955759d90610918908790600401614454565b90506000612a45612a3e73c00e94cb662c3520282e6f5717214004a7f26888611df3565b60006125ca565b90506122c98282612ae7565b6000611313612a5e612033565b6002546040516370a0823160e01b81526001600160a01b03909116906370a0823190612a8e903090600401614075565b60206040518083038186803b15801561272d57600080fd5b600082612ab557506000610b4e565b82820282848281612ac257fe5b0414612ae05760405162461bcd60e51b81526004016105f3906141eb565b9392505050565b600082820183811015612ae05760405162461bcd60e51b81526004016105f390614122565b6000612ae083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613a55565b60065460405163bfe69c8d60e01b81526000916001600160a01b03169063bfe69c8d90612b7f903090600401614075565b600060405180830381600087803b158015612b9957600080fd5b505af1158015612bad573d6000803e3d6000fd5b505050506000612bbb612033565b6002546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190612bf1903090600401614075565b60206040518083038186803b158015612c0957600080fd5b505afa158015612c1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c419190613f87565b90506000612c4f8383612ae7565b905080851115612c5d578094505b848210612c8c57600154600254612c81916001600160a01b03918216911687612932565b8493505050506109ac565b6000612da3600660009054906101000a90046001600160a01b03166001600160a01b0316638285ef406040518163ffffffff1660e01b815260040160206040518083038186803b158015612cdf57600080fd5b505afa158015612cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d179190613f87565b600660009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d6557600080fd5b505afa158015612d79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d9d9190613f87565b90613a8c565b90506001811115612e9b576000612dba8785613a8c565b9050818111612e305760065460025460405163f3fef3a360e01b81526001600160a01b039283169263f3fef3a392612df99291169085906004016140eb565b600060405180830381600087803b158015612e1357600080fd5b505af1158015612e27573d6000803e3d6000fd5b50505050612e99565b60065460025460405163f3fef3a360e01b81526001600160a01b039283169263f3fef3a392612e669291169086906004016140eb565b600060405180830381600087803b158015612e8057600080fd5b505af1158015612e94573d6000803e3d6000fd5b505050505b505b6002546040516370a0823160e01b81526001600160a01b03909116906370a0823190612ecb903090600401614075565b60206040518083038186803b158015612ee357600080fd5b505afa158015612ef7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1b9190613f87565b600154600254919450612f3b916001600160a01b03908116911685612932565b5090949350505050565b600654604051635b81a7bf60e11b8152731b0e765f6224c21223aea2af16c1c46e38885a409163b7034f7e91612f8c916001600160a01b03169030906001906004016140a3565b600060405180830381600087803b158015612fa657600080fd5b505af1158015612fba573d6000803e3d6000fd5b50505050565b600554600160301b90046001600160a01b0316151580612fe5575060055462ffffff16155b15612fef5761174b565b6040516370a0823160e01b815260009073c00e94cb662c3520282e6f5717214004a7f26888906370a0823190613029903090600401614075565b60206040518083038186803b15801561304157600080fd5b505afa158015613055573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130799190613f87565b9050600954811115610f44576002546001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc214156131a4576130b4613b53565b50604080516101008101825273c00e94cb662c3520282e6f5717214004a7f2688881526002546001600160a01b0316602082015260055462ffffff168183015230606082015242608082015260a08101839052600060c0820181905260e0820152905163414bf38960e01b815273e592427a0aece92de3edee1f18e0157c058615649063414bf3899061314b9084906004016143db565b602060405180830381600087803b15801561316557600080fd5b505af1158015613179573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061319d9190613f87565b5050610f44565b6005546002546040516060926132089273c00e94cb662c3520282e6f5717214004a7f268889262ffffff8084169373c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2936301000000909104909116916001600160a01b0390911690602001614007565b60408051601f1981840301815260a08301825280835230602084015242838301526060830185905260006080840152905163c04b8d5960e01b815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d599161326f9190600401614383565b602060405180830381600087803b15801561328957600080fd5b505af115801561329d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128ba9190613f87565b6005546132f59073c00e94cb662c3520282e6f5717214004a7f2688890600160301b90046001600160a01b031660006127c0565b600554600254604051639cd38be560e01b8152600160301b9092046001600160a01b0390811692639cd38be5926133479273c00e94cb662c3520282e6f5717214004a7f2688892911690600401614089565b600060405180830381600087803b15801561336157600080fd5b505af1158015613375573d6000803e3d6000fd5b5050600580546601000000000000600160d01b03191690555050565b604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81523060601b601482018190526e5af43d82803e903d91602b57fd5bf360881b602883015260009160378184f06040516379ccf11760e11b81529093506001600160a01b038416915063f399e22e9061340b90879087906004016140c7565b600060405180830381600087803b15801561342557600080fd5b505af1158015613439573d6000803e3d6000fd5b50506040516001600160a01b03851692507f783540fb4221a3238720dc7038937d0d79982bcf895274aa6ad179f82cf0d53c9150600090a25092915050565b6006546001600160a01b0316156134a15760405162461bcd60e51b81526004016105f39061419c565b600680546001600160a01b0319166001600160a01b0383811691909117918290556002546040805163c55dae6360e01b81529051918316939092169163c55dae63916004808301926020929190829003018186803b15801561350257600080fd5b505afa158015613516573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353a9190613cfc565b6001600160a01b0316146135605760405162461bcd60e51b81526004016105f390614177565b600660009054906101000a90046001600160a01b03166001600160a01b03166344c1e5eb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156135ae57600080fd5b505afa1580156135c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135e69190613f87565b600755600654604080516396e7a9c160e01b815290516001600160a01b03909216916396e7a9c191600480820192602092909190829003018186803b15801561362e57600080fd5b505afa158015613642573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136669190613fc0565b67ffffffffffffffff1660085560025461368c906001600160a01b0316826000196127c0565b6136c173c00e94cb662c3520282e6f5717214004a7f2688873e592427a0aece92de3edee1f18e0157c058615646000196127c0565b5066b1a2bc2ec50000600955678ac7230489e80000600a55565b600073b5e1cacb567d98faadb60a1fd4820720141f064f6001600160a01b03166334a9e75c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561372a57600080fd5b505afa15801561373e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113139190613df3565b6001546001600160a01b03161561378b5760405162461bcd60e51b81526004016105f39061434c565b600180546001600160a01b0319166001600160a01b0384811691909117918290556040805163fbfa77cf60e01b81529051929091169163fbfa77cf91600480820192602092909190829003018186803b1580156137e757600080fd5b505afa1580156137fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061381f9190613cfc565b600080546001600160a01b0319166001600160a01b03928316179081905560408051637e062a3560e11b81529051919092169163fc0c546a916004808301926020929190829003018186803b15801561387757600080fd5b505afa15801561388b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138af9190613cfc565b600280546001600160a01b0319166001600160a01b039290921691909117905580516138e2906003906020840190613b97565b5061271060045560025461076d906001600160a01b0316836000196127c0565b6060613957826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166128bf9092919063ffffffff16565b8051909150156128ba57808060200190518101906139759190613df3565b6128ba5760405162461bcd60e51b81526004016105f390614288565b606061399c85613ace565b6139b85760405162461bcd60e51b81526004016105f39061422c565b60006060866001600160a01b031685876040516139d59190614059565b60006040518083038185875af1925050503d8060008114613a12576040519150601f19603f3d011682016040523d82523d6000602084013e613a17565b606091505b50915091508115613a2b5791506128ce9050565b805115613a3b5780518082602001fd5b8360405162461bcd60e51b81526004016105f3919061410f565b60008183613a765760405162461bcd60e51b81526004016105f3919061410f565b506000838581613a8257fe5b0495945050505050565b6000612ae083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613b07565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906128ce575050151592915050565b60008184841115613b2b5760405162461bcd60e51b81526004016105f3919061410f565b505050900390565b604080516060810182526000808252602082018190529181019190915290565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613bd857805160ff1916838001178555613c05565b82800160010185558215613c05579182015b82811115613c05578251825591602001919060010190613bea565b50613c11929150613c15565b5090565b5b80821115613c115760008155600101613c16565b8051610b4e816144b0565b600082601f830112613c45578081fd5b813567ffffffffffffffff811115613c5b578182fd5b613c6e601f8201601f191660200161445d565b9150808252836020828501011115613c8557600080fd5b8060208401602084013760009082016020015292915050565b80516001600160801b0381168114610b4e57600080fd5b803562ffffff81168114610b4e57600080fd5b805167ffffffffffffffff81168114610b4e57600080fd5b600060208284031215613cf1578081fd5b8135612ae0816144b0565b600060208284031215613d0d578081fd5b8151612ae0816144b0565b60008060408385031215613d2a578081fd5b8235613d35816144b0565b9150602083013567ffffffffffffffff811115613d50578182fd5b613d5c85828601613c35565b9150509250929050565b600080600060608486031215613d7a578081fd5b8335613d85816144b0565b9250602084013567ffffffffffffffff811115613da0578182fd5b613dac86828701613c35565b9250506040840135613dbd816144b0565b809150509250925092565b60008060408385031215613dda578182fd5b8235613de5816144b0565b946020939093013593505050565b600060208284031215613e04578081fd5b81518015158114612ae0578182fd5b6000610100808385031215613e26578182fd5b613e2f8161445d565b9050825160ff81168114613e41578283fd5b8152613e508460208501613c2a565b6020820152613e628460408501613c2a565b6040820152613e748460608501613cc8565b6060820152613e868460808501613cc8565b6080820152613e988460a08501613cc8565b60a0820152613eaa8460c08501613cc8565b60c0820152613ebc8460e08501613c9e565b60e08201529392505050565b600060608284031215613ed9578081fd5b613ee3606061445d565b8251613eee816144b0565b8152613efd8460208501613cc8565b602082015260408301518015158114613f14578283fd5b60408201529392505050565b600060208284031215613f31578081fd5b612ae08383613c9e565b60008060408385031215613f4d578182fd5b613f578484613cb5565b9150613f668460208501613cb5565b90509250929050565b600060208284031215613f80578081fd5b5035919050565b600060208284031215613f98578081fd5b5051919050565b60008060408385031215613fb1578081fd5b50508035926020909101359150565b600060208284031215613fd1578081fd5b612ae08383613cc8565b60008151808452613ff3816020860160208601614484565b601f01601f19169290920160200192915050565b6bffffffffffffffffffffffff19606096871b811682526001600160e81b031960e896871b8116601484015294871b811660178301529290941b909216602b840152921b909116602e82015260420190565b6000825161406b818460208701614484565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6001600160a01b03831681526040602082018190526000906128ce90830184613fdb565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b600060208252612ae06020830184613fdb565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526004908201526310b3b7bb60e11b604082015260600190565b6020808252600b908201526a3bb937b733903a37b5b2b760a91b604082015260600190565b602080825260139082015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604082015260600190565b602080825260089082015267216b65657065727360c01b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a085b585b9859d95b595b9d60aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b6020808252601a908201527f4c656e64657220616c726561647920696e697469616c697a6564000000000000604082015260600190565b600060208252825160a0602084015261439f60c0840182613fdb565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b81516001600160a01b03908116825260208084015182169083015260408084015162ffffff16908301526060808401518216908301526080808401519083015260a0838101519083015260c0808401519083015260e09283015116918101919091526101000190565b62ffffff91909116815260200190565b90815260200190565b60405181810167ffffffffffffffff8111828210171561447c57600080fd5b604052919050565b60005b8381101561449f578181015183820152602001614487565b83811115612fba5750506000910152565b6001600160a01b0381168114610f4457600080fdfea264697066735822122082e41f580ac70347c8e45d4a344a166c3ff0f07eaaf408f6a665aa3e210d12e164736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002216e44fa633abd2540db72ad34b42c7f1557cd40000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c3d688b66703497daa19211eedff47f25384cdc3000000000000000000000000000000000000000000000000000000000000000d47656e65726963436f6d70563300000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _strategy (address): 0x2216E44fA633ABd2540dB72Ad34b42C7F1557cd4
Arg [1] : name (string): GenericCompV3
Arg [2] : _comet (address): 0xc3d688B66703497DAA19211EEdff47f25384cdc3
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000002216e44fa633abd2540db72ad34b42c7f1557cd4
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 000000000000000000000000c3d688b66703497daa19211eedff47f25384cdc3
Arg [3] : 000000000000000000000000000000000000000000000000000000000000000d
Arg [4] : 47656e65726963436f6d70563300000000000000000000000000000000000000
Deployed Bytecode Sourcemap
67867:12869:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66631:354;;;;;;:::i;:::-;;:::i;:::-;;68907:28;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72797:132;;;:::i;78663:487::-;;;;;;:::i;:::-;;:::i;64926:18::-;;;:::i;:::-;;;;;;;:::i;68711:113::-;;;:::i;72937:124::-;;;;;;:::i;:::-;;:::i;66523:100::-;;;;;;:::i;:::-;;:::i;74785:265::-;;;:::i;70601:91::-;;;;;;:::i;:::-;;:::i;73186:281::-;;;;;;:::i;:::-;;:::i;71067:88::-;;;:::i;78499:156::-;;;:::i;:::-;;;;;;;:::i;68982:21::-;;;:::i;79989:402::-;;;;;;:::i;:::-;;:::i;80399:112::-;;;:::i;69838:271::-;;;;;;:::i;:::-;;:::i;78248:243::-;;;:::i;64951:33::-;;;:::i;:::-;;;;;;;:::i;70435:158::-;;;;;;:::i;:::-;;:::i;72644:145::-;;;;;;:::i;:::-;;:::i;68942:33::-;;;:::i;64887:32::-;;;:::i;70117:200::-;;;;;;:::i;:::-;;:::i;72492:144::-;;;;;;:::i;:::-;;:::i;68686:18::-;;;:::i;76038:85::-;;;:::i;70700:88::-;;;:::i;68400:26::-;;;:::i;:::-;;;;;;;:::i;69201:83::-;;;;;;:::i;:::-;;:::i;70938:121::-;;;:::i;75394:536::-;;;:::i;78079:161::-;;;:::i;68650:27::-;;;:::i;75058:241::-;;;;;;:::i;:::-;;:::i;71824:660::-;;;;;;:::i;:::-;;:::i;65582:125::-;;;;;;:::i;:::-;;:::i;68433:26::-;;;:::i;64991:19::-;;;:::i;64859:21::-;;;:::i;66631:354::-;67154:8;;-1:-1:-1;;;;;67154:8:0;67132:10;:31;;:67;;;67181:5;;;;;;;;-1:-1:-1;;;;;67181:5:0;-1:-1:-1;;;;;67181:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67167:32:0;:10;-1:-1:-1;;;;;67167:32:0;;67132:67;:121;;;;67231:8;;;;;;;;;-1:-1:-1;;;;;67231:8:0;-1:-1:-1;;;;;67217:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67203:50:0;:10;-1:-1:-1;;;;;67203:50:0;;67132:121;67110:182;;;;-1:-1:-1;;;67110:182:0;;;;;;;:::i;:::-;;;;;;;;;66710:33:::1;66746:17;:15;:17::i;:::-;66710:53;;66779:9;66774:102;66794:16;:23;66790:1;:27;66774:102;;;66842:16;66859:1;66842:19;;;;;;;;;;;;;;-1:-1:-1::0;;;;;66832:29:0::1;:6;-1:-1:-1::0;;;;;66832:29:0::1;;;66824:52;;;;-1:-1:-1::0;;;66824:52:0::1;;;;;;;:::i;:::-;66819:3;;66774:102;;;-1:-1:-1::0;66917:5:0::1;::::0;:18:::1;::::0;;-1:-1:-1;;;66917:18:0;;;;66889:88:::1;::::0;-1:-1:-1;;;;;66917:5:0::1;::::0;:16:::1;::::0;:18:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:5;:18;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66937:39;::::0;-1:-1:-1;;;66937:39:0;;-1:-1:-1;;;;;66937:24:0;::::1;::::0;::::1;::::0;:39:::1;::::0;66970:4:::1;::::0;66937:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;66889:27:0;::::1;::::0;:88;:27:::1;:88::i;:::-;67303:1;66631:354:::0;:::o;68907:28::-;;;;:::o;72797:132::-;72852:7;72872:9;72884:6;:4;:6::i;:::-;72872:18;;72908:13;72914:6;:4;:6::i;:::-;72908:1;;:5;:13::i;:::-;72901:20;;;72797:132;:::o;78663:487::-;78736:7;78756:15;78774:5;;;;;;;;;-1:-1:-1;;;;;78774:5:0;-1:-1:-1;;;;;78774:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78756:37;;78804:14;78821:5;;;;;;;;;-1:-1:-1;;;;;78821:5:0;-1:-1:-1;;;;;78821:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78804:36;-1:-1:-1;78853:22:0;78878:41;78900:18;78804:36;78911:6;78900:10;:18::i;:::-;78878:17;:7;78890:4;78878:11;:17::i;:::-;:21;;:41::i;:::-;78950:5;;:35;;-1:-1:-1;;;78950:35:0;;78853:66;;-1:-1:-1;78930:17:0;;78950:57;;68168:8;;-1:-1:-1;;;;;78950:5:0;;;;:19;;:35;;78853:66;;78950:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:39;;:57::i;:::-;78930:77;;79020:17;79040:60;79066:25;68509:42;79066:19;:25::i;:::-;79093:6;79040:25;:60::i;:::-;79020:80;-1:-1:-1;79118:24:0;:9;79020:80;79118:13;:24::i;:::-;79111:31;;;;;;;78663:487;;;;:::o;64926:18::-;;;-1:-1:-1;;;;;64926:18:0;;:::o;68711:113::-;68781:42;68711:113;:::o;72937:124::-;67154:8;;73009:7;;-1:-1:-1;;;;;67154:8:0;67132:10;:31;;:67;;;67181:5;;;;;;;;-1:-1:-1;;;;;67181:5:0;-1:-1:-1;;;;;67181:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67167:32:0;:10;-1:-1:-1;;;;;67167:32:0;;67132:67;:121;;;;67231:8;;;;;;;;;-1:-1:-1;;;;;67231:8:0;-1:-1:-1;;;;;67217:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67203:50:0;:10;-1:-1:-1;;;;;67203:50:0;;67132:121;67110:182;;;;-1:-1:-1;;;67110:182:0;;;;;;;:::i;:::-;73036:17:::1;73046:6;73036:9;:17::i;:::-;73029:24:::0;72937:124;-1:-1:-1;;72937:124:0:o;66523:100::-;67154:8;;-1:-1:-1;;;;;67154:8:0;67132:10;:31;;:67;;;67181:5;;;;;;;;-1:-1:-1;;;;;67181:5:0;-1:-1:-1;;;;;67181:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67167:32:0;:10;-1:-1:-1;;;;;67167:32:0;;67132:67;:121;;;;67231:8;;;;;;;;;-1:-1:-1;;;;;67231:8:0;-1:-1:-1;;;;;67217:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67203:50:0;:10;-1:-1:-1;;;;;67203:50:0;;67132:121;67110:182;;;;-1:-1:-1;;;67110:182:0;;;;;;;:::i;:::-;66603:4:::1;:12:::0;66523:100::o;74785:265::-;79447:6;;-1:-1:-1;;;;;79447:6:0;79425:10;:29;;:64;;-1:-1:-1;79480:8:0;;-1:-1:-1;;;;;79480:8:0;79458:10;:31;79425:64;:100;;;;79507:5;;;;;;;;-1:-1:-1;;;;;79507:5:0;-1:-1:-1;;;;;79507:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;79493:32:0;:10;-1:-1:-1;;;;;79493:32:0;;79425:100;:154;;;;79557:8;;;;;;;;;-1:-1:-1;;;;;79557:8:0;-1:-1:-1;;;;;79543:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;79529:50:0;:10;-1:-1:-1;;;;;79529:50:0;;79425:154;79403:212;;;;-1:-1:-1;;;79403:212:0;;;;;;;:::i;:::-;74832:20:::1;:18;:20::i;:::-;74865:16;:14;:16::i;:::-;74916:4;::::0;:29:::1;::::0;-1:-1:-1;;;74916:29:0;;74894:19:::1;::::0;-1:-1:-1;;;;;74916:4:0::1;::::0;:14:::1;::::0;:29:::1;::::0;74939:4:::1;::::0;74916:29:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74894:51:::0;-1:-1:-1;74959:15:0;;74956:87:::1;;74991:5;::::0;75012:4:::1;::::0;74991:40:::1;::::0;-1:-1:-1;;;74991:40:0;;-1:-1:-1;;;;;74991:5:0;;::::1;::::0;:12:::1;::::0;:40:::1;::::0;75012:4;::::1;::::0;75019:11;;74991:40:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;74956:87;79626:1;74785:265::o:0;70601:91::-;67154:8;;-1:-1:-1;;;;;67154:8:0;67132:10;:31;;:67;;;67181:5;;;;;;;;-1:-1:-1;;;;;67181:5:0;-1:-1:-1;;;;;67181:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67167:32:0;:10;-1:-1:-1;;;;;67167:32:0;;67132:67;:121;;;;67231:8;;;;;;;;;-1:-1:-1;;;;;67231:8:0;-1:-1:-1;;;;;67217:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67203:50:0;:10;-1:-1:-1;;;;;67203:50:0;;67132:121;67110:182;;;;-1:-1:-1;;;67110:182:0;;;;;;;:::i;:::-;70668:6:::1;:16:::0;;-1:-1:-1;;;;;;70668:16:0::1;-1:-1:-1::0;;;;;70668:16:0;;;::::1;::::0;;;::::1;::::0;;70601:91::o;73186:281::-;67379:5;;;;;;;;-1:-1:-1;;;;;67379:5:0;-1:-1:-1;;;;;67379:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67365:32:0;:10;-1:-1:-1;;;;;67365:32:0;;67357:49;;;;-1:-1:-1;;;67357:49:0;;;;;;;:::i;:::-;73341:5:::1;::::0;73364:4:::1;::::0;73341:37:::1;::::0;-1:-1:-1;;;73341:37:0;;-1:-1:-1;;;;;73341:5:0;;::::1;::::0;:14:::1;::::0;:37:::1;::::0;73364:4;::::1;::::0;73371:6;;73341:37:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;73391:68;73409:5;::::0;::::1;;;;;;-1:-1:-1::0;;;;;73409:5:0::1;-1:-1:-1::0;;;;;73409:16:0::1;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;73429:4;::::0;:29:::1;::::0;-1:-1:-1;;;73429:29:0;;-1:-1:-1;;;;;73429:4:0;;::::1;::::0;:14:::1;::::0;:29:::1;::::0;73452:4:::1;::::0;73429:29:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;73391:4;::::0;-1:-1:-1;;;;;73391:4:0::1;::::0;:68;:17:::1;:68::i;71067:88::-:0;71114:7;71141:6;:4;:6::i;:::-;71134:13;;71067:88;:::o;78499:156::-;78576:5;;:30;;-1:-1:-1;;;78576:30:0;;78552:4;;;;-1:-1:-1;;;;;78576:5:0;;;;:15;;:30;;78600:4;;78576:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:34;:71;;;-1:-1:-1;78614:4:0;;:29;;-1:-1:-1;;;78614:29:0;;78646:1;;-1:-1:-1;;;;;78614:4:0;;:14;;:29;;78637:4;;78614:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:33;78569:78;;78499:156;:::o;68982:21::-;;;-1:-1:-1;;;;;68982:21:0;;:::o;79989:402::-;67379:5;;;;;;;;-1:-1:-1;;;;;67379:5:0;-1:-1:-1;;;;;67379:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67365:32:0;:10;-1:-1:-1;;;;;67365:32:0;;67357:49;;;;-1:-1:-1;;;67357:49:0;;;;;;;:::i;:::-;80076:12:::1;::::0;-1:-1:-1;;;80076:12:0;::::1;-1:-1:-1::0;;;;;80076:12:0::1;:26:::0;80072:91:::1;;80119:32;:30;:32::i;:::-;80208:13:::0;80235:58:::1;68509:42;80208:13:::0;-1:-1:-1;;80235:24:0::1;:58::i;:::-;80328:4;::::0;80304:30:::1;::::0;-1:-1:-1;;;80304:30:0;;-1:-1:-1;;;;;80304:9:0;;::::1;::::0;::::1;::::0;:30:::1;::::0;68509:42:::1;::::0;80328:4:::1;::::0;80304:30:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;80355:12:0::1;:28:::0;;-1:-1:-1;;;;;80355:28:0;;::::1;-1:-1:-1::0;;;80355:28:0::1;-1:-1:-1::0;;;;;;80355:28:0;;::::1;::::0;;;::::1;::::0;;;-1:-1:-1;;;79989:402:0:o;80399:112::-;67154:8;;-1:-1:-1;;;;;67154:8:0;67132:10;:31;;:67;;;67181:5;;;;;;;;-1:-1:-1;;;;;67181:5:0;-1:-1:-1;;;;;67181:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67167:32:0;:10;-1:-1:-1;;;;;67167:32:0;;67132:67;:121;;;;67231:8;;;;;;;;;-1:-1:-1;;;;;67231:8:0;-1:-1:-1;;;;;67217:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67203:50:0;:10;-1:-1:-1;;;;;67203:50:0;;67132:121;67110:182;;;;-1:-1:-1;;;67110:182:0;;;;;;;:::i;:::-;80471:32:::1;:30;:32::i;:::-;80399:112::o:0;69838:271::-;69977:17;70019:24;70026:9;70037:5;70019:6;:24::i;:::-;70054:47;;-1:-1:-1;;;70054:47:0;;70007:36;;-1:-1:-1;;;;;;70054:39:0;;;;;:47;;70094:6;;70054:47;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69838:271;;;;;:::o;78248:243::-;67154:8;;78309:4;;-1:-1:-1;;;;;67154:8:0;67132:10;:31;;:67;;;67181:5;;;;;;;;-1:-1:-1;;;;;67181:5:0;-1:-1:-1;;;;;67181:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67167:32:0;:10;-1:-1:-1;;;;;67167:32:0;;67132:67;:121;;;;67231:8;;;;;;;;;-1:-1:-1;;;;;67231:8:0;-1:-1:-1;;;;;67217:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67203:50:0;:10;-1:-1:-1;;;;;67203:50:0;;67132:121;67110:182;;;;-1:-1:-1;;;67110:182:0;;;;;;;:::i;:::-;78326:5:::1;::::0;:34:::1;::::0;-1:-1:-1;;;78326:34:0;;-1:-1:-1;;;;;78326:5:0;;::::1;::::0;:19:::1;::::0;:34:::1;::::0;78354:4:::1;::::0;78326:34:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;78371:16;78390:6;:4;:6::i;:::-;78371:25;;78407:16;78426:19;78436:8;78426:9;:19::i;:::-;78463:20:::0;;;::::1;;::::0;-1:-1:-1;;78248:243:0;:::o;64951:33::-;;;;;;;;;;;;;;;-1:-1:-1;;64951:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;70435:158::-;67154:8;;-1:-1:-1;;;;;67154:8:0;67132:10;:31;;:67;;;67181:5;;;;;;;;-1:-1:-1;;;;;67181:5:0;-1:-1:-1;;;;;67181:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67167:32:0;:10;-1:-1:-1;;;;;67167:32:0;;67132:67;:121;;;;67231:8;;;;;;;;;-1:-1:-1;;;;;67231:8:0;-1:-1:-1;;;;;67217:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67203:50:0;:10;-1:-1:-1;;;;;67203:50:0;;67132:121;67110:182;;;;-1:-1:-1;;;67110:182:0;;;;;;;:::i;:::-;70524:12:::1;:25:::0;;::::1;70560::::0;;::::1;::::0;::::1;-1:-1:-1::0;;70524:25:0;;;::::1;-1:-1:-1::0;;70524:25:0;;::::1;;70560::::0;;;::::1;;::::0;;70435:158::o;72644:145::-;72745:5;;:36;;-1:-1:-1;;;72745:36:0;;72721:4;;-1:-1:-1;;;;;72745:5:0;;:14;;:36;;72760:20;;72745:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;72738:43:0;;72644:145;-1:-1:-1;;72644:145:0:o;68942:33::-;;;;:::o;64887:32::-;;;-1:-1:-1;;;;;64887:32:0;;:::o;70117:200::-;67154:8;;-1:-1:-1;;;;;67154:8:0;67132:10;:31;;:67;;;67181:5;;;;;;;;-1:-1:-1;;;;;67181:5:0;-1:-1:-1;;;;;67181:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67167:32:0;:10;-1:-1:-1;;;;;67167:32:0;;67132:67;:121;;;;67231:8;;;;;;;;;-1:-1:-1;;;;;67231:8:0;-1:-1:-1;;;;;67217:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67203:50:0;:10;-1:-1:-1;;;;;67203:50:0;;67132:121;67110:182;;;;-1:-1:-1;;;67110:182:0;;;;;;;:::i;:::-;70229:13:::1;:30:::0;;;;70270:18:::1;:39:::0;70117:200::o;72492:144::-;72584:5;;:34;;-1:-1:-1;;;72584:34:0;;72557:7;;-1:-1:-1;;;;;72584:5:0;;:27;;:34;;72612:5;;72584:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;;;;72492:144;-1:-1:-1;;72492:144:0:o;68686:18::-;;;-1:-1:-1;;;;;68686:18:0;;:::o;76038:85::-;79447:6;;-1:-1:-1;;;;;79447:6:0;79425:10;:29;;:64;;-1:-1:-1;79480:8:0;;-1:-1:-1;;;;;79480:8:0;79458:10;:31;79425:64;:100;;;;79507:5;;;;;;;;-1:-1:-1;;;;;79507:5:0;-1:-1:-1;;;;;79507:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;79493:32:0;:10;-1:-1:-1;;;;;79493:32:0;;79425:100;:154;;;;79557:8;;;;;;;;;-1:-1:-1;;;;;79557:8:0;-1:-1:-1;;;;;79543:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;79529:50:0;:10;-1:-1:-1;;;;;79529:50:0;;79425:154;79403:212;;;;-1:-1:-1;;;79403:212:0;;;;;;;:::i;:::-;76095:20:::1;:18;:20::i;70700:88::-:0;70747:7;70774:6;:4;:6::i;68400:26::-;;;;;;:::o;69201:83::-;69257:19;69269:6;69257:11;:19::i;70938:121::-;71021:5;;:30;;-1:-1:-1;;;71021:30:0;;70994:7;;-1:-1:-1;;;;;71021:5:0;;:15;;:30;;71045:4;;71021:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;75394:536::-;75441:4;75458:39;;:::i;:::-;75537:5;;75500:44;;-1:-1:-1;;;75500:44:0;;68781:42;;75500:28;;:44;;-1:-1:-1;;;;;75537:5:0;;75500:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75573:5;;:40;;-1:-1:-1;;;75573:40:0;;75458:86;;-1:-1:-1;75555:15:0;;-1:-1:-1;;;;;75573:5:0;;;;:25;;:40;;75607:4;;75573:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75555:58;;;;75628:6;:20;;;75624:148;;;75676:20;;;;75665:31;;;75624:148;;;75740:6;:20;;;75729:31;;;;;;;;;;;75624:148;75839:5;;75800:61;;-1:-1:-1;;;75800:61:0;;75782:15;;68781:42;;75800:30;;:61;;-1:-1:-1;;;;;75839:5:0;;;;75855:4;;75800:61;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75782:79;;75891:7;75881;:17;:41;;75921:1;75881:41;;;75911:7;75901;:17;75881:41;75874:48;;;;;75394:536;:::o;78079:161::-;67154:8;;-1:-1:-1;;;;;67154:8:0;67132:10;:31;;:67;;;67181:5;;;;;;;;-1:-1:-1;;;;;67181:5:0;-1:-1:-1;;;;;67181:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67167:32:0;:10;-1:-1:-1;;;;;67167:32:0;;67132:67;:121;;;;67231:8;;;;;;;;;-1:-1:-1;;;;;67231:8:0;-1:-1:-1;;;;;67217:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;67203:50:0;:10;-1:-1:-1;;;;;67203:50:0;;67132:121;67110:182;;;;-1:-1:-1;;;67110:182:0;;;;;;;:::i;:::-;78156:4:::1;::::0;:29:::1;::::0;-1:-1:-1;;;78156:29:0;;78138:15:::1;::::0;-1:-1:-1;;;;;78156:4:0::1;::::0;:14:::1;::::0;:29:::1;::::0;78179:4:::1;::::0;78156:29:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78196:5;::::0;78217:4:::1;::::0;78196:36:::1;::::0;-1:-1:-1;;;78196:36:0;;78138:47;;-1:-1:-1;;;;;;78196:5:0;;::::1;::::0;:12:::1;::::0;:36:::1;::::0;78217:4:::1;::::0;78138:47;;78196:36:::1;;;:::i;68650:27::-:0;;;-1:-1:-1;;;68650:27:0;;-1:-1:-1;;;;;68650:27:0;;:::o;75058:241::-;75126:4;75147:21;:19;:21::i;:::-;75143:39;;-1:-1:-1;75177:5:0;75170:12;;75143:39;75260:18;;75219:37;;-1:-1:-1;;;75219:37:0;;75198:59;;68509:42;;75219:22;;:37;;75250:4;;75219:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75198:16;:14;:16::i;:::-;:20;;:59::i;:::-;:80;75195:96;;;-1:-1:-1;75287:4:0;75280:11;;71824:660;71926:4;71943:28;71974:93;72053:13;;71974:74;72031:16;;71974:52;68107:12;71974:5;;;;;;;;;-1:-1:-1;;;;;71974:5:0;-1:-1:-1;;;;;71974:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:93;71943:124;-1:-1:-1;72081:28:0;72078:41;;72118:1;72111:8;;;;;72078:41;72132:26;72161:38;72178:20;72161:16;:38::i;:::-;72132:67;;72210:19;72232:44;72249:5;;;;;;;;;-1:-1:-1;;;;;72249:5:0;-1:-1:-1;;;;;72249:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;72232:44::-;72210:66;;72287:20;72310:34;72334:9;72310:5;;;;;;;;;-1:-1:-1;;;;;72310:5:0;-1:-1:-1;;;;;72310:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:34::-;72287:57;-1:-1:-1;72362:114:0;68056:3;72363:93;72419:35;72287:57;72439:14;72419:19;:35::i;:::-;72363:50;:21;72389:23;72363:25;:50::i;72362:114::-;72355:121;71824:660;-1:-1:-1;;;;;;;71824:660:0:o;65582:125::-;65670:29;65682:9;65693:5;65670:11;:29::i;68433:26::-;;;;;;;;;:::o;64991:19::-;;;;:::o;64859:21::-;;;-1:-1:-1;;;;;64859:21:0;;:::o;24039:622::-;24409:10;;;24408:62;;-1:-1:-1;24425:39:0;;-1:-1:-1;;;24425:39:0;;-1:-1:-1;;;;;24425:15:0;;;;;:39;;24449:4;;24456:7;;24425:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;24408:62;24400:152;;;;-1:-1:-1;;;24400:152:0;;;;;;;:::i;:::-;24563:90;24583:5;24613:22;;;24637:7;24646:5;24590:62;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;24590:62:0;;;;;;;;;;;;;;-1:-1:-1;;;;;24590:62:0;-1:-1:-1;;;;;;24590:62:0;;;;;;;;;;24563:19;:90::i;:::-;24039:622;;;:::o;3913:196::-;4016:12;4048:53;4071:6;4079:4;4085:1;4088:12;4048:22;:53::i;:::-;4041:60;3913:196;-1:-1:-1;;;;3913:196:0:o;79158:207::-;79275:16;;;79289:1;79275:16;;;;;;;;;79217;;;;79275;;;;;;;;;;-1:-1:-1;;79325:4:0;;79302:12;;;;-1:-1:-1;;;;;;79325:4:0;;79302:12;;-1:-1:-1;79325:4:0;;79302:12;;;;-1:-1:-1;;;;;79302:28:0;;;:12;;;;;;;;;;;:28;79348:9;-1:-1:-1;79158:207:0;:::o;23380:177::-;23463:86;23483:5;23513:23;;;23538:2;23542:5;23490:58;;;;;;;;;:::i;71163:328::-;71202:7;71222:16;71241:5;;;;;;;;;-1:-1:-1;;;;;71241:5:0;-1:-1:-1;;;;;71241:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71292:5;;:32;;-1:-1:-1;;;71292:32:0;;71222:41;;-1:-1:-1;71274:15:0;;71292:54;;68168:8;;-1:-1:-1;;;;;71292:5:0;;;;:19;;:32;;71222:41;;71292:32;;;:::i;:54::-;71274:72;;71357:15;71375:55;71401:25;68509:42;71401:19;:25::i;:::-;71428:1;71375:25;:55::i;:::-;71357:73;-1:-1:-1;71456:26:0;:10;71357:73;71456:14;:26::i;70796:134::-;70835:7;70862:60;70896:25;:23;:25::i;:::-;70862:4;;:29;;-1:-1:-1;;;70862:29:0;;-1:-1:-1;;;;;70862:4:0;;;;:14;;:29;;70885:4;;70862:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;13551:471;13609:7;13854:6;13850:47;;-1:-1:-1;13884:1:0;13877:8;;13850:47;13921:5;;;13925:1;13921;:5;:1;13945:5;;;;;:10;13937:56;;;;-1:-1:-1;;;13937:56:0;;;;;;;:::i;:::-;14013:1;13551:471;-1:-1:-1;;;13551:471:0:o;12197:181::-;12255:7;12287:5;;;12311:6;;;;12303:46;;;;-1:-1:-1;;;12303:46:0;;;;;;;:::i;14498:132::-;14556:7;14583:39;14587:1;14590;14583:39;;;;;;;;;;;;;;;;;:3;:39::i;73528:1249::-;73690:5;;:34;;-1:-1:-1;;;73690:34:0;;73581:7;;-1:-1:-1;;;;;73690:5:0;;:19;;:34;;73718:4;;73690:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73735:25;73763;:23;:25::i;:::-;73822:4;;:29;;-1:-1:-1;;;73822:29:0;;73735:53;;-1:-1:-1;73799:20:0;;-1:-1:-1;;;;;73822:4:0;;;;:14;;:29;;73845:4;;73822:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;73799:52;-1:-1:-1;73862:13:0;73878:35;:17;73799:52;73878:21;:35::i;:::-;73862:51;;73939:5;73930:6;:14;73926:107;;;74016:5;74007:14;;73926:107;74065:6;74049:12;:22;74045:127;;74114:8;;74088:4;;:44;;-1:-1:-1;;;;;74088:4:0;;;;74114:8;74125:6;74088:17;:44::i;:::-;74154:6;74147:13;;;;;;;74045:127;74184:17;74204:44;74228:5;;;;;;;;;-1:-1:-1;;;;;74228:5:0;-1:-1:-1;;;;;74228:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74204:5;;;;;;;;;-1:-1:-1;;;;;74204:5:0;-1:-1:-1;;;;;74204:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:23;;:44::i;:::-;74184:64;;74277:1;74265:9;:13;74261:363;;;74295:18;74316:24;:6;74327:12;74316:10;:24::i;:::-;74295:45;;74375:9;74361:10;:23;74357:256;;74440:5;;74463:4;;74440:41;;-1:-1:-1;;;74440:41:0;;-1:-1:-1;;;;;74440:5:0;;;;:14;;:41;;74463:4;;;74470:10;;74440:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74357:256;;;74557:5;;74580:4;;74557:40;;-1:-1:-1;;;74557:40:0;;-1:-1:-1;;;;;74557:5:0;;;;:14;;:40;;74580:4;;;74587:9;;74557:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74357:256;74261:363;;74649:4;;:29;;-1:-1:-1;;;74649:29:0;;-1:-1:-1;;;;;74649:4:0;;;;:14;;:29;;74672:4;;74649:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74715:8;;74689:4;;74634:44;;-1:-1:-1;74689:50:0;;-1:-1:-1;;;;;74689:4:0;;;;74715:8;74634:44;74689:17;:50::i;:::-;-1:-1:-1;74757:12:0;;73528:1249;-1:-1:-1;;;;73528:1249:0:o;76208:116::-;76288:5;;76258:58;;-1:-1:-1;;;76258:58:0;;68781:42;;76258:21;;:58;;-1:-1:-1;;;;;76288:5:0;;76304:4;;76288:5;;76258:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76208:116::o;76332:1739::-;76460:12;;-1:-1:-1;;;76460:12:0;;-1:-1:-1;;;;;76460:12:0;:26;;;:47;;-1:-1:-1;76490:12:0;;;;:17;76460:47;76457:59;;;76509:7;;76457:59;76544:37;;-1:-1:-1;;;76544:37:0;;76528:13;;68509:42;;76544:22;;:37;;76575:4;;76544:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;76528:53;;76606:13;;76598:5;:21;76594:1470;;;76649:4;;-1:-1:-1;;;;;76649:4:0;68601:42;76641:21;76638:1415;;;76683:48;;:::i;:::-;-1:-1:-1;76755:435:0;;;;;;;;68509:42;76755:435;;76866:4;;-1:-1:-1;;;;;76866:4:0;76755:435;;;;76910:12;;;;76755:435;;;;76973:4;76755:435;;;;77018:3;76755:435;;;;;;;;;;-1:-1:-1;76755:435:0;;;;;;;;;;77211:31;;-1:-1:-1;;;77211:31:0;;68291:42;;77211:23;;:31;;76755:435;;77211:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;76638:1415;;;;77424:12;;77553:4;;77338:243;;77297:17;;77338:243;;68509:42;;77424:12;;;;;68601:42;;77506:12;;;;;;;;-1:-1:-1;;;;;77553:4:0;;;;77338:243;;;:::i;:::-;;;;-1:-1:-1;;77338:243:0;;;;;;77806:212;;;;;;;;77900:4;77338:243;77806:212;;;77932:3;77806:212;;;;;;;;;;-1:-1:-1;77806:212:0;;;;77766:271;;-1:-1:-1;;;77766:271:0;;77338:243;;-1:-1:-1;68291:42:0;;77766:17;;:271;;77338:243;77766:271;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;80519:214::-;80606:12;;80581:41;;68509:42;;-1:-1:-1;;;80606:12:0;;-1:-1:-1;;;;;80606:12:0;80620:1;80581:24;:41::i;:::-;80647:12;;80683:4;;80633:56;;-1:-1:-1;;;80633:56:0;;-1:-1:-1;;;80647:12:0;;;-1:-1:-1;;;;;80647:12:0;;;;80633:35;;:56;;68509:42;;80683:4;;;80633:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;80700:12:0;:25;;-1:-1:-1;;;;;;80700:25:0;;;-1:-1:-1;;80519:214:0:o;65715:800::-;66067:4;66061:11;-1:-1:-1;;;66086:86:0;;65966:4;65950:22;;66209:4;66193:21;;66186:43;;;-1:-1:-1;;;66266:4:0;66250:21;;66243:97;65789:17;;66389:4;66061:11;65789:17;66367:27;66417:57;;-1:-1:-1;;;66417:57:0;;66354:40;;-1:-1:-1;;;;;;66417:39:0;;;-1:-1:-1;66417:39:0;;:57;;66457:9;;66468:5;;66417:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;66490:17:0;;-1:-1:-1;;;;;66490:17:0;;;-1:-1:-1;66490:17:0;;-1:-1:-1;66490:17:0;;;65715:800;;;;;:::o;69292:538::-;69365:5;;-1:-1:-1;;;;;69365:5:0;69357:28;69349:60;;;;-1:-1:-1;;;69349:60:0;;;;;;;:::i;:::-;69420:5;:21;;-1:-1:-1;;;;;;69420:21:0;-1:-1:-1;;;;;69420:21:0;;;;;;;;;;;69489:4;;69460:17;;;-1:-1:-1;;;69460:17:0;;;;69489:4;;;;69460:5;;;;:15;;:17;;;;;;;;;;;;;;:5;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;69460:34:0;;69452:58;;;;-1:-1:-1;;;69452:58:0;;;;;;;:::i;:::-;69547:5;;;;;;;;;-1:-1:-1;;;;;69547:5:0;-1:-1:-1;;;;;69547:15:0;;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69531:13;:33;69594:5;;:22;;;-1:-1:-1;;;69594:22:0;;;;-1:-1:-1;;;;;69594:5:0;;;;:20;;:22;;;;;;;;;;;;;;;:5;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69575:41;;:16;:41;69629:4;;:43;;-1:-1:-1;;;;;69629:4:0;69646:6;-1:-1:-1;;69629:16:0;:43::i;:::-;69683:60;68509:42;68291;-1:-1:-1;;69683:24:0;:60::i;:::-;-1:-1:-1;69772:10:0;69756:13;:26;69814:8;69793:18;:29;69292:538::o;79709:198::-;79763:4;79809:42;-1:-1:-1;;;;;79800:97:0;;:99;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;65178:396::-;65275:8;;-1:-1:-1;;;;;65275:8:0;65267:31;65259:70;;;;-1:-1:-1;;;65259:70:0;;;;;;;:::i;:::-;65342:8;:20;;-1:-1:-1;;;;;;65342:20:0;-1:-1:-1;;;;;65342:20:0;;;;;;;;;;;65390:31;;;-1:-1:-1;;;65390:31:0;;;;65404:8;;;;;65390:29;;:31;;;;;;;;;;;;;;;65404:8;65390:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;65373:5;:49;;-1:-1:-1;;;;;;65373:49:0;-1:-1:-1;;;;;65373:49:0;;;;;;;;65447:13;;;-1:-1:-1;;;65447:13:0;;;;:5;;;;;:11;;:13;;;;;;;;;;;;;;:5;:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;65433:4;:28;;-1:-1:-1;;;;;;65433:28:0;-1:-1:-1;;;;;65433:28:0;;;;;;;;;;65472:18;;;;:10;;:18;;;;;:::i;:::-;-1:-1:-1;65508:5:0;65501:4;:12;65526:4;;:40;;-1:-1:-1;;;;;65526:4:0;65543:9;-1:-1:-1;;65526:16:0;:40::i;25685:761::-;26109:23;26135:69;26163:4;26135:69;;;;;;;;;;;;;;;;;26143:5;-1:-1:-1;;;;;26135:27:0;;;:69;;;;;:::i;:::-;26219:17;;26109:95;;-1:-1:-1;26219:21:0;26215:224;;26361:10;26350:30;;;;;;;;;;;;:::i;:::-;26342:85;;;;-1:-1:-1;;;26342:85:0;;;;;;;:::i;5290:979::-;5420:12;5453:18;5464:6;5453:10;:18::i;:::-;5445:60;;;;-1:-1:-1;;;5445:60:0;;;;;;;:::i;:::-;5579:12;5593:23;5620:6;-1:-1:-1;;;;;5620:11:0;5640:8;5651:4;5620:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5578:78;;;;5671:7;5667:595;;;5702:10;-1:-1:-1;5695:17:0;;-1:-1:-1;5695:17:0;5667:595;5816:17;;:21;5812:439;;6079:10;6073:17;6140:15;6127:10;6123:2;6119:19;6112:44;6027:148;6222:12;6215:20;;-1:-1:-1;;;6215:20:0;;;;;;;;:::i;15126:278::-;15212:7;15247:12;15240:5;15232:28;;;;-1:-1:-1;;;15232:28:0;;;;;;;;:::i;:::-;;15271:9;15287:1;15283;:5;;;;;;;15126:278;-1:-1:-1;;;;;15126:278:0:o;12661:136::-;12719:7;12746:43;12750:1;12753;12746:43;;;;;;;;;;;;;;;;;:3;:43::i;798:619::-;858:4;1326:20;;1169:66;1366:23;;;;;;:42;;-1:-1:-1;;1393:15:0;;;1358:51;-1:-1:-1;;798:619:0:o;13100:192::-;13186:7;13222:12;13214:6;;;;13206:29;;;;-1:-1:-1;;;13206:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;13258:5:0;;;13100:192::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;142:134;220:13;;238:33;220:13;238:33;:::i;419:442::-;;521:3;514:4;506:6;502:17;498:27;488:2;;-1:-1;;529:12;488:2;576:6;563:20;29567:18;29559:6;29556:30;29553:2;;;-1:-1;;29589:12;29553:2;598:65;29662:9;29643:17;;-1:-1;;29639:33;29730:4;29720:15;598:65;:::i;:::-;589:74;;683:6;676:5;669:21;787:3;29730:4;778:6;711;769:16;;766:25;763:2;;;804:1;;794:12;763:2;32542:6;29730:4;711:6;707:17;29730:4;745:5;741:16;32519:30;32598:1;32580:16;;;29730:4;32580:16;32573:27;745:5;481:380;-1:-1;;481:380::o;3131:134::-;3209:13;;-1:-1;;;;;30747:46;;33797:35;;33787:2;;33846:1;;33836:12;3272:128;3338:20;;31005:8;30994:20;;33920:34;;33910:2;;33968:1;;33958:12;3685:132;3762:13;;31177:18;31166:30;;34166:34;;34156:2;;34214:1;;34204:12;3961:241;;4065:2;4053:9;4044:7;4040:23;4036:32;4033:2;;;-1:-1;;4071:12;4033:2;85:6;72:20;97:33;124:5;97:33;:::i;4209:263::-;;4324:2;4312:9;4303:7;4299:23;4295:32;4292:2;;;-1:-1;;4330:12;4292:2;226:6;220:13;238:33;265:5;238:33;:::i;4479:472::-;;;4610:2;4598:9;4589:7;4585:23;4581:32;4578:2;;;-1:-1;;4616:12;4578:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;4668:63;-1:-1;4796:2;4781:18;;4768:32;4820:18;4809:30;;4806:2;;;-1:-1;;4842:12;4806:2;4872:63;4927:7;4918:6;4907:9;4903:22;4872:63;:::i;:::-;4862:73;;;4572:379;;;;;:::o;4958:597::-;;;;5106:2;5094:9;5085:7;5081:23;5077:32;5074:2;;;-1:-1;;5112:12;5074:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5164:63;-1:-1;5292:2;5277:18;;5264:32;5316:18;5305:30;;5302:2;;;-1:-1;;5338:12;5302:2;5368:63;5423:7;5414:6;5403:9;5399:22;5368:63;:::i;:::-;5358:73;;;5468:2;5511:9;5507:22;72:20;97:33;124:5;97:33;:::i;:::-;5476:63;;;;5068:487;;;;;:::o;5562:366::-;;;5683:2;5671:9;5662:7;5658:23;5654:32;5651:2;;;-1:-1;;5689:12;5651:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5741:63;5841:2;5880:22;;;;3474:20;;-1:-1;;;5645:283::o;5935:257::-;;6047:2;6035:9;6026:7;6022:23;6018:32;6015:2;;;-1:-1;;6053:12;6015:2;364:6;358:13;33701:5;30659:13;30652:21;33679:5;33676:32;33666:2;;-1:-1;;33712:12;6199:316;;6340:3;;6328:9;6319:7;6315:23;6311:33;6308:2;;;-1:-1;;6347:12;6308:2;1069:22;6340:3;1069:22;:::i;:::-;1060:31;;3906:6;3900:13;31279:4;34313:5;31268:16;34290:5;34287:33;34277:2;;-1:-1;;34324:12;34277:2;1150:84;;1329:60;1385:3;1296:2;1361:22;;1329:60;:::i;:::-;1296:2;1315:5;1311:16;1304:86;1489:60;1545:3;1456:2;1525:9;1521:22;1489:60;:::i;:::-;1456:2;1475:5;1471:16;1464:86;1645:59;1700:3;1612:2;1680:9;1676:22;1645:59;:::i;:::-;1612:2;1631:5;1627:16;1620:85;1818:59;1873:3;1784;1853:9;1849:22;1818:59;:::i;:::-;1784:3;1804:5;1800:16;1793:85;1994:59;2049:3;1960;2029:9;2025:22;1994:59;:::i;:::-;1960:3;1980:5;1976:16;1969:85;2162:59;2217:3;2128;2197:9;2193:22;2162:59;:::i;:::-;2128:3;2148:5;2144:16;2137:85;2322:60;2378:3;2288;2358:9;2354:22;2322:60;:::i;:::-;2288:3;2304:16;;2297:86;2308:5;6302:213;-1:-1;;;6302:213::o;6522:321::-;;6666:2;6654:9;6645:7;6641:23;6637:32;6634:2;;;-1:-1;;6672:12;6634:2;2615:20;6666:2;2615:20;:::i;:::-;226:6;220:13;238:33;265:5;238:33;:::i;:::-;2693:86;;2882:59;2937:3;2849:2;2913:22;;2882:59;:::i;:::-;2849:2;2868:5;2864:16;2857:85;3012:2;3078:9;3074:22;358:13;33701:5;30659:13;30652:21;33679:5;33676:32;33666:2;;-1:-1;;33712:12;33666:2;3012;3027:16;;3020:83;3031:5;6628:215;-1:-1;;;6628:215::o;6850:263::-;;6965:2;6953:9;6944:7;6940:23;6936:32;6933:2;;;-1:-1;;6971:12;6933:2;7033:64;7089:7;7065:22;7033:64;:::i;7120:362::-;;;7239:2;7227:9;7218:7;7214:23;7210:32;7207:2;;;-1:-1;;7245:12;7207:2;7307:52;7351:7;7327:22;7307:52;:::i;:::-;7297:62;;7414:52;7458:7;7396:2;7438:9;7434:22;7414:52;:::i;:::-;7404:62;;7201:281;;;;;:::o;7489:241::-;;7593:2;7581:9;7572:7;7568:23;7564:32;7561:2;;;-1:-1;;7599:12;7561:2;-1:-1;3474:20;;7555:175;-1:-1;7555:175::o;7737:263::-;;7852:2;7840:9;7831:7;7827:23;7823:32;7820:2;;;-1:-1;;7858:12;7820:2;-1:-1;3622:13;;7814:186;-1:-1;7814:186::o;8007:366::-;;;8128:2;8116:9;8107:7;8103:23;8099:32;8096:2;;;-1:-1;;8134:12;8096:2;-1:-1;;3474:20;;;8286:2;8325:22;;;3474:20;;-1:-1;8090:283::o;8380:261::-;;8494:2;8482:9;8473:7;8469:23;8465:32;8462:2;;;-1:-1;;8500:12;8462:2;8562:63;8617:7;8593:22;8562:63;:::i;9148:323::-;;9280:5;29839:12;30114:6;30109:3;30102:19;9363:52;9408:6;30151:4;30146:3;30142:14;30151:4;9389:5;9385:16;9363:52;:::i;:::-;29662:9;33253:14;-1:-1;;33249:28;9427:39;;;;30151:4;9427:39;;9228:243;-1:-1;;9228:243::o;18397:799::-;-1:-1;;33468:2;33464:14;;;;;8967:58;;-1:-1;;;;;;33361:15;;;;;;18730:2;18721:12;;18099:56;33464:14;;;;;18830:11;;;8967:58;33361:15;;;;;;;18940:12;;;18099:56;33464:14;;;;;19049:11;;;8967:58;19159:12;;;18621:575::o;19203:271::-;;9638:5;29839:12;9749:52;9794:6;9789:3;9782:4;9775:5;9771:16;9749:52;:::i;:::-;9813:16;;;;;19337:137;-1:-1;;19337:137::o;19481:222::-;-1:-1;;;;;30867:54;;;;8709:37;;19608:2;19593:18;;19579:124::o;19710:333::-;-1:-1;;;;;30867:54;;;8709:37;;30867:54;;20029:2;20014:18;;8709:37;19865:2;19850:18;;19836:207::o;20050:432::-;-1:-1;;;;;30867:54;;;8709:37;;30867:54;;;;20391:2;20376:18;;8709:37;30659:13;;30652:21;20468:2;20453:18;;9102:34;20227:2;20212:18;;20198:284::o;20489:421::-;-1:-1;;;;;30867:54;;8709:37;;20664:2;20782;20767:18;;20760:48;;;20489:421;;20822:78;;20649:18;;20886:6;20822:78;:::i;20917:333::-;-1:-1;;;;;30867:54;;;;8709:37;;21236:2;21221:18;;18228:37;21072:2;21057:18;;21043:207::o;21257:210::-;30659:13;;30652:21;9102:34;;21378:2;21363:18;;21349:118::o;22518:310::-;;22665:2;22686:17;22679:47;22740:78;22665:2;22654:9;22650:18;22804:6;22740:78;:::i;22835:416::-;23035:2;23049:47;;;11080:2;23020:18;;;30102:19;11116:29;30142:14;;;11096:50;11165:12;;;23006:245::o;23258:416::-;23458:2;23472:47;;;11416:1;23443:18;;;30102:19;-1:-1;;;30142:14;;;11431:27;11477:12;;;23429:245::o;23681:416::-;23881:2;23895:47;;;11728:2;23866:18;;;30102:19;-1:-1;;;30142:14;;;11744:34;11797:12;;;23852:245::o;24104:416::-;24304:2;24318:47;;;12048:2;24289:18;;;30102:19;-1:-1;;;30142:14;;;12064:42;12125:12;;;24275:245::o;24527:416::-;24727:2;24741:47;;;12376:1;24712:18;;;30102:19;-1:-1;;;30142:14;;;12391:31;12441:12;;;24698:245::o;24950:416::-;25150:2;25164:47;;;12692:2;25135:18;;;30102:19;12728:34;30142:14;;;12708:55;-1:-1;;;12783:12;;;12776:25;12820:12;;;25121:245::o;25373:416::-;25573:2;25587:47;;;13071:2;25558:18;;;30102:19;13107:31;30142:14;;;13087:52;13158:12;;;25544:245::o;25796:416::-;25996:2;26010:47;;;13409:2;25981:18;;;30102:19;-1:-1;;;30142:14;;;13425:34;13478:12;;;25967:245::o;26219:416::-;26419:2;26433:47;;;13729:2;26404:18;;;30102:19;13765:34;30142:14;;;13745:55;-1:-1;;;13820:12;;;13813:34;13866:12;;;26390:245::o;26642:416::-;26842:2;26856:47;;;14117:2;26827:18;;;30102:19;-1:-1;;;30142:14;;;14133:33;14185:12;;;26813:245::o;27065:416::-;27265:2;27279:47;;;14436:2;27250:18;;;30102:19;14472:34;30142:14;;;14452:55;-1:-1;;;14527:12;;;14520:46;14585:12;;;27236:245::o;27488:416::-;27688:2;27702:47;;;14836:2;27673:18;;;30102:19;14872:28;30142:14;;;14852:49;14920:12;;;27659:245::o;27911:402::-;;28104:2;28125:17;28118:47;15266:16;15260:23;15194:4;28104:2;28093:9;28089:18;15296:38;15349:71;15185:14;28093:9;15185:14;15401:12;15349:71;:::i;:::-;15341:79;;29567:18;;33464:14;;;28104:2;15503:5;15499:16;15493:23;30867:54;15570:14;28093:9;15570:14;8709:37;15570:14;15661:5;15657:16;15651:23;15728:14;28093:9;15728:14;18228:37;15728:14;15819:5;15815:16;15809:23;15886:14;28093:9;15886:14;18228:37;15886:14;15985:5;15981:16;15975:23;15194:4;28093:9;16052:14;18228:37;28171:132;;;;28075:238;;;;:::o;28320:379::-;16441:23;;-1:-1;;;;;30867:54;;;8709:37;;16616:4;16605:16;;;16599:23;30867:54;;16676:14;;;8709:37;16769:4;16758:16;;;16752:23;31005:8;30994:20;16827:14;;;17847:36;16926:4;16915:16;;;16909:23;30867:54;;16986:14;;;8709:37;17084:4;17073:16;;;17067:23;17144:14;;;18228:37;33464:14;17231:16;;;17225:23;17302:14;;;18228:37;17408:4;17397:16;;;17391:23;17468:14;;;18228:37;17575:4;17564:16;;;17558:23;30867:54;17635:14;;;8709:37;;;;28525:3;28510:19;;28496:203::o;28706:218::-;31005:8;30994:20;;;;17847:36;;28831:2;28816:18;;28802:122::o;28931:222::-;18228:37;;;29058:2;29043:18;;29029:124::o;29160:256::-;29222:2;29216:9;29248:17;;;29323:18;29308:34;;29344:22;;;29305:62;29302:2;;;29380:1;;29370:12;29302:2;29222;29389:22;29200:216;;-1:-1;29200:216::o;32615:268::-;32680:1;32687:101;32701:6;32698:1;32695:13;32687:101;;;32768:11;;;32762:18;32749:11;;;32742:39;32723:2;32716:10;32687:101;;;32803:6;32800:1;32797:13;32794:2;;;-1:-1;;32680:1;32850:16;;32843:27;32664:219::o;33496:117::-;-1:-1;;;;;30867:54;;33555:35;;33545:2;;33604:1;;33594:12
Swarm Source
ipfs://82e41f580ac70347c8e45d4a344a166c3ff0f07eaaf408f6a665aa3e210d12e1
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.