Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
16870899 | 609 days ago | Contract Creation | 0 ETH |
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 Name:
Strategy
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-03-20 */ // SPDX-License-Identifier: AGPL-3.0 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: IERC3156FlashBorrower.sol // Copyright (C) 2021 Dai Foundation // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. interface IERC3156FlashBorrower { /** * @dev Receive a flash loan. * @param initiator The initiator of the loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @param fee The additional amount of tokens to repay. * @param data Arbitrary data structure, intended to contain user-defined parameters. * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" */ function onFlashLoan( address initiator, address token, uint256 amount, uint256 fee, bytes calldata data ) external returns (bytes32); } // File: IUniswapV2Router01.sol interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns ( uint256 amountA, uint256 amountB, uint256 liquidity ); function addLiquidityETH( address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external payable returns ( uint256 amountToken, uint256 amountETH, uint256 liquidity ); function removeLiquidity( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETH( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountToken, uint256 amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETHWithPermit( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountToken, uint256 amountETH); function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapTokensForExactTokens( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactETHForTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable returns (uint256[] memory amounts); function swapTokensForExactETH( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactTokensForETH( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapETHForExactTokens( uint256 amountOut, address[] calldata path, address to, uint256 deadline ) external payable returns (uint256[] memory amounts); function quote( uint256 amountA, uint256 reserveA, uint256 reserveB ) external pure returns (uint256 amountB); function getAmountOut( uint256 amountIn, uint256 reserveIn, uint256 reserveOut ) external pure returns (uint256 amountOut); function getAmountIn( uint256 amountOut, uint256 reserveIn, uint256 reserveOut ) external pure returns (uint256 amountIn); function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts); } // 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: InterestRateModel.sol interface InterestRateModel { /** * @notice Calculates the current borrow interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @return The borrow rate per block (as a percentage, and scaled by 1e18) */ function getBorrowRate( uint256 cash, uint256 borrows, uint256 reserves ) external view returns (uint256, uint256); /** * @notice Calculates the current supply interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @param reserveFactorMantissa The current reserve factor the market has * @return The supply rate per block (as a percentage, and scaled by 1e18) */ function getSupplyRate( uint256 cash, uint256 borrows, uint256 reserves, uint256 reserveFactorMantissa ) external view returns (uint256); } // File: Math.sol /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } } // 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: CTokenI.sol interface CTokenI { /*** Market Events ***/ /** * @notice Event emitted when interest is accrued */ event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows); /** * @notice Event emitted when tokens are minted */ event Mint(address minter, uint256 mintAmount, uint256 mintTokens); /** * @notice Event emitted when tokens are redeemed */ event Redeem(address redeemer, uint256 redeemAmount, uint256 redeemTokens); /** * @notice Event emitted when underlying is borrowed */ event Borrow(address borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows); /** * @notice Event emitted when a borrow is repaid */ event RepayBorrow(address payer, address borrower, uint256 repayAmount, uint256 accountBorrows, uint256 totalBorrows); /** * @notice Event emitted when a borrow is liquidated */ event LiquidateBorrow(address liquidator, address borrower, uint256 repayAmount, address cTokenCollateral, uint256 seizeTokens); /*** Admin Events ***/ /** * @notice Event emitted when pendingAdmin is changed */ event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); /** * @notice Event emitted when pendingAdmin is accepted, which means admin is updated */ event NewAdmin(address oldAdmin, address newAdmin); /** * @notice Event emitted when the reserve factor is changed */ event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa); /** * @notice Event emitted when the reserves are added */ event ReservesAdded(address benefactor, uint256 addAmount, uint256 newTotalReserves); /** * @notice Event emitted when the reserves are reduced */ event ReservesReduced(address admin, uint256 reduceAmount, uint256 newTotalReserves); /** * @notice EIP20 Transfer event */ event Transfer(address indexed from, address indexed to, uint256 amount); /** * @notice EIP20 Approval event */ event Approval(address indexed owner, address indexed spender, uint256 amount); /** * @notice Failure event */ event Failure(uint256 error, uint256 info, uint256 detail); function transfer(address dst, uint256 amount) external returns (bool); function transferFrom( address src, address dst, uint256 amount ) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function balanceOfUnderlying(address owner) external returns (uint256); function getAccountSnapshot(address account) external view returns ( uint256, uint256, uint256, uint256 ); function borrowRatePerBlock() external view returns (uint256); function supplyRatePerBlock() external view returns (uint256); function totalBorrowsCurrent() external returns (uint256); function borrowBalanceCurrent(address account) external returns (uint256); function borrowBalanceStored(address account) external view returns (uint256); function exchangeRateCurrent() external returns (uint256); function accrualBlockNumber() external view returns (uint256); function exchangeRateStored() external view returns (uint256); function getCash() external view returns (uint256); function accrueInterest() external returns (uint256); function interestRateModel() external view returns (InterestRateModel); function totalReserves() external view returns (uint256); function reserveFactorMantissa() external view returns (uint256); function seize( address liquidator, address borrower, uint256 seizeTokens ) external returns (uint256); function totalBorrows() external view returns (uint256); function totalSupply() external view returns (uint256); } // File: IERC3156FlashLender.sol // Copyright (C) 2021 Dai Foundation // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. interface IERC3156FlashLender { /** * @dev The amount of currency available to be lent. * @param token The loan currency. * @return The amount of `token` that can be borrowed. */ function maxFlashLoan( address token ) external view returns (uint256); /** * @dev The fee to be charged for a given loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @return The amount of `token` to be charged for the loan, on top of the returned principal. */ function flashFee( address token, uint256 amount ) external view returns (uint256); /** * @dev Initiate a flash loan. * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. * @param token The loan currency. * @param amount The amount of tokens lent. * @param data Arbitrary data structure, intended to contain user-defined parameters. */ function flashLoan( IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data ) external returns (bool); } // File: IUniswapV2Router02.sol interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; } // File: IUniswapV3Router.sol /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface IUniswapV3Router 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); } // 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); // 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 { healthCheck = _healthCheck; } function setDoHealthCheck(bool _doHealthCheck) external onlyVaultManagers { 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 { 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: CErc20I.sol interface CErc20I is CTokenI { function mint(uint256 mintAmount) external returns (uint256); function redeem(uint256 redeemTokens) external returns (uint256); function redeemUnderlying(uint256 redeemAmount) external returns (uint256); function borrow(uint256 borrowAmount) external returns (uint256); function repayBorrow(uint256 repayAmount) external returns (uint256); function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256); function liquidateBorrow( address borrower, uint256 repayAmount, CTokenI cTokenCollateral ) external returns (uint256); function underlying() external view returns (address); function comptroller() external view returns (address); } // File: ComptrollerI.sol interface ComptrollerI { function enterMarkets(address[] calldata cTokens) external returns (uint256[] memory); function exitMarket(address cToken) external returns (uint256); /*** Policy Hooks ***/ function mintAllowed( address cToken, address minter, uint256 mintAmount ) external returns (uint256); function mintVerify( address cToken, address minter, uint256 mintAmount, uint256 mintTokens ) external; function redeemAllowed( address cToken, address redeemer, uint256 redeemTokens ) external returns (uint256); function redeemVerify( address cToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens ) external; function borrowAllowed( address cToken, address borrower, uint256 borrowAmount ) external returns (uint256); function borrowVerify( address cToken, address borrower, uint256 borrowAmount ) external; function repayBorrowAllowed( address cToken, address payer, address borrower, uint256 repayAmount ) external returns (uint256); function repayBorrowVerify( address cToken, address payer, address borrower, uint256 repayAmount, uint256 borrowerIndex ) external; function liquidateBorrowAllowed( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint256 repayAmount ) external returns (uint256); function liquidateBorrowVerify( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint256 repayAmount, uint256 seizeTokens ) external; function seizeAllowed( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint256 seizeTokens ) external returns (uint256); function seizeVerify( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint256 seizeTokens ) external; function transferAllowed( address cToken, address src, address dst, uint256 transferTokens ) external returns (uint256); function transferVerify( address cToken, address src, address dst, uint256 transferTokens ) external; /*** Liquidity/Liquidation Calculations ***/ function liquidateCalculateSeizeTokens( address cTokenBorrowed, address cTokenCollateral, uint256 repayAmount ) external view returns (uint256, uint256); function getAccountLiquidity(address account) external view returns ( uint256, uint256, uint256 ); /*** Comp claims ****/ function claimComp(address holder) external; function claimComp(address holder, CTokenI[] memory cTokens) external; function markets(address ctoken) external view returns ( bool, uint256, bool ); function compSpeeds(address ctoken) external view returns (uint256); // will be deprecated function compSupplySpeeds(address ctoken) external view returns (uint256); function compBorrowSpeeds(address ctoken) external view returns (uint256); function oracle() external view returns (address); } // File: FlashMintLib.sol interface IUniswapAnchoredView { function price(string memory) external returns (uint256); } interface IERC20Extended is IERC20 { function decimals() external view returns (uint8); function name() external view returns (string memory); function symbol() external view returns (string memory); } library FlashMintLib { using SafeMath for uint256; event Leverage(uint256 amountRequested, uint256 requiredDAI, bool deficit, address flashLoan); uint256 private constant PRICE_DECIMALS = 1e6; uint256 private constant DAI_DECIMALS = 1e18; uint256 private constant COLLAT_DECIMALS = 1e18; address public constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; address public constant CDAI = 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643; address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address private constant WBTC = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599; ComptrollerI private constant COMPTROLLER = ComptrollerI(0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B); address public constant LENDER = 0x60744434d6339a6B27d73d9Eda62b6F66a0a04FA; bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); function doFlashMint( bool deficit, uint256 amountDesired, address want, uint256 collatRatioDAI ) public returns (uint256) { if (amountDesired == 0) { return 0; } // calculate amount of DAI we need (uint256 requiredDAI, uint256 amountWant) = getFlashLoanParams(want, amountDesired, collatRatioDAI); bytes memory data = abi.encode(deficit, amountWant); uint256 _fee = IERC3156FlashLender(LENDER).flashFee(DAI, amountWant); // Check that fees have not been increased without us knowing require(_fee == 0); uint256 _allowance = IERC20(DAI).allowance(address(this), address(LENDER)); if (_allowance < requiredDAI) { IERC20(DAI).approve(address(LENDER), 0); IERC20(DAI).approve(address(LENDER), type(uint256).max); } IERC3156FlashLender(LENDER).flashLoan(IERC3156FlashBorrower(address(this)), DAI, requiredDAI, data); emit Leverage(amountDesired, requiredDAI, deficit, address(LENDER)); return amountWant; } function maxLiquidity() public view returns (uint256) { return IERC3156FlashLender(LENDER).maxFlashLoan(DAI); } function getFlashLoanParams( address want, uint256 amountDesired, uint256 collatRatioDAI ) internal returns (uint256 requiredDAI, uint256 amountWant) { uint256 priceDAIWant; uint256 decimalsDifference; (priceDAIWant, decimalsDifference, requiredDAI) = getPriceDAIWant(want, amountDesired, collatRatioDAI); amountWant = amountDesired; // If the cap for flashminting is reduced, we may hit maximum. To avoid reverts in that case we handle the edge case uint256 _maxFlashLoan = maxLiquidity(); if (requiredDAI > _maxFlashLoan) { requiredDAI = _maxFlashLoan.mul(9800).div(10_000); // use 98% of total liquidity available if (address(want) == address(DAI)) { amountWant = requiredDAI; } else { amountWant = requiredDAI.mul(collatRatioDAI).mul(PRICE_DECIMALS).div(priceDAIWant).div(COLLAT_DECIMALS).div(decimalsDifference); } } } function getPriceDAIWant( address want, uint256 amountDesired, uint256 collatRatioDAI ) internal returns ( uint256 priceDAIWant, uint256 decimalsDifference, uint256 requiredDAI ) { if (want == DAI) { requiredDAI = amountDesired; priceDAIWant = PRICE_DECIMALS; // 1:1 decimalsDifference = 1; // 10 ** 0 } else { // NOTE: want decimals need to be <= 18. otherwise this will break uint256 wantDecimals = 10**uint256(IERC20Extended(want).decimals()); decimalsDifference = DAI_DECIMALS.div(wantDecimals); priceDAIWant = getOraclePrice(DAI).mul(PRICE_DECIMALS).div(getOraclePrice(want)); // requiredDAI = desiredWantInDAI / COLLAT_RATIO_DAI // desiredWantInDAI = (desiredWant / priceDAIWant) // NOTE: decimals need adjustment (e.g. BTC: 8 / ETH: 18) requiredDAI = amountDesired.mul(PRICE_DECIMALS).mul(COLLAT_DECIMALS).mul(decimalsDifference).div(priceDAIWant).div(collatRatioDAI); } } function getOraclePrice(address token) internal returns (uint256) { string memory symbol; // Symbol for WBTC is BTC in oracle if (token == WBTC) { symbol = "BTC"; } else if (token == WETH) { symbol = "ETH"; } else { symbol = IERC20Extended(token).symbol(); } IUniswapAnchoredView oracle = IUniswapAnchoredView(COMPTROLLER.oracle()); return oracle.price(symbol); } function loanLogic( bool deficit, uint256 amountDAI, uint256 amount, CErc20I cToken ) public returns (bytes32) { // if want is not DAI, we provide flashminted DAI to borrow want and be able to lever up/down // if want is DAI, we use it directly to lever up/down bool isDai; // We check if cToken is DAI to save a couple of unnecessary calls if (address(cToken) == address(CDAI)) { isDai = true; require(amountDAI == amount, "!amounts"); } uint256 daiBal = IERC20(DAI).balanceOf(address(this)); if (deficit) { if (!isDai) { require(CErc20I(CDAI).mint(daiBal) == 0, "!mint_flash"); require(cToken.redeemUnderlying(amount) == 0, "!redeem_down"); } //if in deficit we repay amount and then withdraw uint256 repayAmount = Math.min(IERC20(cToken.underlying()).balanceOf(address(this)), cToken.borrowBalanceCurrent(address(this))); require(cToken.repayBorrow(repayAmount) == 0, "!repay_down"); require(CErc20I(CDAI).redeemUnderlying(amountDAI) == 0, "!redeem"); } else { // if levering up borrow and deposit require(CErc20I(CDAI).mint(daiBal) == 0, "!mint_flash"); require(cToken.borrow(amount) == 0, "!borrow_up"); if (!isDai) { require(cToken.mint(IERC20(cToken.underlying()).balanceOf(address(this))) == 0, "!mint_up"); require(CErc20I(CDAI).redeemUnderlying(amountDAI) == 0, "!redeem"); } } return CALLBACK_SUCCESS; } } // File: Strategy.sol contract Strategy is BaseStrategy, IERC3156FlashBorrower { using SafeERC20 for IERC20; using Address for address; using SafeMath for uint256; // @notice emitted when trying to do Flash Loan. flashLoan address is 0x00 when no flash loan used event Leverage(uint256 amountRequested, uint256 amountGiven, bool deficit, address flashLoan); // Comptroller address for compound.finance ComptrollerI private constant compound = ComptrollerI(0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B); //Only three tokens we use address private constant comp = 0xc00e94Cb662C3520282E6f5717214004A7f26888; address private constant weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; CErc20I public cToken; bool public useUniV3; // fee pool to use in UniV3 in basis points(default: 0.3% = 3000) uint24 public compToWethSwapFee; uint24 public wethToWantSwapFee; IUniswapV2Router02 public currentV2Router; IUniswapV2Router02 private constant UNI_V2_ROUTER = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); IUniswapV2Router02 private constant SUSHI_V2_ROUTER = IUniswapV2Router02(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); IUniswapV3Router private constant UNI_V3_ROUTER = IUniswapV3Router(0xE592427A0AEce92De3Edee1F18E0157C05861564); uint256 public collatRatioDAI; uint256 public collateralTarget; // total borrow / total supply ratio we are targeting (100% = 1e18) uint256 private blocksToLiquidationDangerZone; // minimum number of blocks before liquidation uint256 public minWant; // minimum amount of want to act on // Rewards handling bool public dontClaimComp; // enable/disables COMP claiming uint256 public minCompToSell; // minimum amount of COMP to be sold bool public flashMintActive; // To deactivate flash loan provider if needed bool public forceMigrate; bool public fourThreeProtection; constructor(address _vault, address _cToken) public BaseStrategy(_vault) { _initializeThis(_cToken); } function approveTokenMax(address token, address spender) internal { IERC20(token).safeApprove(spender, type(uint256).max); } function name() external view override returns (string memory) { return "GenLevCompV4"; } function initialize(address _vault, address _cToken) external { _initialize(_vault, msg.sender, msg.sender, msg.sender); _initializeThis(_cToken); } function _initializeThis(address _cToken) internal { cToken = CErc20I(address(_cToken)); require(IERC20Extended(address(want)).decimals() <= 18); // dev: want not supported currentV2Router = SUSHI_V2_ROUTER; //pre-set approvals approveTokenMax(comp, address(UNI_V2_ROUTER)); approveTokenMax(comp, address(SUSHI_V2_ROUTER)); approveTokenMax(comp, address(UNI_V3_ROUTER)); approveTokenMax(address(want), address(cToken)); approveTokenMax(FlashMintLib.DAI, address(FlashMintLib.LENDER)); // Enter Compound's DAI market to take it into account when using flashminted DAI as collateral address[] memory markets; if (address(cToken) != address(FlashMintLib.CDAI)) { markets = new address[](2); markets[0] = address(FlashMintLib.CDAI); markets[1] = address(cToken); // Only approve this if want != DAI, otherwise will fail approveTokenMax(FlashMintLib.DAI, address(FlashMintLib.CDAI)); } else { markets = new address[](1); markets[0] = address(FlashMintLib.CDAI); } compound.enterMarkets(markets); //comp speed is amount to borrow or deposit (so half the total distribution for want) compToWethSwapFee = 3000; wethToWantSwapFee = 3000; // You can set these parameters on deployment to whatever you want maxReportDelay = 86400; // once per 24 hours profitFactor = 100; // multiple before triggering harvest debtThreshold = 1e30; // set minWant to 1e-5 want minWant = uint256(uint256(10)**uint256((IERC20Extended(address(want))).decimals())).div(1e5); minCompToSell = 0.1 ether; collateralTarget = 0.63 ether; collatRatioDAI = 0.73 ether; blocksToLiquidationDangerZone = 46500; flashMintActive = true; } /* * Control Functions */ function setFourThreeProtection(bool _fourThreeProtection) external management { fourThreeProtection = _fourThreeProtection; } function setUniV3PathFees(uint24 _compToWethSwapFee, uint24 _wethToWantSwapFee) external management { compToWethSwapFee = _compToWethSwapFee; wethToWantSwapFee = _wethToWantSwapFee; } function setDontClaimComp(bool _dontClaimComp) external management { dontClaimComp = _dontClaimComp; } function setUseUniV3(bool _useUniV3) external management { useUniV3 = _useUniV3; } function setToggleV2Router() external management { currentV2Router = currentV2Router == SUSHI_V2_ROUTER ? UNI_V2_ROUTER : SUSHI_V2_ROUTER; } function setFlashMintActive(bool _flashMintActive) external management { flashMintActive = _flashMintActive; } function setForceMigrate(bool _force) external onlyGovernance { forceMigrate = _force; } function setMinCompToSell(uint256 _minCompToSell) external management { minCompToSell = _minCompToSell; } function setMinWant(uint256 _minWant) external management { minWant = _minWant; } function setCollateralTarget(uint256 _collateralTarget) external management { (, uint256 collateralFactorMantissa, ) = compound.markets(address(cToken)); require(collateralFactorMantissa > _collateralTarget); collateralTarget = _collateralTarget; } function setCollatRatioDAI(uint256 _collatRatioDAI) external management { collatRatioDAI = _collatRatioDAI; } /* * Base External Facing Functions */ /* * An accurate estimate for the total amount of assets (principle + return) * that this strategy is currently managing, denominated in terms of want tokens. */ function estimatedTotalAssets() public view override returns (uint256) { (uint256 deposits, uint256 borrows) = getCurrentPosition(); uint256 _claimableComp = predictCompAccrued(); uint256 currentComp = balanceOfToken(comp); // Use touch price. it doesnt matter if we are wrong as this is not used for decision making uint256 estimatedWant = priceCheck(comp, address(want), _claimableComp.add(currentComp)); uint256 conservativeWant = estimatedWant.mul(9).div(10); //10% pessimist return balanceOfToken(address(want)).add(deposits).add(conservativeWant).sub(borrows); } function balanceOfToken(address token) internal view returns (uint256) { return IERC20(token).balanceOf(address(this)); } //predicts our profit at next report function expectedReturn() public view returns (uint256) { uint256 estimateAssets = estimatedTotalAssets(); uint256 debt = vault.strategies(address(this)).totalDebt; if (debt > estimateAssets) { return 0; } else { return estimateAssets.sub(debt); } } /* * Provide a signal to the keeper that `tend()` should be called. * (keepers are always reimbursed by yEarn) * * NOTE: this call and `harvestTrigger` should never return `true` at the same time. * tendTrigger should be called with same gasCost as harvestTrigger */ function tendTrigger(uint256 gasCost) public view override returns (bool) { if (harvestTrigger(gasCost)) { //harvest takes priority return false; } return getblocksUntilLiquidation() <= blocksToLiquidationDangerZone; } //WARNING. manipulatable and simple routing. Only use for safe functions function priceCheck( address start, address end, uint256 _amount ) public view returns (uint256) { if (_amount == 0) { return 0; } uint256[] memory amounts = currentV2Router.getAmountsOut(_amount, getTokenOutPathV2(start, end)); return amounts[amounts.length - 1]; } /***************** * Public non-base function ******************/ //Calculate how many blocks until we are in liquidation based on current interest rates //WARNING does not include compounding so the estimate becomes more innacurate the further ahead we look //equation. Compound doesn't include compounding for most blocks //((deposits*colateralThreshold - borrows) / (borrows*borrowrate - deposits*colateralThreshold*interestrate)); function getblocksUntilLiquidation() public view returns (uint256) { (, uint256 collateralFactorMantissa, ) = compound.markets(address(cToken)); (uint256 deposits, uint256 borrows) = getCurrentPosition(); uint256 borrrowRate = cToken.borrowRatePerBlock(); uint256 supplyRate = cToken.supplyRatePerBlock(); uint256 collateralisedDeposit1 = deposits.mul(collateralFactorMantissa).div(1e18); uint256 collateralisedDeposit = collateralisedDeposit1; uint256 denom1 = borrows.mul(borrrowRate); uint256 denom2 = collateralisedDeposit.mul(supplyRate); if (denom2 >= denom1) { return type(uint256).max; } else { uint256 numer = collateralisedDeposit.sub(borrows); uint256 denom = denom1.sub(denom2); //minus 1 for this block return numer.mul(1e18).div(denom); } } // This function makes a prediction on how much comp is accrued // It is not 100% accurate as it uses current balances in Compound to predict into the past function predictCompAccrued() public view returns (uint256) { (uint256 deposits, uint256 borrows) = getCurrentPosition(); if (deposits == 0) { return 0; // should be impossible to have 0 balance and positive comp accrued } uint256 distributionPerBlockSupply = compound.compSupplySpeeds(address(cToken)); uint256 distributionPerBlockBorrow = compound.compBorrowSpeeds(address(cToken)); uint256 totalBorrow = cToken.totalBorrows(); //total supply needs to be echanged to underlying using exchange rate uint256 totalSupplyCtoken = cToken.totalSupply(); uint256 totalSupply = totalSupplyCtoken.mul(cToken.exchangeRateStored()).div(1e18); uint256 blockShareSupply = 0; if (totalSupply > 0) { blockShareSupply = deposits.mul(distributionPerBlockSupply).div(totalSupply); } uint256 blockShareBorrow = 0; if (totalBorrow > 0) { blockShareBorrow = borrows.mul(distributionPerBlockBorrow).div(totalBorrow); } //how much we expect to earn per block uint256 blockShare = blockShareSupply.add(blockShareBorrow); //last time we ran harvest uint256 lastReport = vault.strategies(address(this)).lastReport; uint256 blocksSinceLast = (block.timestamp.sub(lastReport)).div(13); //roughly 13 seconds per block return blocksSinceLast.mul(blockShare); } //Returns the current position //WARNING - this returns just the balance at last time someone touched the cToken token. Does not accrue interst in between //cToken is very active so not normally an issue. function getCurrentPosition() public view returns (uint256 deposits, uint256 borrows) { (, uint256 ctokenBalance, uint256 borrowBalance, uint256 exchangeRate) = cToken.getAccountSnapshot(address(this)); borrows = borrowBalance; deposits = ctokenBalance.mul(exchangeRate).div(1e18); } //statechanging version function getLivePosition() public returns (uint256 deposits, uint256 borrows) { deposits = cToken.balanceOfUnderlying(address(this)); //we can use non state changing now because we updated state with balanceOfUnderlying call borrows = cToken.borrowBalanceStored(address(this)); } //Same warning as above function netBalanceLent() public view returns (uint256) { (uint256 deposits, uint256 borrows) = getCurrentPosition(); return deposits.sub(borrows); } /*********** * internal core logic *********** */ /* * A core method. * Called at beggining of harvest before providing report to owner * 1 - claim accrued comp * 2 - if enough to be worth it we sell * 3 - because we lose money on our loans we need to offset profit from comp. */ function prepareReturn(uint256 _debtOutstanding) internal override returns ( uint256 _profit, uint256 _loss, uint256 _debtPayment ) { _profit = 0; _loss = 0; // for clarity. also reduces bytesize if (balanceOfToken(address(cToken)) == 0) { uint256 wantBalance = balanceOfToken(address(want)); //no position to harvest //but we may have some debt to return //it is too expensive to free more debt in this method so we do it in adjust position _debtPayment = Math.min(wantBalance, _debtOutstanding); return (_profit, _loss, _debtPayment); } (uint256 deposits, uint256 borrows) = getLivePosition(); //claim comp accrued _claimComp(); //sell comp _disposeOfComp(); uint256 wantBalance = balanceOfToken(address(want)); uint256 investedBalance = deposits.sub(borrows); uint256 balance = investedBalance.add(wantBalance); uint256 debt = vault.strategies(address(this)).totalDebt; //Balance - Total Debt is profit if (balance > debt) { _profit = balance.sub(debt); if (wantBalance < _profit) { //all reserve is profit _profit = wantBalance; } else if (wantBalance > _profit.add(_debtOutstanding)) { _debtPayment = _debtOutstanding; } else { _debtPayment = wantBalance.sub(_profit); } } else { //we will lose money until we claim comp then we will make money //this has an unintended side effect of slowly lowering our total debt allowed _loss = debt.sub(balance); _debtPayment = Math.min(wantBalance, _debtOutstanding); } } /* * Second core function. Happens after report call. * * Similar to deposit function from V1 strategy */ function adjustPosition(uint256 _debtOutstanding) internal override { //emergency exit is dealt with in prepareReturn if (emergencyExit) { return; } //we are spending all our cash unless we have debt outstanding uint256 _wantBal = balanceOfToken(address(want)); if (_wantBal < _debtOutstanding) { //this is graceful withdrawal. dont use backup //we use more than 1 because withdrawunderlying causes problems with 1 token due to different decimals if (balanceOfToken(address(cToken)) > 1) { _withdrawSome(_debtOutstanding.sub(_wantBal)); } return; } (uint256 position, bool deficit) = _calculateDesiredPosition(_wantBal.sub(_debtOutstanding), true); //if we are below minimun want change it is not worth doing //need to be careful in case this pushes to liquidation if (position > minWant) { //if flashloan is not active we just try our best with basic leverage if (!flashMintActive) { uint256 i = 0; while (position > 0) { position = position.sub(_noFlashLoan(position, deficit)); if (i >= 6) { break; } i++; } } else { //if there is huge position to improve we want to do normal leverage. it is quicker if (position > FlashMintLib.maxLiquidity()) { position = position.sub(_noFlashLoan(position, deficit)); } //flash loan to position if (position > minWant) { doFlashMint(deficit, position); } } } } /************* * Very important function * Input: amount we want to withdraw and whether we are happy to pay extra for Aave. * cannot be more than we have * Returns amount we were able to withdraw. notall if user has some balance left * * Deleverage position -> redeem our cTokens ******************** */ function _withdrawSome(uint256 _amount) internal returns (bool notAll) { (uint256 position, bool deficit) = _calculateDesiredPosition(_amount, false); //If there is no deficit we dont need to adjust position //if the position change is tiny do nothing if (deficit && position > minWant) { //we do a flash loan to give us a big gap. from here on out it is cheaper to use normal deleverage. Use Aave for extremely large loans if (flashMintActive) { position = position.sub(doFlashMint(deficit, position)); } uint8 i = 0; //position will equal 0 unless we haven't been able to deleverage enough with flash loan //if we are not in deficit we dont need to do flash loan while (position > minWant.add(100)) { position = position.sub(_noFlashLoan(position, true)); i++; //A limit set so we don't run out of gas if (i >= 5) { notAll = true; break; } } } //now withdraw //if we want too much we just take max //This part makes sure our withdrawal does not force us into liquidation (uint256 depositBalance, uint256 borrowBalance) = getCurrentPosition(); uint256 tempColla = collateralTarget; uint256 reservedAmount = 0; if (tempColla == 0) { tempColla = 1e15; // 0.001 * 1e18. lower we have issues } reservedAmount = borrowBalance.mul(1e18).div(tempColla); if (depositBalance >= reservedAmount) { uint256 redeemable = depositBalance.sub(reservedAmount); uint256 balan = cToken.balanceOf(address(this)); if (balan > 1) { if (redeemable < _amount) { cToken.redeemUnderlying(redeemable); } else { cToken.redeemUnderlying(_amount); } } } if (collateralTarget == 0 && balanceOfToken(address(want)) > borrowBalance) { cToken.repayBorrow(borrowBalance); } } /*********** * This is the main logic for calculating how to change our lends and borrows * Input: balance. The net amount we are going to deposit/withdraw. * Input: dep. Is it a deposit or withdrawal * Output: position. The amount we want to change our current borrow position. * Output: deficit. True if we are reducing position size * * For instance deficit =false, position 100 means increase borrowed balance by 100 ****** */ function _calculateDesiredPosition(uint256 balance, bool dep) internal returns (uint256 position, bool deficit) { //we want to use statechanging for safety (uint256 deposits, uint256 borrows) = getLivePosition(); //When we unwind we end up with the difference between borrow and supply uint256 unwoundDeposit = deposits.sub(borrows); //we want to see how close to collateral target we are. //So we take our unwound deposits and add or remove the balance we are are adding/removing. //This gives us our desired future undwoundDeposit (desired supply) uint256 desiredSupply = 0; if (dep) { desiredSupply = unwoundDeposit.add(balance); } else { if (balance > unwoundDeposit) { balance = unwoundDeposit; } desiredSupply = unwoundDeposit.sub(balance); } //(ds *c)/(1-c) uint256 num = desiredSupply.mul(collateralTarget); uint256 den = uint256(1e18).sub(collateralTarget); uint256 desiredBorrow = num.div(den); if (desiredBorrow > 1e5) { //stop us going right up to the wire desiredBorrow = desiredBorrow.sub(1e5); } //now we see if we want to add or remove balance // if the desired borrow is less than our current borrow we are in deficit. so we want to reduce position if (desiredBorrow < borrows) { deficit = true; position = borrows.sub(desiredBorrow); //safemath check done in if statement } else { //otherwise we want to increase position deficit = false; position = desiredBorrow.sub(borrows); } } /* * Liquidate as many assets as possible to `want`, irregardless of slippage, * up to `_amount`. Any excess should be re-invested here as well. */ function liquidatePosition(uint256 _amountNeeded) internal override returns (uint256 _amountFreed, uint256 _loss) { uint256 _balance = balanceOfToken(address(want)); uint256 assets = netBalanceLent().add(_balance); uint256 debtOutstanding = vault.debtOutstanding(); if (debtOutstanding > assets) { _loss = debtOutstanding.sub(assets); } (uint256 deposits, uint256 borrows) = getLivePosition(); if (assets < _amountNeeded) { //if we cant afford to withdraw we take all we can //withdraw all we can //1 token causes rounding error with withdrawUnderlying if (balanceOfToken(address(cToken)) > 1) { _withdrawSome(deposits.sub(borrows)); } _amountFreed = Math.min(_amountNeeded, balanceOfToken(address(want))); } else { if (_balance < _amountNeeded) { _withdrawSome(_amountNeeded.sub(_balance)); //overflow error if we return more than asked for _amountFreed = Math.min(_amountNeeded, balanceOfToken(address(want))); } else { _amountFreed = _amountNeeded; } } // To prevent the vault from moving on to the next strategy in the queue // when we return the amountRequested minus dust, take a dust sized loss if (_amountFreed < _amountNeeded) { uint256 diff = _amountNeeded.sub(_amountFreed); if (diff <= minWant) { _loss = diff; } } if (fourThreeProtection) { require(_amountNeeded == _amountFreed.add(_loss)); // dev: fourThreeProtection } } function _claimComp() internal { if (dontClaimComp) { return; } CTokenI[] memory tokens = new CTokenI[](1); tokens[0] = cToken; compound.claimComp(address(this), tokens); } //sell comp function function _disposeOfComp() internal { uint256 _comp = balanceOfToken(comp); if (_comp < minCompToSell) { return; } if (useUniV3) { UNI_V3_ROUTER.exactInput(IUniswapV3Router.ExactInputParams(getTokenOutPathV3(comp, address(want)), address(this), now, _comp, 0)); } else { currentV2Router.swapExactTokensForTokens(_comp, 0, getTokenOutPathV2(comp, address(want)), address(this), now); } } function getTokenOutPathV2(address _tokenIn, address _tokenOut) internal pure returns (address[] memory _path) { bool isWeth = _tokenIn == address(weth) || _tokenOut == address(weth); _path = new address[](isWeth ? 2 : 3); _path[0] = _tokenIn; if (isWeth) { _path[1] = _tokenOut; } else { _path[1] = address(weth); _path[2] = _tokenOut; } } function getTokenOutPathV3(address _tokenIn, address _tokenOut) internal view returns (bytes memory _path) { if (address(want) == weth) { _path = abi.encodePacked(address(_tokenIn), compToWethSwapFee, address(weth)); } else { _path = abi.encodePacked(address(_tokenIn), compToWethSwapFee, address(weth), wethToWantSwapFee, address(_tokenOut)); } } //lets leave //if we can't deleverage in one go set collateralFactor to 0 and call harvest multiple times until delevered function prepareMigration(address _newStrategy) internal override { if (!forceMigrate) { (uint256 deposits, uint256 borrows) = getLivePosition(); _withdrawSome(deposits.sub(borrows)); (, , uint256 borrowBalance, ) = cToken.getAccountSnapshot(address(this)); require(borrowBalance < 10_000); IERC20 _comp = IERC20(comp); uint256 _compB = balanceOfToken(address(_comp)); if (_compB > 0) { _comp.safeTransfer(_newStrategy, _compB); } } } //Three functions covering normal leverage and deleverage situations // max is the max amount we want to increase our borrowed balance // returns the amount we actually did function _noFlashLoan(uint256 max, bool deficit) internal returns (uint256 amount) { //we can use non-state changing because this function is always called after _calculateDesiredPosition (uint256 lent, uint256 borrowed) = getCurrentPosition(); //if we have nothing borrowed then we can't deleverage any more if (borrowed == 0 && deficit) { return 0; } (, uint256 collateralFactorMantissa, ) = compound.markets(address(cToken)); if (deficit) { amount = _normalDeleverage(max, lent, borrowed, collateralFactorMantissa); } else { amount = _normalLeverage(max, lent, borrowed, collateralFactorMantissa); } emit Leverage(max, amount, deficit, address(0)); } //maxDeleverage is how much we want to reduce by function _normalDeleverage( uint256 maxDeleverage, uint256 lent, uint256 borrowed, uint256 collatRatio ) internal returns (uint256 deleveragedAmount) { uint256 theoreticalLent = 0; //collat ration should never be 0. if it is something is very wrong... but just incase if (collatRatio != 0) { theoreticalLent = borrowed.mul(1e18).div(collatRatio); } deleveragedAmount = lent.sub(theoreticalLent); if (deleveragedAmount >= borrowed) { deleveragedAmount = borrowed; } if (deleveragedAmount >= maxDeleverage) { deleveragedAmount = maxDeleverage; } uint256 exchangeRateStored = cToken.exchangeRateStored(); //redeemTokens = redeemAmountIn * 1e18 / exchangeRate. must be more than 0 //a rounding error means we need another small addition if (deleveragedAmount.mul(1e18) >= exchangeRateStored && deleveragedAmount > 10) { deleveragedAmount = deleveragedAmount.sub(uint256(10)); cToken.redeemUnderlying(deleveragedAmount); //our borrow has been increased by no more than maxDeleverage cToken.repayBorrow(deleveragedAmount); } } //maxDeleverage is how much we want to increase by function _normalLeverage( uint256 maxLeverage, uint256 lent, uint256 borrowed, uint256 collatRatio ) internal returns (uint256 leveragedAmount) { uint256 theoreticalBorrow = lent.mul(collatRatio).div(1e18); leveragedAmount = theoreticalBorrow.sub(borrowed); if (leveragedAmount >= maxLeverage) { leveragedAmount = maxLeverage; } if (leveragedAmount > 10) { leveragedAmount = leveragedAmount.sub(uint256(10)); cToken.borrow(leveragedAmount); cToken.mint(balanceOfToken(address(want))); } } //emergency function that we can use to deleverage manually if something is broken function manualDeleverage(uint256 amount) external management { require(cToken.redeemUnderlying(amount) == 0); require(cToken.repayBorrow(amount) == 0); } //emergency function that we can use to deleverage manually if something is broken function manualReleaseWant(uint256 amount) external onlyGovernance { require(cToken.redeemUnderlying(amount) == 0); // dev: !manual-release-want } function protectedTokens() internal view override returns (address[] memory) {} /****************** * Flash mint stuff ****************/ // Flash loan // amount desired is how much we are willing for position to change function doFlashMint(bool deficit, uint256 amountDesired) internal returns (uint256) { return FlashMintLib.doFlashMint(deficit, amountDesired, address(want), collatRatioDAI); } //returns our current collateralisation ratio. Should be compared with collateralTarget function storedCollateralisation() public view returns (uint256 collat) { (uint256 lend, uint256 borrow) = getCurrentPosition(); if (lend == 0) { return 0; } collat = uint256(1e18).mul(borrow).div(lend); } function onFlashLoan( address initiator, address token, uint256 amount, uint256 fee, bytes calldata data ) external override returns (bytes32) { require(msg.sender == FlashMintLib.LENDER); require(initiator == address(this)); (bool deficit, uint256 amountWant) = abi.decode(data, (bool, uint256)); return FlashMintLib.loanLogic(deficit, amount, amountWant, cToken); } // -- Internal Helper functions -- // function ethToWant(uint256 _amtInWei) public view override returns (uint256) { return priceCheck(weth, address(want), _amtInWei); } function liquidateAllPositions() internal override returns (uint256 _amountFreed) { (_amountFreed, ) = liquidatePosition(vault.debtOutstanding()); (uint256 deposits, uint256 borrows) = getCurrentPosition(); uint256 position = deposits.sub(borrows); //we want to revert if we can't liquidateall if (!forceMigrate) { require(position < minWant); } } function mgtm_check() internal view { require(msg.sender == governance() || msg.sender == vault.management() || msg.sender == strategist, "!authorized"); } modifier management() { mgtm_check(); _; } } // File: LevCompFactory.sol contract LevCompFactory { address public immutable original; event Cloned(address indexed clone); event Deployed(address indexed original); constructor( address _vault, address _cToken ) public { Strategy _original = new Strategy(_vault, _cToken); emit Deployed(address(_original)); original = address(_original); _original.setStrategist(msg.sender); } function name() external view returns (string memory) { return string(abi.encodePacked("Factory", Strategy(payable(original)).name(), "@", Strategy(payable(original)).apiVersion())); } function cloneLevComp( address _vault, address _cToken ) external returns (address payable newStrategy) { // Copied from https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol bytes20 addressBytes = bytes20(original); 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) } Strategy(newStrategy).initialize(_vault, _cToken); Strategy(newStrategy).setStrategist(msg.sender); emit Cloned(newStrategy); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_cToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"EmergencyExitEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loss","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtPayment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtOutstanding","type":"uint256"}],"name":"Harvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amountRequested","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountGiven","type":"uint256"},{"indexed":false,"internalType":"bool","name":"deficit","type":"bool"},{"indexed":false,"internalType":"address","name":"flashLoan","type":"address"}],"name":"Leverage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"debtThreshold","type":"uint256"}],"name":"UpdatedDebtThreshold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newKeeper","type":"address"}],"name":"UpdatedKeeper","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"delay","type":"uint256"}],"name":"UpdatedMaxReportDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"metadataURI","type":"string"}],"name":"UpdatedMetadataURI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"delay","type":"uint256"}],"name":"UpdatedMinReportDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profitFactor","type":"uint256"}],"name":"UpdatedProfitFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"rewards","type":"address"}],"name":"UpdatedRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newStrategist","type":"address"}],"name":"UpdatedStrategist","type":"event"},{"inputs":[],"name":"apiVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"cToken","outputs":[{"internalType":"contract CErc20I","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatRatioDAI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralTarget","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"compToWethSwapFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentV2Router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delegatedAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"doHealthCheck","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dontClaimComp","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyExit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"estimatedTotalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amtInWei","type":"uint256"}],"name":"ethToWant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"expectedReturn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flashMintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"forceMigrate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fourThreeProtection","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentPosition","outputs":[{"internalType":"uint256","name":"deposits","type":"uint256"},{"internalType":"uint256","name":"borrows","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLivePosition","outputs":[{"internalType":"uint256","name":"deposits","type":"uint256"},{"internalType":"uint256","name":"borrows","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getblocksUntilLiquidation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"callCostInWei","type":"uint256"}],"name":"harvestTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"healthCheck","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_cToken","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"manualDeleverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"manualReleaseWant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxReportDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newStrategy","type":"address"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minCompToSell","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minReportDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minWant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"netBalanceLent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onFlashLoan","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"predictCompAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"start","type":"address"},{"internalType":"address","name":"end","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"priceCheck","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"profitFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collatRatioDAI","type":"uint256"}],"name":"setCollatRatioDAI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralTarget","type":"uint256"}],"name":"setCollateralTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debtThreshold","type":"uint256"}],"name":"setDebtThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_doHealthCheck","type":"bool"}],"name":"setDoHealthCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_dontClaimComp","type":"bool"}],"name":"setDontClaimComp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setEmergencyExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_flashMintActive","type":"bool"}],"name":"setFlashMintActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_force","type":"bool"}],"name":"setForceMigrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_fourThreeProtection","type":"bool"}],"name":"setFourThreeProtection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_healthCheck","type":"address"}],"name":"setHealthCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"setKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setMaxReportDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_metadataURI","type":"string"}],"name":"setMetadataURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minCompToSell","type":"uint256"}],"name":"setMinCompToSell","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setMinReportDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minWant","type":"uint256"}],"name":"setMinWant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_profitFactor","type":"uint256"}],"name":"setProfitFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewards","type":"address"}],"name":"setRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategist","type":"address"}],"name":"setStrategist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setToggleV2Router","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"_compToWethSwapFee","type":"uint24"},{"internalType":"uint24","name":"_wethToWantSwapFee","type":"uint24"}],"name":"setUniV3PathFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_useUniV3","type":"bool"}],"name":"setUseUniV3","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"storedCollateralisation","outputs":[{"internalType":"uint256","name":"collat","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategist","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":"tend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"gasCost","type":"uint256"}],"name":"tendTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"useUniV3","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"wethToWantSwapFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountNeeded","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"_loss","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162006e6938038062006e69833981016040819052620000349162000ada565b81620000438133808062000057565b506200004f816200023b565b505062000e91565b6006546001600160a01b0316156200008c5760405162461bcd60e51b8152600401620000839062000ce9565b60405180910390fd5b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b158015620000e957600080fd5b505afa158015620000fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000124919062000ab1565b600680546001600160a01b0319166001600160a01b0392831617908190556200015e9116856000196200072b602090811b620031a717901c565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b393620001de93911691600019910162000c4c565b602060405180830381600087803b158015620001f957600080fd5b505af11580156200020e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000234919062000bb6565b5050505050565b80600b60016101000a8154816001600160a01b0302191690836001600160a01b031602179055506012600660009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015620002b357600080fd5b505afa158015620002c8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ee919062000bf1565b60ff161115620002fd57600080fd5b600c80546001600160a01b03191673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f1790556200035773c00e94cb662c3520282e6f5717214004a7f26888737a250d5630b4cf539739df2c5dacb4c659f2488d62000839565b6200038b73c00e94cb662c3520282e6f5717214004a7f2688873d9e1ce17f2641f24ae83637ab66a2cca9c378b9f62000839565b620003bf73c00e94cb662c3520282e6f5717214004a7f2688873e592427a0aece92de3edee1f18e0157c0586156462000839565b600654600b54620003e2916001600160a01b039081169161010090041662000839565b62000416736b175474e89094c44da98b954eedeac495271d0f7360744434d6339a6b27d73d9eda62b6f66a0a04fa62000839565b600b5460609061010090046001600160a01b0316735d3a536e4d6dbd6114cc1ead35777bab948e3643146200050d576040805160028082526060820183529091602083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e3643816000815181106200048857fe5b6001600160a01b039283166020918202929092010152600b5482516101009091049091169082906001908110620004bb57fe5b6001600160a01b039092166020928302919091019091015262000507736b175474e89094c44da98b954eedeac495271d0f735d3a536e4d6dbd6114cc1ead35777bab948e364362000839565b62000571565b6040805160018082528183019092529060208083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e3643816000815181106200055057fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b604051631853304760e31b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b9063c299823890620005aa90849060040162000c65565b600060405180830381600087803b158015620005c557600080fd5b505af1158015620005da573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000604919081019062000b18565b50600b805462ffffff60b01b191661017760b31b1762ffffff60c81b191661017760cb1b1790556201518060085560646009556c0c9f2c9cd04674edea40000000600a556006546040805163313ce56760e01b81529051620006ed92620186a0926001600160a01b039091169163313ce56791600480820192602092909190829003018186803b1580156200069857600080fd5b505afa158015620006ad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006d3919062000bf1565b60ff16600a0a6200086460201b620032a61790919060201c565b601055505067016345785d8a00006012556708be35a9807f0000600e55670a217b21de090000600d5561b5a4600f556013805460ff19166001179055565b801580620007ba5750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e9062000764903090869060040162000c32565b60206040518083038186803b1580156200077d57600080fd5b505afa15801562000792573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620007b8919062000bd8565b155b620007d95760405162461bcd60e51b8152600401620000839062000da1565b620008348363095ea7b360e01b8484604051602401620007fb92919062000c4c565b60408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b0393841617905290620008b516565b505050565b6200086081600019846001600160a01b03166200072b60201b620031a7179092919060201c565b5050565b6000620008ae83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506200095160201b60201c565b9392505050565b606062000911826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200098c60201b620032e8179092919060201c565b80519091501562000834578080602001905181019062000932919062000bb6565b620008345760405162461bcd60e51b8152600401620000839062000d57565b60008183620009755760405162461bcd60e51b815260040162000083919062000cb4565b5060008385816200098257fe5b0495945050505050565b60606200099d8484600085620009a5565b949350505050565b6060620009b28562000a77565b620009d15760405162461bcd60e51b8152600401620000839062000d20565b60006060866001600160a01b03168587604051620009f0919062000c14565b60006040518083038185875af1925050503d806000811462000a2f576040519150601f19603f3d011682016040523d82523d6000602084013e62000a34565b606091505b5091509150811562000a4a5791506200099d9050565b80511562000a5b5780518082602001fd5b8360405162461bcd60e51b815260040162000083919062000cb4565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906200099d575050151592915050565b60006020828403121562000ac3578081fd5b81516001600160a01b0381168114620008ae578182fd5b6000806040838503121562000aed578081fd5b825162000afa8162000e78565b602084015190925062000b0d8162000e78565b809150509250929050565b6000602080838503121562000b2b578182fd5b82516001600160401b0381111562000b41578283fd5b8301601f8101851362000b52578283fd5b805162000b6962000b638262000e25565b62000dfe565b818152838101908385018584028501860189101562000b86578687fd5b8694505b8385101562000baa57805183526001949094019391850191850162000b8a565b50979650505050505050565b60006020828403121562000bc8578081fd5b81518015158114620008ae578182fd5b60006020828403121562000bea578081fd5b5051919050565b60006020828403121562000c03578081fd5b815160ff81168114620008ae578182fd5b6000825162000c2881846020870162000e45565b9190910192915050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b8181101562000ca85783516001600160a01b03168352928401929184019160010162000c81565b50909695505050505050565b600060208252825180602084015262000cd581604085016020870162000e45565b601f01601f19169190910160400192915050565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606082015260800190565b6040518181016001600160401b038111828210171562000e1d57600080fd5b604052919050565b60006001600160401b0382111562000e3b578081fd5b5060209081020190565b60005b8381101562000e6257818101518382015260200162000e48565b8381111562000e72576000848401525b50505050565b6001600160a01b038116811462000e8e57600080fd5b50565b615fc88062000ea16000396000f3fe608060405234801561001057600080fd5b50600436106104335760003560e01c806373b3828511610236578063b2c5f6581161013b578063d3406abd116100c3578063ed882c2b11610087578063ed882c2b146107f1578063efbb5cb014610804578063f017c92f1461080c578063fbfa77cf1461081f578063fcf2d0ad1461082757610433565b8063d3406abd146107b3578063db2fd745146107bb578063e00425a3146107ce578063e0b8c948146107d6578063ec38a862146107de57610433565b8063c1bb4b541161010a578063c1bb4b5414610775578063c59848471461077d578063c7b9d53014610785578063cb1965dd14610798578063ce5494bb146107a057610433565b8063b2c5f6581461074a578063b2d0c8e214610752578063ba0ad98614610765578063bf83e0af1461076d57610433565b806391397ab4116101be5780639ec5a8941161018d5780639ec5a8941461070c578063ac00ff2614610714578063aced166114610727578063aef6679e1461072f578063b252720b1461074257610433565b806391397ab4146106d657806395e80c50146106e95780639a561fbf146106f15780639be8ef141461070457610433565b8063780022a011610205578063780022a014610698578063853e0a3b146106ab57806389be318a146106b35780638cdfe166146106c65780638e6350e2146106ce57610433565b806373b3828514610655578063748747e61461066a578063750521f51461067d578063775d35e51461069057610433565b80632e1a7d4d1161033c578063440368a3116102c45780635641ec03116102935780635641ec031461061757806356cdac2c1461061f578063650d1880146106325780636718835f1461064557806369e527da1461064d57610433565b8063440368a3146105e15780634641257d146105e9578063485cc955146105f157806354f809e31461060457610433565b8063396794cd1161030b578063396794cd1461059557806339a172a8146105a85780633e5f0ae8146105bb57806340f8bc43146105c3578063418f35cc146105cb57610433565b80632e1a7d4d146105495780633042087c1461055c5780633631ad5f1461056f5780633922b4a81461058257610433565b80631d12f28b116103bf57806322f3e2d41161038e57806322f3e2d41461050957806323e30c8b1461051e578063258294101461053157806327cc1ea21461053957806328b7ccf71461054157610433565b80631d12f28b146104dc5780631f1fcd51146104e45780631fe4a686146104f9578063205409d31461050157610433565b806305a82f9a1161040657806305a82f9a1461048857806306fdde031461049b5780630c17c733146104a35780630f969b87146104b657806311bc8245146104c957610433565b806301681a62146104385780630268ff0b1461044d57806303ee438c1461046b57806304324af814610480575b600080fd5b61044b6104463660046154f1565b61082f565b005b6104556109ce565b6040516104629190615af2565b60405180910390f35b6104736109f2565b6040516104629190615b2a565b610455610a80565b61044b6104963660046156b0565b610a86565b610473610aa1565b61044b6104b136600461585f565b610ac7565b61044b6104c436600461585f565b610ad4565b61044b6104d73660046154f1565b610b61565b610455610c62565b6104ec610c68565b60405161046291906159e5565b6104ec610c77565b610455610c86565b610511610c8c565b6040516104629190615a9b565b61045561052c3660046155a1565b610d2e565b610473610e24565b61044b610e43565b610455610ec3565b61045561055736600461585f565b610ec9565b61044b61056a36600461585f565b610f24565b61044b61057d36600461585f565b61104f565b61044b6105903660046156b0565b61105c565b61044b6105a336600461585f565b611080565b61044b6105b636600461585f565b6110ec565b61045561116e565b610511611174565b6105d361117d565b604051610462929190615e74565b61044b611243565b61044b61146c565b61044b6105ff366004615529565b611945565b61044b6106123660046156b0565b61195a565b6105116119ac565b61044b61062d3660046156b0565b6119b5565b61051161064036600461585f565b6119d0565b6105116119fd565b6104ec611a06565b61065d611a1a565b6040516104629190615e0f565b61044b6106783660046154f1565b611a2c565b61044b61068b36600461576d565b611ad7565b6105d3611b6e565b6104556106a636600461585f565b611c85565b610455611cba565b6104556106c1366004615561565b611f12565b610455611fd6565b610455611fdc565b61044b6106e436600461585f565b611fe1565b610455612063565b61044b6106ff36600461585f565b612069565b610455612122565b6104ec61215d565b61044b6107223660046156b0565b61216c565b6104ec612258565b61044b61073d36600461582b565b612267565b6104ec6122a7565b61065d6122bb565b61044b6107603660046156b0565b6122cd565b6105116122f3565b610511612302565b61045561230b565b610511612311565b61044b6107933660046154f1565b612321565b6105116123cc565b61044b6107ae3660046154f1565b6123da565b610455612525565b61044b6107c936600461585f565b6125e3565b6104556125f0565b6104ec6129fc565b61044b6107ec3660046154f1565b612a0b565b6105116107ff36600461585f565b612b9e565b610455612e28565b61044b61081a36600461585f565b612ef1565b6104ec612f73565b61044b612f82565b6108376132ff565b6001600160a01b0316336001600160a01b0316146108705760405162461bcd60e51b815260040161086790615cce565b60405180910390fd5b6006546001600160a01b038281169116141561089e5760405162461bcd60e51b815260040161086790615b62565b6002546001600160a01b03828116911614156108cc5760405162461bcd60e51b815260040161086790615c76565b60606108d661337c565b905060005b8151811015610931578181815181106108f057fe5b60200260200101516001600160a01b0316836001600160a01b031614156109295760405162461bcd60e51b815260040161086790615d3d565b6001016108db565b506109ca61093d6132ff565b6040516370a0823160e01b81526001600160a01b038516906370a08231906109699030906004016159e5565b60206040518083038186803b15801561098157600080fd5b505afa158015610995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b99190615755565b6001600160a01b0385169190613381565b5050565b60008060006109db61117d565b90925090506109ea82826133a0565b925050505b90565b6000805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610a785780601f10610a4d57610100808354040283529160200191610a78565b820191906000526020600020905b815481529060010190602001808311610a5b57829003601f168201915b505050505081565b60125481565b610a8e6133e2565b6011805460ff1916911515919091179055565b60408051808201909152600c81526b11d95b93195d90dbdb5c158d60a21b602082015290565b610acf6133e2565b600d55565b6003546001600160a01b0316331480610b055750610af06132ff565b6001600160a01b0316336001600160a01b0316145b610b215760405162461bcd60e51b815260040161086790615cce565b600a8190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a860090610b56908390615af2565b60405180910390a150565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610baf57600080fd5b505afa158015610bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be7919061550d565b6001600160a01b0316336001600160a01b03161480610c1e5750610c096132ff565b6001600160a01b0316336001600160a01b0316145b610c3a5760405162461bcd60e51b815260040161086790615cce565b600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600a5481565b6006546001600160a01b031681565b6003546001600160a01b031681565b60105481565b6002546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610cc19030906004016159e5565b6101206040518083038186803b158015610cda57600080fd5b505afa158015610cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1291906157ad565b604001511180610d2957506000610d27612e28565b115b905090565b6000337360744434d6339a6b27d73d9eda62b6f66a0a04fa14610d5057600080fd5b6001600160a01b0387163014610d6557600080fd5b600080610d74848601866156e8565b600b546040516353cd344560e11b815292945090925073caa86f8df2ddca5c08fe81842900700f599a1b269163a79a688a91610dc79186918c91879161010090046001600160a01b031690600401615acc565b60206040518083038186803b158015610ddf57600080fd5b505af4158015610df3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e179190615755565b9998505050505050505050565b604080518082019091526005815264302e342e3360d81b602082015290565b610e4b6133e2565b600c546001600160a01b031673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f14610e8b5773d9e1ce17f2641f24ae83637ab66a2cca9c378b9f610ea1565b737a250d5630b4cf539739df2c5dacb4c659f2488d5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b60085481565b6002546000906001600160a01b03163314610ef65760405162461bcd60e51b815260040161086790615c56565b6000610f01836134d0565b600654909350909150610f1e906001600160a01b03163383613381565b50919050565b610f2c6133e2565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390610f60908490600401615af2565b602060405180830381600087803b158015610f7a57600080fd5b505af1158015610f8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb29190615755565b15610fbc57600080fd5b600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290610ff0908490600401615af2565b602060405180830381600087803b15801561100a57600080fd5b505af115801561101e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110429190615755565b1561104c57600080fd5b50565b6110576133e2565b601055565b6110646133e2565b60138054911515620100000262ff000019909216919091179055565b6110886132ff565b6001600160a01b0316336001600160a01b0316146110b85760405162461bcd60e51b815260040161086790615cce565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390610ff0908490600401615af2565b6003546001600160a01b031633148061111d57506111086132ff565b6001600160a01b0316336001600160a01b0316145b6111395760405162461bcd60e51b815260040161086790615cce565b60078190556040517fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190610b56908390615af2565b600d5481565b60115460ff1681565b600b546040516361bfb47160e11b8152600091829182918291829161010090046001600160a01b03169063c37f68e2906111bb9030906004016159e5565b60806040518083038186803b1580156111d357600080fd5b505afa1580156111e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120b9190615877565b9350935093505081935061123a670de0b6b3a7640000611234838661368090919063ffffffff16565b906132a6565b94505050509091565b6005546001600160a01b031633148061126657506003546001600160a01b031633145b8061128957506112746132ff565b6001600160a01b0316336001600160a01b0316145b8061132a5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156112dd57600080fd5b505afa1580156112f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611315919061550d565b6001600160a01b0316336001600160a01b0316145b806113cb5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561137e57600080fd5b505afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b6919061550d565b6001600160a01b0316336001600160a01b0316145b6113e75760405162461bcd60e51b815260040161086790615cce565b6002546040805163bf3759b560e01b8152905161146a926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561142d57600080fd5b505afa158015611441573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114659190615755565b6136ba565b565b6005546001600160a01b031633148061148f57506003546001600160a01b031633145b806114b2575061149d6132ff565b6001600160a01b0316336001600160a01b0316145b806115535750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561150657600080fd5b505afa15801561151a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153e919061550d565b6001600160a01b0316336001600160a01b0316145b806115f45750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156115a757600080fd5b505afa1580156115bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115df919061550d565b6001600160a01b0316336001600160a01b0316145b6116105760405162461bcd60e51b815260040161086790615cce565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561166357600080fd5b505afa158015611677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169b9190615755565b600b5490915060009060ff16156116f85760006116b6613843565b9050828110156116d1576116ca83826133a0565b93506116e6565b828111156116e6576116e381846133a0565b94505b6116f083856133a0565b915050611709565b61170182613918565b919550935090505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf8239061173a9030906004016159e5565b6101206040518083038186803b15801561175357600080fd5b505afa158015611767573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178b91906157ad565b60c001516002546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc906117c490889088908790600401615ea8565b602060405180830381600087803b1580156117de57600080fd5b505af11580156117f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118169190615755565b9250611821836136ba565b60015460ff168015611842575060015461010090046001600160a01b031615155b156118f45760015460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b906118839088908890879089908890600401615ed9565b60206040518083038186803b15801561189b57600080fd5b505afa1580156118af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d391906156cc565b6118ef5760405162461bcd60e51b815260040161086790615bb8565b611901565b6001805460ff1916811790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d509858584866040516119369493929190615ebe565b60405180910390a15050505050565b61195182333333613abf565b6109ca81613c78565b6119626132ff565b6001600160a01b0316336001600160a01b0316146119925760405162461bcd60e51b815260040161086790615cce565b601380549115156101000261ff0019909216919091179055565b600b5460ff1681565b6119bd6133e2565b6013805460ff1916911515919091179055565b60006119db82612b9e565b156119e8575060006119f8565b600f546119f3611cba565b111590505b919050565b60015460ff1681565b600b5461010090046001600160a01b031681565b600b54600160c81b900462ffffff1681565b6003546001600160a01b0316331480611a5d5750611a486132ff565b6001600160a01b0316336001600160a01b0316145b611a795760405162461bcd60e51b815260040161086790615cce565b6001600160a01b038116611a8c57600080fd5b600580546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490610b569083906159e5565b6003546001600160a01b0316331480611b085750611af36132ff565b6001600160a01b0316336001600160a01b0316145b611b245760405162461bcd60e51b815260040161086790615cce565b611b30600083836153b8565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda68282604051611b62929190615afb565b60405180910390a15050565b600b54604051633af9e66960e01b815260009182916101009091046001600160a01b031690633af9e66990611ba79030906004016159e5565b602060405180830381600087803b158015611bc157600080fd5b505af1158015611bd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf99190615755565b600b546040516395dd919360e01b815291935061010090046001600160a01b0316906395dd919390611c2f9030906004016159e5565b60206040518083038186803b158015611c4757600080fd5b505afa158015611c5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c7f9190615755565b90509091565b600654600090611cb49073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906001600160a01b031684611f12565b92915050565b600b54604051638e8f294b60e01b81526000918291733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91611d069161010090046001600160a01b0316906004016159e5565b60606040518083038186803b158015611d1e57600080fd5b505afa158015611d32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d569190615713565b50915050600080611d6561117d565b915091506000600b60019054906101000a90046001600160a01b03166001600160a01b031663f8f9da286040518163ffffffff1660e01b815260040160206040518083038186803b158015611db957600080fd5b505afa158015611dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df19190615755565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b031663ae9d70b06040518163ffffffff1660e01b815260040160206040518083038186803b158015611e4357600080fd5b505afa158015611e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7b9190615755565b90506000611e95670de0b6b3a76400006112348789613680565b9050806000611ea48686613680565b90506000611eb28386613680565b9050818110611ece5760001999505050505050505050506109ef565b6000611eda84896133a0565b90506000611ee884846133a0565b9050611f008161123484670de0b6b3a7640000613680565b9b5050505050505050505050506109ef565b600081611f2157506000611fcf565b600c546060906001600160a01b031663d06ca61f84611f408888614141565b6040518363ffffffff1660e01b8152600401611f5d929190615e1f565b60006040518083038186803b158015611f7557600080fd5b505afa158015611f89573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fb1919081019061561b565b905080600182510381518110611fc357fe5b60200260200101519150505b9392505050565b60095481565b600090565b6003546001600160a01b03163314806120125750611ffd6132ff565b6001600160a01b0316336001600160a01b0316145b61202e5760405162461bcd60e51b815260040161086790615cce565b60098190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec29890610b56908390615af2565b60075481565b6120716133e2565b600b54604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b916120bc916101009091046001600160a01b0316906004016159e5565b60606040518083038186803b1580156120d457600080fd5b505afa1580156120e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061210c9190615713565b5091505081811161211c57600080fd5b50600e55565b600080600061212f61117d565b915091508160001415612147576000925050506109ef565b6109ea82611234670de0b6b3a764000084613680565b6004546001600160a01b031681565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156121ba57600080fd5b505afa1580156121ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f2919061550d565b6001600160a01b0316336001600160a01b0316148061222957506122146132ff565b6001600160a01b0316336001600160a01b0316145b6122455760405162461bcd60e51b815260040161086790615cce565b6001805460ff1916911515919091179055565b6005546001600160a01b031681565b61226f6133e2565b600b805462ffffff928316600160c81b0262ffffff60c81b1994909316600160b01b0262ffffff60b01b199091161792909216179055565b60015461010090046001600160a01b031681565b600b54600160b01b900462ffffff1681565b6122d56133e2565b600b8054911515600160a81b0260ff60a81b19909216919091179055565b60135462010000900460ff1681565b60135460ff1681565b600e5481565b600b54600160a81b900460ff1681565b6003546001600160a01b0316331480612352575061233d6132ff565b6001600160a01b0316336001600160a01b0316145b61236e5760405162461bcd60e51b815260040161086790615cce565b6001600160a01b03811661238157600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490610b569083906159e5565b601354610100900460ff1681565b6002546001600160a01b031633146123f157600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b15801561243857600080fd5b505afa15801561244c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612470919061550d565b6001600160a01b03161461248357600080fd5b61248c816142c2565b6006546040516370a0823160e01b815261104c9183916001600160a01b03909116906370a08231906124c29030906004016159e5565b60206040518083038186803b1580156124da57600080fd5b505afa1580156124ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125129190615755565b6006546001600160a01b03169190613381565b600080612530612e28565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906125669030906004016159e5565b6101206040518083038186803b15801561257f57600080fd5b505afa158015612593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b791906157ad565b60c001519050818111156125d0576000925050506109ef565b6125da82826133a0565b925050506109ef565b6125eb6133e2565b601255565b60008060006125fd61117d565b915091508160001415612615576000925050506109ef565b600b54604051636aa875b560e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91636aa875b591612660916101009091046001600160a01b0316906004016159e5565b60206040518083038186803b15801561267857600080fd5b505afa15801561268c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b09190615755565b600b546040516303d290cf60e61b8152919250600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b9163f4a433c0916126fd9161010090046001600160a01b0316906004016159e5565b60206040518083038186803b15801561271557600080fd5b505afa158015612729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274d9190615755565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561279f57600080fd5b505afa1580156127b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127d79190615755565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561282957600080fd5b505afa15801561283d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128619190615755565b90506000612901670de0b6b3a7640000611234600b60019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b1580156128c257600080fd5b505afa1580156128d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128fa9190615755565b8590613680565b90506000811561291c57612919826112348a89613680565b90505b6000841561293557612932856112348a89613680565b90505b600061294183836143cc565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906129779030906004016159e5565b6101206040518083038186803b15801561299057600080fd5b505afa1580156129a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c891906157ad565b60a00151905060006129df600d61123442856133a0565b90506129eb8184613680565b9c5050505050505050505050505090565b600c546001600160a01b031681565b6003546001600160a01b03163314612a355760405162461bcd60e51b815260040161086790615b3d565b6001600160a01b038116612a4857600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b393612a7f939091169160009101615a6f565b602060405180830381600087803b158015612a9957600080fd5b505af1158015612aad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad191906156cc565b50600480546001600160a01b0319166001600160a01b038381169190911780835560025460405163095ea7b360e01b81529083169363095ea7b393612b1c9316916000199101615a6f565b602060405180830381600087803b158015612b3657600080fd5b505af1158015612b4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6e91906156cc565b507fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06981604051610b5691906159e5565b600080612baa83611c85565b9050612bb4615436565b6002546040516339ebf82360e01b81526001600160a01b03909116906339ebf82390612be49030906004016159e5565b6101206040518083038186803b158015612bfd57600080fd5b505afa158015612c11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3591906157ad565b9050806020015160001415612c4f576000925050506119f8565b60075460a0820151612c629042906133a0565b1015612c73576000925050506119f8565b60085460a0820151612c869042906133a0565b10612c96576001925050506119f8565b6002546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b158015612cdb57600080fd5b505afa158015612cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d139190615755565b9050600a54811115612d2b57600193505050506119f8565b6000612d35612e28565b90508260c00151612d51600a54836143cc90919063ffffffff16565b1015612d645760019450505050506119f8565b60008360c00151821115612d855760c0840151612d829083906133a0565b90505b6002546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b158015612dca57600080fd5b505afa158015612dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e029190615755565b9050612e0e81836143cc565b600954612e1b9088613680565b1098975050505050505050565b6000806000612e3561117d565b915091506000612e436125f0565b90506000612e6473c00e94cb662c3520282e6f5717214004a7f268886143f1565b600654909150600090612e9a9073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b03166106c186866143cc565b90506000612eae600a611234846009613680565b9050612ee685612ee083612eda8a612eda600660009054906101000a90046001600160a01b03166143f1565b906143cc565b906133a0565b965050505050505090565b6003546001600160a01b0316331480612f225750612f0d6132ff565b6001600160a01b0316336001600160a01b0316145b612f3e5760405162461bcd60e51b815260040161086790615cce565b60088190556040517f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590610b56908390615af2565b6002546001600160a01b031681565b6003546001600160a01b0316331480612fb35750612f9e6132ff565b6001600160a01b0316336001600160a01b0316145b806130545750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561300757600080fd5b505afa15801561301b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303f919061550d565b6001600160a01b0316336001600160a01b0316145b806130f55750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156130a857600080fd5b505afa1580156130bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e0919061550d565b6001600160a01b0316336001600160a01b0316145b6131115760405162461bcd60e51b815260040161086790615cce565b600b805460ff191660011790556002546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b15801561316457600080fd5b505af1158015613178573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b80158061322f5750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906131dd90309086906004016159f9565b60206040518083038186803b1580156131f557600080fd5b505afa158015613209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322d9190615755565b155b61324b5760405162461bcd60e51b815260040161086790615d61565b6132a18363095ea7b360e01b848460405160240161326a929190615a6f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614470565b505050565b6000611fcf83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506144ff565b60606132f78484600085614536565b949350505050565b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b15801561334457600080fd5b505afa158015613358573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d29919061550d565b606090565b6132a18363a9059cbb60e01b848460405160240161326a929190615a6f565b6000611fcf83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614604565b6133ea6132ff565b6001600160a01b0316336001600160a01b0316148061349f5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561345257600080fd5b505afa158015613466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348a919061550d565b6001600160a01b0316336001600160a01b0316145b806134b457506003546001600160a01b031633145b61146a5760405162461bcd60e51b815260040161086790615cce565b600654600090819081906134ec906001600160a01b03166143f1565b905060006134fc82612eda6109ce565b90506000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561354e57600080fd5b505afa158015613562573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135869190615755565b90508181111561359d5761359a81836133a0565b93505b6000806135a8611b6e565b915091508784101561361257600b546001906135d19061010090046001600160a01b03166143f1565b11156135eb576135e96135e483836133a0565b614630565b505b60065461360b908990613606906001600160a01b03166143f1565b614978565b965061362b565b87851015613627576135e96135e489876133a0565b8796505b8787101561365057600061363f89896133a0565b9050601054811161364e578096505b505b60135462010000900460ff16156136765761366b87876143cc565b881461367657600080fd5b5050505050915091565b60008261368f57506000611cb4565b8282028284828161369c57fe5b0414611fcf5760405162461bcd60e51b815260040161086790615c15565b600b5460ff16156136ca5761104c565b6006546000906136e2906001600160a01b03166143f1565b90508181101561372457600b546001906137099061010090046001600160a01b03166143f1565b111561371e5761371c6135e483836133a0565b505b5061104c565b60008061373b61373484866133a0565b600161498e565b9150915060105482111561383d5760135460ff1661378d5760005b8215613787576137706137698484614a80565b84906133a0565b92506006811061377f57613787565b600101613756565b5061383d565b73caa86f8df2ddca5c08fe81842900700f599a1b266370c0345c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156137d157600080fd5b505af41580156137e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138099190615755565b8211156138275761382461381d8383614a80565b83906133a0565b91505b60105482111561383d5761383b8183614bbc565b505b50505050565b60006138d3600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561389657600080fd5b505afa1580156138aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ce9190615755565b6134d0565b5090506000806138e161117d565b909250905060006138f283836133a0565b601354909150610100900460ff1661391257601054811061391257600080fd5b50505090565b600b54600090819081906139399061010090046001600160a01b03166143f1565b61396957600654600090613955906001600160a01b03166143f1565b90506139618186614978565b915050613ab8565b600080613974611b6e565b91509150613980614c5a565b613988614d2d565b6006546000906139a0906001600160a01b03166143f1565b905060006139ae84846133a0565b905060006139bc82846143cc565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906139f29030906004016159e5565b6101206040518083038186803b158015613a0b57600080fd5b505afa158015613a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a4391906157ad565b60c00151905080821115613a9857613a5b82826133a0565b985088841015613a6d57839850613a93565b613a77898b6143cc565b841115613a8657899650613a93565b613a90848a6133a0565b96505b613ab1565b613aa281836133a0565b9750613aae848b614978565b96505b5050505050505b9193909250565b6006546001600160a01b031615613ae85760405162461bcd60e51b815260040161086790615bde565b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b158015613b4457600080fd5b505afa158015613b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b7c919061550d565b600680546001600160a01b0319166001600160a01b039283161790819055613ba89116856000196131a7565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b393613c26939116916000199101615a6f565b602060405180830381600087803b158015613c4057600080fd5b505af1158015613c54573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061383b91906156cc565b80600b60016101000a8154816001600160a01b0302191690836001600160a01b031602179055506012600660009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015613cef57600080fd5b505afa158015613d03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d2791906158ac565b60ff161115613d3557600080fd5b600c80546001600160a01b03191673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f179055613d8d73c00e94cb662c3520282e6f5717214004a7f26888737a250d5630b4cf539739df2c5dacb4c659f2488d614f0c565b613dbf73c00e94cb662c3520282e6f5717214004a7f2688873d9e1ce17f2641f24ae83637ab66a2cca9c378b9f614f0c565b613df173c00e94cb662c3520282e6f5717214004a7f2688873e592427a0aece92de3edee1f18e0157c05861564614f0c565b600654600b54613e12916001600160a01b0390811691610100900416614f0c565b613e44736b175474e89094c44da98b954eedeac495271d0f7360744434d6339a6b27d73d9eda62b6f66a0a04fa614f0c565b600b5460609061010090046001600160a01b0316735d3a536e4d6dbd6114cc1ead35777bab948e364314613f3d576040805160028082526060820183529091602083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e364381600081518110613eb457fe5b6001600160a01b039283166020918202929092010152600b5482516101009091049091169082906001908110613ee657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050613f38736b175474e89094c44da98b954eedeac495271d0f735d3a536e4d6dbd6114cc1ead35777bab948e3643614f0c565b613fa0565b6040805160018082528183019092529060208083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e364381600081518110613f7f57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b604051631853304760e31b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b9063c299823890613fd7908490600401615a88565b600060405180830381600087803b158015613ff157600080fd5b505af1158015614005573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261402d919081019061561b565b50600b805462ffffff60b01b191661017760b31b1762ffffff60c81b191661017760cb1b1790556201518060085560646009556c0c9f2c9cd04674edea40000000600a556006546040805163313ce56760e01b8152905161410392620186a0926001600160a01b039091169163313ce56791600480820192602092909190829003018186803b1580156140bf57600080fd5b505afa1580156140d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140f791906158ac565b60ff16600a0a906132a6565b601055505067016345785d8a00006012556708be35a9807f0000600e55670a217b21de090000600d5561b5a4600f556013805460ff19166001179055565b606060006001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2148061418c57506001600160a01b03831673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b90508061419a57600361419d565b60025b60ff1667ffffffffffffffff811180156141b657600080fd5b506040519080825280602002602001820160405280156141e0578160200160208202803683370190505b50915083826000815181106141f157fe5b60200260200101906001600160a01b031690816001600160a01b031681525050801561424a57828260018151811061422557fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506142bb565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28260018151811061426c57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050828260028151811061429a57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b5092915050565b601354610100900460ff1661104c576000806142dc611b6e565b90925090506142ee6135e483836133a0565b50600b546040516361bfb47160e11b815260009161010090046001600160a01b03169063c37f68e2906143259030906004016159e5565b60806040518083038186803b15801561433d57600080fd5b505afa158015614351573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143759190615877565b5092505050612710811061438857600080fd5b73c00e94cb662c3520282e6f5717214004a7f2688860006143a8826143f1565b905080156143c4576143c46001600160a01b0383168783613381565b505050505050565b600082820183811015611fcf5760405162461bcd60e51b815260040161086790615b81565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906144209030906004016159e5565b60206040518083038186803b15801561443857600080fd5b505afa15801561444c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb49190615755565b60606144c5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132e89092919063ffffffff16565b8051909150156132a157808060200190518101906144e391906156cc565b6132a15760405162461bcd60e51b815260040161086790615cf3565b600081836145205760405162461bcd60e51b81526004016108679190615b2a565b50600083858161452c57fe5b0495945050505050565b606061454185614f22565b61455d5760405162461bcd60e51b815260040161086790615c97565b60006060866001600160a01b0316858760405161457a91906159c9565b60006040518083038185875af1925050503d80600081146145b7576040519150601f19603f3d011682016040523d82523d6000602084013e6145bc565b606091505b509150915081156145d05791506132f79050565b8051156145e05780518082602001fd5b8360405162461bcd60e51b81526004016108679190615b2a565b5050949350505050565b600081848411156146285760405162461bcd60e51b81526004016108679190615b2a565b505050900390565b600080600061464084600061498e565b91509150808015614652575060105482115b156146b85760135460ff16156146725761466f61381d8284614bbc565b91505b60005b6010546146839060646143cc565b8311156146b657614698613769846001614a80565b9250600101600560ff8216106146b157600193506146b6565b614675565b505b6000806146c361117d565b600e5491935091506000816146dd5766038d7ea4c6800091505b6146f38261123485670de0b6b3a7640000613680565b90508084106148bc57600061470885836133a0565b600b546040516370a0823160e01b81529192506000916101009091046001600160a01b0316906370a08231906147429030906004016159e5565b60206040518083038186803b15801561475a57600080fd5b505afa15801561476e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147929190615755565b905060018111156148b9578982101561483157600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e3906147d9908590600401615af2565b602060405180830381600087803b1580156147f357600080fd5b505af1158015614807573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061482b9190615755565b506148b9565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390614865908d90600401615af2565b602060405180830381600087803b15801561487f57600080fd5b505af1158015614893573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148b79190615755565b505b50505b600e541580156148e0575060065483906148de906001600160a01b03166143f1565b115b1561496d57600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290614919908690600401615af2565b602060405180830381600087803b15801561493357600080fd5b505af1158015614947573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061496b9190615755565b505b505050505050919050565b60008183106149875781611fcf565b5090919050565b60008060008061499c611b6e565b909250905060006149ad83836133a0565b9050600086156149c8576149c182896143cc565b90506149e1565b818811156149d4578197505b6149de82896133a0565b90505b60006149f8600e548361368090919063ffffffff16565b90506000614a19600e54670de0b6b3a76400006133a090919063ffffffff16565b90506000614a2783836132a6565b9050620186a0811115614a4457614a4181620186a06133a0565b90505b85811015614a615760019750614a5a86826133a0565b9850614a72565b60009750614a6f81876133a0565b98505b505050505050509250929050565b6000806000614a8d61117d565b91509150806000148015614a9e5750835b15614aae57600092505050611cb4565b600b54604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91614af9916101009091046001600160a01b0316906004016159e5565b60606040518083038186803b158015614b1157600080fd5b505afa158015614b25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b499190615713565b509150508415614b6657614b5f86848484614f5b565b9350614b75565b614b7286848484615174565b93505b7f012a05dea1e4b56be6c250aaa3e6189a1f531f1fd201b35b2a74c56577000bf48685876000604051614bab9493929190615e82565b60405180910390a150505092915050565b600654600d54604051633469949d60e01b815260009273caa86f8df2ddca5c08fe81842900700f599a1b2692633469949d92614c0a92889288926001600160a01b0390921691600401615aa6565b60206040518083038186803b158015614c2257600080fd5b505af4158015614c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fcf9190615755565b60115460ff1615614c6a5761146a565b60408051600180825281830190925260609160208083019080368337019050509050600b60019054906101000a90046001600160a01b031681600081518110614caf57fe5b6001600160a01b039092166020928302919091019091015260405162e1ed9760e51b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b90631c3db2e090614cff9030908590600401615a13565b600060405180830381600087803b158015614d1957600080fd5b505af115801561383b573d6000803e3d6000fd5b6000614d4c73c00e94cb662c3520282e6f5717214004a7f268886143f1565b9050601254811015614d5e575061146a565b600b54600160a81b900460ff1615614e57576040805160a0810190915260065473e592427a0aece92de3edee1f18e0157c058615649163c04b8d59918190614dc49073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b03166152e1565b8152602001306001600160a01b0316815260200142815260200184815260200160008152506040518263ffffffff1660e01b8152600401614e059190615db7565b602060405180830381600087803b158015614e1f57600080fd5b505af1158015614e33573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371e9190615755565b600c546006546001600160a01b03918216916338ed1739918491600091614e949173c00e94cb662c3520282e6f5717214004a7f268889116614141565b30426040518663ffffffff1660e01b8152600401614eb6959493929190615e38565b600060405180830381600087803b158015614ed057600080fd5b505af1158015614ee4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109ca919081019061561b565b6109ca6001600160a01b038316826000196131a7565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906132f7575050151592915050565b6000808215614f7d57614f7a8361123486670de0b6b3a7640000613680565b90505b614f8785826133a0565b9150838210614f94578391505b858210614f9f578591505b6000600b60019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015614fef57600080fd5b505afa158015615003573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150279190615755565b90508061503c84670de0b6b3a7640000613680565b1015801561504a5750600a83115b156145fa5761505a83600a6133a0565b600b5460405163852a12e360e01b815291945061010090046001600160a01b03169063852a12e390615090908690600401615af2565b602060405180830381600087803b1580156150aa57600080fd5b505af11580156150be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150e29190615755565b50600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290615117908690600401615af2565b602060405180830381600087803b15801561513157600080fd5b505af1158015615145573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151699190615755565b505050949350505050565b60008061518d670de0b6b3a76400006112348786613680565b905061519981856133a0565b91508582106151a6578591505b600a8211156152d8576151ba82600a6133a0565b600b5460405163317afabb60e21b815291935061010090046001600160a01b03169063c5ebeaec906151f0908590600401615af2565b602060405180830381600087803b15801561520a57600080fd5b505af115801561521e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906152429190615755565b50600b546006546001600160a01b0361010090920482169163a0712d689161526a91166143f1565b6040518263ffffffff1660e01b81526004016152869190615af2565b602060405180830381600087803b1580156152a057600080fd5b505af11580156152b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145fa9190615755565b50949350505050565b6006546060906001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561535b5782600b60169054906101000a900462ffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26040516020016153459392919061593c565b6040516020818303038152906040529050611cb4565b600b546040516153a191859162ffffff600160b01b830481169273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc292600160c81b909104909116908790602001615977565b604051602081830303815290604052905092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106153f95782800160ff19823516178555615426565b82800160010185558215615426579182015b8281111561542657823582559160200191906001019061540b565b50615432929150615482565b5090565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5b808211156154325760008155600101615483565b60008083601f8401126154a8578182fd5b50813567ffffffffffffffff8111156154bf578182fd5b6020830191508360208285010111156154d757600080fd5b9250929050565b803562ffffff81168114611cb457600080fd5b600060208284031215615502578081fd5b8135611fcf81615f6f565b60006020828403121561551e578081fd5b8151611fcf81615f6f565b6000806040838503121561553b578081fd5b823561554681615f6f565b9150602083013561555681615f6f565b809150509250929050565b600080600060608486031215615575578081fd5b833561558081615f6f565b9250602084013561559081615f6f565b929592945050506040919091013590565b60008060008060008060a087890312156155b9578182fd5b86356155c481615f6f565b955060208701356155d481615f6f565b94506040870135935060608701359250608087013567ffffffffffffffff8111156155fd578283fd5b61560989828a01615497565b979a9699509497509295939492505050565b6000602080838503121561562d578182fd5b825167ffffffffffffffff811115615643578283fd5b8301601f81018513615653578283fd5b805161566661566182615f23565b615efc565b8181528381019083850185840285018601891015615682578687fd5b8694505b838510156156a4578051835260019490940193918501918501615686565b50979650505050505050565b6000602082840312156156c1578081fd5b8135611fcf81615f84565b6000602082840312156156dd578081fd5b8151611fcf81615f84565b600080604083850312156156fa578182fd5b823561570581615f84565b946020939093013593505050565b600080600060608486031215615727578283fd5b835161573281615f84565b60208501516040860151919450925061574a81615f84565b809150509250925092565b600060208284031215615766578081fd5b5051919050565b6000806020838503121561577f578182fd5b823567ffffffffffffffff811115615795578283fd5b6157a185828601615497565b90969095509350505050565b60006101208083850312156157c0578182fd5b6157c981615efc565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b6000806040838503121561583d578182fd5b61584784846154de565b915061585684602085016154de565b90509250929050565b600060208284031215615870578081fd5b5035919050565b6000806000806080858703121561588c578182fd5b505082516020840151604085015160609095015191969095509092509050565b6000602082840312156158bd578081fd5b815160ff81168114611fcf578182fd5b6000815180845260208085019450808401835b838110156159055781516001600160a01b0316875295820195908201906001016158e0565b509495945050505050565b60008151808452615928816020860160208601615f43565b601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b6001600160e81b0319166014820152921b166017820152602b0190565b6bffffffffffffffffffffffff19606096871b811682526001600160e81b031960e896871b8116601484015294871b811660178301529290941b909216602b840152921b909116602e82015260420190565b600082516159db818460208701615f43565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b81811015615a61578551851683529483019491830191600101615a43565b509098975050505050505050565b6001600160a01b03929092168252602082015260400190565b600060208252611fcf60208301846158cd565b901515815260200190565b931515845260208401929092526001600160a01b03166040830152606082015260800190565b9315158452602084019290925260408301526001600160a01b0316606082015260800190565b90815260200190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b600060208252611fcf6020830184615910565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b600060208252825160a06020840152615dd360c0840182615910565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b62ffffff91909116815260200190565b6000838252604060208301526132f760408301846158cd565b600086825285602083015260a06040830152615e5760a08301866158cd565b6001600160a01b0394909416606083015250608001529392505050565b918252602082015260400190565b9384526020840192909252151560408301526001600160a01b0316606082015260800190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff81118282101715615f1b57600080fd5b604052919050565b600067ffffffffffffffff821115615f39578081fd5b5060209081020190565b60005b83811015615f5e578181015183820152602001615f46565b8381111561383d5750506000910152565b6001600160a01b038116811461104c57600080fd5b801515811461104c57600080fdfea26469706673582212205008b1a5eb901bc0cd0fd2f320b670b8ed0feb3f770e6c4e2ebec6e70c67eafb64736f6c634300060c0033000000000000000000000000da816459f1ab5631232fe5e97a05bbbb94970c950000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104335760003560e01c806373b3828511610236578063b2c5f6581161013b578063d3406abd116100c3578063ed882c2b11610087578063ed882c2b146107f1578063efbb5cb014610804578063f017c92f1461080c578063fbfa77cf1461081f578063fcf2d0ad1461082757610433565b8063d3406abd146107b3578063db2fd745146107bb578063e00425a3146107ce578063e0b8c948146107d6578063ec38a862146107de57610433565b8063c1bb4b541161010a578063c1bb4b5414610775578063c59848471461077d578063c7b9d53014610785578063cb1965dd14610798578063ce5494bb146107a057610433565b8063b2c5f6581461074a578063b2d0c8e214610752578063ba0ad98614610765578063bf83e0af1461076d57610433565b806391397ab4116101be5780639ec5a8941161018d5780639ec5a8941461070c578063ac00ff2614610714578063aced166114610727578063aef6679e1461072f578063b252720b1461074257610433565b806391397ab4146106d657806395e80c50146106e95780639a561fbf146106f15780639be8ef141461070457610433565b8063780022a011610205578063780022a014610698578063853e0a3b146106ab57806389be318a146106b35780638cdfe166146106c65780638e6350e2146106ce57610433565b806373b3828514610655578063748747e61461066a578063750521f51461067d578063775d35e51461069057610433565b80632e1a7d4d1161033c578063440368a3116102c45780635641ec03116102935780635641ec031461061757806356cdac2c1461061f578063650d1880146106325780636718835f1461064557806369e527da1461064d57610433565b8063440368a3146105e15780634641257d146105e9578063485cc955146105f157806354f809e31461060457610433565b8063396794cd1161030b578063396794cd1461059557806339a172a8146105a85780633e5f0ae8146105bb57806340f8bc43146105c3578063418f35cc146105cb57610433565b80632e1a7d4d146105495780633042087c1461055c5780633631ad5f1461056f5780633922b4a81461058257610433565b80631d12f28b116103bf57806322f3e2d41161038e57806322f3e2d41461050957806323e30c8b1461051e578063258294101461053157806327cc1ea21461053957806328b7ccf71461054157610433565b80631d12f28b146104dc5780631f1fcd51146104e45780631fe4a686146104f9578063205409d31461050157610433565b806305a82f9a1161040657806305a82f9a1461048857806306fdde031461049b5780630c17c733146104a35780630f969b87146104b657806311bc8245146104c957610433565b806301681a62146104385780630268ff0b1461044d57806303ee438c1461046b57806304324af814610480575b600080fd5b61044b6104463660046154f1565b61082f565b005b6104556109ce565b6040516104629190615af2565b60405180910390f35b6104736109f2565b6040516104629190615b2a565b610455610a80565b61044b6104963660046156b0565b610a86565b610473610aa1565b61044b6104b136600461585f565b610ac7565b61044b6104c436600461585f565b610ad4565b61044b6104d73660046154f1565b610b61565b610455610c62565b6104ec610c68565b60405161046291906159e5565b6104ec610c77565b610455610c86565b610511610c8c565b6040516104629190615a9b565b61045561052c3660046155a1565b610d2e565b610473610e24565b61044b610e43565b610455610ec3565b61045561055736600461585f565b610ec9565b61044b61056a36600461585f565b610f24565b61044b61057d36600461585f565b61104f565b61044b6105903660046156b0565b61105c565b61044b6105a336600461585f565b611080565b61044b6105b636600461585f565b6110ec565b61045561116e565b610511611174565b6105d361117d565b604051610462929190615e74565b61044b611243565b61044b61146c565b61044b6105ff366004615529565b611945565b61044b6106123660046156b0565b61195a565b6105116119ac565b61044b61062d3660046156b0565b6119b5565b61051161064036600461585f565b6119d0565b6105116119fd565b6104ec611a06565b61065d611a1a565b6040516104629190615e0f565b61044b6106783660046154f1565b611a2c565b61044b61068b36600461576d565b611ad7565b6105d3611b6e565b6104556106a636600461585f565b611c85565b610455611cba565b6104556106c1366004615561565b611f12565b610455611fd6565b610455611fdc565b61044b6106e436600461585f565b611fe1565b610455612063565b61044b6106ff36600461585f565b612069565b610455612122565b6104ec61215d565b61044b6107223660046156b0565b61216c565b6104ec612258565b61044b61073d36600461582b565b612267565b6104ec6122a7565b61065d6122bb565b61044b6107603660046156b0565b6122cd565b6105116122f3565b610511612302565b61045561230b565b610511612311565b61044b6107933660046154f1565b612321565b6105116123cc565b61044b6107ae3660046154f1565b6123da565b610455612525565b61044b6107c936600461585f565b6125e3565b6104556125f0565b6104ec6129fc565b61044b6107ec3660046154f1565b612a0b565b6105116107ff36600461585f565b612b9e565b610455612e28565b61044b61081a36600461585f565b612ef1565b6104ec612f73565b61044b612f82565b6108376132ff565b6001600160a01b0316336001600160a01b0316146108705760405162461bcd60e51b815260040161086790615cce565b60405180910390fd5b6006546001600160a01b038281169116141561089e5760405162461bcd60e51b815260040161086790615b62565b6002546001600160a01b03828116911614156108cc5760405162461bcd60e51b815260040161086790615c76565b60606108d661337c565b905060005b8151811015610931578181815181106108f057fe5b60200260200101516001600160a01b0316836001600160a01b031614156109295760405162461bcd60e51b815260040161086790615d3d565b6001016108db565b506109ca61093d6132ff565b6040516370a0823160e01b81526001600160a01b038516906370a08231906109699030906004016159e5565b60206040518083038186803b15801561098157600080fd5b505afa158015610995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b99190615755565b6001600160a01b0385169190613381565b5050565b60008060006109db61117d565b90925090506109ea82826133a0565b925050505b90565b6000805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610a785780601f10610a4d57610100808354040283529160200191610a78565b820191906000526020600020905b815481529060010190602001808311610a5b57829003601f168201915b505050505081565b60125481565b610a8e6133e2565b6011805460ff1916911515919091179055565b60408051808201909152600c81526b11d95b93195d90dbdb5c158d60a21b602082015290565b610acf6133e2565b600d55565b6003546001600160a01b0316331480610b055750610af06132ff565b6001600160a01b0316336001600160a01b0316145b610b215760405162461bcd60e51b815260040161086790615cce565b600a8190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a860090610b56908390615af2565b60405180910390a150565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610baf57600080fd5b505afa158015610bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be7919061550d565b6001600160a01b0316336001600160a01b03161480610c1e5750610c096132ff565b6001600160a01b0316336001600160a01b0316145b610c3a5760405162461bcd60e51b815260040161086790615cce565b600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600a5481565b6006546001600160a01b031681565b6003546001600160a01b031681565b60105481565b6002546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610cc19030906004016159e5565b6101206040518083038186803b158015610cda57600080fd5b505afa158015610cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1291906157ad565b604001511180610d2957506000610d27612e28565b115b905090565b6000337360744434d6339a6b27d73d9eda62b6f66a0a04fa14610d5057600080fd5b6001600160a01b0387163014610d6557600080fd5b600080610d74848601866156e8565b600b546040516353cd344560e11b815292945090925073caa86f8df2ddca5c08fe81842900700f599a1b269163a79a688a91610dc79186918c91879161010090046001600160a01b031690600401615acc565b60206040518083038186803b158015610ddf57600080fd5b505af4158015610df3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e179190615755565b9998505050505050505050565b604080518082019091526005815264302e342e3360d81b602082015290565b610e4b6133e2565b600c546001600160a01b031673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f14610e8b5773d9e1ce17f2641f24ae83637ab66a2cca9c378b9f610ea1565b737a250d5630b4cf539739df2c5dacb4c659f2488d5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b60085481565b6002546000906001600160a01b03163314610ef65760405162461bcd60e51b815260040161086790615c56565b6000610f01836134d0565b600654909350909150610f1e906001600160a01b03163383613381565b50919050565b610f2c6133e2565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390610f60908490600401615af2565b602060405180830381600087803b158015610f7a57600080fd5b505af1158015610f8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb29190615755565b15610fbc57600080fd5b600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290610ff0908490600401615af2565b602060405180830381600087803b15801561100a57600080fd5b505af115801561101e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110429190615755565b1561104c57600080fd5b50565b6110576133e2565b601055565b6110646133e2565b60138054911515620100000262ff000019909216919091179055565b6110886132ff565b6001600160a01b0316336001600160a01b0316146110b85760405162461bcd60e51b815260040161086790615cce565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390610ff0908490600401615af2565b6003546001600160a01b031633148061111d57506111086132ff565b6001600160a01b0316336001600160a01b0316145b6111395760405162461bcd60e51b815260040161086790615cce565b60078190556040517fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190610b56908390615af2565b600d5481565b60115460ff1681565b600b546040516361bfb47160e11b8152600091829182918291829161010090046001600160a01b03169063c37f68e2906111bb9030906004016159e5565b60806040518083038186803b1580156111d357600080fd5b505afa1580156111e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120b9190615877565b9350935093505081935061123a670de0b6b3a7640000611234838661368090919063ffffffff16565b906132a6565b94505050509091565b6005546001600160a01b031633148061126657506003546001600160a01b031633145b8061128957506112746132ff565b6001600160a01b0316336001600160a01b0316145b8061132a5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156112dd57600080fd5b505afa1580156112f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611315919061550d565b6001600160a01b0316336001600160a01b0316145b806113cb5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561137e57600080fd5b505afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b6919061550d565b6001600160a01b0316336001600160a01b0316145b6113e75760405162461bcd60e51b815260040161086790615cce565b6002546040805163bf3759b560e01b8152905161146a926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561142d57600080fd5b505afa158015611441573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114659190615755565b6136ba565b565b6005546001600160a01b031633148061148f57506003546001600160a01b031633145b806114b2575061149d6132ff565b6001600160a01b0316336001600160a01b0316145b806115535750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561150657600080fd5b505afa15801561151a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153e919061550d565b6001600160a01b0316336001600160a01b0316145b806115f45750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156115a757600080fd5b505afa1580156115bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115df919061550d565b6001600160a01b0316336001600160a01b0316145b6116105760405162461bcd60e51b815260040161086790615cce565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561166357600080fd5b505afa158015611677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169b9190615755565b600b5490915060009060ff16156116f85760006116b6613843565b9050828110156116d1576116ca83826133a0565b93506116e6565b828111156116e6576116e381846133a0565b94505b6116f083856133a0565b915050611709565b61170182613918565b919550935090505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf8239061173a9030906004016159e5565b6101206040518083038186803b15801561175357600080fd5b505afa158015611767573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178b91906157ad565b60c001516002546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc906117c490889088908790600401615ea8565b602060405180830381600087803b1580156117de57600080fd5b505af11580156117f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118169190615755565b9250611821836136ba565b60015460ff168015611842575060015461010090046001600160a01b031615155b156118f45760015460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b906118839088908890879089908890600401615ed9565b60206040518083038186803b15801561189b57600080fd5b505afa1580156118af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d391906156cc565b6118ef5760405162461bcd60e51b815260040161086790615bb8565b611901565b6001805460ff1916811790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d509858584866040516119369493929190615ebe565b60405180910390a15050505050565b61195182333333613abf565b6109ca81613c78565b6119626132ff565b6001600160a01b0316336001600160a01b0316146119925760405162461bcd60e51b815260040161086790615cce565b601380549115156101000261ff0019909216919091179055565b600b5460ff1681565b6119bd6133e2565b6013805460ff1916911515919091179055565b60006119db82612b9e565b156119e8575060006119f8565b600f546119f3611cba565b111590505b919050565b60015460ff1681565b600b5461010090046001600160a01b031681565b600b54600160c81b900462ffffff1681565b6003546001600160a01b0316331480611a5d5750611a486132ff565b6001600160a01b0316336001600160a01b0316145b611a795760405162461bcd60e51b815260040161086790615cce565b6001600160a01b038116611a8c57600080fd5b600580546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490610b569083906159e5565b6003546001600160a01b0316331480611b085750611af36132ff565b6001600160a01b0316336001600160a01b0316145b611b245760405162461bcd60e51b815260040161086790615cce565b611b30600083836153b8565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda68282604051611b62929190615afb565b60405180910390a15050565b600b54604051633af9e66960e01b815260009182916101009091046001600160a01b031690633af9e66990611ba79030906004016159e5565b602060405180830381600087803b158015611bc157600080fd5b505af1158015611bd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf99190615755565b600b546040516395dd919360e01b815291935061010090046001600160a01b0316906395dd919390611c2f9030906004016159e5565b60206040518083038186803b158015611c4757600080fd5b505afa158015611c5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c7f9190615755565b90509091565b600654600090611cb49073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906001600160a01b031684611f12565b92915050565b600b54604051638e8f294b60e01b81526000918291733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91611d069161010090046001600160a01b0316906004016159e5565b60606040518083038186803b158015611d1e57600080fd5b505afa158015611d32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d569190615713565b50915050600080611d6561117d565b915091506000600b60019054906101000a90046001600160a01b03166001600160a01b031663f8f9da286040518163ffffffff1660e01b815260040160206040518083038186803b158015611db957600080fd5b505afa158015611dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df19190615755565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b031663ae9d70b06040518163ffffffff1660e01b815260040160206040518083038186803b158015611e4357600080fd5b505afa158015611e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7b9190615755565b90506000611e95670de0b6b3a76400006112348789613680565b9050806000611ea48686613680565b90506000611eb28386613680565b9050818110611ece5760001999505050505050505050506109ef565b6000611eda84896133a0565b90506000611ee884846133a0565b9050611f008161123484670de0b6b3a7640000613680565b9b5050505050505050505050506109ef565b600081611f2157506000611fcf565b600c546060906001600160a01b031663d06ca61f84611f408888614141565b6040518363ffffffff1660e01b8152600401611f5d929190615e1f565b60006040518083038186803b158015611f7557600080fd5b505afa158015611f89573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fb1919081019061561b565b905080600182510381518110611fc357fe5b60200260200101519150505b9392505050565b60095481565b600090565b6003546001600160a01b03163314806120125750611ffd6132ff565b6001600160a01b0316336001600160a01b0316145b61202e5760405162461bcd60e51b815260040161086790615cce565b60098190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec29890610b56908390615af2565b60075481565b6120716133e2565b600b54604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b916120bc916101009091046001600160a01b0316906004016159e5565b60606040518083038186803b1580156120d457600080fd5b505afa1580156120e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061210c9190615713565b5091505081811161211c57600080fd5b50600e55565b600080600061212f61117d565b915091508160001415612147576000925050506109ef565b6109ea82611234670de0b6b3a764000084613680565b6004546001600160a01b031681565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156121ba57600080fd5b505afa1580156121ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f2919061550d565b6001600160a01b0316336001600160a01b0316148061222957506122146132ff565b6001600160a01b0316336001600160a01b0316145b6122455760405162461bcd60e51b815260040161086790615cce565b6001805460ff1916911515919091179055565b6005546001600160a01b031681565b61226f6133e2565b600b805462ffffff928316600160c81b0262ffffff60c81b1994909316600160b01b0262ffffff60b01b199091161792909216179055565b60015461010090046001600160a01b031681565b600b54600160b01b900462ffffff1681565b6122d56133e2565b600b8054911515600160a81b0260ff60a81b19909216919091179055565b60135462010000900460ff1681565b60135460ff1681565b600e5481565b600b54600160a81b900460ff1681565b6003546001600160a01b0316331480612352575061233d6132ff565b6001600160a01b0316336001600160a01b0316145b61236e5760405162461bcd60e51b815260040161086790615cce565b6001600160a01b03811661238157600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490610b569083906159e5565b601354610100900460ff1681565b6002546001600160a01b031633146123f157600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b15801561243857600080fd5b505afa15801561244c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612470919061550d565b6001600160a01b03161461248357600080fd5b61248c816142c2565b6006546040516370a0823160e01b815261104c9183916001600160a01b03909116906370a08231906124c29030906004016159e5565b60206040518083038186803b1580156124da57600080fd5b505afa1580156124ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125129190615755565b6006546001600160a01b03169190613381565b600080612530612e28565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906125669030906004016159e5565b6101206040518083038186803b15801561257f57600080fd5b505afa158015612593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b791906157ad565b60c001519050818111156125d0576000925050506109ef565b6125da82826133a0565b925050506109ef565b6125eb6133e2565b601255565b60008060006125fd61117d565b915091508160001415612615576000925050506109ef565b600b54604051636aa875b560e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91636aa875b591612660916101009091046001600160a01b0316906004016159e5565b60206040518083038186803b15801561267857600080fd5b505afa15801561268c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b09190615755565b600b546040516303d290cf60e61b8152919250600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b9163f4a433c0916126fd9161010090046001600160a01b0316906004016159e5565b60206040518083038186803b15801561271557600080fd5b505afa158015612729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274d9190615755565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561279f57600080fd5b505afa1580156127b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127d79190615755565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561282957600080fd5b505afa15801561283d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128619190615755565b90506000612901670de0b6b3a7640000611234600b60019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b1580156128c257600080fd5b505afa1580156128d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128fa9190615755565b8590613680565b90506000811561291c57612919826112348a89613680565b90505b6000841561293557612932856112348a89613680565b90505b600061294183836143cc565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906129779030906004016159e5565b6101206040518083038186803b15801561299057600080fd5b505afa1580156129a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c891906157ad565b60a00151905060006129df600d61123442856133a0565b90506129eb8184613680565b9c5050505050505050505050505090565b600c546001600160a01b031681565b6003546001600160a01b03163314612a355760405162461bcd60e51b815260040161086790615b3d565b6001600160a01b038116612a4857600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b393612a7f939091169160009101615a6f565b602060405180830381600087803b158015612a9957600080fd5b505af1158015612aad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad191906156cc565b50600480546001600160a01b0319166001600160a01b038381169190911780835560025460405163095ea7b360e01b81529083169363095ea7b393612b1c9316916000199101615a6f565b602060405180830381600087803b158015612b3657600080fd5b505af1158015612b4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6e91906156cc565b507fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06981604051610b5691906159e5565b600080612baa83611c85565b9050612bb4615436565b6002546040516339ebf82360e01b81526001600160a01b03909116906339ebf82390612be49030906004016159e5565b6101206040518083038186803b158015612bfd57600080fd5b505afa158015612c11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3591906157ad565b9050806020015160001415612c4f576000925050506119f8565b60075460a0820151612c629042906133a0565b1015612c73576000925050506119f8565b60085460a0820151612c869042906133a0565b10612c96576001925050506119f8565b6002546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b158015612cdb57600080fd5b505afa158015612cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d139190615755565b9050600a54811115612d2b57600193505050506119f8565b6000612d35612e28565b90508260c00151612d51600a54836143cc90919063ffffffff16565b1015612d645760019450505050506119f8565b60008360c00151821115612d855760c0840151612d829083906133a0565b90505b6002546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b158015612dca57600080fd5b505afa158015612dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e029190615755565b9050612e0e81836143cc565b600954612e1b9088613680565b1098975050505050505050565b6000806000612e3561117d565b915091506000612e436125f0565b90506000612e6473c00e94cb662c3520282e6f5717214004a7f268886143f1565b600654909150600090612e9a9073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b03166106c186866143cc565b90506000612eae600a611234846009613680565b9050612ee685612ee083612eda8a612eda600660009054906101000a90046001600160a01b03166143f1565b906143cc565b906133a0565b965050505050505090565b6003546001600160a01b0316331480612f225750612f0d6132ff565b6001600160a01b0316336001600160a01b0316145b612f3e5760405162461bcd60e51b815260040161086790615cce565b60088190556040517f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590610b56908390615af2565b6002546001600160a01b031681565b6003546001600160a01b0316331480612fb35750612f9e6132ff565b6001600160a01b0316336001600160a01b0316145b806130545750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561300757600080fd5b505afa15801561301b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303f919061550d565b6001600160a01b0316336001600160a01b0316145b806130f55750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156130a857600080fd5b505afa1580156130bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e0919061550d565b6001600160a01b0316336001600160a01b0316145b6131115760405162461bcd60e51b815260040161086790615cce565b600b805460ff191660011790556002546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b15801561316457600080fd5b505af1158015613178573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b80158061322f5750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906131dd90309086906004016159f9565b60206040518083038186803b1580156131f557600080fd5b505afa158015613209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322d9190615755565b155b61324b5760405162461bcd60e51b815260040161086790615d61565b6132a18363095ea7b360e01b848460405160240161326a929190615a6f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614470565b505050565b6000611fcf83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506144ff565b60606132f78484600085614536565b949350505050565b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b15801561334457600080fd5b505afa158015613358573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d29919061550d565b606090565b6132a18363a9059cbb60e01b848460405160240161326a929190615a6f565b6000611fcf83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614604565b6133ea6132ff565b6001600160a01b0316336001600160a01b0316148061349f5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561345257600080fd5b505afa158015613466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348a919061550d565b6001600160a01b0316336001600160a01b0316145b806134b457506003546001600160a01b031633145b61146a5760405162461bcd60e51b815260040161086790615cce565b600654600090819081906134ec906001600160a01b03166143f1565b905060006134fc82612eda6109ce565b90506000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561354e57600080fd5b505afa158015613562573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135869190615755565b90508181111561359d5761359a81836133a0565b93505b6000806135a8611b6e565b915091508784101561361257600b546001906135d19061010090046001600160a01b03166143f1565b11156135eb576135e96135e483836133a0565b614630565b505b60065461360b908990613606906001600160a01b03166143f1565b614978565b965061362b565b87851015613627576135e96135e489876133a0565b8796505b8787101561365057600061363f89896133a0565b9050601054811161364e578096505b505b60135462010000900460ff16156136765761366b87876143cc565b881461367657600080fd5b5050505050915091565b60008261368f57506000611cb4565b8282028284828161369c57fe5b0414611fcf5760405162461bcd60e51b815260040161086790615c15565b600b5460ff16156136ca5761104c565b6006546000906136e2906001600160a01b03166143f1565b90508181101561372457600b546001906137099061010090046001600160a01b03166143f1565b111561371e5761371c6135e483836133a0565b505b5061104c565b60008061373b61373484866133a0565b600161498e565b9150915060105482111561383d5760135460ff1661378d5760005b8215613787576137706137698484614a80565b84906133a0565b92506006811061377f57613787565b600101613756565b5061383d565b73caa86f8df2ddca5c08fe81842900700f599a1b266370c0345c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156137d157600080fd5b505af41580156137e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138099190615755565b8211156138275761382461381d8383614a80565b83906133a0565b91505b60105482111561383d5761383b8183614bbc565b505b50505050565b60006138d3600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561389657600080fd5b505afa1580156138aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ce9190615755565b6134d0565b5090506000806138e161117d565b909250905060006138f283836133a0565b601354909150610100900460ff1661391257601054811061391257600080fd5b50505090565b600b54600090819081906139399061010090046001600160a01b03166143f1565b61396957600654600090613955906001600160a01b03166143f1565b90506139618186614978565b915050613ab8565b600080613974611b6e565b91509150613980614c5a565b613988614d2d565b6006546000906139a0906001600160a01b03166143f1565b905060006139ae84846133a0565b905060006139bc82846143cc565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906139f29030906004016159e5565b6101206040518083038186803b158015613a0b57600080fd5b505afa158015613a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a4391906157ad565b60c00151905080821115613a9857613a5b82826133a0565b985088841015613a6d57839850613a93565b613a77898b6143cc565b841115613a8657899650613a93565b613a90848a6133a0565b96505b613ab1565b613aa281836133a0565b9750613aae848b614978565b96505b5050505050505b9193909250565b6006546001600160a01b031615613ae85760405162461bcd60e51b815260040161086790615bde565b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b158015613b4457600080fd5b505afa158015613b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b7c919061550d565b600680546001600160a01b0319166001600160a01b039283161790819055613ba89116856000196131a7565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b393613c26939116916000199101615a6f565b602060405180830381600087803b158015613c4057600080fd5b505af1158015613c54573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061383b91906156cc565b80600b60016101000a8154816001600160a01b0302191690836001600160a01b031602179055506012600660009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015613cef57600080fd5b505afa158015613d03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d2791906158ac565b60ff161115613d3557600080fd5b600c80546001600160a01b03191673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f179055613d8d73c00e94cb662c3520282e6f5717214004a7f26888737a250d5630b4cf539739df2c5dacb4c659f2488d614f0c565b613dbf73c00e94cb662c3520282e6f5717214004a7f2688873d9e1ce17f2641f24ae83637ab66a2cca9c378b9f614f0c565b613df173c00e94cb662c3520282e6f5717214004a7f2688873e592427a0aece92de3edee1f18e0157c05861564614f0c565b600654600b54613e12916001600160a01b0390811691610100900416614f0c565b613e44736b175474e89094c44da98b954eedeac495271d0f7360744434d6339a6b27d73d9eda62b6f66a0a04fa614f0c565b600b5460609061010090046001600160a01b0316735d3a536e4d6dbd6114cc1ead35777bab948e364314613f3d576040805160028082526060820183529091602083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e364381600081518110613eb457fe5b6001600160a01b039283166020918202929092010152600b5482516101009091049091169082906001908110613ee657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050613f38736b175474e89094c44da98b954eedeac495271d0f735d3a536e4d6dbd6114cc1ead35777bab948e3643614f0c565b613fa0565b6040805160018082528183019092529060208083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e364381600081518110613f7f57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b604051631853304760e31b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b9063c299823890613fd7908490600401615a88565b600060405180830381600087803b158015613ff157600080fd5b505af1158015614005573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261402d919081019061561b565b50600b805462ffffff60b01b191661017760b31b1762ffffff60c81b191661017760cb1b1790556201518060085560646009556c0c9f2c9cd04674edea40000000600a556006546040805163313ce56760e01b8152905161410392620186a0926001600160a01b039091169163313ce56791600480820192602092909190829003018186803b1580156140bf57600080fd5b505afa1580156140d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140f791906158ac565b60ff16600a0a906132a6565b601055505067016345785d8a00006012556708be35a9807f0000600e55670a217b21de090000600d5561b5a4600f556013805460ff19166001179055565b606060006001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2148061418c57506001600160a01b03831673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b90508061419a57600361419d565b60025b60ff1667ffffffffffffffff811180156141b657600080fd5b506040519080825280602002602001820160405280156141e0578160200160208202803683370190505b50915083826000815181106141f157fe5b60200260200101906001600160a01b031690816001600160a01b031681525050801561424a57828260018151811061422557fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506142bb565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28260018151811061426c57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050828260028151811061429a57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b5092915050565b601354610100900460ff1661104c576000806142dc611b6e565b90925090506142ee6135e483836133a0565b50600b546040516361bfb47160e11b815260009161010090046001600160a01b03169063c37f68e2906143259030906004016159e5565b60806040518083038186803b15801561433d57600080fd5b505afa158015614351573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143759190615877565b5092505050612710811061438857600080fd5b73c00e94cb662c3520282e6f5717214004a7f2688860006143a8826143f1565b905080156143c4576143c46001600160a01b0383168783613381565b505050505050565b600082820183811015611fcf5760405162461bcd60e51b815260040161086790615b81565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906144209030906004016159e5565b60206040518083038186803b15801561443857600080fd5b505afa15801561444c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb49190615755565b60606144c5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132e89092919063ffffffff16565b8051909150156132a157808060200190518101906144e391906156cc565b6132a15760405162461bcd60e51b815260040161086790615cf3565b600081836145205760405162461bcd60e51b81526004016108679190615b2a565b50600083858161452c57fe5b0495945050505050565b606061454185614f22565b61455d5760405162461bcd60e51b815260040161086790615c97565b60006060866001600160a01b0316858760405161457a91906159c9565b60006040518083038185875af1925050503d80600081146145b7576040519150601f19603f3d011682016040523d82523d6000602084013e6145bc565b606091505b509150915081156145d05791506132f79050565b8051156145e05780518082602001fd5b8360405162461bcd60e51b81526004016108679190615b2a565b5050949350505050565b600081848411156146285760405162461bcd60e51b81526004016108679190615b2a565b505050900390565b600080600061464084600061498e565b91509150808015614652575060105482115b156146b85760135460ff16156146725761466f61381d8284614bbc565b91505b60005b6010546146839060646143cc565b8311156146b657614698613769846001614a80565b9250600101600560ff8216106146b157600193506146b6565b614675565b505b6000806146c361117d565b600e5491935091506000816146dd5766038d7ea4c6800091505b6146f38261123485670de0b6b3a7640000613680565b90508084106148bc57600061470885836133a0565b600b546040516370a0823160e01b81529192506000916101009091046001600160a01b0316906370a08231906147429030906004016159e5565b60206040518083038186803b15801561475a57600080fd5b505afa15801561476e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147929190615755565b905060018111156148b9578982101561483157600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e3906147d9908590600401615af2565b602060405180830381600087803b1580156147f357600080fd5b505af1158015614807573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061482b9190615755565b506148b9565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390614865908d90600401615af2565b602060405180830381600087803b15801561487f57600080fd5b505af1158015614893573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148b79190615755565b505b50505b600e541580156148e0575060065483906148de906001600160a01b03166143f1565b115b1561496d57600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290614919908690600401615af2565b602060405180830381600087803b15801561493357600080fd5b505af1158015614947573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061496b9190615755565b505b505050505050919050565b60008183106149875781611fcf565b5090919050565b60008060008061499c611b6e565b909250905060006149ad83836133a0565b9050600086156149c8576149c182896143cc565b90506149e1565b818811156149d4578197505b6149de82896133a0565b90505b60006149f8600e548361368090919063ffffffff16565b90506000614a19600e54670de0b6b3a76400006133a090919063ffffffff16565b90506000614a2783836132a6565b9050620186a0811115614a4457614a4181620186a06133a0565b90505b85811015614a615760019750614a5a86826133a0565b9850614a72565b60009750614a6f81876133a0565b98505b505050505050509250929050565b6000806000614a8d61117d565b91509150806000148015614a9e5750835b15614aae57600092505050611cb4565b600b54604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91614af9916101009091046001600160a01b0316906004016159e5565b60606040518083038186803b158015614b1157600080fd5b505afa158015614b25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b499190615713565b509150508415614b6657614b5f86848484614f5b565b9350614b75565b614b7286848484615174565b93505b7f012a05dea1e4b56be6c250aaa3e6189a1f531f1fd201b35b2a74c56577000bf48685876000604051614bab9493929190615e82565b60405180910390a150505092915050565b600654600d54604051633469949d60e01b815260009273caa86f8df2ddca5c08fe81842900700f599a1b2692633469949d92614c0a92889288926001600160a01b0390921691600401615aa6565b60206040518083038186803b158015614c2257600080fd5b505af4158015614c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fcf9190615755565b60115460ff1615614c6a5761146a565b60408051600180825281830190925260609160208083019080368337019050509050600b60019054906101000a90046001600160a01b031681600081518110614caf57fe5b6001600160a01b039092166020928302919091019091015260405162e1ed9760e51b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b90631c3db2e090614cff9030908590600401615a13565b600060405180830381600087803b158015614d1957600080fd5b505af115801561383b573d6000803e3d6000fd5b6000614d4c73c00e94cb662c3520282e6f5717214004a7f268886143f1565b9050601254811015614d5e575061146a565b600b54600160a81b900460ff1615614e57576040805160a0810190915260065473e592427a0aece92de3edee1f18e0157c058615649163c04b8d59918190614dc49073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b03166152e1565b8152602001306001600160a01b0316815260200142815260200184815260200160008152506040518263ffffffff1660e01b8152600401614e059190615db7565b602060405180830381600087803b158015614e1f57600080fd5b505af1158015614e33573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371e9190615755565b600c546006546001600160a01b03918216916338ed1739918491600091614e949173c00e94cb662c3520282e6f5717214004a7f268889116614141565b30426040518663ffffffff1660e01b8152600401614eb6959493929190615e38565b600060405180830381600087803b158015614ed057600080fd5b505af1158015614ee4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109ca919081019061561b565b6109ca6001600160a01b038316826000196131a7565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906132f7575050151592915050565b6000808215614f7d57614f7a8361123486670de0b6b3a7640000613680565b90505b614f8785826133a0565b9150838210614f94578391505b858210614f9f578591505b6000600b60019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015614fef57600080fd5b505afa158015615003573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150279190615755565b90508061503c84670de0b6b3a7640000613680565b1015801561504a5750600a83115b156145fa5761505a83600a6133a0565b600b5460405163852a12e360e01b815291945061010090046001600160a01b03169063852a12e390615090908690600401615af2565b602060405180830381600087803b1580156150aa57600080fd5b505af11580156150be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150e29190615755565b50600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290615117908690600401615af2565b602060405180830381600087803b15801561513157600080fd5b505af1158015615145573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151699190615755565b505050949350505050565b60008061518d670de0b6b3a76400006112348786613680565b905061519981856133a0565b91508582106151a6578591505b600a8211156152d8576151ba82600a6133a0565b600b5460405163317afabb60e21b815291935061010090046001600160a01b03169063c5ebeaec906151f0908590600401615af2565b602060405180830381600087803b15801561520a57600080fd5b505af115801561521e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906152429190615755565b50600b546006546001600160a01b0361010090920482169163a0712d689161526a91166143f1565b6040518263ffffffff1660e01b81526004016152869190615af2565b602060405180830381600087803b1580156152a057600080fd5b505af11580156152b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145fa9190615755565b50949350505050565b6006546060906001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561535b5782600b60169054906101000a900462ffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26040516020016153459392919061593c565b6040516020818303038152906040529050611cb4565b600b546040516153a191859162ffffff600160b01b830481169273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc292600160c81b909104909116908790602001615977565b604051602081830303815290604052905092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106153f95782800160ff19823516178555615426565b82800160010185558215615426579182015b8281111561542657823582559160200191906001019061540b565b50615432929150615482565b5090565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5b808211156154325760008155600101615483565b60008083601f8401126154a8578182fd5b50813567ffffffffffffffff8111156154bf578182fd5b6020830191508360208285010111156154d757600080fd5b9250929050565b803562ffffff81168114611cb457600080fd5b600060208284031215615502578081fd5b8135611fcf81615f6f565b60006020828403121561551e578081fd5b8151611fcf81615f6f565b6000806040838503121561553b578081fd5b823561554681615f6f565b9150602083013561555681615f6f565b809150509250929050565b600080600060608486031215615575578081fd5b833561558081615f6f565b9250602084013561559081615f6f565b929592945050506040919091013590565b60008060008060008060a087890312156155b9578182fd5b86356155c481615f6f565b955060208701356155d481615f6f565b94506040870135935060608701359250608087013567ffffffffffffffff8111156155fd578283fd5b61560989828a01615497565b979a9699509497509295939492505050565b6000602080838503121561562d578182fd5b825167ffffffffffffffff811115615643578283fd5b8301601f81018513615653578283fd5b805161566661566182615f23565b615efc565b8181528381019083850185840285018601891015615682578687fd5b8694505b838510156156a4578051835260019490940193918501918501615686565b50979650505050505050565b6000602082840312156156c1578081fd5b8135611fcf81615f84565b6000602082840312156156dd578081fd5b8151611fcf81615f84565b600080604083850312156156fa578182fd5b823561570581615f84565b946020939093013593505050565b600080600060608486031215615727578283fd5b835161573281615f84565b60208501516040860151919450925061574a81615f84565b809150509250925092565b600060208284031215615766578081fd5b5051919050565b6000806020838503121561577f578182fd5b823567ffffffffffffffff811115615795578283fd5b6157a185828601615497565b90969095509350505050565b60006101208083850312156157c0578182fd5b6157c981615efc565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b6000806040838503121561583d578182fd5b61584784846154de565b915061585684602085016154de565b90509250929050565b600060208284031215615870578081fd5b5035919050565b6000806000806080858703121561588c578182fd5b505082516020840151604085015160609095015191969095509092509050565b6000602082840312156158bd578081fd5b815160ff81168114611fcf578182fd5b6000815180845260208085019450808401835b838110156159055781516001600160a01b0316875295820195908201906001016158e0565b509495945050505050565b60008151808452615928816020860160208601615f43565b601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b6001600160e81b0319166014820152921b166017820152602b0190565b6bffffffffffffffffffffffff19606096871b811682526001600160e81b031960e896871b8116601484015294871b811660178301529290941b909216602b840152921b909116602e82015260420190565b600082516159db818460208701615f43565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b81811015615a61578551851683529483019491830191600101615a43565b509098975050505050505050565b6001600160a01b03929092168252602082015260400190565b600060208252611fcf60208301846158cd565b901515815260200190565b931515845260208401929092526001600160a01b03166040830152606082015260800190565b9315158452602084019290925260408301526001600160a01b0316606082015260800190565b90815260200190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b600060208252611fcf6020830184615910565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b600060208252825160a06020840152615dd360c0840182615910565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b62ffffff91909116815260200190565b6000838252604060208301526132f760408301846158cd565b600086825285602083015260a06040830152615e5760a08301866158cd565b6001600160a01b0394909416606083015250608001529392505050565b918252602082015260400190565b9384526020840192909252151560408301526001600160a01b0316606082015260800190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff81118282101715615f1b57600080fd5b604052919050565b600067ffffffffffffffff821115615f39578081fd5b5060209081020190565b60005b83811015615f5e578181015183820152602001615f46565b8381111561383d5750506000910152565b6001600160a01b038116811461104c57600080fd5b801515811461104c57600080fdfea26469706673582212205008b1a5eb901bc0cd0fd2f320b670b8ed0feb3f770e6c4e2ebec6e70c67eafb64736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000da816459f1ab5631232fe5e97a05bbbb94970c950000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643
-----Decoded View---------------
Arg [0] : _vault (address): 0xdA816459F1AB5631232FE5e97a05BBBb94970c95
Arg [1] : _cToken (address): 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000da816459f1ab5631232fe5e97a05bbbb94970c95
Arg [1] : 0000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643
Deployed Bytecode Sourcemap
86459:32000:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72923:444;;;;;;:::i;:::-;;:::i;:::-;;99069:172;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;44152:25;;;:::i;:::-;;;;;;;:::i;88193:28::-;;;:::i;91347:116::-;;;;;;:::i;:::-;;:::i;88689:103::-;;;:::i;92497:123::-;;;;;;:::i;:::-;;:::i;54525:175::-;;;;;;:::i;:::-;;:::i;50093:118::-;;;;;;:::i;:::-;;:::i;47431:28::-;;;:::i;46179:18::-;;;:::i;:::-;;;;;;;:::i;46088:25::-;;;:::i;88036:22::-;;;:::i;57927:148::-;;;:::i;:::-;;;;;;;:::i;117117:460::-;;;;;;:::i;:::-;;:::i;44551:91::-;;;:::i;91575:154::-;;;:::i;47067:29::-;;;:::i;69327:515::-;;;;;;:::i;:::-;;:::i;115863:177::-;;;;;;:::i;:::-;;:::i;92106:95::-;;;;;;:::i;:::-;;:::i;90985:140::-;;;;;;:::i;:::-;;:::i;116136:160::-;;;;;;:::i;:::-;;:::i;52574:154::-;;;;;;:::i;:::-;;:::i;87793:29::-;;;:::i;88128:25::-;;;:::i;98365:317::-;;;:::i;:::-;;;;;;;;:::i;63024:170::-;;;:::i;67503:1580::-;;;:::i;88800:171::-;;;;;;:::i;:::-;;:::i;91869:102::-;;;;;;:::i;:::-;;:::i;47510:25::-;;;:::i;91737:124::-;;;;;;:::i;:::-;;:::i;94347:278::-;;;;;;:::i;:::-;;:::i;44208:25::-;;;:::i;87178:21::-;;;:::i;87344:31::-;;;:::i;:::-;;;;;;;:::i;51331:174::-;;;;;;:::i;:::-;;:::i;55003:171::-;;;;;;:::i;:::-;;:::i;98719:313::-;;;:::i;117630:145::-;;;;;;:::i;:::-;;:::i;95549:935::-;;;:::i;94711:356::-;;;;;;:::i;:::-;;:::i;47253:27::-;;;:::i;45958:94::-;;;:::i;53799:169::-;;;;;;:::i;:::-;;:::i;46916:29::-;;;:::i;92209:280::-;;;;;;:::i;:::-;;:::i;116850:259::-;;;:::i;46120:22::-;;;:::i;50219:123::-;;;;;;:::i;:::-;;:::i;46149:21::-;;;:::i;91133:206::-;;;;;;:::i;:::-;;:::i;44240:26::-;;;:::i;87306:31::-;;;:::i;91471:96::-;;;;;;:::i;:::-;;:::i;88379:31::-;;;:::i;88267:27::-;;;:::i;87829:31::-;;;:::i;87208:20::-;;;:::i;50575:202::-;;;;;;:::i;:::-;;:::i;88348:24::-;;;:::i;70614:281::-;;;;;;:::i;:::-;;:::i;93704:327::-;;;:::i;91979:119::-;;;;;;:::i;:::-;;:::i;96658:1479::-;;;:::i;87382:41::-;;;:::i;51794:263::-;;;;;;:::i;:::-;;:::i;64961:1736::-;;;;;;:::i;:::-;;:::i;92869:642::-;;;:::i;53245:154::-;;;;;;:::i;:::-;;:::i;46060:21::-;;;:::i;71324:173::-;;;:::i;72923:444::-;48136:12;:10;:12::i;:::-;-1:-1:-1;;;;;48122:26:0;:10;:26;48114:50;;;;-1:-1:-1;;;48114:50:0;;;;;;;:::i;:::-;;;;;;;;;73015:4:::1;::::0;-1:-1:-1;;;;;72997:23:0;;::::1;73015:4:::0;::::1;72997:23;;72989:41;;;::::0;-1:-1:-1;;;72989:41:0;;::::1;::::0;::::1;;;:::i;:::-;73067:5;::::0;-1:-1:-1;;;;;73049:24:0;;::::1;73067:5:::0;::::1;73049:24;;73041:44;;;::::0;-1:-1:-1;;;73041:44:0;;::::1;::::0;::::1;;;:::i;:::-;73098:33;73134:17;:15;:17::i;:::-;73098:53;;73167:9;73162:102;73182:16;:23;73178:1;:27;73162:102;;;73230:16;73247:1;73230:19;;;;;;;;;::::0;;::::1;::::0;;;;;;-1:-1:-1;;;;;73220:29:0;;::::1;::::0;::::1;;;73212:52;;;::::0;-1:-1:-1;;;73212:52:0;;::::1;::::0;::::1;;;:::i;:::-;73207:3;;73162:102;;;;73277:82;73305:12;:10;:12::i;:::-;73319:39;::::0;-1:-1:-1;;;73319:39:0;;-1:-1:-1;;;;;73319:24:0;::::1;::::0;-1:-1:-1;;73319:39:0::1;::::0;73352:4:::1;::::0;73319:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;73277:27:0;::::1;::::0;;::::1;:82::i;:::-;48175:1;72923:444:::0;:::o;99069:172::-;99116:7;99137:16;99155:15;99174:20;:18;:20::i;:::-;99136:58;;-1:-1:-1;99136:58:0;-1:-1:-1;99212:21:0;99136:58;;99212:12;:21::i;:::-;99205:28;;;;99069:172;;:::o;44152:25::-;;;;;;;;;;;;;;;-1:-1:-1;;44152:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;88193:28::-;;;;:::o;91347:116::-;118424:12;:10;:12::i;:::-;91425:13:::1;:30:::0;;-1:-1:-1;;91425:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;91347:116::o;88689:103::-;88763:21;;;;;;;;;;;;-1:-1:-1;;;88763:21:0;;;;;88689:103::o;92497:123::-;118424:12;:10;:12::i;:::-;92580:14:::1;:32:::0;92497:123::o;54525:175::-;47621:10;;-1:-1:-1;;;;;47621:10:0;47607;:24;;:54;;;47649:12;:10;:12::i;:::-;-1:-1:-1;;;;;47635:26:0;:10;:26;47607:54;47599:78;;;;-1:-1:-1;;;47599:78:0;;;;;;;:::i;:::-;54610:13:::1;:30:::0;;;54656:36:::1;::::0;::::1;::::0;::::1;::::0;54626:14;;54656:36:::1;:::i;:::-;;;;;;;;54525:175:::0;:::o;50093:118::-;48593:5;;:18;;;-1:-1:-1;;;48593:18:0;;;;-1:-1:-1;;;;;48593:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;48579:32:0;:10;:32;;:62;;;48629:12;:10;:12::i;:::-;-1:-1:-1;;;;;48615:26:0;:10;:26;48579:62;48571:86;;;;-1:-1:-1;;;48571:86:0;;;;;;;:::i;:::-;50177:11:::1;:26:::0;;-1:-1:-1;;;;;50177:26:0;;;::::1;;;-1:-1:-1::0;;;;;;50177:26:0;;::::1;::::0;;;::::1;::::0;;50093:118::o;47431:28::-;;;;:::o;46179:18::-;;;-1:-1:-1;;;;;46179:18:0;;:::o;46088:25::-;;;-1:-1:-1;;;;;46088:25:0;;:::o;88036:22::-;;;;:::o;57927:148::-;57992:5;;:31;;-1:-1:-1;;;57992:31:0;;57968:4;;;;-1:-1:-1;;;;;57992:5:0;;;;-1:-1:-1;;57992:31:0;;58017:4;;57992:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;:45;:75;;;;58066:1;58041:22;:20;:22::i;:::-;:26;57992:75;57985:82;;57927:148;:::o;117117:460::-;117301:7;117329:10;80643:42;117329:33;117321:42;;;;;;117403:4;-1:-1:-1;;;;;117382:26:0;;;117374:35;;;;;;117421:12;;117457:33;;;;117468:4;117457:33;:::i;:::-;117562:6;;117510:59;;-1:-1:-1;;;117510:59:0;;117420:70;;-1:-1:-1;117420:70:0;;-1:-1:-1;117510:12:0;;:22;;:59;;117420:70;;117542:6;;117420:70;;117562:6;;;-1:-1:-1;;;;;117562:6:0;;117510:59;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;117503:66;117117:460;-1:-1:-1;;;;;;;;;117117:460:0:o;44551:91::-;44620:14;;;;;;;;;;;;-1:-1:-1;;;44620:14:0;;;;;44551:91::o;91575:154::-;118424:12;:10;:12::i;:::-;91653:15:::1;::::0;-1:-1:-1;;;;;91653:15:0::1;87624:42;91653:34;:68;;87624:42;91653:68;;;87501:42;91653:68;91635:15;:86:::0;;-1:-1:-1;;;;;;91635:86:0::1;-1:-1:-1::0;;;;;91635:86:0;;;::::1;::::0;;;::::1;::::0;;91575:154::o;47067:29::-;;;;:::o;69327:515::-;69442:5;;69386:13;;-1:-1:-1;;;;;69442:5:0;69420:10;:28;69412:47;;;;-1:-1:-1;;;69412:47:0;;;;;;;:::i;:::-;69545:19;69598:32;69616:13;69598:17;:32::i;:::-;69722:4;;69575:55;;-1:-1:-1;69575:55:0;;-1:-1:-1;69722:42:0;;-1:-1:-1;;;;;69722:4:0;69740:10;69575:55;69722:17;:42::i;:::-;69327:515;;;;:::o;115863:177::-;118424:12;:10;:12::i;:::-;115944:6:::1;::::0;:31:::1;::::0;-1:-1:-1;;;115944:31:0;;:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;115944:6:0::1;::::0;-1:-1:-1;;115944:31:0::1;::::0;115968:6;;115944:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:36:::0;115936:45:::1;;;::::0;::::1;;116000:6;::::0;:26:::1;::::0;-1:-1:-1;;;116000:26:0;;:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;116000:6:0::1;::::0;:18:::1;::::0;:26:::1;::::0;116019:6;;116000:26:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:31:::0;115992:40:::1;;;::::0;::::1;;115863:177:::0;:::o;92106:95::-;118424:12;:10;:12::i;:::-;92175:7:::1;:18:::0;92106:95::o;90985:140::-;118424:12;:10;:12::i;:::-;91075:19:::1;:42:::0;;;::::1;;::::0;::::1;-1:-1:-1::0;;91075:42:0;;::::1;::::0;;;::::1;::::0;;90985:140::o;116136:160::-;48136:12;:10;:12::i;:::-;-1:-1:-1;;;;;48122:26:0;:10;:26;48114:50;;;;-1:-1:-1;;;48114:50:0;;;;;;;:::i;:::-;116222:6:::1;::::0;:31:::1;::::0;-1:-1:-1;;;116222:31:0;;:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;116222:6:0::1;::::0;-1:-1:-1;;116222:31:0::1;::::0;116246:6;;116222:31:::1;;;:::i;52574:154::-:0;47621:10;;-1:-1:-1;;;;;47621:10:0;47607;:24;;:54;;;47649:12;:10;:12::i;:::-;-1:-1:-1;;;;;47635:26:0;:10;:26;47607:54;47599:78;;;;-1:-1:-1;;;47599:78:0;;;;;;;:::i;:::-;52652:14:::1;:23:::0;;;52691:29:::1;::::0;::::1;::::0;::::1;::::0;52669:6;;52691:29:::1;:::i;87793:::-:0;;;;:::o;88128:25::-;;;;;;:::o;98365:317::-;98535:6;;:40;;-1:-1:-1;;;98535:40:0;;98416:16;;;;;;;;;;98535:6;;;-1:-1:-1;;;;;98535:6:0;;:25;;:40;;98569:4;;98535:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98462:113;;;;;;;98596:13;98586:23;;98633:41;98669:4;98633:31;98651:12;98633:13;:17;;:31;;;;:::i;:::-;:35;;:41::i;:::-;98622:52;;98365:317;;;;;:::o;63024:170::-;48262:6;;-1:-1:-1;;;;;48262:6:0;48248:10;:20;;:65;;-1:-1:-1;48303:10:0;;-1:-1:-1;;;;;48303:10:0;48289;:24;48248:65;:112;;;;48348:12;:10;:12::i;:::-;-1:-1:-1;;;;;48334:26:0;:10;:26;48248:112;:163;;;-1:-1:-1;48395:5:0;;:16;;;-1:-1:-1;;;48395:16:0;;;;-1:-1:-1;;;;;48395:5:0;;;;:14;;:16;;;;;;;;;;;;;;;:5;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;48381:30:0;:10;:30;48248:163;:216;;;-1:-1:-1;48446:5:0;;:18;;;-1:-1:-1;;;48446:18:0;;;;-1:-1:-1;;;;;48446:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;48432:32:0;:10;:32;48248:216;48226:277;;;;-1:-1:-1;;;48226:277:0;;;;;;;:::i;:::-;63162:5:::1;::::0;:23:::1;::::0;;-1:-1:-1;;;63162:23:0;;;;63147:39:::1;::::0;-1:-1:-1;;;;;63162:5:0::1;::::0;-1:-1:-1;;63162:23:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:5;:23;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63147:14;:39::i;:::-;63024:170::o:0;67503:1580::-;48262:6;;-1:-1:-1;;;;;48262:6:0;48248:10;:20;;:65;;-1:-1:-1;48303:10:0;;-1:-1:-1;;;;;48303:10:0;48289;:24;48248:65;:112;;;;48348:12;:10;:12::i;:::-;-1:-1:-1;;;;;48334:26:0;:10;:26;48248:112;:163;;;-1:-1:-1;48395:5:0;;:16;;;-1:-1:-1;;;48395:16:0;;;;-1:-1:-1;;;;;48395:5:0;;;;:14;;:16;;;;;;;;;;;;;;;:5;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;48381:30:0;:10;:30;48248:163;:216;;;-1:-1:-1;48446:5:0;;:18;;;-1:-1:-1;;;48446:18:0;;;;-1:-1:-1;;;;;48446:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;48432:32:0;:10;:32;48248:216;48226:277;;;;-1:-1:-1;;;48226:277:0;;;;;;;:::i;:::-;67636:5:::1;::::0;:23:::1;::::0;;-1:-1:-1;;;67636:23:0;;;;67554:14:::1;::::0;;;;;-1:-1:-1;;;;;67636:5:0;;::::1;::::0;:21:::1;::::0;:23:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;:5;:23;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67708:13;::::0;67610:49;;-1:-1:-1;67670:19:0::1;::::0;67708:13:::1;;67704:580;;;67790:19;67812:23;:21;:23::i;:::-;67790:45;;67868:15;67854:11;:29;67850:226;;;67911:32;:15:::0;67931:11;67911:19:::1;:32::i;:::-;67904:39;;67850:226;;;67983:15;67969:11;:29;67965:111;;;68028:32;:11:::0;68044:15;68028::::1;:32::i;:::-;68019:41;;67965:111;68104:25;:15:::0;68124:4;68104:19:::1;:25::i;:::-;68090:39;;67704:580;;;;68242:30;68256:15;68242:13;:30::i;:::-;68212:60:::0;;-1:-1:-1;68212:60:0;-1:-1:-1;68212:60:0;-1:-1:-1;67704:580:0::1;68500:5;::::0;:31:::1;::::0;-1:-1:-1;;;68500:31:0;;68480:17:::1;::::0;-1:-1:-1;;;;;68500:5:0::1;::::0;-1:-1:-1;;68500:31:0::1;::::0;68525:4:::1;::::0;68500:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;::::0;68570:5:::1;::::0;:39:::1;::::0;-1:-1:-1;;;68570:39:0;;68500:41;;-1:-1:-1;;;;;;68570:5:0::1;::::0;:12:::1;::::0;:39:::1;::::0;68583:6;;68591:4;;68597:11;;68570:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68552:57;;68685:31;68700:15;68685:14;:31::i;:::-;68771:13;::::0;::::1;;:42:::0;::::1;;;-1:-1:-1::0;68788:11:0::1;::::0;::::1;::::0;::::1;-1:-1:-1::0;;;;;68788:11:0::1;:25:::0;::::1;68771:42;68767:238;;;68850:11;::::0;68838:85:::1;::::0;-1:-1:-1;;;68838:85:0;;68850:11:::1;::::0;;::::1;-1:-1:-1::0;;;;;68850:11:0::1;::::0;-1:-1:-1;;68838:85:0::1;::::0;68869:6;;68877:4;;68883:11;;68896:15;;68913:9;;68838:85:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68830:110;;;::::0;-1:-1:-1;;;68830:110:0;;::::1;::::0;::::1;;;:::i;:::-;68767:238;;;68989:4;68973:20:::0;;-1:-1:-1;;68973:20:0::1;::::0;::::1;::::0;;68767:238:::1;69022:53;69032:6;69040:4;69046:11;69059:15;69022:53;;;;;;;;;:::i;:::-;;;;;;;;48514:1;;;;;67503:1580::o:0;88800:171::-;88873:55;88885:6;88893:10;88905;88917;88873:11;:55::i;:::-;88939:24;88955:7;88939:15;:24::i;91869:102::-;48136:12;:10;:12::i;:::-;-1:-1:-1;;;;;48122:26:0;:10;:26;48114:50;;;;-1:-1:-1;;;48114:50:0;;;;;;;:::i;:::-;91942:12:::1;:21:::0;;;::::1;;;;-1:-1:-1::0;;91942:21:0;;::::1;::::0;;;::::1;::::0;;91869:102::o;47510:25::-;;;;;;:::o;91737:124::-;118424:12;:10;:12::i;:::-;91819:15:::1;:34:::0;;-1:-1:-1;;91819:34:0::1;::::0;::::1;;::::0;;;::::1;::::0;;91737:124::o;94347:278::-;94415:4;94436:23;94451:7;94436:14;:23::i;:::-;94432:106;;;-1:-1:-1;94521:5:0;94514:12;;94432:106;94588:29;;94557:27;:25;:27::i;:::-;:60;;94550:67;;94347:278;;;;:::o;44208:25::-;;;;;;:::o;87178:21::-;;;;;;-1:-1:-1;;;;;87178:21:0;;:::o;87344:31::-;;;-1:-1:-1;;;87344:31:0;;;;;:::o;51331:174::-;47621:10;;-1:-1:-1;;;;;47621:10:0;47607;:24;;:54;;;47649:12;:10;:12::i;:::-;-1:-1:-1;;;;;47635:26:0;:10;:26;47607:54;47599:78;;;;-1:-1:-1;;;47599:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;51410:21:0;::::1;51402:30;;;::::0;::::1;;51443:6;:16:::0;;-1:-1:-1;;;;;;51443:16:0::1;-1:-1:-1::0;;;;;51443:16:0;::::1;;::::0;;51475:22:::1;::::0;::::1;::::0;::::1;::::0;51443:16;;51475:22:::1;:::i;55003:171::-:0;47621:10;;-1:-1:-1;;;;;47621:10:0;47607;:24;;:54;;;47649:12;:10;:12::i;:::-;-1:-1:-1;;;;;47635:26:0;:10;:26;47607:54;47599:78;;;;-1:-1:-1;;;47599:78:0;;;;;;;:::i;:::-;55092:26:::1;:11;55106:12:::0;;55092:26:::1;:::i;:::-;;55134:32;55153:12;;55134:32;;;;;;;:::i;:::-;;;;;;;;55003:171:::0;;:::o;98719:313::-;98819:6;;:41;;-1:-1:-1;;;98819:41:0;;98762:16;;;;98819:6;;;;-1:-1:-1;;;;;98819:6:0;;-1:-1:-1;;98819:41:0;;98854:4;;98819:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98983:6;;:41;;-1:-1:-1;;;98983:41:0;;98808:52;;-1:-1:-1;98983:6:0;;;-1:-1:-1;;;;;98983:6:0;;-1:-1:-1;;98983:41:0;;99018:4;;98983:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98973:51;;98719:313;;:::o;117630:145::-;117750:4;;117698:7;;117725:42;;87129;;-1:-1:-1;;;;;117750:4:0;117757:9;117725:10;:42::i;:::-;117718:49;117630:145;-1:-1:-1;;117630:145:0:o;95549:935::-;95693:6;;95668:33;;-1:-1:-1;;;95668:33:0;;95607:7;;;;86932:42;;-1:-1:-1;;95668:33:0;;95693:6;;;-1:-1:-1;;;;;95693:6:0;;95668:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95627:74;;;;95715:16;95733:15;95752:20;:18;:20::i;:::-;95807:6;;:27;;;-1:-1:-1;;;95807:27:0;;;;95714:58;;-1:-1:-1;95714:58:0;;-1:-1:-1;95785:19:0;;95807:6;;;;-1:-1:-1;;;;;95807:6:0;;:25;;:27;;;;;;;;;;;;;;:6;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95868:6;;:27;;;-1:-1:-1;;;95868:27:0;;;;95785:49;;-1:-1:-1;95847:18:0;;95868:6;;;;-1:-1:-1;;;;;95868:6:0;;:25;;:27;;;;;;;;;;;;;;;:6;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95847:48;-1:-1:-1;95908:30:0;95941:48;95984:4;95941:38;:8;95954:24;95941:12;:38::i;:48::-;95908:81;-1:-1:-1;95908:81:0;96000:29;96084:24;:7;96096:11;96084;:24::i;:::-;96067:41;-1:-1:-1;96119:14:0;96136:37;:21;96162:10;96136:25;:37::i;:::-;96119:54;;96200:6;96190;:16;96186:291;;-1:-1:-1;;96223:24:0;;;;;;;;;;;;;96186:291;96280:13;96296:34;:21;96322:7;96296:25;:34::i;:::-;96280:50;-1:-1:-1;96345:13:0;96361:18;:6;96372;96361:10;:18::i;:::-;96345:34;-1:-1:-1;96439:26:0;96345:34;96439:15;:5;96449:4;96439:9;:15::i;:26::-;96432:33;;;;;;;;;;;;;;;94711:356;94831:7;94855:12;94851:53;;-1:-1:-1;94891:1:0;94884:8;;94851:53;94943:15;;94916:24;;-1:-1:-1;;;;;94943:15:0;:29;94973:7;94982:29;95000:5;95007:3;94982:17;:29::i;:::-;94943:69;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;94943:69:0;;;;;;;;;;;;:::i;:::-;94916:96;;95032:7;95057:1;95040:7;:14;:18;95032:27;;;;;;;;;;;;;;95025:34;;;94711:356;;;;;;:::o;47253:27::-;;;;:::o;45958:94::-;46016:7;45958:94;:::o;53799:169::-;47621:10;;-1:-1:-1;;;;;47621:10:0;47607;:24;;:54;;;47649:12;:10;:12::i;:::-;-1:-1:-1;;;;;47635:26:0;:10;:26;47607:54;47599:78;;;;-1:-1:-1;;;47599:78:0;;;;;;;:::i;:::-;53882:12:::1;:28:::0;;;53926:34:::1;::::0;::::1;::::0;::::1;::::0;53897:13;;53926:34:::1;:::i;46916:29::-:0;;;;:::o;92209:280::-;118424:12;:10;:12::i;:::-;92362:6:::1;::::0;92337:33:::1;::::0;-1:-1:-1;;;92337:33:0;;92299:32:::1;::::0;86932:42:::1;::::0;-1:-1:-1;;92337:33:0::1;::::0;92362:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;92362:6:0::1;::::0;92337:33:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92296:74;;;;92416:17;92389:24;:44;92381:53;;;::::0;::::1;;-1:-1:-1::0;92445:16:0::1;:36:::0;92209:280::o;116850:259::-;116906:14;116934:12;116948:14;116966:20;:18;:20::i;:::-;116933:53;;;;117001:4;117009:1;117001:9;116997:50;;;117034:1;117027:8;;;;;;116997:50;117066:35;117096:4;117066:25;117074:4;117084:6;117066:17;:25::i;46120:22::-;;;-1:-1:-1;;;;;46120:22:0;;:::o;50219:123::-;48593:5;;:18;;;-1:-1:-1;;;48593:18:0;;;;-1:-1:-1;;;;;48593:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;48579:32:0;:10;:32;;:62;;;48629:12;:10;:12::i;:::-;-1:-1:-1;;;;;48615:26:0;:10;:26;48579:62;48571:86;;;;-1:-1:-1;;;48571:86:0;;;;;;;:::i;:::-;50304:13:::1;:30:::0;;-1:-1:-1;;50304:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;50219:123::o;46149:21::-;;;-1:-1:-1;;;;;46149:21:0;;:::o;91133:206::-;118424:12;:10;:12::i;:::-;91244:17:::1;:38:::0;;::::1;91293::::0;;::::1;-1:-1:-1::0;;;91293:38:0::1;-1:-1:-1::0;;;;91244:38:0;;;::::1;-1:-1:-1::0;;;91244:38:0::1;-1:-1:-1::0;;;;91244:38:0;;::::1;;91293::::0;;;::::1;;::::0;;91133:206::o;44240:26::-;;;;;;-1:-1:-1;;;;;44240:26:0;;:::o;87306:31::-;;;-1:-1:-1;;;87306:31:0;;;;;:::o;91471:96::-;118424:12;:10;:12::i;:::-;91539:8:::1;:20:::0;;;::::1;;-1:-1:-1::0;;;91539:20:0::1;-1:-1:-1::0;;;;91539:20:0;;::::1;::::0;;;::::1;::::0;;91471:96::o;88379:31::-;;;;;;;;;:::o;88267:27::-;;;;;;:::o;87829:31::-;;;;:::o;87208:20::-;;;-1:-1:-1;;;87208:20:0;;;;;:::o;50575:202::-;47621:10;;-1:-1:-1;;;;;47621:10:0;47607;:24;;:54;;;47649:12;:10;:12::i;:::-;-1:-1:-1;;;;;47635:26:0;:10;:26;47607:54;47599:78;;;;-1:-1:-1;;;47599:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;50662:25:0;::::1;50654:34;;;::::0;::::1;;50699:10;:24:::0;;-1:-1:-1;;;;;;50699:24:0::1;-1:-1:-1::0;;;;;50699:24:0;::::1;;::::0;;50739:30:::1;::::0;::::1;::::0;::::1;::::0;50699:24;;50739:30:::1;:::i;88348:24::-:0;;;;;;;;;:::o;70614:281::-;70703:5;;-1:-1:-1;;;;;70703:5:0;70681:10;:28;70673:37;;;;;;70767:5;;70729:34;;;-1:-1:-1;;;70729:34:0;;;;-1:-1:-1;;;;;70767:5:0;;;;70729:32;;;-1:-1:-1;;70729:34:0;;;;;;;;;;;;;;:32;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;70729:43:0;;70721:52;;;;;;70784:30;70801:12;70784:16;:30::i;:::-;70857:4;;:29;;-1:-1:-1;;;70857:29:0;;70825:62;;70843:12;;-1:-1:-1;;;;;70857:4:0;;;;-1:-1:-1;;70857:29:0;;70880:4;;70857:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70825:4;;-1:-1:-1;;;;;70825:4:0;;;:17;:62::i;93704:327::-;93751:7;93771:22;93796;:20;:22::i;:::-;93846:5;;:31;;-1:-1:-1;;;93846:31:0;;93771:47;;-1:-1:-1;93831:12:0;;-1:-1:-1;;;;;93846:5:0;;;;-1:-1:-1;;93846:31:0;;93871:4;;93846:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;93831:56;;93909:14;93902:4;:21;93898:126;;;93947:1;93940:8;;;;;;93898:126;93988:24;:14;94007:4;93988:18;:24::i;:::-;93981:31;;;;;;91979:119;118424:12;:10;:12::i;:::-;92060:13:::1;:30:::0;91979:119::o;96658:1479::-;96709:7;96730:16;96748:15;96767:20;:18;:20::i;:::-;96729:58;;;;96802:8;96814:1;96802:13;96798:122;;;96839:1;96832:8;;;;;;96798:122;97003:6;;96969:42;;-1:-1:-1;;;96969:42:0;;96932:34;;86932:42;;-1:-1:-1;;96969:42:0;;97003:6;;;;-1:-1:-1;;;;;97003:6:0;;96969:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97093:6;;97059:42;;-1:-1:-1;;;97059:42:0;;96932:79;;-1:-1:-1;97022:34:0;;86932:42;;97059:25;;:42;;97093:6;;;-1:-1:-1;;;;;97093:6:0;;97059:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97134:6;;:21;;;-1:-1:-1;;;97134:21:0;;;;97022:79;;-1:-1:-1;97112:19:0;;97134:6;;;;-1:-1:-1;;;;;97134:6:0;;:19;;:21;;;;;;;;;;;;;;;:6;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97275:6;;:20;;;-1:-1:-1;;;97275:20:0;;;;97112:43;;-1:-1:-1;97247:25:0;;97275:6;;;;-1:-1:-1;;;;;97275:6:0;;:18;;:20;;;;;;;;;;;;;;;:6;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97247:48;;97306:19;97328:60;97383:4;97328:50;97350:6;;;;;;;;;-1:-1:-1;;;;;97350:6:0;-1:-1:-1;;;;;97350:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97328:17;;:21;:50::i;:60::-;97306:82;-1:-1:-1;97401:24:0;97444:15;;97440:124;;97495:57;97540:11;97495:40;:8;97508:26;97495:12;:40::i;:57::-;97476:76;;97440:124;97576:24;97619:15;;97615:123;;97670:56;97714:11;97670:39;:7;97682:26;97670:11;:39::i;:56::-;97651:75;;97615:123;97798:18;97819:38;:16;97840;97819:20;:38::i;:::-;97927:5;;:31;;-1:-1:-1;;;97927:31:0;;97798:59;;-1:-1:-1;97906:18:0;;-1:-1:-1;;;;;97927:5:0;;;;-1:-1:-1;;97927:31:0;;97952:4;;97927:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;;;-1:-1:-1;97980:23:0;98006:41;98044:2;98007:31;:15;97927:42;98007:19;:31::i;98006:41::-;97980:67;-1:-1:-1;98098:31:0;97980:67;98118:10;98098:19;:31::i;:::-;98091:38;;;;;;;;;;;;;;96658:1479;:::o;87382:41::-;;;-1:-1:-1;;;;;87382:41:0;;:::o;51794:263::-;48023:10;;-1:-1:-1;;;;;48023:10:0;48009;:24;48001:48;;;;-1:-1:-1;;;48001:48:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;51875:22:0;::::1;51867:31;;;::::0;::::1;;51909:5;::::0;51923:7:::1;::::0;;51909:25:::1;::::0;-1:-1:-1;;;51909:25:0;;-1:-1:-1;;;;;51909:5:0;;::::1;::::0;-1:-1:-1;;51909:25:0::1;::::0;51923:7;;;::::1;::::0;51909:5:::1;::::0;:25:::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;51945:7:0::1;:18:::0;;-1:-1:-1;;;;;;51945:18:0::1;-1:-1:-1::0;;;;;51945:18:0;;::::1;::::0;;;::::1;::::0;;;51974:5:::1;::::0;:35:::1;::::0;-1:-1:-1;;;51974:35:0;;:5;;::::1;::::0;-1:-1:-1;;51974:35:0::1;::::0;51988:7:::1;::::0;-1:-1:-1;;;51974:35:0::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;52025:24;52040:8;52025:24;;;;;;:::i;64961:1736::-:0;65037:4;65054:16;65073:24;65083:13;65073:9;:24::i;:::-;65054:43;;65108:28;;:::i;:::-;65139:5;;:31;;-1:-1:-1;;;65139:31:0;;-1:-1:-1;;;;;65139:5:0;;;;-1:-1:-1;;65139:31:0;;65164:4;;65139:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;65108:62;;65247:6;:17;;;65268:1;65247:22;65243:40;;;65278:5;65271:12;;;;;;65243:40;65428:14;;65407:17;;;;65387:38;;:15;;:19;:38::i;:::-;:55;65383:73;;;65451:5;65444:12;;;;;;65383:73;65575:14;;65553:17;;;;65533:38;;:15;;:19;:38::i;:::-;:56;65529:73;;65598:4;65591:11;;;;;;65529:73;66032:5;;:23;;;-1:-1:-1;;;66032:23:0;;;;66010:19;;-1:-1:-1;;;;;66032:5:0;;-1:-1:-1;;66032:23:0;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66010:45;;66084:13;;66070:11;:27;66066:44;;;66106:4;66099:11;;;;;;;66066:44;66164:13;66180:22;:20;:22::i;:::-;66164:38;;66292:6;:16;;;66265:24;66275:13;;66265:5;:9;;:24;;;;:::i;:::-;:43;66261:60;;;66317:4;66310:11;;;;;;;;66261:60;66334:14;66375:6;:16;;;66367:5;:24;66363:66;;;66412:16;;;;66402:27;;:5;;:9;:27::i;:::-;66393:36;;66363:66;66599:5;;:23;;;-1:-1:-1;;;66599:23:0;;;;66582:14;;-1:-1:-1;;;;;66599:5:0;;-1:-1:-1;;66599:23:0;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66582:40;-1:-1:-1;66670:18:0;66582:40;66681:6;66670:10;:18::i;:::-;66641:12;;:26;;66658:8;66641:16;:26::i;:::-;:47;;64961:1736;-1:-1:-1;;;;;;;;64961:1736:0:o;92869:642::-;92931:7;92952:16;92970:15;92989:20;:18;:20::i;:::-;92951:58;;;;93022:22;93047:20;:18;:20::i;:::-;93022:45;;93078:19;93100:20;87048:42;93100:14;:20::i;:::-;93284:4;;93078:42;;-1:-1:-1;93235:21:0;;93259:64;;87048:42;;-1:-1:-1;;;;;93284:4:0;93291:31;:14;93078:42;93291:18;:31::i;93259:64::-;93235:88;-1:-1:-1;93334:24:0;93361:28;93386:2;93361:20;93235:88;93379:1;93361:17;:20::i;:28::-;93448:4;;93334:55;;-1:-1:-1;93425:78:0;;93495:7;;93425:65;;93334:55;;93425:43;;93459:8;;93425:43;;-1:-1:-1;;;;;93448:4:0;93425:14;:29::i;:::-;:33;;:43::i;:65::-;:69;;:78::i;:::-;93418:85;;;;;;;;92869:642;:::o;53245:154::-;47621:10;;-1:-1:-1;;;;;47621:10:0;47607;:24;;:54;;;47649:12;:10;:12::i;:::-;-1:-1:-1;;;;;47635:26:0;:10;:26;47607:54;47599:78;;;;-1:-1:-1;;;47599:78:0;;;;;;;:::i;:::-;53323:14:::1;:23:::0;;;53362:29:::1;::::0;::::1;::::0;::::1;::::0;53340:6;;53362:29:::1;:::i;46060:21::-:0;;;-1:-1:-1;;;;;46060:21:0;;:::o;71324:173::-;47787:10;;-1:-1:-1;;;;;47787:10:0;47773;:24;;:54;;;47815:12;:10;:12::i;:::-;-1:-1:-1;;;;;47801:26:0;:10;:26;47773:54;:88;;;-1:-1:-1;47845:5:0;;:16;;;-1:-1:-1;;;47845:16:0;;;;-1:-1:-1;;;;;47845:5:0;;;;:14;;:16;;;;;;;;;;;;;;;:5;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;47831:30:0;:10;:30;47773:88;:124;;;-1:-1:-1;47879:5:0;;:18;;;-1:-1:-1;;;47879:18:0;;;;-1:-1:-1;;;;;47879:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;47865:32:0;:10;:32;47773:124;47751:185;;;;-1:-1:-1;;;47751:185:0;;;;;;;:::i;:::-;71396:13:::1;:20:::0;;-1:-1:-1;;71396:20:0::1;71412:4;71396:20;::::0;;71427:5:::1;::::0;:22:::1;::::0;;-1:-1:-1;;;71427:22:0;;;;-1:-1:-1;;;;;71427:5:0;;::::1;::::0;:20:::1;::::0;:22:::1;::::0;;::::1;::::0;-1:-1:-1;;71427:22:0;;;;;;;;-1:-1:-1;71427:5:0;:22;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;71467:22:0::1;::::0;::::1;::::0;-1:-1:-1;71467:22:0;;-1:-1:-1;71467:22:0::1;71324:173::o:0;35061:622::-;35431:10;;;35430:62;;-1:-1:-1;35447:39:0;;-1:-1:-1;;;35447:39:0;;-1:-1:-1;;;;;35447:15:0;;;;;:39;;35471:4;;35478:7;;35447:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;35430:62;35422:152;;;;-1:-1:-1;;;35422:152:0;;;;;;;:::i;:::-;35585:90;35605:5;35635:22;;;35659:7;35668:5;35612:62;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;35612:62:0;;;;;;;;;;;;;;-1:-1:-1;;;;;35612:62:0;-1:-1:-1;;;;;;35612:62:0;;;;;;;;;;;35585:19;:90::i;:::-;35061:622;;;:::o;21207:132::-;21265:7;21292:39;21296:1;21299;21292:39;;;;;;;;;;;;;;;;;:3;:39::i;3920:196::-;4023:12;4055:53;4078:6;4086:4;4092:1;4095:12;4055:22;:53::i;:::-;4048:60;3920:196;-1:-1:-1;;;;3920:196:0:o;55328:98::-;55400:5;;:18;;;-1:-1:-1;;;55400:18:0;;;;55373:7;;-1:-1:-1;;;;;55400:5:0;;-1:-1:-1;;55400:18:0;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;116304:79::-;116363:16;116304:79;:::o;34402:177::-;34485:86;34505:5;34535:23;;;34560:2;34564:5;34512:58;;;;;;;;;:::i;19370:136::-;19428:7;19455:43;19459:1;19462;19455:43;;;;;;;;;;;;;;;;;:3;:43::i;118214:169::-;118283:12;:10;:12::i;:::-;-1:-1:-1;;;;;118269:26:0;:10;:26;;:62;;-1:-1:-1;118313:5:0;;:18;;;-1:-1:-1;;;118313:18:0;;;;-1:-1:-1;;;;;118313:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;118299:32:0;:10;:32;118269:62;:90;;;-1:-1:-1;118349:10:0;;-1:-1:-1;;;;;118349:10:0;118335;:24;118269:90;118261:114;;;;-1:-1:-1;;;118261:114:0;;;;;;;:::i;108592:1776::-;108759:4;;108669:20;;;;;;108736:29;;-1:-1:-1;;;;;108759:4:0;108736:14;:29::i;:::-;108717:48;;108776:14;108793:30;108814:8;108793:16;:14;:16::i;:30::-;108862:5;;:23;;;-1:-1:-1;;;108862:23:0;;;;108776:47;;-1:-1:-1;108836:23:0;;-1:-1:-1;;;;;108862:5:0;;;;:21;;:23;;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;108836:49;;108920:6;108902:15;:24;108898:92;;;108951:27;:15;108971:6;108951:19;:27::i;:::-;108943:35;;108898:92;109003:16;109021:15;109040:17;:15;:17::i;:::-;109002:55;;;;109081:13;109072:6;:22;109068:787;;;109308:6;;109319:1;;109285:31;;109308:6;;;-1:-1:-1;;;;;109308:6:0;109285:14;:31::i;:::-;:35;109281:112;;;109341:36;109355:21;:8;109368:7;109355:12;:21::i;:::-;109341:13;:36::i;:::-;;109281:112;109471:4;;109424:54;;109433:13;;109448:29;;-1:-1:-1;;;;;109471:4:0;109448:14;:29::i;:::-;109424:8;:54::i;:::-;109409:69;;109068:787;;;109526:13;109515:8;:24;109511:333;;;109560:42;109574:27;:13;109592:8;109574:17;:27::i;109511:333::-;109815:13;109800:28;;109511:333;110050:13;110035:12;:28;110031:189;;;110080:12;110095:31;:13;110113:12;110095:17;:31::i;:::-;110080:46;;110153:7;;110145:4;:15;110141:68;;110189:4;110181:12;;110141:68;110031:189;;110236:19;;;;;;;110232:129;;;110297:23;:12;110314:5;110297:16;:23::i;:::-;110280:13;:40;110272:49;;;;;;108592:1776;;;;;;;;:::o;20260:471::-;20318:7;20563:6;20559:47;;-1:-1:-1;20593:1:0;20586:8;;20559:47;20630:5;;;20634:1;20630;:5;:1;20654:5;;;;;:10;20646:56;;;;-1:-1:-1;;;20646:56:0;;;;;;;:::i;101662:1874::-;101802:13;;;;101798:52;;;101832:7;;101798:52;101976:4;;101934:16;;101953:29;;-1:-1:-1;;;;;101976:4:0;101953:14;:29::i;:::-;101934:48;;102008:16;101997:8;:27;101993:379;;;102244:6;;102255:1;;102221:31;;102244:6;;;-1:-1:-1;;;;;102244:6:0;102221:14;:31::i;:::-;:35;102217:121;;;102277:45;102291:30;:16;102312:8;102291:20;:30::i;102277:45::-;;102217:121;102354:7;;;101993:379;102385:16;;102419:63;102445:30;:8;102458:16;102445:12;:30::i;:::-;102477:4;102419:25;:63::i;:::-;102384:98;;;;102644:7;;102633:8;:18;102629:900;;;102756:15;;;;102751:767;;102792:9;102824:236;102831:12;;102824:236;;102879:45;102892:31;102905:8;102915:7;102892:12;:31::i;:::-;102879:8;;:12;:45::i;:::-;102868:56;;102956:1;102951;:6;102947:68;;102986:5;;102947:68;103037:3;;102824:236;;;102751:767;;;;103216:12;:25;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103205:8;:38;103201:143;;;103279:45;103292:31;103305:8;103315:7;103292:12;:31::i;:::-;103279:8;;:12;:45::i;:::-;103268:56;;103201:143;103421:7;;103410:8;:18;103406:97;;;103453:30;103465:7;103474:8;103453:11;:30::i;:::-;;103406:97;101662:1874;;;;:::o;117783:423::-;117913:5;;:23;;;-1:-1:-1;;;117913:23:0;;;;117843:20;;117895:42;;-1:-1:-1;;;;;117913:5:0;;;;:21;;:23;;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;117895:17;:42::i;:::-;-1:-1:-1;117876:61:0;-1:-1:-1;117949:16:0;;117986:20;:18;:20::i;:::-;117948:58;;-1:-1:-1;117948:58:0;-1:-1:-1;118019:16:0;118038:21;117948:58;;118038:12;:21::i;:::-;118131:12;;118019:40;;-1:-1:-1;118131:12:0;;;;;118126:73;;118179:7;;118168:8;:18;118160:27;;;;;;117783:423;;;;:::o;99587:1930::-;99919:6;;99704:15;;;;;;99896:31;;99919:6;;;-1:-1:-1;;;;;99919:6:0;99896:14;:31::i;:::-;99892:429;;99994:4;;99949:19;;99971:29;;-1:-1:-1;;;;;99994:4:0;99971:14;:29::i;:::-;99949:51;;100218:39;100227:11;100240:16;100218:8;:39::i;:::-;100203:54;;100272:37;;;99892:429;100334:16;100352:15;100371:17;:15;:17::i;:::-;100333:55;;;;100431:12;:10;:12::i;:::-;100475:16;:14;:16::i;:::-;100549:4;;100504:19;;100526:29;;-1:-1:-1;;;;;100549:4:0;100526:14;:29::i;:::-;100504:51;-1:-1:-1;100568:23:0;100594:21;:8;100607:7;100594:12;:21::i;:::-;100568:47;-1:-1:-1;100626:15:0;100644:32;100568:47;100664:11;100644:19;:32::i;:::-;100704:5;;:31;;-1:-1:-1;;;100704:31:0;;100626:50;;-1:-1:-1;100689:12:0;;-1:-1:-1;;;;;100704:5:0;;;;-1:-1:-1;;100704:31:0;;100729:4;;100704:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;100689:56;;100814:4;100804:7;:14;100800:710;;;100845:17;:7;100857:4;100845:11;:17::i;:::-;100835:27;;100895:7;100881:11;:21;100877:325;;;100974:11;100964:21;;100877:325;;;101025:29;:7;101037:16;101025:11;:29::i;:::-;101011:11;:43;101007:195;;;101090:16;101075:31;;101007:195;;;101162:24;:11;101178:7;101162:15;:24::i;:::-;101147:39;;101007:195;100800:710;;;101412:17;:4;101421:7;101412:8;:17::i;:::-;101404:25;;101459:39;101468:11;101481:16;101459:8;:39::i;:::-;101444:54;;100800:710;99587:1930;;;;;;;;;;;;:::o;49358:727::-;49530:4;;-1:-1:-1;;;;;49530:4:0;49522:27;49514:68;;;;-1:-1:-1;;;49514:68:0;;;;;;;:::i;:::-;49595:5;:24;;-1:-1:-1;;;;;;49595:24:0;-1:-1:-1;;;;;49595:24:0;;;;;;;;;;;49644:13;;;-1:-1:-1;;;49644:13:0;;;;:5;;;;;:11;;:13;;;;;;;;;;;;;;;:5;:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49630:4;:28;;-1:-1:-1;;;;;;49630:28:0;-1:-1:-1;;;;;49630:28:0;;;;;;;;49669:37;;:4;49686:6;-1:-1:-1;;49669:16:0;:37::i;:::-;49765:10;:24;;-1:-1:-1;;;;;;49765:24:0;;;-1:-1:-1;;;;;49765:24:0;;;;;;;;;;49800:7;:18;;;;;;;;;;;49829:6;:16;;;;;;;;;;;;-1:-1:-1;49891:14:0;:18;;;49937:5;49920:14;:22;49968:3;49953:12;:18;49982:13;:17;50012:5;;:35;;-1:-1:-1;;;50012:35:0;;:5;;;;-1:-1:-1;;50012:35:0;;50026:7;;;-1:-1:-1;;;50012:35:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;88979:1953::-;89041:6;:34;;-1:-1:-1;;;;;89041:34:0;;;;;-1:-1:-1;;;;;;89041:34:0;;;;;;;;;;89117:4;;89094:40;;;-1:-1:-1;;;89094:40:0;;;;89138:2;;89117:4;;;;;89094:38;;:40;;;;;;;;;;;;;;;89117:4;89094:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:46;;;;89086:55;;;;;;89179:15;:33;;-1:-1:-1;;;;;;89179:33:0;87624:42;89179:33;;;89254:45;87048:42;87501;89254:15;:45::i;:::-;89310:47;87048:42;87624;89310:15;:47::i;:::-;89368:45;87048:42;87741;89368:15;:45::i;:::-;89448:4;;89463:6;;89424:47;;-1:-1:-1;;;;;89448:4:0;;;;;89463:6;;;89424:15;:47::i;:::-;89482:63;80212:42;80643;89482:15;:63::i;:::-;89708:6;;89661:24;;89708:6;;;-1:-1:-1;;;;;89708:6:0;80292:42;89700:45;89696:460;;89772:16;;;89786:1;89772:16;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89772:16:0;89762:26;;80292:42;89803:7;89811:1;89803:10;;;;;;;;-1:-1:-1;;;;;89803:39:0;;;:10;;;;;;;;;:39;89878:6;;89857:10;;89878:6;;;;;;;;89857:10;;-1:-1:-1;;89857:10:0;;;;;;-1:-1:-1;;;;;89857:28:0;;;:10;;;;;;;;;;;:28;89970:61;80212:42;80292;89970:15;:61::i;:::-;89696:460;;;90074:16;;;90088:1;90074:16;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;90074:16:0;90064:26;;80292:42;90105:7;90113:1;90105:10;;;;;;;;-1:-1:-1;;;;;90105:39:0;;;:10;;;;;;;;;;;:39;89696:460;90166:30;;-1:-1:-1;;;90166:30:0;;86932:42;;90166:21;;:30;;90188:7;;90166:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;90166:30:0;;;;;;;;;;;;:::i;:::-;-1:-1:-1;90302:17:0;:24;;-1:-1:-1;;;;90302:24:0;-1:-1:-1;;;90302:24:0;-1:-1:-1;;;;90337:24:0;-1:-1:-1;;;90337:24:0;;;90465:5;90448:14;:22;90517:3;90502:12;:18;90585:4;90569:13;:20;90700:4;;90676:42;;;-1:-1:-1;;;90676:42:0;;;;90647:82;;90725:3;;-1:-1:-1;;;;;90700:4:0;;;;-1:-1:-1;;90676:42:0;;;;;;;;;;;;;;;90700:4;90676:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90668:51;;90663:2;90655:64;;90647:77;:82::i;:::-;90637:7;:92;-1:-1:-1;;90756:9:0;90740:13;:25;90795:10;90776:16;:29;90833:10;90816:14;:27;90886:5;90854:29;:37;90902:15;:22;;-1:-1:-1;;90902:22:0;-1:-1:-1;90902:22:0;;;88979:1953::o;111140:440::-;111227:22;111262:11;87129:42;-1:-1:-1;;;;;111276:25:0;;;;:55;;-1:-1:-1;87129:42:0;-1:-1:-1;;;;;111305:26:0;;;111276:55;111262:69;;111364:6;:14;;111377:1;111364:14;;;111373:1;111364:14;111350:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;111350:29:0;;111342:37;;111401:8;111390:5;111396:1;111390:8;;;;;;;;-1:-1:-1;;;;;111390:19:0;;;:8;;;;;;;;;;;:19;111422:151;;;;111460:9;111449:5;111455:1;111449:8;;;;;;;;-1:-1:-1;;;;;111449:20:0;;;:8;;;;;;;;;;;:20;111422:151;;;87129:42;111502:5;111508:1;111502:8;;;;;;;;-1:-1:-1;;;;;111502:24:0;;;:8;;;;;;;;;;;:24;111541:8;;111552:9;;111541:5;;111547:1;;111541:8;;;;;;-1:-1:-1;;;;;111541:20:0;;;:8;;;;;;;;;;;:20;111422:151;111140:440;;;;;:::o;112133:584::-;112215:12;;;;;;;112210:500;;112245:16;112263:15;112282:17;:15;:17::i;:::-;112244:55;;-1:-1:-1;112244:55:0;-1:-1:-1;112314:36:0;112328:21;112244:55;;112328:12;:21::i;112314:36::-;-1:-1:-1;112399:6:0;;:40;;-1:-1:-1;;;112399:40:0;;112372:21;;112399:6;;;-1:-1:-1;;;;;112399:6:0;;:25;;:40;;112433:4;;112399:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;112367:72;;;;;112480:6;112464:13;:22;112456:31;;;;;;87048:42;112504:12;112563:30;87048:42;112563:14;:30::i;:::-;112546:47;-1:-1:-1;112612:10:0;;112608:91;;112643:40;-1:-1:-1;;;;;112643:18:0;;112662:12;112676:6;112643:18;:40::i;:::-;112210:500;;;;;112133:584;:::o;18906:181::-;18964:7;18996:5;;;19020:6;;;;19012:46;;;;-1:-1:-1;;;19012:46:0;;;;;;;:::i;93519:135::-;93608:38;;-1:-1:-1;;;93608:38:0;;93581:7;;-1:-1:-1;;;;;93608:23:0;;;-1:-1:-1;;93608:38:0;;93640:4;;93608:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;36707:761::-;37157:69;;;;;;;;;;;;;;;;;;37131:23;;37157:69;;-1:-1:-1;;;;;37157:27:0;;;37185:4;;37157:27;:69::i;:::-;37241:17;;37131:95;;-1:-1:-1;37241:21:0;37237:224;;37383:10;37372:30;;;;;;;;;;;;:::i;:::-;37364:85;;;;-1:-1:-1;;;37364:85:0;;;;;;;:::i;21835:278::-;21921:7;21956:12;21949:5;21941:28;;;;-1:-1:-1;;;21941:28:0;;;;;;;;:::i;:::-;;21980:9;21996:1;21992;:5;;;;;;;21835:278;-1:-1:-1;;;;;21835:278:0:o;5297:979::-;5427:12;5460:18;5471:6;5460:10;:18::i;:::-;5452:60;;;;-1:-1:-1;;;5452:60:0;;;;;;;:::i;:::-;5586:12;5600:23;5627:6;-1:-1:-1;;;;;5627:11:0;5647:8;5658:4;5627:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5585:78;;;;5678:7;5674:595;;;5709:10;-1:-1:-1;5702:17:0;;-1:-1:-1;5702:17:0;5674:595;5823:17;;:21;5819:439;;6086:10;6080:17;6147:15;6134:10;6130:2;6126:19;6119:44;6034:148;6222:20;;-1:-1:-1;;;6222:20:0;;;;6229:12;;6222:20;;;:::i;5819:439::-;5297:979;;;;;;;;:::o;19809:192::-;19895:7;19931:12;19923:6;;;;19915:29;;;;-1:-1:-1;;;19915:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;19967:5:0;;;19809:192::o;103902:2239::-;103960:11;103985:16;104003:12;104019:41;104045:7;104054:5;104019:25;:41::i;:::-;103984:76;;;;104196:7;:29;;;;;104218:7;;104207:8;:18;104196:29;104192:850;;;104394:15;;;;104390:111;;;104441:44;104454:30;104466:7;104475:8;104454:11;:30::i;104441:44::-;104430:55;;104390:111;104515:7;104713:318;104731:7;;:16;;104743:3;104731:11;:16::i;:::-;104720:8;:27;104713:318;;;104779:42;104792:28;104805:8;104815:4;104792:12;:28::i;104779:42::-;104768:53;-1:-1:-1;104840:3:0;;104929:1;104924:6;;;;104920:96;;104964:4;104955:13;;104991:5;;104920:96;104713:318;;;104192:850;;105209:22;105233:21;105258:20;:18;:20::i;:::-;105311:16;;105208:70;;-1:-1:-1;105208:70:0;-1:-1:-1;105291:17:0;105381:14;105377:101;;105424:4;105412:16;;105377:101;105507:38;105535:9;105507:23;:13;105525:4;105507:17;:23::i;:38::-;105490:55;;105578:14;105560;:32;105556:430;;105609:18;105630:34;:14;105649;105630:18;:34::i;:::-;105695:6;;:31;;-1:-1:-1;;;105695:31:0;;105609:55;;-1:-1:-1;105679:13:0;;105695:6;;;;-1:-1:-1;;;;;105695:6:0;;-1:-1:-1;;105695:31:0;;105720:4;;105695:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;105679:47;;105753:1;105745:5;:9;105741:234;;;105792:7;105779:10;:20;105775:185;;;105824:6;;:35;;-1:-1:-1;;;105824:35:0;;:6;;;;-1:-1:-1;;;;;105824:6:0;;-1:-1:-1;;105824:35:0;;105848:10;;105824:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;105775:185;;;105908:6;;:32;;-1:-1:-1;;;105908:32:0;;:6;;;;-1:-1:-1;;;;;105908:6:0;;-1:-1:-1;;105908:32:0;;105932:7;;105908:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;105775:185;105556:430;;;106002:16;;:21;:70;;;;-1:-1:-1;106050:4:0;;106059:13;;106027:29;;-1:-1:-1;;;;;106050:4:0;106027:14;:29::i;:::-;:45;106002:70;105998:136;;;106089:6;;:33;;-1:-1:-1;;;106089:33:0;;:6;;;;-1:-1:-1;;;;;106089:6:0;;:18;;:33;;106108:13;;106089:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;105998:136;103902:2239;;;;;;;;;:::o;17616:106::-;17674:7;17705:1;17701;:5;:13;;17713:1;17701:13;;;-1:-1:-1;17709:1:0;;17616:106;-1:-1:-1;17616:106:0:o;106639:1774::-;106719:16;106737:12;106814:16;106832:15;106851:17;:15;:17::i;:::-;106813:55;;-1:-1:-1;106813:55:0;-1:-1:-1;106963:22:0;106988:21;106813:55;;106988:12;:21::i;:::-;106963:46;;107267:21;107307:3;107303:258;;;107343:27;:14;107362:7;107343:18;:27::i;:::-;107327:43;;107303:258;;;107417:14;107407:7;:24;107403:89;;;107462:14;107452:24;;107403:89;107522:27;:14;107541:7;107522:18;:27::i;:::-;107506:43;;107303:258;107598:11;107612:35;107630:16;;107612:13;:17;;:35;;;;:::i;:::-;107598:49;;107658:11;107672:35;107690:16;;107680:4;107672:17;;:35;;;;:::i;:::-;107658:49;-1:-1:-1;107720:21:0;107744:12;:3;107658:49;107744:7;:12::i;:::-;107720:36;;107787:3;107771:13;:19;107767:140;;;107873:22;:13;107891:3;107873:17;:22::i;:::-;107857:38;;107767:140;108112:7;108096:13;:23;108092:314;;;108146:4;;-1:-1:-1;108176:26:0;:7;108188:13;108176:11;:26::i;:::-;108165:37;;108092:314;;;108337:5;;-1:-1:-1;108368:26:0;:13;108386:7;108368:17;:26::i;:::-;108357:37;;108092:314;106639:1774;;;;;;;;;;;;:::o;112913:795::-;112980:14;113120:12;113134:16;113154:20;:18;:20::i;:::-;113119:55;;;;113264:8;113276:1;113264:13;:24;;;;;113281:7;113264:24;113260:65;;;113312:1;113305:8;;;;;;113260:65;113403:6;;113378:33;;-1:-1:-1;;;113378:33:0;;113340:32;;86932:42;;-1:-1:-1;;113378:33:0;;113403:6;;;;-1:-1:-1;;;;;113403:6:0;;113378:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;113337:74;;;;113428:7;113424:217;;;113461:64;113479:3;113484:4;113490:8;113500:24;113461:17;:64::i;:::-;113452:73;;113424:217;;;113567:62;113583:3;113588:4;113594:8;113604:24;113567:15;:62::i;:::-;113558:71;;113424:217;113658:42;113667:3;113672:6;113680:7;113697:1;113658:42;;;;;;;;;:::i;:::-;;;;;;;;112913:795;;;;;;;:::o;116559:190::-;116719:4;;116726:14;;116662:79;;-1:-1:-1;;;116662:79:0;;116635:7;;116662:12;;-1:-1:-1;;116662:79:0;;116687:7;;116696:13;;-1:-1:-1;;;;;116719:4:0;;;;116662:79;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;110376:237::-;110422:13;;;;110418:52;;;110452:7;;110418:52;110506:16;;;110520:1;110506:16;;;;;;;;;110480:23;;110506:16;;;;;;;;;-1:-1:-1;;110545:6:0;;110533:9;;;;-1:-1:-1;110545:6:0;;;-1:-1:-1;;;;;110545:6:0;;110533:9;;-1:-1:-1;110540:1:0;;110533:9;;;;-1:-1:-1;;;;;110533:18:0;;;;:9;;;;;;;;;;;:18;110564:41;;-1:-1:-1;;;110564:41:0;;86932:42;;110564:18;;:41;;110591:4;;110598:6;;110564:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110647:485;110693:13;110709:20;87048:42;110709:14;:20::i;:::-;110693:36;;110752:13;;110744:5;:21;110740:60;;;110782:7;;;110740:60;110816:8;;-1:-1:-1;;;110816:8:0;;;;110812:313;;;110866:103;;;;;;;;;110932:4;;87741:42;;110841:24;;110866:103;;110900:38;;87048:42;;-1:-1:-1;;;;;110932:4:0;110900:17;:38::i;:::-;110866:103;;;;110948:4;-1:-1:-1;;;;;110866:103:0;;;;;110955:3;110866:103;;;;110960:5;110866:103;;;;110967:1;110866:103;;;110841:129;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;110812:313::-;111003:15;;111086:4;;-1:-1:-1;;;;;111003:15:0;;;;:40;;111044:5;;111003:15;;111054:38;;87048:42;;111086:4;111054:17;:38::i;:::-;111102:4;111109:3;111003:110;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;111003:110:0;;;;;;;;;;;;:::i;88543:138::-;88620:53;-1:-1:-1;;;;;88620:25:0;;88646:7;-1:-1:-1;;88620:25:0;:53::i;805:619::-;865:4;1333:20;;1176:66;1373:23;;;;;;:42;;-1:-1:-1;;1400:15:0;;;1365:51;-1:-1:-1;;805:619:0:o;113770:1289::-;113934:25;;114112:16;;114108:102;;114163:35;114186:11;114163:18;:8;114176:4;114163:12;:18::i;:35::-;114145:53;;114108:102;114240:25;:4;114249:15;114240:8;:25::i;:::-;114220:45;;114303:8;114282:17;:29;114278:90;;114348:8;114328:28;;114278:90;114403:13;114382:17;:34;114378:100;;114453:13;114433:33;;114378:100;114517:6;;:27;;;-1:-1:-1;;;114517:27:0;;;;114488:26;;114517:6;;;-1:-1:-1;;;;;114517:6:0;;:25;;:27;;;;;;;;;;;;;;:6;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;114488:56;-1:-1:-1;114488:56:0;114708:27;:17;114730:4;114708:21;:27::i;:::-;:49;;:75;;;;;114781:2;114761:17;:22;114708:75;114704:348;;;114820:34;:17;114850:2;114820:21;:34::i;:::-;114869:6;;:42;;-1:-1:-1;;;114869:42:0;;114800:54;;-1:-1:-1;114869:6:0;;;-1:-1:-1;;;;;114869:6:0;;-1:-1:-1;;114869:42:0;;114800:54;;114869:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;115003:6:0;;:37;;-1:-1:-1;;;115003:37:0;;:6;;;;-1:-1:-1;;;;;115003:6:0;;:18;;:37;;115022:17;;115003:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;113770:1289;;;;;;;;:::o;115123:644::-;115283:23;;115347:31;115373:4;115347:21;:4;115356:11;115347:8;:21::i;:31::-;115319:59;-1:-1:-1;115409:31:0;115319:59;115431:8;115409:21;:31::i;:::-;115391:49;;115476:11;115457:15;:30;115453:92;;115522:11;115504:29;;115453:92;115577:2;115559:15;:20;115555:205;;;115614:32;:15;115642:2;115614:19;:32::i;:::-;115661:6;;:30;;-1:-1:-1;;;115661:30:0;;115596:50;;-1:-1:-1;115661:6:0;;;-1:-1:-1;;;;;115661:6:0;;:13;;:30;;115596:50;;115661:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;115706:6:0;;115741:4;;-1:-1:-1;;;;;115706:6:0;;;;;;;:11;;115718:29;;115741:4;115718:14;:29::i;:::-;115706:42;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;115555:205::-;115123:644;;;;;;;:::o;111588:405::-;111718:4;;111675:18;;-1:-1:-1;;;;;111718:4:0;87129:42;111710:21;111706:280;;;111781:8;111792:17;;;;;;;;;;;87129:42;111756:69;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;111748:77;;111706:280;;;111902:17;;111866:108;;;;111891:8;;111902:17;-1:-1:-1;;;111902:17:0;;;;;87129:42;;-1:-1:-1;;;111936:17:0;;;;;;;111963:9;;111866:108;;;:::i;:::-;;;;;;;;;;;;;111858:116;;111588:405;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;1452:336;;;1566:3;1559:4;1551:6;1547:17;1543:27;1533:2;;-1:-1;;1574:12;1533:2;-1:-1;1604:20;;1644:18;1633:30;;1630:2;;;-1:-1;;1666:12;1630:2;1710:4;1702:6;1698:17;1686:29;;1761:3;1710:4;1741:17;1702:6;1727:32;;1724:41;1721:2;;;1778:1;;1768:12;1721:2;1526:262;;;;;:::o;4037:128::-;4103:20;;43881:8;43870:20;;47674:34;;47664:2;;47722:1;;47712:12;4587:241;;4691:2;4679:9;4670:7;4666:23;4662:32;4659:2;;;-1:-1;;4697:12;4659:2;85:6;72:20;97:33;124:5;97:33;:::i;4835:263::-;;4950:2;4938:9;4929:7;4925:23;4921:32;4918:2;;;-1:-1;;4956:12;4918:2;226:6;220:13;238:33;265:5;238:33;:::i;5105:366::-;;;5226:2;5214:9;5205:7;5201:23;5197:32;5194:2;;;-1:-1;;5232:12;5194:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5284:63;-1:-1;5384:2;5423:22;;72:20;97:33;72:20;97:33;:::i;:::-;5392:63;;;;5188:283;;;;;:::o;5478:491::-;;;;5616:2;5604:9;5595:7;5591:23;5587:32;5584:2;;;-1:-1;;5622:12;5584:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5674:63;-1:-1;5774:2;5813:22;;72:20;97:33;72:20;97:33;:::i;:::-;5578:391;;5782:63;;-1:-1;;;5882:2;5921:22;;;;4239:20;;5578:391::o;5976:867::-;;;;;;;6167:3;6155:9;6146:7;6142:23;6138:33;6135:2;;;-1:-1;;6174:12;6135:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;6226:63;-1:-1;6326:2;6365:22;;72:20;97:33;72:20;97:33;:::i;:::-;6334:63;-1:-1;6434:2;6473:22;;4239:20;;-1:-1;6542:2;6581:22;;4239:20;;-1:-1;6678:3;6663:19;;6650:33;6703:18;6692:30;;6689:2;;;-1:-1;;6725:12;6689:2;6763:64;6819:7;6810:6;6799:9;6795:22;6763:64;:::i;:::-;6129:714;;;;-1:-1;6129:714;;-1:-1;6129:714;;6745:82;;6129:714;-1:-1;;;6129:714::o;6850:392::-;;6990:2;;6978:9;6969:7;6965:23;6961:32;6958:2;;;-1:-1;;6996:12;6958:2;7047:17;7041:24;7085:18;7077:6;7074:30;7071:2;;;-1:-1;;7107:12;7071:2;7194:22;;422:4;410:17;;406:27;-1:-1;396:2;;-1:-1;;437:12;396:2;477:6;471:13;499:80;514:64;571:6;514:64;:::i;:::-;499:80;:::i;:::-;607:21;;;664:14;;;;639:17;;;753;;;744:27;;;;741:36;-1:-1;738:2;;;-1:-1;;780:12;738:2;-1:-1;806:10;;800:217;825:6;822:1;819:13;800:217;;;4387:13;;893:61;;847:1;840:9;;;;;968:14;;;;996;;800:217;;;-1:-1;7127:99;6952:290;-1:-1;;;;;;;6952:290::o;7249:235::-;;7350:2;7338:9;7329:7;7325:23;7321:32;7318:2;;;-1:-1;;7356:12;7318:2;1108:6;1095:20;1120:30;1144:5;1120:30;:::i;7491:257::-;;7603:2;7591:9;7582:7;7578:23;7574:32;7571:2;;;-1:-1;;7609:12;7571:2;1243:6;1237:13;1255:30;1279:5;1255:30;:::i;7755:360::-;;;7873:2;7861:9;7852:7;7848:23;7844:32;7841:2;;;-1:-1;;7879:12;7841:2;1108:6;1095:20;1120:30;1144:5;1120:30;:::i;:::-;7931:60;8028:2;8067:22;;;;4239:20;;-1:-1;;;7835:280::o;8122:523::-;;;;8265:2;8253:9;8244:7;8240:23;8236:32;8233:2;;;-1:-1;;8271:12;8233:2;1243:6;1237:13;1255:30;1279:5;1255:30;:::i;:::-;8431:2;8481:22;;4387:13;8550:2;8597:22;;1237:13;8323:71;;-1:-1;4387:13;-1:-1;1255:30;1237:13;1255:30;:::i;:::-;8558:71;;;;8227:418;;;;;:::o;8652:263::-;;8767:2;8755:9;8746:7;8742:23;8738:32;8735:2;;;-1:-1;;8773:12;8735:2;-1:-1;1375:13;;8729:186;-1:-1;8729:186::o;9226:367::-;;;9350:2;9338:9;9329:7;9325:23;9321:32;9318:2;;;-1:-1;;9356:12;9318:2;9414:17;9401:31;9452:18;9444:6;9441:30;9438:2;;;-1:-1;;9474:12;9438:2;9512:65;9569:7;9560:6;9549:9;9545:22;9512:65;:::i;:::-;9494:83;;;;-1:-1;9312:281;-1:-1;;;;9312:281::o;9600:328::-;;9747:3;;9735:9;9726:7;9722:23;9718:33;9715:2;;;-1:-1;;9754:12;9715:2;2529:22;9747:3;2529:22;:::i;:::-;2520:31;;2675:22;4387:13;2625:16;2618:86;2771:2;2840:9;2836:22;4387:13;2771:2;2790:5;2786:16;2779:86;2931:2;3000:9;2996:22;4387:13;2931:2;2950:5;2946:16;2939:86;3099:2;3168:9;3164:22;4387:13;3099:2;3118:5;3114:16;3107:86;3267:3;3337:9;3333:22;4387:13;3267:3;3287:5;3283:16;3276:86;3429:3;3499:9;3495:22;4387:13;3429:3;3449:5;3445:16;3438:86;3590:3;3660:9;3656:22;4387:13;3590:3;3610:5;3606:16;3599:86;3751:3;3821:9;3817:22;4387:13;3751:3;3771:5;3767:16;3760:86;3912:3;;3984:9;3980:22;4387:13;3912:3;3932:5;3928:18;3921:88;;9806:106;;;;9709:219;;;;:::o;9935:362::-;;;10054:2;10042:9;10033:7;10029:23;10025:32;10022:2;;;-1:-1;;10060:12;10022:2;10122:52;10166:7;10142:22;10122:52;:::i;:::-;10112:62;;10229:52;10273:7;10211:2;10253:9;10249:22;10229:52;:::i;:::-;10219:62;;10016:281;;;;;:::o;10304:241::-;;10408:2;10396:9;10387:7;10383:23;10379:32;10376:2;;;-1:-1;;10414:12;10376:2;-1:-1;4239:20;;10370:175;-1:-1;10370:175::o;10822:672::-;;;;;10988:3;10976:9;10967:7;10963:23;10959:33;10956:2;;;-1:-1;;10995:12;10956:2;-1:-1;;4387:13;;11158:2;11208:22;;4387:13;11277:2;11327:22;;4387:13;11396:2;11446:22;;;4387:13;;;;;-1:-1;4387:13;;-1:-1;10950:544;-1:-1;10950:544::o;11501:259::-;;11614:2;11602:9;11593:7;11589:23;11585:32;11582:2;;;-1:-1;;11620:12;11582:2;4532:6;4526:13;44052:4;47945:5;44041:16;47922:5;47919:33;47909:2;;-1:-1;;47956:12;12860:690;;13053:5;41920:12;42755:6;42750:3;42743:19;42792:4;;42787:3;42783:14;13065:93;;42792:4;13229:5;41600:14;-1:-1;13268:260;13293:6;13290:1;13287:13;13268:260;;;13354:13;;-1:-1;;;;;43743:54;12373:37;;11921:14;;;;42467;;;;-1:-1;13308:9;13268:260;;;-1:-1;13534:10;;12984:566;-1:-1;;;;;12984:566::o;14726:323::-;;14858:5;41920:12;42755:6;42750:3;42743:19;14941:52;14986:6;42792:4;42787:3;42783:14;42792:4;14967:5;14963:16;14941:52;:::i;:::-;46865:7;46849:14;-1:-1;;46845:28;15005:39;;;;42792:4;15005:39;;14806:243;-1:-1;;14806:243::o;23465:526::-;47064:2;47060:14;;;-1:-1;;47060:14;;;12759:58;;46957:15;;;;;-1:-1;;;;;;46957:15;23744:2;23735:12;;23039:56;47060:14;;;23844:11;;;12759:58;23954:12;;;23635:356::o;23998:799::-;-1:-1;;47064:2;47060:14;;;;;12759:58;;-1:-1;;;;;;;46957:15;;;;;24331:2;24322:12;;23039:56;47060:14;;;;;24431:11;;;12759:58;46957:15;;;;;;;24541:12;;;23039:56;47060:14;;;;;24650:11;;;12759:58;24760:12;;;24222:575::o;24804:271::-;;15216:5;41920:12;15327:52;15372:6;15367:3;15360:4;15353:5;15349:16;15327:52;:::i;:::-;15391:16;;;;;24938:137;-1:-1;;24938:137::o;25082:222::-;-1:-1;;;;;43743:54;;;;12373:37;;25209:2;25194:18;;25180:124::o;25311:333::-;-1:-1;;;;;43743:54;;;12373:37;;43743:54;;25630:2;25615:18;;12373:37;25466:2;25451:18;;25437:207::o;25651:513::-;-1:-1;;;;;43743:54;;;12373:37;;25872:2;25990;25975:18;;;25968:48;;;41920:12;;25857:18;;;42743:19;;;-1:-1;;41600:14;;;;-1:-1;;25990:2;42783:14;;;;-1:-1;14054:292;14079:6;14076:1;14073:13;14054:292;;;14140:13;;43743:54;;15506:66;;42467:14;;;;12135;;;;14101:1;14094:9;14054:292;;;-1:-1;26022:132;;25843:321;-1:-1;;;;;;;;25843:321::o;26171:349::-;-1:-1;;;;;43743:54;;;;12373:37;;26506:2;26491:18;;16506:58;26334:2;26319:18;;26305:215::o;26867:370::-;;27044:2;27065:17;27058:47;27119:108;27044:2;27033:9;27029:18;27213:6;27119:108;:::i;27244:210::-;43461:13;;43454:21;14441:34;;27365:2;27350:18;;27336:118::o;27461:584::-;43461:13;;43454:21;14441:34;;27849:2;27834:18;;14677:37;;;;-1:-1;;;;;43743:54;27940:2;27925:18;;12373:37;28031:2;28016:18;;14677:37;27674:3;27659:19;;27645:400::o;28052:616::-;43461:13;;43454:21;14441:34;;28456:2;28441:18;;14677:37;;;;28547:2;28532:18;;14677:37;-1:-1;;;;;43743:54;28654:2;28639:18;;15506:66;28281:3;28266:19;;28252:416::o;28675:222::-;14677:37;;;28802:2;28787:18;;28773:124::o;29968:330::-;;30125:2;30146:17;30139:47;42755:6;30125:2;30114:9;30110:18;42743:19;46138:6;46133:3;42783:14;30114:9;42783:14;46115:30;46176:16;;;42783:14;46176:16;;;46169:27;;;;46865:7;46849:14;;;-1:-1;;46845:28;16856:39;;;30096:202;-1:-1;30096:202::o;30305:310::-;;30452:2;30473:17;30466:47;30527:78;30452:2;30441:9;30437:18;30591:6;30527:78;:::i;30622:416::-;30822:2;30836:47;;;17488:2;30807:18;;;42743:19;-1:-1;;;42783:14;;;17504:34;17557:12;;;30793:245::o;31045:416::-;31245:2;31259:47;;;17808:1;31230:18;;;42743:19;-1:-1;;;42783:14;;;17823:28;17870:12;;;31216:245::o;31468:416::-;31668:2;31682:47;;;18121:2;31653:18;;;42743:19;18157:29;42783:14;;;18137:50;18206:12;;;31639:245::o;31891:416::-;32091:2;32105:47;;;18457:2;32076:18;;;42743:19;-1:-1;;;42783:14;;;18473:35;18527:12;;;32062:245::o;32314:416::-;32514:2;32528:47;;;18778:2;32499:18;;;42743:19;18814:30;42783:14;;;18794:51;18864:12;;;32485:245::o;32737:416::-;32937:2;32951:47;;;19115:2;32922:18;;;42743:19;19151:34;42783:14;;;19131:55;-1:-1;;;19206:12;;;19199:25;19243:12;;;32908:245::o;33160:416::-;33360:2;33374:47;;;19494:1;33345:18;;;42743:19;-1:-1;;;42783:14;;;19509:29;19557:12;;;33331:245::o;33583:416::-;33783:2;33797:47;;;19808:1;33768:18;;;42743:19;-1:-1;;;42783:14;;;19823:30;19872:12;;;33754:245::o;34006:416::-;34206:2;34220:47;;;20123:2;34191:18;;;42743:19;20159:31;42783:14;;;20139:52;20210:12;;;34177:245::o;34429:416::-;34629:2;34643:47;;;20461:2;34614:18;;;42743:19;-1:-1;;;42783:14;;;20477:34;20530:12;;;34600:245::o;34852:416::-;35052:2;35066:47;;;20781:2;35037:18;;;42743:19;20817:34;42783:14;;;20797:55;-1:-1;;;20872:12;;;20865:34;20918:12;;;35023:245::o;35275:416::-;35475:2;35489:47;;;21169:2;35460:18;;;42743:19;-1:-1;;;42783:14;;;21185:33;21237:12;;;35446:245::o;35698:416::-;35898:2;35912:47;;;21488:2;35883:18;;;42743:19;21524:34;42783:14;;;21504:55;-1:-1;;;21579:12;;;21572:46;21637:12;;;35869:245::o;36121:406::-;;36316:2;36337:17;36330:47;21995:16;21989:23;21923:4;36316:2;36305:9;36301:18;22025:38;22078:71;21914:14;36305:9;21914:14;22130:12;22078:71;:::i;:::-;22070:79;;1644:18;;43754:42;;;36316:2;22232:5;22228:16;22222:23;43743:54;22299:14;36305:9;22299:14;12373:37;22299:14;22390:5;22386:16;22380:23;22457:14;36305:9;22457:14;14677:37;22457:14;22548:5;22544:16;22538:23;22615:14;36305:9;22615:14;14677:37;22615:14;22714:5;22710:16;22704:23;21923:4;36305:9;22781:14;14677:37;36383:134;;;;36287:240;;;;:::o;36534:218::-;43881:8;43870:20;;;;22904:36;;36659:2;36644:18;;36630:122::o;36988:481::-;;14707:5;14684:3;14677:37;37193:2;37311;37300:9;37296:18;37289:48;37351:108;37193:2;37182:9;37178:18;37445:6;37351:108;:::i;37476:832::-;;14707:5;14684:3;14677:37;45777:24;37946:2;37935:9;37931:18;16506:58;37773:3;37983:2;37972:9;37968:18;37961:48;38023:108;37773:3;37762:9;37758:19;38117:6;38023:108;:::i;:::-;-1:-1;;;;;43743:54;;;;38210:2;38195:18;;12373:37;-1:-1;38293:3;38278:19;14677:37;43743:54;38015:116;-1:-1;;;37744:564::o;38315:333::-;14677:37;;;38634:2;38619:18;;14677:37;38470:2;38455:18;;38441:207::o;38655:560::-;14677:37;;;39033:2;39018:18;;14677:37;;;;43461:13;43454:21;39110:2;39095:18;;14441:34;-1:-1;;;;;43743:54;39201:2;39186:18;;12242:58;38868:3;38853:19;;38839:376::o;39222:444::-;14677:37;;;39569:2;39554:18;;14677:37;;;;39652:2;39637:18;;14677:37;39405:2;39390:18;;39376:290::o;39673:556::-;14677:37;;;40049:2;40034:18;;14677:37;;;;40132:2;40117:18;;14677:37;40215:2;40200:18;;14677:37;39884:3;39869:19;;39855:374::o;40236:668::-;14677:37;;;40640:2;40625:18;;14677:37;;;;40723:2;40708:18;;14677:37;;;;40806:2;40791:18;;14677:37;40889:3;40874:19;;14677:37;40475:3;40460:19;;40446:458::o;40911:256::-;40973:2;40967:9;40999:17;;;41074:18;41059:34;;41095:22;;;41056:62;41053:2;;;41131:1;;41121:12;41053:2;40973;41140:22;40951:216;;-1:-1;40951:216::o;41174:304::-;;41333:18;41325:6;41322:30;41319:2;;;-1:-1;;41355:12;41319:2;-1:-1;41400:4;41388:17;;;41453:15;;41256:222::o;46211:268::-;46276:1;46283:101;46297:6;46294:1;46291:13;46283:101;;;46364:11;;;46358:18;46345:11;;;46338:39;46319:2;46312:10;46283:101;;;46399:6;46396:1;46393:13;46390:2;;;-1:-1;;46276:1;46446:16;;46439:27;46260:219::o;47092:117::-;-1:-1;;;;;43743:54;;47151:35;;47141:2;;47200:1;;47190:12;47216:111;47297:5;43461:13;43454:21;47275:5;47272:32;47262:2;;47318:1;;47308:12
Swarm Source
ipfs://5008b1a5eb901bc0cd0fd2f320b670b8ed0feb3f770e6c4e2ebec6e70c67eafb
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.