Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Strategist | 13487857 | 1129 days ago | IN | 0 ETH | 0.00452236 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
13456369 | 1134 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 2021-10-20 */ // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.6.12; pragma experimental ABIEncoderV2; // Global Enums and Structs struct StrategyParams { uint256 performanceFee; uint256 activation; uint256 debtRatio; uint256 minDebtPerHarvest; uint256 maxDebtPerHarvest; uint256 lastReport; uint256 totalDebt; uint256 totalGain; uint256 totalLoss; } // Part: IERC3156FlashBorrower 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); } // Part: IUniswapAnchoredView interface IUniswapAnchoredView { function price(string memory) external returns (uint256); } // Part: IUniswapV2Router01 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); } // Part: IUniswapV3SwapCallback /// @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; } // Part: InterestRateModel 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); } // Part: OpenZeppelin/[email protected]/Address /** * @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); } } } } // Part: OpenZeppelin/[email protected]/IERC20 /** * @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); } // Part: OpenZeppelin/[email protected]/Math /** * @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); } } // Part: OpenZeppelin/[email protected]/SafeMath /** * @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; } } // Part: iearn-finance/[email protected]/HealthCheck interface HealthCheck { function check( uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding, uint256 totalDebt ) external view returns (bool); } // Part: CTokenI 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); } // Part: IERC20Extended interface IERC20Extended is IERC20 { function decimals() external view returns (uint8); function name() external view returns (string memory); function symbol() external view returns (string memory); } // Part: IERC3156FlashLender 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); } // Part: IUniswapV2Router02 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; } // Part: IUniswapV3Router /// @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); } // Part: OpenZeppelin/[email protected]/SafeERC20 /** * @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"); } } } // Part: iearn-finance/[email protected]/VaultAPI 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); } // Part: CErc20I 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); } // Part: ComptrollerI 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); } // Part: iearn-finance/[email protected]/BaseStrategy /** * @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))); } } // Part: FlashMintLib 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 = 0x1EB4CF3A948E7D72A198fe073cCb8C7a948cD853; 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 require(cToken.repayBorrow(amount) == 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(amount) == 0, "!mint_up"); require(CErc20I(CDAI).redeemUnderlying(amountDAI) == 0, "!redeem"); } } return CALLBACK_SUCCESS; } } // Part: Strategy 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 "GenLevCompV3"; } 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-3 want minWant = uint256(uint256(10)**uint256((IERC20Extended(address(want))).decimals())).div(1000); 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); } 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
60806040523480156200001157600080fd5b5060405162006e6738038062006e67833981016040819052620000349162000ad9565b81620000438133808062000057565b506200004f816200023b565b505062000e90565b6006546001600160a01b0316156200008c5760405162461bcd60e51b8152600401620000839062000ce8565b60405180910390fd5b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b158015620000e957600080fd5b505afa158015620000fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000124919062000ab0565b600680546001600160a01b0319166001600160a01b0392831617908190556200015e9116856000196200072a602090811b620031a717901c565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b393620001de93911691600019910162000c4b565b602060405180830381600087803b158015620001f957600080fd5b505af11580156200020e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000234919062000bb5565b5050505050565b80600b60016101000a8154816001600160a01b0302191690836001600160a01b031602179055506012600660009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015620002b357600080fd5b505afa158015620002c8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ee919062000bf0565b60ff161115620002fd57600080fd5b600c80546001600160a01b03191673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f1790556200035773c00e94cb662c3520282e6f5717214004a7f26888737a250d5630b4cf539739df2c5dacb4c659f2488d62000838565b6200038b73c00e94cb662c3520282e6f5717214004a7f2688873d9e1ce17f2641f24ae83637ab66a2cca9c378b9f62000838565b620003bf73c00e94cb662c3520282e6f5717214004a7f2688873e592427a0aece92de3edee1f18e0157c0586156462000838565b600654600b54620003e2916001600160a01b039081169161010090041662000838565b62000416736b175474e89094c44da98b954eedeac495271d0f731eb4cf3a948e7d72a198fe073ccb8c7a948cd85362000838565b600b5460609061010090046001600160a01b0316735d3a536e4d6dbd6114cc1ead35777bab948e3643146200050d576040805160028082526060820183529091602083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e3643816000815181106200048857fe5b6001600160a01b039283166020918202929092010152600b5482516101009091049091169082906001908110620004bb57fe5b6001600160a01b039092166020928302919091019091015262000507736b175474e89094c44da98b954eedeac495271d0f735d3a536e4d6dbd6114cc1ead35777bab948e364362000838565b62000571565b6040805160018082528183019092529060208083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e3643816000815181106200055057fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b604051631853304760e31b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b9063c299823890620005aa90849060040162000c64565b600060405180830381600087803b158015620005c557600080fd5b505af1158015620005da573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000604919081019062000b17565b50600b805462ffffff60b01b191661017760b31b1762ffffff60c81b191661017760cb1b1790556201518060085560646009556c0c9f2c9cd04674edea40000000600a556006546040805163313ce56760e01b81529051620006ec926103e8926001600160a01b039091169163313ce56791600480820192602092909190829003018186803b1580156200069757600080fd5b505afa158015620006ac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006d2919062000bf0565b60ff16600a0a6200086360201b620032a61790919060201c565b601055505067016345785d8a00006012556708be35a9807f0000600e55670a217b21de090000600d5561b5a4600f556013805460ff19166001179055565b801580620007b95750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e9062000763903090869060040162000c31565b60206040518083038186803b1580156200077c57600080fd5b505afa15801562000791573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620007b7919062000bd7565b155b620007d85760405162461bcd60e51b8152600401620000839062000da0565b620008338363095ea7b360e01b8484604051602401620007fa92919062000c4b565b60408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b0393841617905290620008b416565b505050565b6200085f81600019846001600160a01b03166200072a60201b620031a7179092919060201c565b5050565b6000620008ad83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506200095060201b60201c565b9392505050565b606062000910826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200098b60201b620032e8179092919060201c565b80519091501562000833578080602001905181019062000931919062000bb5565b620008335760405162461bcd60e51b8152600401620000839062000d56565b60008183620009745760405162461bcd60e51b815260040162000083919062000cb3565b5060008385816200098157fe5b0495945050505050565b60606200099c8484600085620009a4565b949350505050565b6060620009b18562000a76565b620009d05760405162461bcd60e51b8152600401620000839062000d1f565b60006060866001600160a01b03168587604051620009ef919062000c13565b60006040518083038185875af1925050503d806000811462000a2e576040519150601f19603f3d011682016040523d82523d6000602084013e62000a33565b606091505b5091509150811562000a495791506200099c9050565b80511562000a5a5780518082602001fd5b8360405162461bcd60e51b815260040162000083919062000cb3565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906200099c575050151592915050565b60006020828403121562000ac2578081fd5b81516001600160a01b0381168114620008ad578182fd5b6000806040838503121562000aec578081fd5b825162000af98162000e77565b602084015190925062000b0c8162000e77565b809150509250929050565b6000602080838503121562000b2a578182fd5b82516001600160401b0381111562000b40578283fd5b8301601f8101851362000b51578283fd5b805162000b6862000b628262000e24565b62000dfd565b818152838101908385018584028501860189101562000b85578687fd5b8694505b8385101562000ba957805183526001949094019391850191850162000b89565b50979650505050505050565b60006020828403121562000bc7578081fd5b81518015158114620008ad578182fd5b60006020828403121562000be9578081fd5b5051919050565b60006020828403121562000c02578081fd5b815160ff81168114620008ad578182fd5b6000825162000c2781846020870162000e44565b9190910192915050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b8181101562000ca75783516001600160a01b03168352928401929184019160010162000c80565b50909695505050505050565b600060208252825180602084015262000cd481604085016020870162000e44565b601f01601f19169190910160400192915050565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606082015260800190565b6040518181016001600160401b038111828210171562000e1c57600080fd5b604052919050565b60006001600160401b0382111562000e3a578081fd5b5060209081020190565b60005b8381101562000e6157818101518382015260200162000e47565b8381111562000e71576000848401525b50505050565b6001600160a01b038116811462000e8d57600080fd5b50565b615fc78062000ea06000396000f3fe608060405234801561001057600080fd5b50600436106104335760003560e01c806373b3828511610236578063b2c5f6581161013b578063d3406abd116100c3578063ed882c2b11610087578063ed882c2b146107f1578063efbb5cb014610804578063f017c92f1461080c578063fbfa77cf1461081f578063fcf2d0ad1461082757610433565b8063d3406abd146107b3578063db2fd745146107bb578063e00425a3146107ce578063e0b8c948146107d6578063ec38a862146107de57610433565b8063c1bb4b541161010a578063c1bb4b5414610775578063c59848471461077d578063c7b9d53014610785578063cb1965dd14610798578063ce5494bb146107a057610433565b8063b2c5f6581461074a578063b2d0c8e214610752578063ba0ad98614610765578063bf83e0af1461076d57610433565b806391397ab4116101be5780639ec5a8941161018d5780639ec5a8941461070c578063ac00ff2614610714578063aced166114610727578063aef6679e1461072f578063b252720b1461074257610433565b806391397ab4146106d657806395e80c50146106e95780639a561fbf146106f15780639be8ef141461070457610433565b8063780022a011610205578063780022a014610698578063853e0a3b146106ab57806389be318a146106b35780638cdfe166146106c65780638e6350e2146106ce57610433565b806373b3828514610655578063748747e61461066a578063750521f51461067d578063775d35e51461069057610433565b80632e1a7d4d1161033c578063440368a3116102c45780635641ec03116102935780635641ec031461061757806356cdac2c1461061f578063650d1880146106325780636718835f1461064557806369e527da1461064d57610433565b8063440368a3146105e15780634641257d146105e9578063485cc955146105f157806354f809e31461060457610433565b8063396794cd1161030b578063396794cd1461059557806339a172a8146105a85780633e5f0ae8146105bb57806340f8bc43146105c3578063418f35cc146105cb57610433565b80632e1a7d4d146105495780633042087c1461055c5780633631ad5f1461056f5780633922b4a81461058257610433565b80631d12f28b116103bf57806322f3e2d41161038e57806322f3e2d41461050957806323e30c8b1461051e578063258294101461053157806327cc1ea21461053957806328b7ccf71461054157610433565b80631d12f28b146104dc5780631f1fcd51146104e45780631fe4a686146104f9578063205409d31461050157610433565b806305a82f9a1161040657806305a82f9a1461048857806306fdde031461049b5780630c17c733146104a35780630f969b87146104b657806311bc8245146104c957610433565b806301681a62146104385780630268ff0b1461044d57806303ee438c1461046b57806304324af814610480575b600080fd5b61044b6104463660046154f0565b61082f565b005b6104556109ce565b6040516104629190615af1565b60405180910390f35b6104736109f2565b6040516104629190615b29565b610455610a80565b61044b6104963660046156af565b610a86565b610473610aa1565b61044b6104b136600461585e565b610ac7565b61044b6104c436600461585e565b610ad4565b61044b6104d73660046154f0565b610b61565b610455610c62565b6104ec610c68565b60405161046291906159e4565b6104ec610c77565b610455610c86565b610511610c8c565b6040516104629190615a9a565b61045561052c3660046155a0565b610d2e565b610473610e24565b61044b610e43565b610455610ec3565b61045561055736600461585e565b610ec9565b61044b61056a36600461585e565b610f24565b61044b61057d36600461585e565b61104f565b61044b6105903660046156af565b61105c565b61044b6105a336600461585e565b611080565b61044b6105b636600461585e565b6110ec565b61045561116e565b610511611174565b6105d361117d565b604051610462929190615e73565b61044b611243565b61044b61146c565b61044b6105ff366004615528565b611945565b61044b6106123660046156af565b61195a565b6105116119ac565b61044b61062d3660046156af565b6119b5565b61051161064036600461585e565b6119d0565b6105116119fd565b6104ec611a06565b61065d611a1a565b6040516104629190615e0e565b61044b6106783660046154f0565b611a2c565b61044b61068b36600461576c565b611ad7565b6105d3611b6e565b6104556106a636600461585e565b611c85565b610455611cba565b6104556106c1366004615560565b611f12565b610455611fd6565b610455611fdc565b61044b6106e436600461585e565b611fe1565b610455612063565b61044b6106ff36600461585e565b612069565b610455612122565b6104ec61215d565b61044b6107223660046156af565b61216c565b6104ec612258565b61044b61073d36600461582a565b612267565b6104ec6122a7565b61065d6122bb565b61044b6107603660046156af565b6122cd565b6105116122f3565b610511612302565b61045561230b565b610511612311565b61044b6107933660046154f0565b612321565b6105116123cc565b61044b6107ae3660046154f0565b6123da565b610455612525565b61044b6107c936600461585e565b6125e3565b6104556125f0565b6104ec6129fc565b61044b6107ec3660046154f0565b612a0b565b6105116107ff36600461585e565b612b9e565b610455612e28565b61044b61081a36600461585e565b612ef1565b6104ec612f73565b61044b612f82565b6108376132ff565b6001600160a01b0316336001600160a01b0316146108705760405162461bcd60e51b815260040161086790615ccd565b60405180910390fd5b6006546001600160a01b038281169116141561089e5760405162461bcd60e51b815260040161086790615b61565b6002546001600160a01b03828116911614156108cc5760405162461bcd60e51b815260040161086790615c75565b60606108d661337c565b905060005b8151811015610931578181815181106108f057fe5b60200260200101516001600160a01b0316836001600160a01b031614156109295760405162461bcd60e51b815260040161086790615d3c565b6001016108db565b506109ca61093d6132ff565b6040516370a0823160e01b81526001600160a01b038516906370a08231906109699030906004016159e4565b60206040518083038186803b15801561098157600080fd5b505afa158015610995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b99190615754565b6001600160a01b0385169190613381565b5050565b60008060006109db61117d565b90925090506109ea82826133a0565b925050505b90565b6000805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610a785780601f10610a4d57610100808354040283529160200191610a78565b820191906000526020600020905b815481529060010190602001808311610a5b57829003601f168201915b505050505081565b60125481565b610a8e6133e2565b6011805460ff1916911515919091179055565b60408051808201909152600c81526b47656e4c6576436f6d70563360a01b602082015290565b610acf6133e2565b600d55565b6003546001600160a01b0316331480610b055750610af06132ff565b6001600160a01b0316336001600160a01b0316145b610b215760405162461bcd60e51b815260040161086790615ccd565b600a8190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a860090610b56908390615af1565b60405180910390a150565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610baf57600080fd5b505afa158015610bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be7919061550c565b6001600160a01b0316336001600160a01b03161480610c1e5750610c096132ff565b6001600160a01b0316336001600160a01b0316145b610c3a5760405162461bcd60e51b815260040161086790615ccd565b600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600a5481565b6006546001600160a01b031681565b6003546001600160a01b031681565b60105481565b6002546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610cc19030906004016159e4565b6101206040518083038186803b158015610cda57600080fd5b505afa158015610cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1291906157ac565b604001511180610d2957506000610d27612e28565b115b905090565b600033731eb4cf3a948e7d72a198fe073ccb8c7a948cd85314610d5057600080fd5b6001600160a01b0387163014610d6557600080fd5b600080610d74848601866156e7565b600b546040516353cd344560e11b8152929450909250738c2cc5ff69bc3760d7ce81812a2848421495972a9163a79a688a91610dc79186918c91879161010090046001600160a01b031690600401615acb565b60206040518083038186803b158015610ddf57600080fd5b505af4158015610df3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e179190615754565b9998505050505050505050565b604080518082019091526005815264302e342e3360d81b602082015290565b610e4b6133e2565b600c546001600160a01b031673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f14610e8b5773d9e1ce17f2641f24ae83637ab66a2cca9c378b9f610ea1565b737a250d5630b4cf539739df2c5dacb4c659f2488d5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b60085481565b6002546000906001600160a01b03163314610ef65760405162461bcd60e51b815260040161086790615c55565b6000610f01836134d0565b600654909350909150610f1e906001600160a01b03163383613381565b50919050565b610f2c6133e2565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390610f60908490600401615af1565b602060405180830381600087803b158015610f7a57600080fd5b505af1158015610f8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb29190615754565b15610fbc57600080fd5b600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290610ff0908490600401615af1565b602060405180830381600087803b15801561100a57600080fd5b505af115801561101e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110429190615754565b1561104c57600080fd5b50565b6110576133e2565b601055565b6110646133e2565b60138054911515620100000262ff000019909216919091179055565b6110886132ff565b6001600160a01b0316336001600160a01b0316146110b85760405162461bcd60e51b815260040161086790615ccd565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390610ff0908490600401615af1565b6003546001600160a01b031633148061111d57506111086132ff565b6001600160a01b0316336001600160a01b0316145b6111395760405162461bcd60e51b815260040161086790615ccd565b60078190556040517fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190610b56908390615af1565b600d5481565b60115460ff1681565b600b546040516361bfb47160e11b8152600091829182918291829161010090046001600160a01b03169063c37f68e2906111bb9030906004016159e4565b60806040518083038186803b1580156111d357600080fd5b505afa1580156111e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120b9190615876565b9350935093505081935061123a670de0b6b3a7640000611234838661368090919063ffffffff16565b906132a6565b94505050509091565b6005546001600160a01b031633148061126657506003546001600160a01b031633145b8061128957506112746132ff565b6001600160a01b0316336001600160a01b0316145b8061132a5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156112dd57600080fd5b505afa1580156112f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611315919061550c565b6001600160a01b0316336001600160a01b0316145b806113cb5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561137e57600080fd5b505afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b6919061550c565b6001600160a01b0316336001600160a01b0316145b6113e75760405162461bcd60e51b815260040161086790615ccd565b6002546040805163bf3759b560e01b8152905161146a926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561142d57600080fd5b505afa158015611441573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114659190615754565b6136ba565b565b6005546001600160a01b031633148061148f57506003546001600160a01b031633145b806114b2575061149d6132ff565b6001600160a01b0316336001600160a01b0316145b806115535750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561150657600080fd5b505afa15801561151a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153e919061550c565b6001600160a01b0316336001600160a01b0316145b806115f45750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156115a757600080fd5b505afa1580156115bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115df919061550c565b6001600160a01b0316336001600160a01b0316145b6116105760405162461bcd60e51b815260040161086790615ccd565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561166357600080fd5b505afa158015611677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169b9190615754565b600b5490915060009060ff16156116f85760006116b6613843565b9050828110156116d1576116ca83826133a0565b93506116e6565b828111156116e6576116e381846133a0565b94505b6116f083856133a0565b915050611709565b61170182613918565b919550935090505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf8239061173a9030906004016159e4565b6101206040518083038186803b15801561175357600080fd5b505afa158015611767573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178b91906157ac565b60c001516002546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc906117c490889088908790600401615ea7565b602060405180830381600087803b1580156117de57600080fd5b505af11580156117f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118169190615754565b9250611821836136ba565b60015460ff168015611842575060015461010090046001600160a01b031615155b156118f45760015460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b906118839088908890879089908890600401615ed8565b60206040518083038186803b15801561189b57600080fd5b505afa1580156118af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d391906156cb565b6118ef5760405162461bcd60e51b815260040161086790615bb7565b611901565b6001805460ff1916811790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d509858584866040516119369493929190615ebd565b60405180910390a15050505050565b61195182333333613abf565b6109ca81613c78565b6119626132ff565b6001600160a01b0316336001600160a01b0316146119925760405162461bcd60e51b815260040161086790615ccd565b601380549115156101000261ff0019909216919091179055565b600b5460ff1681565b6119bd6133e2565b6013805460ff1916911515919091179055565b60006119db82612b9e565b156119e8575060006119f8565b600f546119f3611cba565b111590505b919050565b60015460ff1681565b600b5461010090046001600160a01b031681565b600b54600160c81b900462ffffff1681565b6003546001600160a01b0316331480611a5d5750611a486132ff565b6001600160a01b0316336001600160a01b0316145b611a795760405162461bcd60e51b815260040161086790615ccd565b6001600160a01b038116611a8c57600080fd5b600580546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490610b569083906159e4565b6003546001600160a01b0316331480611b085750611af36132ff565b6001600160a01b0316336001600160a01b0316145b611b245760405162461bcd60e51b815260040161086790615ccd565b611b30600083836153b7565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda68282604051611b62929190615afa565b60405180910390a15050565b600b54604051633af9e66960e01b815260009182916101009091046001600160a01b031690633af9e66990611ba79030906004016159e4565b602060405180830381600087803b158015611bc157600080fd5b505af1158015611bd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf99190615754565b600b546040516395dd919360e01b815291935061010090046001600160a01b0316906395dd919390611c2f9030906004016159e4565b60206040518083038186803b158015611c4757600080fd5b505afa158015611c5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c7f9190615754565b90509091565b600654600090611cb49073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906001600160a01b031684611f12565b92915050565b600b54604051638e8f294b60e01b81526000918291733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91611d069161010090046001600160a01b0316906004016159e4565b60606040518083038186803b158015611d1e57600080fd5b505afa158015611d32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d569190615712565b50915050600080611d6561117d565b915091506000600b60019054906101000a90046001600160a01b03166001600160a01b031663f8f9da286040518163ffffffff1660e01b815260040160206040518083038186803b158015611db957600080fd5b505afa158015611dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df19190615754565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b031663ae9d70b06040518163ffffffff1660e01b815260040160206040518083038186803b158015611e4357600080fd5b505afa158015611e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7b9190615754565b90506000611e95670de0b6b3a76400006112348789613680565b9050806000611ea48686613680565b90506000611eb28386613680565b9050818110611ece5760001999505050505050505050506109ef565b6000611eda84896133a0565b90506000611ee884846133a0565b9050611f008161123484670de0b6b3a7640000613680565b9b5050505050505050505050506109ef565b600081611f2157506000611fcf565b600c546060906001600160a01b031663d06ca61f84611f408888614140565b6040518363ffffffff1660e01b8152600401611f5d929190615e1e565b60006040518083038186803b158015611f7557600080fd5b505afa158015611f89573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fb1919081019061561a565b905080600182510381518110611fc357fe5b60200260200101519150505b9392505050565b60095481565b600090565b6003546001600160a01b03163314806120125750611ffd6132ff565b6001600160a01b0316336001600160a01b0316145b61202e5760405162461bcd60e51b815260040161086790615ccd565b60098190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec29890610b56908390615af1565b60075481565b6120716133e2565b600b54604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b916120bc916101009091046001600160a01b0316906004016159e4565b60606040518083038186803b1580156120d457600080fd5b505afa1580156120e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061210c9190615712565b5091505081811161211c57600080fd5b50600e55565b600080600061212f61117d565b915091508160001415612147576000925050506109ef565b6109ea82611234670de0b6b3a764000084613680565b6004546001600160a01b031681565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156121ba57600080fd5b505afa1580156121ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f2919061550c565b6001600160a01b0316336001600160a01b0316148061222957506122146132ff565b6001600160a01b0316336001600160a01b0316145b6122455760405162461bcd60e51b815260040161086790615ccd565b6001805460ff1916911515919091179055565b6005546001600160a01b031681565b61226f6133e2565b600b805462ffffff928316600160c81b0262ffffff60c81b1994909316600160b01b0262ffffff60b01b199091161792909216179055565b60015461010090046001600160a01b031681565b600b54600160b01b900462ffffff1681565b6122d56133e2565b600b8054911515600160a81b0260ff60a81b19909216919091179055565b60135462010000900460ff1681565b60135460ff1681565b600e5481565b600b54600160a81b900460ff1681565b6003546001600160a01b0316331480612352575061233d6132ff565b6001600160a01b0316336001600160a01b0316145b61236e5760405162461bcd60e51b815260040161086790615ccd565b6001600160a01b03811661238157600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490610b569083906159e4565b601354610100900460ff1681565b6002546001600160a01b031633146123f157600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b15801561243857600080fd5b505afa15801561244c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612470919061550c565b6001600160a01b03161461248357600080fd5b61248c816142c1565b6006546040516370a0823160e01b815261104c9183916001600160a01b03909116906370a08231906124c29030906004016159e4565b60206040518083038186803b1580156124da57600080fd5b505afa1580156124ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125129190615754565b6006546001600160a01b03169190613381565b600080612530612e28565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906125669030906004016159e4565b6101206040518083038186803b15801561257f57600080fd5b505afa158015612593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b791906157ac565b60c001519050818111156125d0576000925050506109ef565b6125da82826133a0565b925050506109ef565b6125eb6133e2565b601255565b60008060006125fd61117d565b915091508160001415612615576000925050506109ef565b600b54604051636aa875b560e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91636aa875b591612660916101009091046001600160a01b0316906004016159e4565b60206040518083038186803b15801561267857600080fd5b505afa15801561268c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b09190615754565b600b546040516303d290cf60e61b8152919250600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b9163f4a433c0916126fd9161010090046001600160a01b0316906004016159e4565b60206040518083038186803b15801561271557600080fd5b505afa158015612729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274d9190615754565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561279f57600080fd5b505afa1580156127b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127d79190615754565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561282957600080fd5b505afa15801561283d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128619190615754565b90506000612901670de0b6b3a7640000611234600b60019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b1580156128c257600080fd5b505afa1580156128d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128fa9190615754565b8590613680565b90506000811561291c57612919826112348a89613680565b90505b6000841561293557612932856112348a89613680565b90505b600061294183836143cb565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906129779030906004016159e4565b6101206040518083038186803b15801561299057600080fd5b505afa1580156129a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c891906157ac565b60a00151905060006129df600d61123442856133a0565b90506129eb8184613680565b9c5050505050505050505050505090565b600c546001600160a01b031681565b6003546001600160a01b03163314612a355760405162461bcd60e51b815260040161086790615b3c565b6001600160a01b038116612a4857600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b393612a7f939091169160009101615a6e565b602060405180830381600087803b158015612a9957600080fd5b505af1158015612aad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad191906156cb565b50600480546001600160a01b0319166001600160a01b038381169190911780835560025460405163095ea7b360e01b81529083169363095ea7b393612b1c9316916000199101615a6e565b602060405180830381600087803b158015612b3657600080fd5b505af1158015612b4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6e91906156cb565b507fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06981604051610b5691906159e4565b600080612baa83611c85565b9050612bb4615435565b6002546040516339ebf82360e01b81526001600160a01b03909116906339ebf82390612be49030906004016159e4565b6101206040518083038186803b158015612bfd57600080fd5b505afa158015612c11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3591906157ac565b9050806020015160001415612c4f576000925050506119f8565b60075460a0820151612c629042906133a0565b1015612c73576000925050506119f8565b60085460a0820151612c869042906133a0565b10612c96576001925050506119f8565b6002546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b158015612cdb57600080fd5b505afa158015612cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d139190615754565b9050600a54811115612d2b57600193505050506119f8565b6000612d35612e28565b90508260c00151612d51600a54836143cb90919063ffffffff16565b1015612d645760019450505050506119f8565b60008360c00151821115612d855760c0840151612d829083906133a0565b90505b6002546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b158015612dca57600080fd5b505afa158015612dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e029190615754565b9050612e0e81836143cb565b600954612e1b9088613680565b1098975050505050505050565b6000806000612e3561117d565b915091506000612e436125f0565b90506000612e6473c00e94cb662c3520282e6f5717214004a7f268886143f0565b600654909150600090612e9a9073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b03166106c186866143cb565b90506000612eae600a611234846009613680565b9050612ee685612ee083612eda8a612eda600660009054906101000a90046001600160a01b03166143f0565b906143cb565b906133a0565b965050505050505090565b6003546001600160a01b0316331480612f225750612f0d6132ff565b6001600160a01b0316336001600160a01b0316145b612f3e5760405162461bcd60e51b815260040161086790615ccd565b60088190556040517f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590610b56908390615af1565b6002546001600160a01b031681565b6003546001600160a01b0316331480612fb35750612f9e6132ff565b6001600160a01b0316336001600160a01b0316145b806130545750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561300757600080fd5b505afa15801561301b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303f919061550c565b6001600160a01b0316336001600160a01b0316145b806130f55750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156130a857600080fd5b505afa1580156130bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e0919061550c565b6001600160a01b0316336001600160a01b0316145b6131115760405162461bcd60e51b815260040161086790615ccd565b600b805460ff191660011790556002546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b15801561316457600080fd5b505af1158015613178573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b80158061322f5750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906131dd90309086906004016159f8565b60206040518083038186803b1580156131f557600080fd5b505afa158015613209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322d9190615754565b155b61324b5760405162461bcd60e51b815260040161086790615d60565b6132a18363095ea7b360e01b848460405160240161326a929190615a6e565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261446f565b505050565b6000611fcf83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506144fe565b60606132f78484600085614535565b949350505050565b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b15801561334457600080fd5b505afa158015613358573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d29919061550c565b606090565b6132a18363a9059cbb60e01b848460405160240161326a929190615a6e565b6000611fcf83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614603565b6133ea6132ff565b6001600160a01b0316336001600160a01b0316148061349f5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561345257600080fd5b505afa158015613466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348a919061550c565b6001600160a01b0316336001600160a01b0316145b806134b457506003546001600160a01b031633145b61146a5760405162461bcd60e51b815260040161086790615ccd565b600654600090819081906134ec906001600160a01b03166143f0565b905060006134fc82612eda6109ce565b90506000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561354e57600080fd5b505afa158015613562573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135869190615754565b90508181111561359d5761359a81836133a0565b93505b6000806135a8611b6e565b915091508784101561361257600b546001906135d19061010090046001600160a01b03166143f0565b11156135eb576135e96135e483836133a0565b61462f565b505b60065461360b908990613606906001600160a01b03166143f0565b614977565b965061362b565b87851015613627576135e96135e489876133a0565b8796505b8787101561365057600061363f89896133a0565b9050601054811161364e578096505b505b60135462010000900460ff16156136765761366b87876143cb565b881461367657600080fd5b5050505050915091565b60008261368f57506000611cb4565b8282028284828161369c57fe5b0414611fcf5760405162461bcd60e51b815260040161086790615c14565b600b5460ff16156136ca5761104c565b6006546000906136e2906001600160a01b03166143f0565b90508181101561372457600b546001906137099061010090046001600160a01b03166143f0565b111561371e5761371c6135e483836133a0565b505b5061104c565b60008061373b61373484866133a0565b600161498d565b9150915060105482111561383d5760135460ff1661378d5760005b8215613787576137706137698484614a7f565b84906133a0565b92506006811061377f57613787565b600101613756565b5061383d565b738c2cc5ff69bc3760d7ce81812a2848421495972a6370c0345c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156137d157600080fd5b505af41580156137e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138099190615754565b8211156138275761382461381d8383614a7f565b83906133a0565b91505b60105482111561383d5761383b8183614bbb565b505b50505050565b60006138d3600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561389657600080fd5b505afa1580156138aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ce9190615754565b6134d0565b5090506000806138e161117d565b909250905060006138f283836133a0565b601354909150610100900460ff1661391257601054811061391257600080fd5b50505090565b600b54600090819081906139399061010090046001600160a01b03166143f0565b61396957600654600090613955906001600160a01b03166143f0565b90506139618186614977565b915050613ab8565b600080613974611b6e565b91509150613980614c59565b613988614d2c565b6006546000906139a0906001600160a01b03166143f0565b905060006139ae84846133a0565b905060006139bc82846143cb565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906139f29030906004016159e4565b6101206040518083038186803b158015613a0b57600080fd5b505afa158015613a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a4391906157ac565b60c00151905080821115613a9857613a5b82826133a0565b985088841015613a6d57839850613a93565b613a77898b6143cb565b841115613a8657899650613a93565b613a90848a6133a0565b96505b613ab1565b613aa281836133a0565b9750613aae848b614977565b96505b5050505050505b9193909250565b6006546001600160a01b031615613ae85760405162461bcd60e51b815260040161086790615bdd565b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b158015613b4457600080fd5b505afa158015613b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b7c919061550c565b600680546001600160a01b0319166001600160a01b039283161790819055613ba89116856000196131a7565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b393613c26939116916000199101615a6e565b602060405180830381600087803b158015613c4057600080fd5b505af1158015613c54573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061383b91906156cb565b80600b60016101000a8154816001600160a01b0302191690836001600160a01b031602179055506012600660009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015613cef57600080fd5b505afa158015613d03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d2791906158ab565b60ff161115613d3557600080fd5b600c80546001600160a01b03191673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f179055613d8d73c00e94cb662c3520282e6f5717214004a7f26888737a250d5630b4cf539739df2c5dacb4c659f2488d614f0b565b613dbf73c00e94cb662c3520282e6f5717214004a7f2688873d9e1ce17f2641f24ae83637ab66a2cca9c378b9f614f0b565b613df173c00e94cb662c3520282e6f5717214004a7f2688873e592427a0aece92de3edee1f18e0157c05861564614f0b565b600654600b54613e12916001600160a01b0390811691610100900416614f0b565b613e44736b175474e89094c44da98b954eedeac495271d0f731eb4cf3a948e7d72a198fe073ccb8c7a948cd853614f0b565b600b5460609061010090046001600160a01b0316735d3a536e4d6dbd6114cc1ead35777bab948e364314613f3d576040805160028082526060820183529091602083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e364381600081518110613eb457fe5b6001600160a01b039283166020918202929092010152600b5482516101009091049091169082906001908110613ee657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050613f38736b175474e89094c44da98b954eedeac495271d0f735d3a536e4d6dbd6114cc1ead35777bab948e3643614f0b565b613fa0565b6040805160018082528183019092529060208083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e364381600081518110613f7f57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b604051631853304760e31b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b9063c299823890613fd7908490600401615a87565b600060405180830381600087803b158015613ff157600080fd5b505af1158015614005573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261402d919081019061561a565b50600b805462ffffff60b01b191661017760b31b1762ffffff60c81b191661017760cb1b1790556201518060085560646009556c0c9f2c9cd04674edea40000000600a556006546040805163313ce56760e01b81529051614102926103e8926001600160a01b039091169163313ce56791600480820192602092909190829003018186803b1580156140be57600080fd5b505afa1580156140d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140f691906158ab565b60ff16600a0a906132a6565b601055505067016345785d8a00006012556708be35a9807f0000600e55670a217b21de090000600d5561b5a4600f556013805460ff19166001179055565b606060006001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2148061418b57506001600160a01b03831673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b90508061419957600361419c565b60025b60ff1667ffffffffffffffff811180156141b557600080fd5b506040519080825280602002602001820160405280156141df578160200160208202803683370190505b50915083826000815181106141f057fe5b60200260200101906001600160a01b031690816001600160a01b031681525050801561424957828260018151811061422457fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506142ba565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28260018151811061426b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050828260028151811061429957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b5092915050565b601354610100900460ff1661104c576000806142db611b6e565b90925090506142ed6135e483836133a0565b50600b546040516361bfb47160e11b815260009161010090046001600160a01b03169063c37f68e2906143249030906004016159e4565b60806040518083038186803b15801561433c57600080fd5b505afa158015614350573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143749190615876565b5092505050612710811061438757600080fd5b73c00e94cb662c3520282e6f5717214004a7f2688860006143a7826143f0565b905080156143c3576143c36001600160a01b0383168783613381565b505050505050565b600082820183811015611fcf5760405162461bcd60e51b815260040161086790615b80565b6040516370a0823160e01b81526000906001600160a01b038316906370a082319061441f9030906004016159e4565b60206040518083038186803b15801561443757600080fd5b505afa15801561444b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb49190615754565b60606144c4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132e89092919063ffffffff16565b8051909150156132a157808060200190518101906144e291906156cb565b6132a15760405162461bcd60e51b815260040161086790615cf2565b6000818361451f5760405162461bcd60e51b81526004016108679190615b29565b50600083858161452b57fe5b0495945050505050565b606061454085614f21565b61455c5760405162461bcd60e51b815260040161086790615c96565b60006060866001600160a01b0316858760405161457991906159c8565b60006040518083038185875af1925050503d80600081146145b6576040519150601f19603f3d011682016040523d82523d6000602084013e6145bb565b606091505b509150915081156145cf5791506132f79050565b8051156145df5780518082602001fd5b8360405162461bcd60e51b81526004016108679190615b29565b5050949350505050565b600081848411156146275760405162461bcd60e51b81526004016108679190615b29565b505050900390565b600080600061463f84600061498d565b91509150808015614651575060105482115b156146b75760135460ff16156146715761466e61381d8284614bbb565b91505b60005b6010546146829060646143cb565b8311156146b557614697613769846001614a7f565b9250600101600560ff8216106146b057600193506146b5565b614674565b505b6000806146c261117d565b600e5491935091506000816146dc5766038d7ea4c6800091505b6146f28261123485670de0b6b3a7640000613680565b90508084106148bb57600061470785836133a0565b600b546040516370a0823160e01b81529192506000916101009091046001600160a01b0316906370a08231906147419030906004016159e4565b60206040518083038186803b15801561475957600080fd5b505afa15801561476d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147919190615754565b905060018111156148b8578982101561483057600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e3906147d8908590600401615af1565b602060405180830381600087803b1580156147f257600080fd5b505af1158015614806573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061482a9190615754565b506148b8565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390614864908d90600401615af1565b602060405180830381600087803b15801561487e57600080fd5b505af1158015614892573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148b69190615754565b505b50505b600e541580156148df575060065483906148dd906001600160a01b03166143f0565b115b1561496c57600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290614918908690600401615af1565b602060405180830381600087803b15801561493257600080fd5b505af1158015614946573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061496a9190615754565b505b505050505050919050565b60008183106149865781611fcf565b5090919050565b60008060008061499b611b6e565b909250905060006149ac83836133a0565b9050600086156149c7576149c082896143cb565b90506149e0565b818811156149d3578197505b6149dd82896133a0565b90505b60006149f7600e548361368090919063ffffffff16565b90506000614a18600e54670de0b6b3a76400006133a090919063ffffffff16565b90506000614a2683836132a6565b9050620186a0811115614a4357614a4081620186a06133a0565b90505b85811015614a605760019750614a5986826133a0565b9850614a71565b60009750614a6e81876133a0565b98505b505050505050509250929050565b6000806000614a8c61117d565b91509150806000148015614a9d5750835b15614aad57600092505050611cb4565b600b54604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91614af8916101009091046001600160a01b0316906004016159e4565b60606040518083038186803b158015614b1057600080fd5b505afa158015614b24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b489190615712565b509150508415614b6557614b5e86848484614f5a565b9350614b74565b614b7186848484615173565b93505b7f012a05dea1e4b56be6c250aaa3e6189a1f531f1fd201b35b2a74c56577000bf48685876000604051614baa9493929190615e81565b60405180910390a150505092915050565b600654600d54604051633469949d60e01b8152600092738c2cc5ff69bc3760d7ce81812a2848421495972a92633469949d92614c0992889288926001600160a01b0390921691600401615aa5565b60206040518083038186803b158015614c2157600080fd5b505af4158015614c35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fcf9190615754565b60115460ff1615614c695761146a565b60408051600180825281830190925260609160208083019080368337019050509050600b60019054906101000a90046001600160a01b031681600081518110614cae57fe5b6001600160a01b039092166020928302919091019091015260405162e1ed9760e51b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b90631c3db2e090614cfe9030908590600401615a12565b600060405180830381600087803b158015614d1857600080fd5b505af115801561383b573d6000803e3d6000fd5b6000614d4b73c00e94cb662c3520282e6f5717214004a7f268886143f0565b9050601254811015614d5d575061146a565b600b54600160a81b900460ff1615614e56576040805160a0810190915260065473e592427a0aece92de3edee1f18e0157c058615649163c04b8d59918190614dc39073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b03166152e0565b8152602001306001600160a01b0316815260200142815260200184815260200160008152506040518263ffffffff1660e01b8152600401614e049190615db6565b602060405180830381600087803b158015614e1e57600080fd5b505af1158015614e32573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371e9190615754565b600c546006546001600160a01b03918216916338ed1739918491600091614e939173c00e94cb662c3520282e6f5717214004a7f268889116614140565b30426040518663ffffffff1660e01b8152600401614eb5959493929190615e37565b600060405180830381600087803b158015614ecf57600080fd5b505af1158015614ee3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109ca919081019061561a565b6109ca6001600160a01b038316826000196131a7565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906132f7575050151592915050565b6000808215614f7c57614f798361123486670de0b6b3a7640000613680565b90505b614f8685826133a0565b9150838210614f93578391505b858210614f9e578591505b6000600b60019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015614fee57600080fd5b505afa158015615002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150269190615754565b90508061503b84670de0b6b3a7640000613680565b101580156150495750600a83115b156145f95761505983600a6133a0565b600b5460405163852a12e360e01b815291945061010090046001600160a01b03169063852a12e39061508f908690600401615af1565b602060405180830381600087803b1580156150a957600080fd5b505af11580156150bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150e19190615754565b50600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290615116908690600401615af1565b602060405180830381600087803b15801561513057600080fd5b505af1158015615144573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151689190615754565b505050949350505050565b60008061518c670de0b6b3a76400006112348786613680565b905061519881856133a0565b91508582106151a5578591505b600a8211156152d7576151b982600a6133a0565b600b5460405163317afabb60e21b815291935061010090046001600160a01b03169063c5ebeaec906151ef908590600401615af1565b602060405180830381600087803b15801561520957600080fd5b505af115801561521d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906152419190615754565b50600b546006546001600160a01b0361010090920482169163a0712d689161526991166143f0565b6040518263ffffffff1660e01b81526004016152859190615af1565b602060405180830381600087803b15801561529f57600080fd5b505af11580156152b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145f99190615754565b50949350505050565b6006546060906001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561535a5782600b60169054906101000a900462ffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26040516020016153449392919061593b565b6040516020818303038152906040529050611cb4565b600b546040516153a091859162ffffff600160b01b830481169273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc292600160c81b909104909116908790602001615976565b604051602081830303815290604052905092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106153f85782800160ff19823516178555615425565b82800160010185558215615425579182015b8281111561542557823582559160200191906001019061540a565b50615431929150615481565b5090565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5b808211156154315760008155600101615482565b60008083601f8401126154a7578182fd5b50813567ffffffffffffffff8111156154be578182fd5b6020830191508360208285010111156154d657600080fd5b9250929050565b803562ffffff81168114611cb457600080fd5b600060208284031215615501578081fd5b8135611fcf81615f6e565b60006020828403121561551d578081fd5b8151611fcf81615f6e565b6000806040838503121561553a578081fd5b823561554581615f6e565b9150602083013561555581615f6e565b809150509250929050565b600080600060608486031215615574578081fd5b833561557f81615f6e565b9250602084013561558f81615f6e565b929592945050506040919091013590565b60008060008060008060a087890312156155b8578182fd5b86356155c381615f6e565b955060208701356155d381615f6e565b94506040870135935060608701359250608087013567ffffffffffffffff8111156155fc578283fd5b61560889828a01615496565b979a9699509497509295939492505050565b6000602080838503121561562c578182fd5b825167ffffffffffffffff811115615642578283fd5b8301601f81018513615652578283fd5b805161566561566082615f22565b615efb565b8181528381019083850185840285018601891015615681578687fd5b8694505b838510156156a3578051835260019490940193918501918501615685565b50979650505050505050565b6000602082840312156156c0578081fd5b8135611fcf81615f83565b6000602082840312156156dc578081fd5b8151611fcf81615f83565b600080604083850312156156f9578182fd5b823561570481615f83565b946020939093013593505050565b600080600060608486031215615726578283fd5b835161573181615f83565b60208501516040860151919450925061574981615f83565b809150509250925092565b600060208284031215615765578081fd5b5051919050565b6000806020838503121561577e578182fd5b823567ffffffffffffffff811115615794578283fd5b6157a085828601615496565b90969095509350505050565b60006101208083850312156157bf578182fd5b6157c881615efb565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b6000806040838503121561583c578182fd5b61584684846154dd565b915061585584602085016154dd565b90509250929050565b60006020828403121561586f578081fd5b5035919050565b6000806000806080858703121561588b578182fd5b505082516020840151604085015160609095015191969095509092509050565b6000602082840312156158bc578081fd5b815160ff81168114611fcf578182fd5b6000815180845260208085019450808401835b838110156159045781516001600160a01b0316875295820195908201906001016158df565b509495945050505050565b60008151808452615927816020860160208601615f42565b601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b6001600160e81b0319166014820152921b166017820152602b0190565b6bffffffffffffffffffffffff19606096871b811682526001600160e81b031960e896871b8116601484015294871b811660178301529290941b909216602b840152921b909116602e82015260420190565b600082516159da818460208701615f42565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b81811015615a60578551851683529483019491830191600101615a42565b509098975050505050505050565b6001600160a01b03929092168252602082015260400190565b600060208252611fcf60208301846158cc565b901515815260200190565b931515845260208401929092526001600160a01b03166040830152606082015260800190565b9315158452602084019290925260408301526001600160a01b0316606082015260800190565b90815260200190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b600060208252611fcf602083018461590f565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b600060208252825160a06020840152615dd260c084018261590f565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b62ffffff91909116815260200190565b6000838252604060208301526132f760408301846158cc565b600086825285602083015260a06040830152615e5660a08301866158cc565b6001600160a01b0394909416606083015250608001529392505050565b918252602082015260400190565b9384526020840192909252151560408301526001600160a01b0316606082015260800190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff81118282101715615f1a57600080fd5b604052919050565b600067ffffffffffffffff821115615f38578081fd5b5060209081020190565b60005b83811015615f5d578181015183820152602001615f45565b8381111561383d5750506000910152565b6001600160a01b038116811461104c57600080fd5b801515811461104c57600080fdfea26469706673582212204fbe1f6c346640ade3ea6687ce05bc5b2469b59584aa4a7c2a914b6f2ecc4d9d64736f6c634300060c0033000000000000000000000000da816459f1ab5631232fe5e97a05bbbb94970c950000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104335760003560e01c806373b3828511610236578063b2c5f6581161013b578063d3406abd116100c3578063ed882c2b11610087578063ed882c2b146107f1578063efbb5cb014610804578063f017c92f1461080c578063fbfa77cf1461081f578063fcf2d0ad1461082757610433565b8063d3406abd146107b3578063db2fd745146107bb578063e00425a3146107ce578063e0b8c948146107d6578063ec38a862146107de57610433565b8063c1bb4b541161010a578063c1bb4b5414610775578063c59848471461077d578063c7b9d53014610785578063cb1965dd14610798578063ce5494bb146107a057610433565b8063b2c5f6581461074a578063b2d0c8e214610752578063ba0ad98614610765578063bf83e0af1461076d57610433565b806391397ab4116101be5780639ec5a8941161018d5780639ec5a8941461070c578063ac00ff2614610714578063aced166114610727578063aef6679e1461072f578063b252720b1461074257610433565b806391397ab4146106d657806395e80c50146106e95780639a561fbf146106f15780639be8ef141461070457610433565b8063780022a011610205578063780022a014610698578063853e0a3b146106ab57806389be318a146106b35780638cdfe166146106c65780638e6350e2146106ce57610433565b806373b3828514610655578063748747e61461066a578063750521f51461067d578063775d35e51461069057610433565b80632e1a7d4d1161033c578063440368a3116102c45780635641ec03116102935780635641ec031461061757806356cdac2c1461061f578063650d1880146106325780636718835f1461064557806369e527da1461064d57610433565b8063440368a3146105e15780634641257d146105e9578063485cc955146105f157806354f809e31461060457610433565b8063396794cd1161030b578063396794cd1461059557806339a172a8146105a85780633e5f0ae8146105bb57806340f8bc43146105c3578063418f35cc146105cb57610433565b80632e1a7d4d146105495780633042087c1461055c5780633631ad5f1461056f5780633922b4a81461058257610433565b80631d12f28b116103bf57806322f3e2d41161038e57806322f3e2d41461050957806323e30c8b1461051e578063258294101461053157806327cc1ea21461053957806328b7ccf71461054157610433565b80631d12f28b146104dc5780631f1fcd51146104e45780631fe4a686146104f9578063205409d31461050157610433565b806305a82f9a1161040657806305a82f9a1461048857806306fdde031461049b5780630c17c733146104a35780630f969b87146104b657806311bc8245146104c957610433565b806301681a62146104385780630268ff0b1461044d57806303ee438c1461046b57806304324af814610480575b600080fd5b61044b6104463660046154f0565b61082f565b005b6104556109ce565b6040516104629190615af1565b60405180910390f35b6104736109f2565b6040516104629190615b29565b610455610a80565b61044b6104963660046156af565b610a86565b610473610aa1565b61044b6104b136600461585e565b610ac7565b61044b6104c436600461585e565b610ad4565b61044b6104d73660046154f0565b610b61565b610455610c62565b6104ec610c68565b60405161046291906159e4565b6104ec610c77565b610455610c86565b610511610c8c565b6040516104629190615a9a565b61045561052c3660046155a0565b610d2e565b610473610e24565b61044b610e43565b610455610ec3565b61045561055736600461585e565b610ec9565b61044b61056a36600461585e565b610f24565b61044b61057d36600461585e565b61104f565b61044b6105903660046156af565b61105c565b61044b6105a336600461585e565b611080565b61044b6105b636600461585e565b6110ec565b61045561116e565b610511611174565b6105d361117d565b604051610462929190615e73565b61044b611243565b61044b61146c565b61044b6105ff366004615528565b611945565b61044b6106123660046156af565b61195a565b6105116119ac565b61044b61062d3660046156af565b6119b5565b61051161064036600461585e565b6119d0565b6105116119fd565b6104ec611a06565b61065d611a1a565b6040516104629190615e0e565b61044b6106783660046154f0565b611a2c565b61044b61068b36600461576c565b611ad7565b6105d3611b6e565b6104556106a636600461585e565b611c85565b610455611cba565b6104556106c1366004615560565b611f12565b610455611fd6565b610455611fdc565b61044b6106e436600461585e565b611fe1565b610455612063565b61044b6106ff36600461585e565b612069565b610455612122565b6104ec61215d565b61044b6107223660046156af565b61216c565b6104ec612258565b61044b61073d36600461582a565b612267565b6104ec6122a7565b61065d6122bb565b61044b6107603660046156af565b6122cd565b6105116122f3565b610511612302565b61045561230b565b610511612311565b61044b6107933660046154f0565b612321565b6105116123cc565b61044b6107ae3660046154f0565b6123da565b610455612525565b61044b6107c936600461585e565b6125e3565b6104556125f0565b6104ec6129fc565b61044b6107ec3660046154f0565b612a0b565b6105116107ff36600461585e565b612b9e565b610455612e28565b61044b61081a36600461585e565b612ef1565b6104ec612f73565b61044b612f82565b6108376132ff565b6001600160a01b0316336001600160a01b0316146108705760405162461bcd60e51b815260040161086790615ccd565b60405180910390fd5b6006546001600160a01b038281169116141561089e5760405162461bcd60e51b815260040161086790615b61565b6002546001600160a01b03828116911614156108cc5760405162461bcd60e51b815260040161086790615c75565b60606108d661337c565b905060005b8151811015610931578181815181106108f057fe5b60200260200101516001600160a01b0316836001600160a01b031614156109295760405162461bcd60e51b815260040161086790615d3c565b6001016108db565b506109ca61093d6132ff565b6040516370a0823160e01b81526001600160a01b038516906370a08231906109699030906004016159e4565b60206040518083038186803b15801561098157600080fd5b505afa158015610995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b99190615754565b6001600160a01b0385169190613381565b5050565b60008060006109db61117d565b90925090506109ea82826133a0565b925050505b90565b6000805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610a785780601f10610a4d57610100808354040283529160200191610a78565b820191906000526020600020905b815481529060010190602001808311610a5b57829003601f168201915b505050505081565b60125481565b610a8e6133e2565b6011805460ff1916911515919091179055565b60408051808201909152600c81526b47656e4c6576436f6d70563360a01b602082015290565b610acf6133e2565b600d55565b6003546001600160a01b0316331480610b055750610af06132ff565b6001600160a01b0316336001600160a01b0316145b610b215760405162461bcd60e51b815260040161086790615ccd565b600a8190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a860090610b56908390615af1565b60405180910390a150565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610baf57600080fd5b505afa158015610bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be7919061550c565b6001600160a01b0316336001600160a01b03161480610c1e5750610c096132ff565b6001600160a01b0316336001600160a01b0316145b610c3a5760405162461bcd60e51b815260040161086790615ccd565b600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600a5481565b6006546001600160a01b031681565b6003546001600160a01b031681565b60105481565b6002546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610cc19030906004016159e4565b6101206040518083038186803b158015610cda57600080fd5b505afa158015610cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1291906157ac565b604001511180610d2957506000610d27612e28565b115b905090565b600033731eb4cf3a948e7d72a198fe073ccb8c7a948cd85314610d5057600080fd5b6001600160a01b0387163014610d6557600080fd5b600080610d74848601866156e7565b600b546040516353cd344560e11b8152929450909250738c2cc5ff69bc3760d7ce81812a2848421495972a9163a79a688a91610dc79186918c91879161010090046001600160a01b031690600401615acb565b60206040518083038186803b158015610ddf57600080fd5b505af4158015610df3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e179190615754565b9998505050505050505050565b604080518082019091526005815264302e342e3360d81b602082015290565b610e4b6133e2565b600c546001600160a01b031673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f14610e8b5773d9e1ce17f2641f24ae83637ab66a2cca9c378b9f610ea1565b737a250d5630b4cf539739df2c5dacb4c659f2488d5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b60085481565b6002546000906001600160a01b03163314610ef65760405162461bcd60e51b815260040161086790615c55565b6000610f01836134d0565b600654909350909150610f1e906001600160a01b03163383613381565b50919050565b610f2c6133e2565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390610f60908490600401615af1565b602060405180830381600087803b158015610f7a57600080fd5b505af1158015610f8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb29190615754565b15610fbc57600080fd5b600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290610ff0908490600401615af1565b602060405180830381600087803b15801561100a57600080fd5b505af115801561101e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110429190615754565b1561104c57600080fd5b50565b6110576133e2565b601055565b6110646133e2565b60138054911515620100000262ff000019909216919091179055565b6110886132ff565b6001600160a01b0316336001600160a01b0316146110b85760405162461bcd60e51b815260040161086790615ccd565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390610ff0908490600401615af1565b6003546001600160a01b031633148061111d57506111086132ff565b6001600160a01b0316336001600160a01b0316145b6111395760405162461bcd60e51b815260040161086790615ccd565b60078190556040517fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190610b56908390615af1565b600d5481565b60115460ff1681565b600b546040516361bfb47160e11b8152600091829182918291829161010090046001600160a01b03169063c37f68e2906111bb9030906004016159e4565b60806040518083038186803b1580156111d357600080fd5b505afa1580156111e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120b9190615876565b9350935093505081935061123a670de0b6b3a7640000611234838661368090919063ffffffff16565b906132a6565b94505050509091565b6005546001600160a01b031633148061126657506003546001600160a01b031633145b8061128957506112746132ff565b6001600160a01b0316336001600160a01b0316145b8061132a5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156112dd57600080fd5b505afa1580156112f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611315919061550c565b6001600160a01b0316336001600160a01b0316145b806113cb5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561137e57600080fd5b505afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b6919061550c565b6001600160a01b0316336001600160a01b0316145b6113e75760405162461bcd60e51b815260040161086790615ccd565b6002546040805163bf3759b560e01b8152905161146a926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561142d57600080fd5b505afa158015611441573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114659190615754565b6136ba565b565b6005546001600160a01b031633148061148f57506003546001600160a01b031633145b806114b2575061149d6132ff565b6001600160a01b0316336001600160a01b0316145b806115535750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561150657600080fd5b505afa15801561151a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153e919061550c565b6001600160a01b0316336001600160a01b0316145b806115f45750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156115a757600080fd5b505afa1580156115bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115df919061550c565b6001600160a01b0316336001600160a01b0316145b6116105760405162461bcd60e51b815260040161086790615ccd565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561166357600080fd5b505afa158015611677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169b9190615754565b600b5490915060009060ff16156116f85760006116b6613843565b9050828110156116d1576116ca83826133a0565b93506116e6565b828111156116e6576116e381846133a0565b94505b6116f083856133a0565b915050611709565b61170182613918565b919550935090505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf8239061173a9030906004016159e4565b6101206040518083038186803b15801561175357600080fd5b505afa158015611767573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178b91906157ac565b60c001516002546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc906117c490889088908790600401615ea7565b602060405180830381600087803b1580156117de57600080fd5b505af11580156117f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118169190615754565b9250611821836136ba565b60015460ff168015611842575060015461010090046001600160a01b031615155b156118f45760015460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b906118839088908890879089908890600401615ed8565b60206040518083038186803b15801561189b57600080fd5b505afa1580156118af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d391906156cb565b6118ef5760405162461bcd60e51b815260040161086790615bb7565b611901565b6001805460ff1916811790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d509858584866040516119369493929190615ebd565b60405180910390a15050505050565b61195182333333613abf565b6109ca81613c78565b6119626132ff565b6001600160a01b0316336001600160a01b0316146119925760405162461bcd60e51b815260040161086790615ccd565b601380549115156101000261ff0019909216919091179055565b600b5460ff1681565b6119bd6133e2565b6013805460ff1916911515919091179055565b60006119db82612b9e565b156119e8575060006119f8565b600f546119f3611cba565b111590505b919050565b60015460ff1681565b600b5461010090046001600160a01b031681565b600b54600160c81b900462ffffff1681565b6003546001600160a01b0316331480611a5d5750611a486132ff565b6001600160a01b0316336001600160a01b0316145b611a795760405162461bcd60e51b815260040161086790615ccd565b6001600160a01b038116611a8c57600080fd5b600580546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490610b569083906159e4565b6003546001600160a01b0316331480611b085750611af36132ff565b6001600160a01b0316336001600160a01b0316145b611b245760405162461bcd60e51b815260040161086790615ccd565b611b30600083836153b7565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda68282604051611b62929190615afa565b60405180910390a15050565b600b54604051633af9e66960e01b815260009182916101009091046001600160a01b031690633af9e66990611ba79030906004016159e4565b602060405180830381600087803b158015611bc157600080fd5b505af1158015611bd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf99190615754565b600b546040516395dd919360e01b815291935061010090046001600160a01b0316906395dd919390611c2f9030906004016159e4565b60206040518083038186803b158015611c4757600080fd5b505afa158015611c5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c7f9190615754565b90509091565b600654600090611cb49073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906001600160a01b031684611f12565b92915050565b600b54604051638e8f294b60e01b81526000918291733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91611d069161010090046001600160a01b0316906004016159e4565b60606040518083038186803b158015611d1e57600080fd5b505afa158015611d32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d569190615712565b50915050600080611d6561117d565b915091506000600b60019054906101000a90046001600160a01b03166001600160a01b031663f8f9da286040518163ffffffff1660e01b815260040160206040518083038186803b158015611db957600080fd5b505afa158015611dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df19190615754565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b031663ae9d70b06040518163ffffffff1660e01b815260040160206040518083038186803b158015611e4357600080fd5b505afa158015611e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7b9190615754565b90506000611e95670de0b6b3a76400006112348789613680565b9050806000611ea48686613680565b90506000611eb28386613680565b9050818110611ece5760001999505050505050505050506109ef565b6000611eda84896133a0565b90506000611ee884846133a0565b9050611f008161123484670de0b6b3a7640000613680565b9b5050505050505050505050506109ef565b600081611f2157506000611fcf565b600c546060906001600160a01b031663d06ca61f84611f408888614140565b6040518363ffffffff1660e01b8152600401611f5d929190615e1e565b60006040518083038186803b158015611f7557600080fd5b505afa158015611f89573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fb1919081019061561a565b905080600182510381518110611fc357fe5b60200260200101519150505b9392505050565b60095481565b600090565b6003546001600160a01b03163314806120125750611ffd6132ff565b6001600160a01b0316336001600160a01b0316145b61202e5760405162461bcd60e51b815260040161086790615ccd565b60098190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec29890610b56908390615af1565b60075481565b6120716133e2565b600b54604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b916120bc916101009091046001600160a01b0316906004016159e4565b60606040518083038186803b1580156120d457600080fd5b505afa1580156120e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061210c9190615712565b5091505081811161211c57600080fd5b50600e55565b600080600061212f61117d565b915091508160001415612147576000925050506109ef565b6109ea82611234670de0b6b3a764000084613680565b6004546001600160a01b031681565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156121ba57600080fd5b505afa1580156121ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f2919061550c565b6001600160a01b0316336001600160a01b0316148061222957506122146132ff565b6001600160a01b0316336001600160a01b0316145b6122455760405162461bcd60e51b815260040161086790615ccd565b6001805460ff1916911515919091179055565b6005546001600160a01b031681565b61226f6133e2565b600b805462ffffff928316600160c81b0262ffffff60c81b1994909316600160b01b0262ffffff60b01b199091161792909216179055565b60015461010090046001600160a01b031681565b600b54600160b01b900462ffffff1681565b6122d56133e2565b600b8054911515600160a81b0260ff60a81b19909216919091179055565b60135462010000900460ff1681565b60135460ff1681565b600e5481565b600b54600160a81b900460ff1681565b6003546001600160a01b0316331480612352575061233d6132ff565b6001600160a01b0316336001600160a01b0316145b61236e5760405162461bcd60e51b815260040161086790615ccd565b6001600160a01b03811661238157600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490610b569083906159e4565b601354610100900460ff1681565b6002546001600160a01b031633146123f157600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b15801561243857600080fd5b505afa15801561244c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612470919061550c565b6001600160a01b03161461248357600080fd5b61248c816142c1565b6006546040516370a0823160e01b815261104c9183916001600160a01b03909116906370a08231906124c29030906004016159e4565b60206040518083038186803b1580156124da57600080fd5b505afa1580156124ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125129190615754565b6006546001600160a01b03169190613381565b600080612530612e28565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906125669030906004016159e4565b6101206040518083038186803b15801561257f57600080fd5b505afa158015612593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b791906157ac565b60c001519050818111156125d0576000925050506109ef565b6125da82826133a0565b925050506109ef565b6125eb6133e2565b601255565b60008060006125fd61117d565b915091508160001415612615576000925050506109ef565b600b54604051636aa875b560e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91636aa875b591612660916101009091046001600160a01b0316906004016159e4565b60206040518083038186803b15801561267857600080fd5b505afa15801561268c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b09190615754565b600b546040516303d290cf60e61b8152919250600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b9163f4a433c0916126fd9161010090046001600160a01b0316906004016159e4565b60206040518083038186803b15801561271557600080fd5b505afa158015612729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274d9190615754565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561279f57600080fd5b505afa1580156127b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127d79190615754565b90506000600b60019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561282957600080fd5b505afa15801561283d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128619190615754565b90506000612901670de0b6b3a7640000611234600b60019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b1580156128c257600080fd5b505afa1580156128d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128fa9190615754565b8590613680565b90506000811561291c57612919826112348a89613680565b90505b6000841561293557612932856112348a89613680565b90505b600061294183836143cb565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906129779030906004016159e4565b6101206040518083038186803b15801561299057600080fd5b505afa1580156129a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c891906157ac565b60a00151905060006129df600d61123442856133a0565b90506129eb8184613680565b9c5050505050505050505050505090565b600c546001600160a01b031681565b6003546001600160a01b03163314612a355760405162461bcd60e51b815260040161086790615b3c565b6001600160a01b038116612a4857600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b393612a7f939091169160009101615a6e565b602060405180830381600087803b158015612a9957600080fd5b505af1158015612aad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad191906156cb565b50600480546001600160a01b0319166001600160a01b038381169190911780835560025460405163095ea7b360e01b81529083169363095ea7b393612b1c9316916000199101615a6e565b602060405180830381600087803b158015612b3657600080fd5b505af1158015612b4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6e91906156cb565b507fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06981604051610b5691906159e4565b600080612baa83611c85565b9050612bb4615435565b6002546040516339ebf82360e01b81526001600160a01b03909116906339ebf82390612be49030906004016159e4565b6101206040518083038186803b158015612bfd57600080fd5b505afa158015612c11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3591906157ac565b9050806020015160001415612c4f576000925050506119f8565b60075460a0820151612c629042906133a0565b1015612c73576000925050506119f8565b60085460a0820151612c869042906133a0565b10612c96576001925050506119f8565b6002546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b158015612cdb57600080fd5b505afa158015612cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d139190615754565b9050600a54811115612d2b57600193505050506119f8565b6000612d35612e28565b90508260c00151612d51600a54836143cb90919063ffffffff16565b1015612d645760019450505050506119f8565b60008360c00151821115612d855760c0840151612d829083906133a0565b90505b6002546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b158015612dca57600080fd5b505afa158015612dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e029190615754565b9050612e0e81836143cb565b600954612e1b9088613680565b1098975050505050505050565b6000806000612e3561117d565b915091506000612e436125f0565b90506000612e6473c00e94cb662c3520282e6f5717214004a7f268886143f0565b600654909150600090612e9a9073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b03166106c186866143cb565b90506000612eae600a611234846009613680565b9050612ee685612ee083612eda8a612eda600660009054906101000a90046001600160a01b03166143f0565b906143cb565b906133a0565b965050505050505090565b6003546001600160a01b0316331480612f225750612f0d6132ff565b6001600160a01b0316336001600160a01b0316145b612f3e5760405162461bcd60e51b815260040161086790615ccd565b60088190556040517f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590610b56908390615af1565b6002546001600160a01b031681565b6003546001600160a01b0316331480612fb35750612f9e6132ff565b6001600160a01b0316336001600160a01b0316145b806130545750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561300757600080fd5b505afa15801561301b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303f919061550c565b6001600160a01b0316336001600160a01b0316145b806130f55750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156130a857600080fd5b505afa1580156130bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e0919061550c565b6001600160a01b0316336001600160a01b0316145b6131115760405162461bcd60e51b815260040161086790615ccd565b600b805460ff191660011790556002546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b15801561316457600080fd5b505af1158015613178573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b80158061322f5750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906131dd90309086906004016159f8565b60206040518083038186803b1580156131f557600080fd5b505afa158015613209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322d9190615754565b155b61324b5760405162461bcd60e51b815260040161086790615d60565b6132a18363095ea7b360e01b848460405160240161326a929190615a6e565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261446f565b505050565b6000611fcf83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506144fe565b60606132f78484600085614535565b949350505050565b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b15801561334457600080fd5b505afa158015613358573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d29919061550c565b606090565b6132a18363a9059cbb60e01b848460405160240161326a929190615a6e565b6000611fcf83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614603565b6133ea6132ff565b6001600160a01b0316336001600160a01b0316148061349f5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561345257600080fd5b505afa158015613466573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061348a919061550c565b6001600160a01b0316336001600160a01b0316145b806134b457506003546001600160a01b031633145b61146a5760405162461bcd60e51b815260040161086790615ccd565b600654600090819081906134ec906001600160a01b03166143f0565b905060006134fc82612eda6109ce565b90506000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561354e57600080fd5b505afa158015613562573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135869190615754565b90508181111561359d5761359a81836133a0565b93505b6000806135a8611b6e565b915091508784101561361257600b546001906135d19061010090046001600160a01b03166143f0565b11156135eb576135e96135e483836133a0565b61462f565b505b60065461360b908990613606906001600160a01b03166143f0565b614977565b965061362b565b87851015613627576135e96135e489876133a0565b8796505b8787101561365057600061363f89896133a0565b9050601054811161364e578096505b505b60135462010000900460ff16156136765761366b87876143cb565b881461367657600080fd5b5050505050915091565b60008261368f57506000611cb4565b8282028284828161369c57fe5b0414611fcf5760405162461bcd60e51b815260040161086790615c14565b600b5460ff16156136ca5761104c565b6006546000906136e2906001600160a01b03166143f0565b90508181101561372457600b546001906137099061010090046001600160a01b03166143f0565b111561371e5761371c6135e483836133a0565b505b5061104c565b60008061373b61373484866133a0565b600161498d565b9150915060105482111561383d5760135460ff1661378d5760005b8215613787576137706137698484614a7f565b84906133a0565b92506006811061377f57613787565b600101613756565b5061383d565b738c2cc5ff69bc3760d7ce81812a2848421495972a6370c0345c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156137d157600080fd5b505af41580156137e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138099190615754565b8211156138275761382461381d8383614a7f565b83906133a0565b91505b60105482111561383d5761383b8183614bbb565b505b50505050565b60006138d3600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561389657600080fd5b505afa1580156138aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ce9190615754565b6134d0565b5090506000806138e161117d565b909250905060006138f283836133a0565b601354909150610100900460ff1661391257601054811061391257600080fd5b50505090565b600b54600090819081906139399061010090046001600160a01b03166143f0565b61396957600654600090613955906001600160a01b03166143f0565b90506139618186614977565b915050613ab8565b600080613974611b6e565b91509150613980614c59565b613988614d2c565b6006546000906139a0906001600160a01b03166143f0565b905060006139ae84846133a0565b905060006139bc82846143cb565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf823906139f29030906004016159e4565b6101206040518083038186803b158015613a0b57600080fd5b505afa158015613a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a4391906157ac565b60c00151905080821115613a9857613a5b82826133a0565b985088841015613a6d57839850613a93565b613a77898b6143cb565b841115613a8657899650613a93565b613a90848a6133a0565b96505b613ab1565b613aa281836133a0565b9750613aae848b614977565b96505b5050505050505b9193909250565b6006546001600160a01b031615613ae85760405162461bcd60e51b815260040161086790615bdd565b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b158015613b4457600080fd5b505afa158015613b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b7c919061550c565b600680546001600160a01b0319166001600160a01b039283161790819055613ba89116856000196131a7565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b393613c26939116916000199101615a6e565b602060405180830381600087803b158015613c4057600080fd5b505af1158015613c54573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061383b91906156cb565b80600b60016101000a8154816001600160a01b0302191690836001600160a01b031602179055506012600660009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015613cef57600080fd5b505afa158015613d03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d2791906158ab565b60ff161115613d3557600080fd5b600c80546001600160a01b03191673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f179055613d8d73c00e94cb662c3520282e6f5717214004a7f26888737a250d5630b4cf539739df2c5dacb4c659f2488d614f0b565b613dbf73c00e94cb662c3520282e6f5717214004a7f2688873d9e1ce17f2641f24ae83637ab66a2cca9c378b9f614f0b565b613df173c00e94cb662c3520282e6f5717214004a7f2688873e592427a0aece92de3edee1f18e0157c05861564614f0b565b600654600b54613e12916001600160a01b0390811691610100900416614f0b565b613e44736b175474e89094c44da98b954eedeac495271d0f731eb4cf3a948e7d72a198fe073ccb8c7a948cd853614f0b565b600b5460609061010090046001600160a01b0316735d3a536e4d6dbd6114cc1ead35777bab948e364314613f3d576040805160028082526060820183529091602083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e364381600081518110613eb457fe5b6001600160a01b039283166020918202929092010152600b5482516101009091049091169082906001908110613ee657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050613f38736b175474e89094c44da98b954eedeac495271d0f735d3a536e4d6dbd6114cc1ead35777bab948e3643614f0b565b613fa0565b6040805160018082528183019092529060208083019080368337019050509050735d3a536e4d6dbd6114cc1ead35777bab948e364381600081518110613f7f57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b604051631853304760e31b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b9063c299823890613fd7908490600401615a87565b600060405180830381600087803b158015613ff157600080fd5b505af1158015614005573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261402d919081019061561a565b50600b805462ffffff60b01b191661017760b31b1762ffffff60c81b191661017760cb1b1790556201518060085560646009556c0c9f2c9cd04674edea40000000600a556006546040805163313ce56760e01b81529051614102926103e8926001600160a01b039091169163313ce56791600480820192602092909190829003018186803b1580156140be57600080fd5b505afa1580156140d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140f691906158ab565b60ff16600a0a906132a6565b601055505067016345785d8a00006012556708be35a9807f0000600e55670a217b21de090000600d5561b5a4600f556013805460ff19166001179055565b606060006001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2148061418b57506001600160a01b03831673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b90508061419957600361419c565b60025b60ff1667ffffffffffffffff811180156141b557600080fd5b506040519080825280602002602001820160405280156141df578160200160208202803683370190505b50915083826000815181106141f057fe5b60200260200101906001600160a01b031690816001600160a01b031681525050801561424957828260018151811061422457fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506142ba565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28260018151811061426b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050828260028151811061429957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b5092915050565b601354610100900460ff1661104c576000806142db611b6e565b90925090506142ed6135e483836133a0565b50600b546040516361bfb47160e11b815260009161010090046001600160a01b03169063c37f68e2906143249030906004016159e4565b60806040518083038186803b15801561433c57600080fd5b505afa158015614350573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143749190615876565b5092505050612710811061438757600080fd5b73c00e94cb662c3520282e6f5717214004a7f2688860006143a7826143f0565b905080156143c3576143c36001600160a01b0383168783613381565b505050505050565b600082820183811015611fcf5760405162461bcd60e51b815260040161086790615b80565b6040516370a0823160e01b81526000906001600160a01b038316906370a082319061441f9030906004016159e4565b60206040518083038186803b15801561443757600080fd5b505afa15801561444b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb49190615754565b60606144c4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132e89092919063ffffffff16565b8051909150156132a157808060200190518101906144e291906156cb565b6132a15760405162461bcd60e51b815260040161086790615cf2565b6000818361451f5760405162461bcd60e51b81526004016108679190615b29565b50600083858161452b57fe5b0495945050505050565b606061454085614f21565b61455c5760405162461bcd60e51b815260040161086790615c96565b60006060866001600160a01b0316858760405161457991906159c8565b60006040518083038185875af1925050503d80600081146145b6576040519150601f19603f3d011682016040523d82523d6000602084013e6145bb565b606091505b509150915081156145cf5791506132f79050565b8051156145df5780518082602001fd5b8360405162461bcd60e51b81526004016108679190615b29565b5050949350505050565b600081848411156146275760405162461bcd60e51b81526004016108679190615b29565b505050900390565b600080600061463f84600061498d565b91509150808015614651575060105482115b156146b75760135460ff16156146715761466e61381d8284614bbb565b91505b60005b6010546146829060646143cb565b8311156146b557614697613769846001614a7f565b9250600101600560ff8216106146b057600193506146b5565b614674565b505b6000806146c261117d565b600e5491935091506000816146dc5766038d7ea4c6800091505b6146f28261123485670de0b6b3a7640000613680565b90508084106148bb57600061470785836133a0565b600b546040516370a0823160e01b81529192506000916101009091046001600160a01b0316906370a08231906147419030906004016159e4565b60206040518083038186803b15801561475957600080fd5b505afa15801561476d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147919190615754565b905060018111156148b8578982101561483057600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e3906147d8908590600401615af1565b602060405180830381600087803b1580156147f257600080fd5b505af1158015614806573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061482a9190615754565b506148b8565b600b5460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390614864908d90600401615af1565b602060405180830381600087803b15801561487e57600080fd5b505af1158015614892573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148b69190615754565b505b50505b600e541580156148df575060065483906148dd906001600160a01b03166143f0565b115b1561496c57600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290614918908690600401615af1565b602060405180830381600087803b15801561493257600080fd5b505af1158015614946573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061496a9190615754565b505b505050505050919050565b60008183106149865781611fcf565b5090919050565b60008060008061499b611b6e565b909250905060006149ac83836133a0565b9050600086156149c7576149c082896143cb565b90506149e0565b818811156149d3578197505b6149dd82896133a0565b90505b60006149f7600e548361368090919063ffffffff16565b90506000614a18600e54670de0b6b3a76400006133a090919063ffffffff16565b90506000614a2683836132a6565b9050620186a0811115614a4357614a4081620186a06133a0565b90505b85811015614a605760019750614a5986826133a0565b9850614a71565b60009750614a6e81876133a0565b98505b505050505050509250929050565b6000806000614a8c61117d565b91509150806000148015614a9d5750835b15614aad57600092505050611cb4565b600b54604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91614af8916101009091046001600160a01b0316906004016159e4565b60606040518083038186803b158015614b1057600080fd5b505afa158015614b24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b489190615712565b509150508415614b6557614b5e86848484614f5a565b9350614b74565b614b7186848484615173565b93505b7f012a05dea1e4b56be6c250aaa3e6189a1f531f1fd201b35b2a74c56577000bf48685876000604051614baa9493929190615e81565b60405180910390a150505092915050565b600654600d54604051633469949d60e01b8152600092738c2cc5ff69bc3760d7ce81812a2848421495972a92633469949d92614c0992889288926001600160a01b0390921691600401615aa5565b60206040518083038186803b158015614c2157600080fd5b505af4158015614c35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fcf9190615754565b60115460ff1615614c695761146a565b60408051600180825281830190925260609160208083019080368337019050509050600b60019054906101000a90046001600160a01b031681600081518110614cae57fe5b6001600160a01b039092166020928302919091019091015260405162e1ed9760e51b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b90631c3db2e090614cfe9030908590600401615a12565b600060405180830381600087803b158015614d1857600080fd5b505af115801561383b573d6000803e3d6000fd5b6000614d4b73c00e94cb662c3520282e6f5717214004a7f268886143f0565b9050601254811015614d5d575061146a565b600b54600160a81b900460ff1615614e56576040805160a0810190915260065473e592427a0aece92de3edee1f18e0157c058615649163c04b8d59918190614dc39073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b03166152e0565b8152602001306001600160a01b0316815260200142815260200184815260200160008152506040518263ffffffff1660e01b8152600401614e049190615db6565b602060405180830381600087803b158015614e1e57600080fd5b505af1158015614e32573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371e9190615754565b600c546006546001600160a01b03918216916338ed1739918491600091614e939173c00e94cb662c3520282e6f5717214004a7f268889116614140565b30426040518663ffffffff1660e01b8152600401614eb5959493929190615e37565b600060405180830381600087803b158015614ecf57600080fd5b505af1158015614ee3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109ca919081019061561a565b6109ca6001600160a01b038316826000196131a7565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906132f7575050151592915050565b6000808215614f7c57614f798361123486670de0b6b3a7640000613680565b90505b614f8685826133a0565b9150838210614f93578391505b858210614f9e578591505b6000600b60019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b158015614fee57600080fd5b505afa158015615002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150269190615754565b90508061503b84670de0b6b3a7640000613680565b101580156150495750600a83115b156145f95761505983600a6133a0565b600b5460405163852a12e360e01b815291945061010090046001600160a01b03169063852a12e39061508f908690600401615af1565b602060405180830381600087803b1580156150a957600080fd5b505af11580156150bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150e19190615754565b50600b5460405163073a938160e11b81526101009091046001600160a01b031690630e75270290615116908690600401615af1565b602060405180830381600087803b15801561513057600080fd5b505af1158015615144573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151689190615754565b505050949350505050565b60008061518c670de0b6b3a76400006112348786613680565b905061519881856133a0565b91508582106151a5578591505b600a8211156152d7576151b982600a6133a0565b600b5460405163317afabb60e21b815291935061010090046001600160a01b03169063c5ebeaec906151ef908590600401615af1565b602060405180830381600087803b15801561520957600080fd5b505af115801561521d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906152419190615754565b50600b546006546001600160a01b0361010090920482169163a0712d689161526991166143f0565b6040518263ffffffff1660e01b81526004016152859190615af1565b602060405180830381600087803b15801561529f57600080fd5b505af11580156152b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145f99190615754565b50949350505050565b6006546060906001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561535a5782600b60169054906101000a900462ffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26040516020016153449392919061593b565b6040516020818303038152906040529050611cb4565b600b546040516153a091859162ffffff600160b01b830481169273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc292600160c81b909104909116908790602001615976565b604051602081830303815290604052905092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106153f85782800160ff19823516178555615425565b82800160010185558215615425579182015b8281111561542557823582559160200191906001019061540a565b50615431929150615481565b5090565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5b808211156154315760008155600101615482565b60008083601f8401126154a7578182fd5b50813567ffffffffffffffff8111156154be578182fd5b6020830191508360208285010111156154d657600080fd5b9250929050565b803562ffffff81168114611cb457600080fd5b600060208284031215615501578081fd5b8135611fcf81615f6e565b60006020828403121561551d578081fd5b8151611fcf81615f6e565b6000806040838503121561553a578081fd5b823561554581615f6e565b9150602083013561555581615f6e565b809150509250929050565b600080600060608486031215615574578081fd5b833561557f81615f6e565b9250602084013561558f81615f6e565b929592945050506040919091013590565b60008060008060008060a087890312156155b8578182fd5b86356155c381615f6e565b955060208701356155d381615f6e565b94506040870135935060608701359250608087013567ffffffffffffffff8111156155fc578283fd5b61560889828a01615496565b979a9699509497509295939492505050565b6000602080838503121561562c578182fd5b825167ffffffffffffffff811115615642578283fd5b8301601f81018513615652578283fd5b805161566561566082615f22565b615efb565b8181528381019083850185840285018601891015615681578687fd5b8694505b838510156156a3578051835260019490940193918501918501615685565b50979650505050505050565b6000602082840312156156c0578081fd5b8135611fcf81615f83565b6000602082840312156156dc578081fd5b8151611fcf81615f83565b600080604083850312156156f9578182fd5b823561570481615f83565b946020939093013593505050565b600080600060608486031215615726578283fd5b835161573181615f83565b60208501516040860151919450925061574981615f83565b809150509250925092565b600060208284031215615765578081fd5b5051919050565b6000806020838503121561577e578182fd5b823567ffffffffffffffff811115615794578283fd5b6157a085828601615496565b90969095509350505050565b60006101208083850312156157bf578182fd5b6157c881615efb565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b6000806040838503121561583c578182fd5b61584684846154dd565b915061585584602085016154dd565b90509250929050565b60006020828403121561586f578081fd5b5035919050565b6000806000806080858703121561588b578182fd5b505082516020840151604085015160609095015191969095509092509050565b6000602082840312156158bc578081fd5b815160ff81168114611fcf578182fd5b6000815180845260208085019450808401835b838110156159045781516001600160a01b0316875295820195908201906001016158df565b509495945050505050565b60008151808452615927816020860160208601615f42565b601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b6001600160e81b0319166014820152921b166017820152602b0190565b6bffffffffffffffffffffffff19606096871b811682526001600160e81b031960e896871b8116601484015294871b811660178301529290941b909216602b840152921b909116602e82015260420190565b600082516159da818460208701615f42565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b81811015615a60578551851683529483019491830191600101615a42565b509098975050505050505050565b6001600160a01b03929092168252602082015260400190565b600060208252611fcf60208301846158cc565b901515815260200190565b931515845260208401929092526001600160a01b03166040830152606082015260800190565b9315158452602084019290925260408301526001600160a01b0316606082015260800190565b90815260200190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b600060208252611fcf602083018461590f565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b600060208252825160a06020840152615dd260c084018261590f565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b62ffffff91909116815260200190565b6000838252604060208301526132f760408301846158cc565b600086825285602083015260a06040830152615e5660a08301866158cc565b6001600160a01b0394909416606083015250608001529392505050565b918252602082015260400190565b9384526020840192909252151560408301526001600160a01b0316606082015260800190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff81118282101715615f1a57600080fd5b604052919050565b600067ffffffffffffffff821115615f38578081fd5b5060209081020190565b60005b83811015615f5d578181015183820152602001615f45565b8381111561383d5750506000910152565b6001600160a01b038116811461104c57600080fd5b801515811461104c57600080fdfea26469706673582212204fbe1f6c346640ade3ea6687ce05bc5b2469b59584aa4a7c2a914b6f2ecc4d9d64736f6c634300060c0033
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
82666:31972:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75791:444;;;;;;:::i;:::-;;:::i;:::-;;95277:172;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;47020:25;;;:::i;:::-;;;;;;;:::i;84400:28::-;;;:::i;87555:116::-;;;;;;:::i;:::-;;:::i;84896:103::-;;;:::i;88705:123::-;;;;;;:::i;:::-;;:::i;57393:175::-;;;;;;:::i;:::-;;:::i;52961:118::-;;;;;;:::i;:::-;;:::i;50299:28::-;;;:::i;49047:18::-;;;:::i;:::-;;;;;;;:::i;48956:25::-;;;:::i;84243:22::-;;;:::i;60795:148::-;;;:::i;:::-;;;;;;;:::i;113296:460::-;;;;;;:::i;:::-;;:::i;47419:91::-;;;:::i;87783:154::-;;;:::i;49935:29::-;;;:::i;72195:515::-;;;;;;:::i;:::-;;:::i;112071:177::-;;;;;;:::i;:::-;;:::i;88314:95::-;;;;;;:::i;:::-;;:::i;87193:140::-;;;;;;:::i;:::-;;:::i;112344:131::-;;;;;;:::i;:::-;;:::i;55442:154::-;;;;;;:::i;:::-;;:::i;84000:29::-;;;:::i;84335:25::-;;;:::i;94573:317::-;;;:::i;:::-;;;;;;;;:::i;65892:170::-;;;:::i;70371:1580::-;;;:::i;85007:171::-;;;;;;:::i;:::-;;:::i;88077:102::-;;;;;;:::i;:::-;;:::i;50378:25::-;;;:::i;87945:124::-;;;;;;:::i;:::-;;:::i;90555:278::-;;;;;;:::i;:::-;;:::i;47076:25::-;;;:::i;83385:21::-;;;:::i;83551:31::-;;;:::i;:::-;;;;;;;:::i;54199:174::-;;;;;;:::i;:::-;;:::i;57871:171::-;;;;;;:::i;:::-;;:::i;94927:313::-;;;:::i;113809:145::-;;;;;;:::i;:::-;;:::i;91757:935::-;;;:::i;90919:356::-;;;;;;:::i;:::-;;:::i;50121:27::-;;;:::i;48826:94::-;;;:::i;56667:169::-;;;;;;:::i;:::-;;:::i;49784:29::-;;;:::i;88417:280::-;;;;;;:::i;:::-;;:::i;113029:259::-;;;:::i;48988:22::-;;;:::i;53087:123::-;;;;;;:::i;:::-;;:::i;49017:21::-;;;:::i;87341:206::-;;;;;;:::i;:::-;;:::i;47108:26::-;;;:::i;83513:31::-;;;:::i;87679:96::-;;;;;;:::i;:::-;;:::i;84586:31::-;;;:::i;84474:27::-;;;:::i;84036:31::-;;;:::i;83415:20::-;;;:::i;53443:202::-;;;;;;:::i;:::-;;:::i;84555:24::-;;;:::i;73482:281::-;;;;;;:::i;:::-;;:::i;89912:327::-;;;:::i;88187:119::-;;;;;;:::i;:::-;;:::i;92866:1479::-;;;:::i;83589:41::-;;;:::i;54662:263::-;;;;;;:::i;:::-;;:::i;67829:1736::-;;;;;;:::i;:::-;;:::i;89077:642::-;;;:::i;56113:154::-;;;;;;:::i;:::-;;:::i;48928:21::-;;;:::i;74192:173::-;;;:::i;75791:444::-;51004:12;:10;:12::i;:::-;-1:-1:-1;;;;;50990:26:0;:10;:26;50982:50;;;;-1:-1:-1;;;50982:50:0;;;;;;;:::i;:::-;;;;;;;;;75883:4:::1;::::0;-1:-1:-1;;;;;75865:23:0;;::::1;75883:4:::0;::::1;75865:23;;75857:41;;;::::0;-1:-1:-1;;;75857:41:0;;::::1;::::0;::::1;;;:::i;:::-;75935:5;::::0;-1:-1:-1;;;;;75917:24:0;;::::1;75935:5:::0;::::1;75917:24;;75909:44;;;::::0;-1:-1:-1;;;75909:44:0;;::::1;::::0;::::1;;;:::i;:::-;75966:33;76002:17;:15;:17::i;:::-;75966:53;;76035:9;76030:102;76050:16;:23;76046:1;:27;76030:102;;;76098:16;76115:1;76098:19;;;;;;;;;::::0;;::::1;::::0;;;;;;-1:-1:-1;;;;;76088:29:0;;::::1;::::0;::::1;;;76080:52;;;::::0;-1:-1:-1;;;76080:52:0;;::::1;::::0;::::1;;;:::i;:::-;76075:3;;76030:102;;;;76145:82;76173:12;:10;:12::i;:::-;76187:39;::::0;-1:-1:-1;;;76187:39:0;;-1:-1:-1;;;;;76187:24:0;::::1;::::0;-1:-1:-1;;76187:39:0::1;::::0;76220:4:::1;::::0;76187:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;76145:27:0;::::1;::::0;;::::1;:82::i;:::-;51043:1;75791:444:::0;:::o;95277:172::-;95324:7;95345:16;95363:15;95382:20;:18;:20::i;:::-;95344:58;;-1:-1:-1;95344:58:0;-1:-1:-1;95420:21:0;95344:58;;95420:12;:21::i;:::-;95413:28;;;;95277:172;;:::o;47020:25::-;;;;;;;;;;;;;;;-1:-1:-1;;47020:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;84400:28::-;;;;:::o;87555:116::-;114603:12;:10;:12::i;:::-;87633:13:::1;:30:::0;;-1:-1:-1;;87633:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;87555:116::o;84896:103::-;84970:21;;;;;;;;;;;;-1:-1:-1;;;84970:21:0;;;;;84896:103::o;88705:123::-;114603:12;:10;:12::i;:::-;88788:14:::1;:32:::0;88705:123::o;57393:175::-;50489:10;;-1:-1:-1;;;;;50489:10:0;50475;:24;;:54;;;50517:12;:10;:12::i;:::-;-1:-1:-1;;;;;50503:26:0;:10;:26;50475:54;50467:78;;;;-1:-1:-1;;;50467:78:0;;;;;;;:::i;:::-;57478:13:::1;:30:::0;;;57524:36:::1;::::0;::::1;::::0;::::1;::::0;57494:14;;57524:36:::1;:::i;:::-;;;;;;;;57393:175:::0;:::o;52961:118::-;51461:5;;:18;;;-1:-1:-1;;;51461:18:0;;;;-1:-1:-1;;;;;51461:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;51447:32:0;:10;:32;;:62;;;51497:12;:10;:12::i;:::-;-1:-1:-1;;;;;51483:26:0;:10;:26;51447:62;51439:86;;;;-1:-1:-1;;;51439:86:0;;;;;;;:::i;:::-;53045:11:::1;:26:::0;;-1:-1:-1;;;;;53045:26:0;;;::::1;;;-1:-1:-1::0;;;;;;53045:26:0;;::::1;::::0;;;::::1;::::0;;52961:118::o;50299:28::-;;;;:::o;49047:18::-;;;-1:-1:-1;;;;;49047:18:0;;:::o;48956:25::-;;;-1:-1:-1;;;;;48956:25:0;;:::o;84243:22::-;;;;:::o;60795:148::-;60860:5;;:31;;-1:-1:-1;;;60860:31:0;;60836:4;;;;-1:-1:-1;;;;;60860:5:0;;;;-1:-1:-1;;60860:31:0;;60885:4;;60860:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;:45;:75;;;;60934:1;60909:22;:20;:22::i;:::-;:26;60860:75;60853:82;;60795:148;:::o;113296:460::-;113480:7;113508:10;77048:42;113508:33;113500:42;;;;;;113582:4;-1:-1:-1;;;;;113561:26:0;;;113553:35;;;;;;113600:12;;113636:33;;;;113647:4;113636:33;:::i;:::-;113741:6;;113689:59;;-1:-1:-1;;;113689:59:0;;113599:70;;-1:-1:-1;113599:70:0;;-1:-1:-1;113689:12:0;;:22;;:59;;113599:70;;113721:6;;113599:70;;113741:6;;;-1:-1:-1;;;;;113741:6:0;;113689:59;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;113682:66;113296:460;-1:-1:-1;;;;;;;;;113296:460:0:o;47419:91::-;47488:14;;;;;;;;;;;;-1:-1:-1;;;47488:14:0;;;;;47419:91::o;87783:154::-;114603:12;:10;:12::i;:::-;87861:15:::1;::::0;-1:-1:-1;;;;;87861:15:0::1;83831:42;87861:34;:68;;83831:42;87861:68;;;83708:42;87861:68;87843:15;:86:::0;;-1:-1:-1;;;;;;87843:86:0::1;-1:-1:-1::0;;;;;87843:86:0;;;::::1;::::0;;;::::1;::::0;;87783:154::o;49935:29::-;;;;:::o;72195:515::-;72310:5;;72254:13;;-1:-1:-1;;;;;72310:5:0;72288:10;:28;72280:47;;;;-1:-1:-1;;;72280:47:0;;;;;;;:::i;:::-;72413:19;72466:32;72484:13;72466:17;:32::i;:::-;72590:4;;72443:55;;-1:-1:-1;72443:55:0;;-1:-1:-1;72590:42:0;;-1:-1:-1;;;;;72590:4:0;72608:10;72443:55;72590:17;:42::i;:::-;72195:515;;;;:::o;112071:177::-;114603:12;:10;:12::i;:::-;112152:6:::1;::::0;:31:::1;::::0;-1:-1:-1;;;112152:31:0;;:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;112152:6:0::1;::::0;-1:-1:-1;;112152:31:0::1;::::0;112176:6;;112152:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:36:::0;112144:45:::1;;;::::0;::::1;;112208:6;::::0;:26:::1;::::0;-1:-1:-1;;;112208:26:0;;:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;112208:6:0::1;::::0;:18:::1;::::0;:26:::1;::::0;112227:6;;112208:26:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:31:::0;112200:40:::1;;;::::0;::::1;;112071:177:::0;:::o;88314:95::-;114603:12;:10;:12::i;:::-;88383:7:::1;:18:::0;88314:95::o;87193:140::-;114603:12;:10;:12::i;:::-;87283:19:::1;:42:::0;;;::::1;;::::0;::::1;-1:-1:-1::0;;87283:42:0;;::::1;::::0;;;::::1;::::0;;87193:140::o;112344:131::-;51004:12;:10;:12::i;:::-;-1:-1:-1;;;;;50990:26:0;:10;:26;50982:50;;;;-1:-1:-1;;;50982:50:0;;;;;;;:::i;:::-;112430:6:::1;::::0;:31:::1;::::0;-1:-1:-1;;;112430:31:0;;:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;112430:6:0::1;::::0;-1:-1:-1;;112430:31:0::1;::::0;112454:6;;112430:31:::1;;;:::i;55442:154::-:0;50489:10;;-1:-1:-1;;;;;50489:10:0;50475;:24;;:54;;;50517:12;:10;:12::i;:::-;-1:-1:-1;;;;;50503:26:0;:10;:26;50475:54;50467:78;;;;-1:-1:-1;;;50467:78:0;;;;;;;:::i;:::-;55520:14:::1;:23:::0;;;55559:29:::1;::::0;::::1;::::0;::::1;::::0;55537:6;;55559:29:::1;:::i;84000:::-:0;;;;:::o;84335:25::-;;;;;;:::o;94573:317::-;94743:6;;:40;;-1:-1:-1;;;94743:40:0;;94624:16;;;;;;;;;;94743:6;;;-1:-1:-1;;;;;94743:6:0;;:25;;:40;;94777:4;;94743:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94670:113;;;;;;;94804:13;94794:23;;94841:41;94877:4;94841:31;94859:12;94841:13;:17;;:31;;;;:::i;:::-;:35;;:41::i;:::-;94830:52;;94573:317;;;;;:::o;65892:170::-;51130:6;;-1:-1:-1;;;;;51130:6:0;51116:10;:20;;:65;;-1:-1:-1;51171:10:0;;-1:-1:-1;;;;;51171:10:0;51157;:24;51116:65;:112;;;;51216:12;:10;:12::i;:::-;-1:-1:-1;;;;;51202:26:0;:10;:26;51116:112;:163;;;-1:-1:-1;51263:5:0;;:16;;;-1:-1:-1;;;51263:16:0;;;;-1:-1:-1;;;;;51263:5:0;;;;:14;;:16;;;;;;;;;;;;;;;:5;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;51249:30:0;:10;:30;51116:163;:216;;;-1:-1:-1;51314:5:0;;:18;;;-1:-1:-1;;;51314:18:0;;;;-1:-1:-1;;;;;51314:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;51300:32:0;:10;:32;51116:216;51094:277;;;;-1:-1:-1;;;51094:277:0;;;;;;;:::i;:::-;66030:5:::1;::::0;:23:::1;::::0;;-1:-1:-1;;;66030:23:0;;;;66015:39:::1;::::0;-1:-1:-1;;;;;66030:5:0::1;::::0;-1:-1:-1;;66030:23:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:5;:23;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66015:14;:39::i;:::-;65892:170::o:0;70371:1580::-;51130:6;;-1:-1:-1;;;;;51130:6:0;51116:10;:20;;:65;;-1:-1:-1;51171:10:0;;-1:-1:-1;;;;;51171:10:0;51157;:24;51116:65;:112;;;;51216:12;:10;:12::i;:::-;-1:-1:-1;;;;;51202:26:0;:10;:26;51116:112;:163;;;-1:-1:-1;51263:5:0;;:16;;;-1:-1:-1;;;51263:16:0;;;;-1:-1:-1;;;;;51263:5:0;;;;:14;;:16;;;;;;;;;;;;;;;:5;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;51249:30:0;:10;:30;51116:163;:216;;;-1:-1:-1;51314:5:0;;:18;;;-1:-1:-1;;;51314:18:0;;;;-1:-1:-1;;;;;51314:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;51300:32:0;:10;:32;51116:216;51094:277;;;;-1:-1:-1;;;51094:277:0;;;;;;;:::i;:::-;70504:5:::1;::::0;:23:::1;::::0;;-1:-1:-1;;;70504:23:0;;;;70422:14:::1;::::0;;;;;-1:-1:-1;;;;;70504:5:0;;::::1;::::0;:21:::1;::::0;:23:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;:5;:23;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70576:13;::::0;70478:49;;-1:-1:-1;70538:19:0::1;::::0;70576:13:::1;;70572:580;;;70658:19;70680:23;:21;:23::i;:::-;70658:45;;70736:15;70722:11;:29;70718:226;;;70779:32;:15:::0;70799:11;70779:19:::1;:32::i;:::-;70772:39;;70718:226;;;70851:15;70837:11;:29;70833:111;;;70896:32;:11:::0;70912:15;70896::::1;:32::i;:::-;70887:41;;70833:111;70972:25;:15:::0;70992:4;70972:19:::1;:25::i;:::-;70958:39;;70572:580;;;;71110:30;71124:15;71110:13;:30::i;:::-;71080:60:::0;;-1:-1:-1;71080:60:0;-1:-1:-1;71080:60:0;-1:-1:-1;70572:580:0::1;71368:5;::::0;:31:::1;::::0;-1:-1:-1;;;71368:31:0;;71348:17:::1;::::0;-1:-1:-1;;;;;71368:5:0::1;::::0;-1:-1:-1;;71368:31:0::1;::::0;71393:4:::1;::::0;71368:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;::::0;71438:5:::1;::::0;:39:::1;::::0;-1:-1:-1;;;71438:39:0;;71368:41;;-1:-1:-1;;;;;;71438:5:0::1;::::0;:12:::1;::::0;:39:::1;::::0;71451:6;;71459:4;;71465:11;;71438:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71420:57;;71553:31;71568:15;71553:14;:31::i;:::-;71639:13;::::0;::::1;;:42:::0;::::1;;;-1:-1:-1::0;71656:11:0::1;::::0;::::1;::::0;::::1;-1:-1:-1::0;;;;;71656:11:0::1;:25:::0;::::1;71639:42;71635:238;;;71718:11;::::0;71706:85:::1;::::0;-1:-1:-1;;;71706:85:0;;71718:11:::1;::::0;;::::1;-1:-1:-1::0;;;;;71718:11:0::1;::::0;-1:-1:-1;;71706:85:0::1;::::0;71737:6;;71745:4;;71751:11;;71764:15;;71781:9;;71706:85:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71698:110;;;::::0;-1:-1:-1;;;71698:110:0;;::::1;::::0;::::1;;;:::i;:::-;71635:238;;;71857:4;71841:20:::0;;-1:-1:-1;;71841:20:0::1;::::0;::::1;::::0;;71635:238:::1;71890:53;71900:6;71908:4;71914:11;71927:15;71890:53;;;;;;;;;:::i;:::-;;;;;;;;51382:1;;;;;70371:1580::o:0;85007:171::-;85080:55;85092:6;85100:10;85112;85124;85080:11;:55::i;:::-;85146:24;85162:7;85146:15;:24::i;88077:102::-;51004:12;:10;:12::i;:::-;-1:-1:-1;;;;;50990:26:0;:10;:26;50982:50;;;;-1:-1:-1;;;50982:50:0;;;;;;;:::i;:::-;88150:12:::1;:21:::0;;;::::1;;;;-1:-1:-1::0;;88150:21:0;;::::1;::::0;;;::::1;::::0;;88077:102::o;50378:25::-;;;;;;:::o;87945:124::-;114603:12;:10;:12::i;:::-;88027:15:::1;:34:::0;;-1:-1:-1;;88027:34:0::1;::::0;::::1;;::::0;;;::::1;::::0;;87945:124::o;90555:278::-;90623:4;90644:23;90659:7;90644:14;:23::i;:::-;90640:106;;;-1:-1:-1;90729:5:0;90722:12;;90640:106;90796:29;;90765:27;:25;:27::i;:::-;:60;;90758:67;;90555:278;;;;:::o;47076:25::-;;;;;;:::o;83385:21::-;;;;;;-1:-1:-1;;;;;83385:21:0;;:::o;83551:31::-;;;-1:-1:-1;;;83551:31:0;;;;;:::o;54199:174::-;50489:10;;-1:-1:-1;;;;;50489:10:0;50475;:24;;:54;;;50517:12;:10;:12::i;:::-;-1:-1:-1;;;;;50503:26:0;:10;:26;50475:54;50467:78;;;;-1:-1:-1;;;50467:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;54278:21:0;::::1;54270:30;;;::::0;::::1;;54311:6;:16:::0;;-1:-1:-1;;;;;;54311:16:0::1;-1:-1:-1::0;;;;;54311:16:0;::::1;;::::0;;54343:22:::1;::::0;::::1;::::0;::::1;::::0;54311:16;;54343:22:::1;:::i;57871:171::-:0;50489:10;;-1:-1:-1;;;;;50489:10:0;50475;:24;;:54;;;50517:12;:10;:12::i;:::-;-1:-1:-1;;;;;50503:26:0;:10;:26;50475:54;50467:78;;;;-1:-1:-1;;;50467:78:0;;;;;;;:::i;:::-;57960:26:::1;:11;57974:12:::0;;57960:26:::1;:::i;:::-;;58002:32;58021:12;;58002:32;;;;;;;:::i;:::-;;;;;;;;57871:171:::0;;:::o;94927:313::-;95027:6;;:41;;-1:-1:-1;;;95027:41:0;;94970:16;;;;95027:6;;;;-1:-1:-1;;;;;95027:6:0;;-1:-1:-1;;95027:41:0;;95062:4;;95027:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95191:6;;:41;;-1:-1:-1;;;95191:41:0;;95016:52;;-1:-1:-1;95191:6:0;;;-1:-1:-1;;;;;95191:6:0;;-1:-1:-1;;95191:41:0;;95226:4;;95191:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95181:51;;94927:313;;:::o;113809:145::-;113929:4;;113877:7;;113904:42;;83336;;-1:-1:-1;;;;;113929:4:0;113936:9;113904:10;:42::i;:::-;113897:49;113809:145;-1:-1:-1;;113809:145:0:o;91757:935::-;91901:6;;91876:33;;-1:-1:-1;;;91876:33:0;;91815:7;;;;83139:42;;-1:-1:-1;;91876:33:0;;91901:6;;;-1:-1:-1;;;;;91901:6:0;;91876:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91835:74;;;;91923:16;91941:15;91960:20;:18;:20::i;:::-;92015:6;;:27;;;-1:-1:-1;;;92015:27:0;;;;91922:58;;-1:-1:-1;91922:58:0;;-1:-1:-1;91993:19:0;;92015:6;;;;-1:-1:-1;;;;;92015:6:0;;:25;;:27;;;;;;;;;;;;;;:6;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92076:6;;:27;;;-1:-1:-1;;;92076:27:0;;;;91993:49;;-1:-1:-1;92055:18:0;;92076:6;;;;-1:-1:-1;;;;;92076:6:0;;:25;;:27;;;;;;;;;;;;;;;:6;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92055:48;-1:-1:-1;92116:30:0;92149:48;92192:4;92149:38;:8;92162:24;92149:12;:38::i;:48::-;92116:81;-1:-1:-1;92116:81:0;92208:29;92292:24;:7;92304:11;92292;:24::i;:::-;92275:41;-1:-1:-1;92327:14:0;92344:37;:21;92370:10;92344:25;:37::i;:::-;92327:54;;92408:6;92398;:16;92394:291;;-1:-1:-1;;92431:24:0;;;;;;;;;;;;;92394:291;92488:13;92504:34;:21;92530:7;92504:25;:34::i;:::-;92488:50;-1:-1:-1;92553:13:0;92569:18;:6;92580;92569:10;:18::i;:::-;92553:34;-1:-1:-1;92647:26:0;92553:34;92647:15;:5;92657:4;92647:9;:15::i;:26::-;92640:33;;;;;;;;;;;;;;;90919:356;91039:7;91063:12;91059:53;;-1:-1:-1;91099:1:0;91092:8;;91059:53;91151:15;;91124:24;;-1:-1:-1;;;;;91151:15:0;:29;91181:7;91190:29;91208:5;91215:3;91190:17;:29::i;:::-;91151:69;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;91151:69:0;;;;;;;;;;;;:::i;:::-;91124:96;;91240:7;91265:1;91248:7;:14;:18;91240:27;;;;;;;;;;;;;;91233:34;;;90919:356;;;;;;:::o;50121:27::-;;;;:::o;48826:94::-;48884:7;48826:94;:::o;56667:169::-;50489:10;;-1:-1:-1;;;;;50489:10:0;50475;:24;;:54;;;50517:12;:10;:12::i;:::-;-1:-1:-1;;;;;50503:26:0;:10;:26;50475:54;50467:78;;;;-1:-1:-1;;;50467:78:0;;;;;;;:::i;:::-;56750:12:::1;:28:::0;;;56794:34:::1;::::0;::::1;::::0;::::1;::::0;56765:13;;56794:34:::1;:::i;49784:29::-:0;;;;:::o;88417:280::-;114603:12;:10;:12::i;:::-;88570:6:::1;::::0;88545:33:::1;::::0;-1:-1:-1;;;88545:33:0;;88507:32:::1;::::0;83139:42:::1;::::0;-1:-1:-1;;88545:33:0::1;::::0;88570:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;88570:6:0::1;::::0;88545:33:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;88504:74;;;;88624:17;88597:24;:44;88589:53;;;::::0;::::1;;-1:-1:-1::0;88653:16:0::1;:36:::0;88417:280::o;113029:259::-;113085:14;113113:12;113127:14;113145:20;:18;:20::i;:::-;113112:53;;;;113180:4;113188:1;113180:9;113176:50;;;113213:1;113206:8;;;;;;113176:50;113245:35;113275:4;113245:25;113253:4;113263:6;113245:17;:25::i;48988:22::-;;;-1:-1:-1;;;;;48988:22:0;;:::o;53087:123::-;51461:5;;:18;;;-1:-1:-1;;;51461:18:0;;;;-1:-1:-1;;;;;51461:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;51447:32:0;:10;:32;;:62;;;51497:12;:10;:12::i;:::-;-1:-1:-1;;;;;51483:26:0;:10;:26;51447:62;51439:86;;;;-1:-1:-1;;;51439:86:0;;;;;;;:::i;:::-;53172:13:::1;:30:::0;;-1:-1:-1;;53172:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;53087:123::o;49017:21::-;;;-1:-1:-1;;;;;49017:21:0;;:::o;87341:206::-;114603:12;:10;:12::i;:::-;87452:17:::1;:38:::0;;::::1;87501::::0;;::::1;-1:-1:-1::0;;;87501:38:0::1;-1:-1:-1::0;;;;87452:38:0;;;::::1;-1:-1:-1::0;;;87452:38:0::1;-1:-1:-1::0;;;;87452:38:0;;::::1;;87501::::0;;;::::1;;::::0;;87341:206::o;47108:26::-;;;;;;-1:-1:-1;;;;;47108:26:0;;:::o;83513:31::-;;;-1:-1:-1;;;83513:31:0;;;;;:::o;87679:96::-;114603:12;:10;:12::i;:::-;87747:8:::1;:20:::0;;;::::1;;-1:-1:-1::0;;;87747:20:0::1;-1:-1:-1::0;;;;87747:20:0;;::::1;::::0;;;::::1;::::0;;87679:96::o;84586:31::-;;;;;;;;;:::o;84474:27::-;;;;;;:::o;84036:31::-;;;;:::o;83415:20::-;;;-1:-1:-1;;;83415:20:0;;;;;:::o;53443:202::-;50489:10;;-1:-1:-1;;;;;50489:10:0;50475;:24;;:54;;;50517:12;:10;:12::i;:::-;-1:-1:-1;;;;;50503:26:0;:10;:26;50475:54;50467:78;;;;-1:-1:-1;;;50467:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;53530:25:0;::::1;53522:34;;;::::0;::::1;;53567:10;:24:::0;;-1:-1:-1;;;;;;53567:24:0::1;-1:-1:-1::0;;;;;53567:24:0;::::1;;::::0;;53607:30:::1;::::0;::::1;::::0;::::1;::::0;53567:24;;53607:30:::1;:::i;84555:24::-:0;;;;;;;;;:::o;73482:281::-;73571:5;;-1:-1:-1;;;;;73571:5:0;73549:10;:28;73541:37;;;;;;73635:5;;73597:34;;;-1:-1:-1;;;73597:34:0;;;;-1:-1:-1;;;;;73635:5:0;;;;73597:32;;;-1:-1:-1;;73597:34:0;;;;;;;;;;;;;;:32;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;73597:43:0;;73589:52;;;;;;73652:30;73669:12;73652:16;:30::i;:::-;73725:4;;:29;;-1:-1:-1;;;73725:29:0;;73693:62;;73711:12;;-1:-1:-1;;;;;73725:4:0;;;;-1:-1:-1;;73725:29:0;;73748:4;;73725:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;73693:4;;-1:-1:-1;;;;;73693:4:0;;;:17;:62::i;89912:327::-;89959:7;89979:22;90004;:20;:22::i;:::-;90054:5;;:31;;-1:-1:-1;;;90054:31:0;;89979:47;;-1:-1:-1;90039:12:0;;-1:-1:-1;;;;;90054:5:0;;;;-1:-1:-1;;90054:31:0;;90079:4;;90054:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;90039:56;;90117:14;90110:4;:21;90106:126;;;90155:1;90148:8;;;;;;90106:126;90196:24;:14;90215:4;90196:18;:24::i;:::-;90189:31;;;;;;88187:119;114603:12;:10;:12::i;:::-;88268:13:::1;:30:::0;88187:119::o;92866:1479::-;92917:7;92938:16;92956:15;92975:20;:18;:20::i;:::-;92937:58;;;;93010:8;93022:1;93010:13;93006:122;;;93047:1;93040:8;;;;;;93006:122;93211:6;;93177:42;;-1:-1:-1;;;93177:42:0;;93140:34;;83139:42;;-1:-1:-1;;93177:42:0;;93211:6;;;;-1:-1:-1;;;;;93211:6:0;;93177:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93301:6;;93267:42;;-1:-1:-1;;;93267:42:0;;93140:79;;-1:-1:-1;93230:34:0;;83139:42;;93267:25;;:42;;93301:6;;;-1:-1:-1;;;;;93301:6:0;;93267:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93342:6;;:21;;;-1:-1:-1;;;93342:21:0;;;;93230:79;;-1:-1:-1;93320:19:0;;93342:6;;;;-1:-1:-1;;;;;93342:6:0;;:19;;:21;;;;;;;;;;;;;;;:6;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93483:6;;:20;;;-1:-1:-1;;;93483:20:0;;;;93320:43;;-1:-1:-1;93455:25:0;;93483:6;;;;-1:-1:-1;;;;;93483:6:0;;:18;;:20;;;;;;;;;;;;;;;:6;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93455:48;;93514:19;93536:60;93591:4;93536:50;93558:6;;;;;;;;;-1:-1:-1;;;;;93558:6:0;-1:-1:-1;;;;;93558:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93536:17;;:21;:50::i;:60::-;93514:82;-1:-1:-1;93609:24:0;93652:15;;93648:124;;93703:57;93748:11;93703:40;:8;93716:26;93703:12;:40::i;:57::-;93684:76;;93648:124;93784:24;93827:15;;93823:123;;93878:56;93922:11;93878:39;:7;93890:26;93878:11;:39::i;:56::-;93859:75;;93823:123;94006:18;94027:38;:16;94048;94027:20;:38::i;:::-;94135:5;;:31;;-1:-1:-1;;;94135:31:0;;94006:59;;-1:-1:-1;94114:18:0;;-1:-1:-1;;;;;94135:5:0;;;;-1:-1:-1;;94135:31:0;;94160:4;;94135:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;;;-1:-1:-1;94188:23:0;94214:41;94252:2;94215:31;:15;94135:42;94215:19;:31::i;94214:41::-;94188:67;-1:-1:-1;94306:31:0;94188:67;94326:10;94306:19;:31::i;:::-;94299:38;;;;;;;;;;;;;;92866:1479;:::o;83589:41::-;;;-1:-1:-1;;;;;83589:41:0;;:::o;54662:263::-;50891:10;;-1:-1:-1;;;;;50891:10:0;50877;:24;50869:48;;;;-1:-1:-1;;;50869:48:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;54743:22:0;::::1;54735:31;;;::::0;::::1;;54777:5;::::0;54791:7:::1;::::0;;54777:25:::1;::::0;-1:-1:-1;;;54777:25:0;;-1:-1:-1;;;;;54777:5:0;;::::1;::::0;-1:-1:-1;;54777:25:0::1;::::0;54791:7;;;::::1;::::0;54777:5:::1;::::0;:25:::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;54813:7:0::1;:18:::0;;-1:-1:-1;;;;;;54813:18:0::1;-1:-1:-1::0;;;;;54813:18:0;;::::1;::::0;;;::::1;::::0;;;54842:5:::1;::::0;:35:::1;::::0;-1:-1:-1;;;54842:35:0;;:5;;::::1;::::0;-1:-1:-1;;54842:35:0::1;::::0;54856:7:::1;::::0;-1:-1:-1;;;54842:35:0::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;54893:24;54908:8;54893:24;;;;;;:::i;67829:1736::-:0;67905:4;67922:16;67941:24;67951:13;67941:9;:24::i;:::-;67922:43;;67976:28;;:::i;:::-;68007:5;;:31;;-1:-1:-1;;;68007:31:0;;-1:-1:-1;;;;;68007:5:0;;;;-1:-1:-1;;68007:31:0;;68032:4;;68007:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67976:62;;68115:6;:17;;;68136:1;68115:22;68111:40;;;68146:5;68139:12;;;;;;68111:40;68296:14;;68275:17;;;;68255:38;;:15;;:19;:38::i;:::-;:55;68251:73;;;68319:5;68312:12;;;;;;68251:73;68443:14;;68421:17;;;;68401:38;;:15;;:19;:38::i;:::-;:56;68397:73;;68466:4;68459:11;;;;;;68397:73;68900:5;;:23;;;-1:-1:-1;;;68900:23:0;;;;68878:19;;-1:-1:-1;;;;;68900:5:0;;-1:-1:-1;;68900:23:0;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68878:45;;68952:13;;68938:11;:27;68934:44;;;68974:4;68967:11;;;;;;;68934:44;69032:13;69048:22;:20;:22::i;:::-;69032:38;;69160:6;:16;;;69133:24;69143:13;;69133:5;:9;;:24;;;;:::i;:::-;:43;69129:60;;;69185:4;69178:11;;;;;;;;69129:60;69202:14;69243:6;:16;;;69235:5;:24;69231:66;;;69280:16;;;;69270:27;;:5;;:9;:27::i;:::-;69261:36;;69231:66;69467:5;;:23;;;-1:-1:-1;;;69467:23:0;;;;69450:14;;-1:-1:-1;;;;;69467:5:0;;-1:-1:-1;;69467:23:0;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69450:40;-1:-1:-1;69538:18:0;69450:40;69549:6;69538:10;:18::i;:::-;69509:12;;:26;;69526:8;69509:16;:26::i;:::-;:47;;67829:1736;-1:-1:-1;;;;;;;;67829:1736:0:o;89077:642::-;89139:7;89160:16;89178:15;89197:20;:18;:20::i;:::-;89159:58;;;;89230:22;89255:20;:18;:20::i;:::-;89230:45;;89286:19;89308:20;83255:42;89308:14;:20::i;:::-;89492:4;;89286:42;;-1:-1:-1;89443:21:0;;89467:64;;83255:42;;-1:-1:-1;;;;;89492:4:0;89499:31;:14;89286:42;89499:18;:31::i;89467:64::-;89443:88;-1:-1:-1;89542:24:0;89569:28;89594:2;89569:20;89443:88;89587:1;89569:17;:20::i;:28::-;89656:4;;89542:55;;-1:-1:-1;89633:78:0;;89703:7;;89633:65;;89542:55;;89633:43;;89667:8;;89633:43;;-1:-1:-1;;;;;89656:4:0;89633:14;:29::i;:::-;:33;;:43::i;:65::-;:69;;:78::i;:::-;89626:85;;;;;;;;89077:642;:::o;56113:154::-;50489:10;;-1:-1:-1;;;;;50489:10:0;50475;:24;;:54;;;50517:12;:10;:12::i;:::-;-1:-1:-1;;;;;50503:26:0;:10;:26;50475:54;50467:78;;;;-1:-1:-1;;;50467:78:0;;;;;;;:::i;:::-;56191:14:::1;:23:::0;;;56230:29:::1;::::0;::::1;::::0;::::1;::::0;56208:6;;56230:29:::1;:::i;48928:21::-:0;;;-1:-1:-1;;;;;48928:21:0;;:::o;74192:173::-;50655:10;;-1:-1:-1;;;;;50655:10:0;50641;:24;;:54;;;50683:12;:10;:12::i;:::-;-1:-1:-1;;;;;50669:26:0;:10;:26;50641:54;:88;;;-1:-1:-1;50713:5:0;;:16;;;-1:-1:-1;;;50713:16:0;;;;-1:-1:-1;;;;;50713:5:0;;;;:14;;:16;;;;;;;;;;;;;;;:5;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;50699:30:0;:10;:30;50641:88;:124;;;-1:-1:-1;50747:5:0;;:18;;;-1:-1:-1;;;50747:18:0;;;;-1:-1:-1;;;;;50747:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;50733:32:0;:10;:32;50641:124;50619:185;;;;-1:-1:-1;;;50619:185:0;;;;;;;:::i;:::-;74264:13:::1;:20:::0;;-1:-1:-1;;74264:20:0::1;74280:4;74264:20;::::0;;74295:5:::1;::::0;:22:::1;::::0;;-1:-1:-1;;;74295:22:0;;;;-1:-1:-1;;;;;74295:5:0;;::::1;::::0;:20:::1;::::0;:22:::1;::::0;;::::1;::::0;-1:-1:-1;;74295:22:0;;;;;;;;-1:-1:-1;74295:5:0;:22;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;74335:22:0::1;::::0;::::1;::::0;-1:-1:-1;74335:22:0;;-1:-1:-1;74335:22:0::1;74192:173::o:0;34744:622::-;35114:10;;;35113:62;;-1:-1:-1;35130:39:0;;-1:-1:-1;;;35130:39:0;;-1:-1:-1;;;;;35130:15:0;;;;;:39;;35154:4;;35161:7;;35130:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;35113:62;35105:152;;;;-1:-1:-1;;;35105:152:0;;;;;;;:::i;:::-;35268:90;35288:5;35318:22;;;35342:7;35351:5;35295:62;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;35295:62:0;;;;;;;;;;;;;;-1:-1:-1;;;;;35295:62:0;-1:-1:-1;;;;;;35295:62:0;;;;;;;;;;;35268:19;:90::i;:::-;34744:622;;;:::o;21055:132::-;21113:7;21140:39;21144:1;21147;21140:39;;;;;;;;;;;;;;;;;:3;:39::i;11883:196::-;11986:12;12018:53;12041:6;12049:4;12055:1;12058:12;12018:22;:53::i;:::-;12011:60;11883:196;-1:-1:-1;;;;11883:196:0:o;58196:98::-;58268:5;;:18;;;-1:-1:-1;;;58268:18:0;;;;58241:7;;-1:-1:-1;;;;;58268:5:0;;-1:-1:-1;;58268:18:0;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;112483:79::-;112542:16;112483:79;:::o;34085:177::-;34168:86;34188:5;34218:23;;;34243:2;34247:5;34195:58;;;;;;;;;:::i;19218:136::-;19276:7;19303:43;19307:1;19310;19303:43;;;;;;;;;;;;;;;;;:3;:43::i;114393:169::-;114462:12;:10;:12::i;:::-;-1:-1:-1;;;;;114448:26:0;:10;:26;;:62;;-1:-1:-1;114492:5:0;;:18;;;-1:-1:-1;;;114492:18:0;;;;-1:-1:-1;;;;;114492:5:0;;;;:16;;:18;;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;114478:32:0;:10;:32;114448:62;:90;;;-1:-1:-1;114528:10:0;;-1:-1:-1;;;;;114528:10:0;114514;:24;114448:90;114440:114;;;;-1:-1:-1;;;114440:114:0;;;;;;;:::i;104800:1776::-;104967:4;;104877:20;;;;;;104944:29;;-1:-1:-1;;;;;104967:4:0;104944:14;:29::i;:::-;104925:48;;104984:14;105001:30;105022:8;105001:16;:14;:16::i;:30::-;105070:5;;:23;;;-1:-1:-1;;;105070:23:0;;;;104984:47;;-1:-1:-1;105044:23:0;;-1:-1:-1;;;;;105070:5:0;;;;:21;;:23;;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;105044:49;;105128:6;105110:15;:24;105106:92;;;105159:27;:15;105179:6;105159:19;:27::i;:::-;105151:35;;105106:92;105211:16;105229:15;105248:17;:15;:17::i;:::-;105210:55;;;;105289:13;105280:6;:22;105276:787;;;105516:6;;105527:1;;105493:31;;105516:6;;;-1:-1:-1;;;;;105516:6:0;105493:14;:31::i;:::-;:35;105489:112;;;105549:36;105563:21;:8;105576:7;105563:12;:21::i;:::-;105549:13;:36::i;:::-;;105489:112;105679:4;;105632:54;;105641:13;;105656:29;;-1:-1:-1;;;;;105679:4:0;105656:14;:29::i;:::-;105632:8;:54::i;:::-;105617:69;;105276:787;;;105734:13;105723:8;:24;105719:333;;;105768:42;105782:27;:13;105800:8;105782:17;:27::i;105719:333::-;106023:13;106008:28;;105719:333;106258:13;106243:12;:28;106239:189;;;106288:12;106303:31;:13;106321:12;106303:17;:31::i;:::-;106288:46;;106361:7;;106353:4;:15;106349:68;;106397:4;106389:12;;106349:68;106239:189;;106444:19;;;;;;;106440:129;;;106505:23;:12;106522:5;106505:16;:23::i;:::-;106488:13;:40;106480:49;;;;;;104800:1776;;;;;;;;:::o;20108:471::-;20166:7;20411:6;20407:47;;-1:-1:-1;20441:1:0;20434:8;;20407:47;20478:5;;;20482:1;20478;:5;:1;20502:5;;;;;:10;20494:56;;;;-1:-1:-1;;;20494:56:0;;;;;;;:::i;97870:1874::-;98010:13;;;;98006:52;;;98040:7;;98006:52;98184:4;;98142:16;;98161:29;;-1:-1:-1;;;;;98184:4:0;98161:14;:29::i;:::-;98142:48;;98216:16;98205:8;:27;98201:379;;;98452:6;;98463:1;;98429:31;;98452:6;;;-1:-1:-1;;;;;98452:6:0;98429:14;:31::i;:::-;:35;98425:121;;;98485:45;98499:30;:16;98520:8;98499:20;:30::i;98485:45::-;;98425:121;98562:7;;;98201:379;98593:16;;98627:63;98653:30;:8;98666:16;98653:12;:30::i;:::-;98685:4;98627:25;:63::i;:::-;98592:98;;;;98852:7;;98841:8;:18;98837:900;;;98964:15;;;;98959:767;;99000:9;99032:236;99039:12;;99032:236;;99087:45;99100:31;99113:8;99123:7;99100:12;:31::i;:::-;99087:8;;:12;:45::i;:::-;99076:56;;99164:1;99159;:6;99155:68;;99194:5;;99155:68;99245:3;;99032:236;;;98959:767;;;;99424:12;:25;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99413:8;:38;99409:143;;;99487:45;99500:31;99513:8;99523:7;99500:12;:31::i;:::-;99487:8;;:12;:45::i;:::-;99476:56;;99409:143;99629:7;;99618:8;:18;99614:97;;;99661:30;99673:7;99682:8;99661:11;:30::i;:::-;;99614:97;97870:1874;;;;:::o;113962:423::-;114092:5;;:23;;;-1:-1:-1;;;114092:23:0;;;;114022:20;;114074:42;;-1:-1:-1;;;;;114092:5:0;;;;:21;;:23;;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;114074:17;:42::i;:::-;-1:-1:-1;114055:61:0;-1:-1:-1;114128:16:0;;114165:20;:18;:20::i;:::-;114127:58;;-1:-1:-1;114127:58:0;-1:-1:-1;114198:16:0;114217:21;114127:58;;114217:12;:21::i;:::-;114310:12;;114198:40;;-1:-1:-1;114310:12:0;;;;;114305:73;;114358:7;;114347:8;:18;114339:27;;;;;;113962:423;;;;:::o;95795:1930::-;96127:6;;95912:15;;;;;;96104:31;;96127:6;;;-1:-1:-1;;;;;96127:6:0;96104:14;:31::i;:::-;96100:429;;96202:4;;96157:19;;96179:29;;-1:-1:-1;;;;;96202:4:0;96179:14;:29::i;:::-;96157:51;;96426:39;96435:11;96448:16;96426:8;:39::i;:::-;96411:54;;96480:37;;;96100:429;96542:16;96560:15;96579:17;:15;:17::i;:::-;96541:55;;;;96639:12;:10;:12::i;:::-;96683:16;:14;:16::i;:::-;96757:4;;96712:19;;96734:29;;-1:-1:-1;;;;;96757:4:0;96734:14;:29::i;:::-;96712:51;-1:-1:-1;96776:23:0;96802:21;:8;96815:7;96802:12;:21::i;:::-;96776:47;-1:-1:-1;96834:15:0;96852:32;96776:47;96872:11;96852:19;:32::i;:::-;96912:5;;:31;;-1:-1:-1;;;96912:31:0;;96834:50;;-1:-1:-1;96897:12:0;;-1:-1:-1;;;;;96912:5:0;;;;-1:-1:-1;;96912:31:0;;96937:4;;96912:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;96897:56;;97022:4;97012:7;:14;97008:710;;;97053:17;:7;97065:4;97053:11;:17::i;:::-;97043:27;;97103:7;97089:11;:21;97085:325;;;97182:11;97172:21;;97085:325;;;97233:29;:7;97245:16;97233:11;:29::i;:::-;97219:11;:43;97215:195;;;97298:16;97283:31;;97215:195;;;97370:24;:11;97386:7;97370:15;:24::i;:::-;97355:39;;97215:195;97008:710;;;97620:17;:4;97629:7;97620:8;:17::i;:::-;97612:25;;97667:39;97676:11;97689:16;97667:8;:39::i;:::-;97652:54;;97008:710;95795:1930;;;;;;;;;;;;:::o;52226:727::-;52398:4;;-1:-1:-1;;;;;52398:4:0;52390:27;52382:68;;;;-1:-1:-1;;;52382:68:0;;;;;;;:::i;:::-;52463:5;:24;;-1:-1:-1;;;;;;52463:24:0;-1:-1:-1;;;;;52463:24:0;;;;;;;;;;;52512:13;;;-1:-1:-1;;;52512:13:0;;;;:5;;;;;:11;;:13;;;;;;;;;;;;;;;:5;:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;52498:4;:28;;-1:-1:-1;;;;;;52498:28:0;-1:-1:-1;;;;;52498:28:0;;;;;;;;52537:37;;:4;52554:6;-1:-1:-1;;52537:16:0;:37::i;:::-;52633:10;:24;;-1:-1:-1;;;;;;52633:24:0;;;-1:-1:-1;;;;;52633:24:0;;;;;;;;;;52668:7;:18;;;;;;;;;;;52697:6;:16;;;;;;;;;;;;-1:-1:-1;52759:14:0;:18;;;52805:5;52788:14;:22;52836:3;52821:12;:18;52850:13;:17;52880:5;;:35;;-1:-1:-1;;;52880:35:0;;:5;;;;-1:-1:-1;;52880:35:0;;52894:7;;;-1:-1:-1;;;52880:35:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;85186:1954::-;85248:6;:34;;-1:-1:-1;;;;;85248:34:0;;;;;-1:-1:-1;;;;;;85248:34:0;;;;;;;;;;85324:4;;85301:40;;;-1:-1:-1;;;85301:40:0;;;;85345:2;;85324:4;;;;;85301:38;;:40;;;;;;;;;;;;;;;85324:4;85301:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:46;;;;85293:55;;;;;;85386:15;:33;;-1:-1:-1;;;;;;85386:33:0;83831:42;85386:33;;;85461:45;83255:42;83708;85461:15;:45::i;:::-;85517:47;83255:42;83831;85517:15;:47::i;:::-;85575:45;83255:42;83948;85575:15;:45::i;:::-;85655:4;;85670:6;;85631:47;;-1:-1:-1;;;;;85655:4:0;;;;;85670:6;;;85631:15;:47::i;:::-;85689:63;76617:42;77048;85689:15;:63::i;:::-;85915:6;;85868:24;;85915:6;;;-1:-1:-1;;;;;85915:6:0;76697:42;85907:45;85903:460;;85979:16;;;85993:1;85979:16;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85979:16:0;85969:26;;76697:42;86010:7;86018:1;86010:10;;;;;;;;-1:-1:-1;;;;;86010:39:0;;;:10;;;;;;;;;:39;86085:6;;86064:10;;86085:6;;;;;;;;86064:10;;-1:-1:-1;;86064:10:0;;;;;;-1:-1:-1;;;;;86064:28:0;;;:10;;;;;;;;;;;:28;86177:61;76617:42;76697;86177:15;:61::i;:::-;85903:460;;;86281:16;;;86295:1;86281:16;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;86281:16:0;86271:26;;76697:42;86312:7;86320:1;86312:10;;;;;;;;-1:-1:-1;;;;;86312:39:0;;;:10;;;;;;;;;;;:39;85903:460;86373:30;;-1:-1:-1;;;86373:30:0;;83139:42;;86373:21;;:30;;86395:7;;86373:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;86373:30:0;;;;;;;;;;;;:::i;:::-;-1:-1:-1;86509:17:0;:24;;-1:-1:-1;;;;86509:24:0;-1:-1:-1;;;86509:24:0;-1:-1:-1;;;;86544:24:0;-1:-1:-1;;;86544:24:0;;;86672:5;86655:14;:22;86724:3;86709:12;:18;86792:4;86776:13;:20;86907:4;;86883:42;;;-1:-1:-1;;;86883:42:0;;;;86854:83;;86932:4;;-1:-1:-1;;;;;86907:4:0;;;;-1:-1:-1;;86883:42:0;;;;;;;;;;;;;;;86907:4;86883:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;86875:51;;86870:2;86862:64;;86854:77;:83::i;:::-;86844:7;:93;-1:-1:-1;;86964:9:0;86948:13;:25;87003:10;86984:16;:29;87041:10;87024:14;:27;87094:5;87062:29;:37;87110:15;:22;;-1:-1:-1;;87110:22:0;-1:-1:-1;87110:22:0;;;85186:1954::o;107348:440::-;107435:22;107470:11;83336:42;-1:-1:-1;;;;;107484:25:0;;;;:55;;-1:-1:-1;83336:42:0;-1:-1:-1;;;;;107513:26:0;;;107484:55;107470:69;;107572:6;:14;;107585:1;107572:14;;;107581:1;107572:14;107558:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;107558:29:0;;107550:37;;107609:8;107598:5;107604:1;107598:8;;;;;;;;-1:-1:-1;;;;;107598:19:0;;;:8;;;;;;;;;;;:19;107630:151;;;;107668:9;107657:5;107663:1;107657:8;;;;;;;;-1:-1:-1;;;;;107657:20:0;;;:8;;;;;;;;;;;:20;107630:151;;;83336:42;107710:5;107716:1;107710:8;;;;;;;;-1:-1:-1;;;;;107710:24:0;;;:8;;;;;;;;;;;:24;107749:8;;107760:9;;107749:5;;107755:1;;107749:8;;;;;;-1:-1:-1;;;;;107749:20:0;;;:8;;;;;;;;;;;:20;107630:151;107348:440;;;;;:::o;108341:584::-;108423:12;;;;;;;108418:500;;108453:16;108471:15;108490:17;:15;:17::i;:::-;108452:55;;-1:-1:-1;108452:55:0;-1:-1:-1;108522:36:0;108536:21;108452:55;;108536:12;:21::i;108522:36::-;-1:-1:-1;108607:6:0;;:40;;-1:-1:-1;;;108607:40:0;;108580:21;;108607:6;;;-1:-1:-1;;;;;108607:6:0;;:25;;:40;;108641:4;;108607:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;108575:72;;;;;108688:6;108672:13;:22;108664:31;;;;;;83255:42;108712:12;108771:30;83255:42;108771:14;:30::i;:::-;108754:47;-1:-1:-1;108820:10:0;;108816:91;;108851:40;-1:-1:-1;;;;;108851:18:0;;108870:12;108884:6;108851:18;:40::i;:::-;108418:500;;;;;108341:584;:::o;18754:181::-;18812:7;18844:5;;;18868:6;;;;18860:46;;;;-1:-1:-1;;;18860:46:0;;;;;;;:::i;89727:135::-;89816:38;;-1:-1:-1;;;89816:38:0;;89789:7;;-1:-1:-1;;;;;89816:23:0;;;-1:-1:-1;;89816:38:0;;89848:4;;89816:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;36390:761::-;36840:69;;;;;;;;;;;;;;;;;;36814:23;;36840:69;;-1:-1:-1;;;;;36840:27:0;;;36868:4;;36840:27;:69::i;:::-;36924:17;;36814:95;;-1:-1:-1;36924:21:0;36920:224;;37066:10;37055:30;;;;;;;;;;;;:::i;:::-;37047:85;;;;-1:-1:-1;;;37047:85:0;;;;;;;:::i;21683:278::-;21769:7;21804:12;21797:5;21789:28;;;;-1:-1:-1;;;21789:28:0;;;;;;;;:::i;:::-;;21828:9;21844:1;21840;:5;;;;;;;21683:278;-1:-1:-1;;;;;21683:278:0:o;13260:979::-;13390:12;13423:18;13434:6;13423:10;:18::i;:::-;13415:60;;;;-1:-1:-1;;;13415:60:0;;;;;;;:::i;:::-;13549:12;13563:23;13590:6;-1:-1:-1;;;;;13590:11:0;13610:8;13621:4;13590:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13548:78;;;;13641:7;13637:595;;;13672:10;-1:-1:-1;13665:17:0;;-1:-1:-1;13665:17:0;13637:595;13786:17;;:21;13782:439;;14049:10;14043:17;14110:15;14097:10;14093:2;14089:19;14082:44;13997:148;14185:20;;-1:-1:-1;;;14185:20:0;;;;14192:12;;14185:20;;;:::i;13782:439::-;13260:979;;;;;;;;:::o;19657:192::-;19743:7;19779:12;19771:6;;;;19763:29;;;;-1:-1:-1;;;19763:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;19815:5:0;;;19657:192::o;100110:2239::-;100168:11;100193:16;100211:12;100227:41;100253:7;100262:5;100227:25;:41::i;:::-;100192:76;;;;100404:7;:29;;;;;100426:7;;100415:8;:18;100404:29;100400:850;;;100602:15;;;;100598:111;;;100649:44;100662:30;100674:7;100683:8;100662:11;:30::i;100649:44::-;100638:55;;100598:111;100723:7;100921:318;100939:7;;:16;;100951:3;100939:11;:16::i;:::-;100928:8;:27;100921:318;;;100987:42;101000:28;101013:8;101023:4;101000:12;:28::i;100987:42::-;100976:53;-1:-1:-1;101048:3:0;;101137:1;101132:6;;;;101128:96;;101172:4;101163:13;;101199:5;;101128:96;100921:318;;;100400:850;;101417:22;101441:21;101466:20;:18;:20::i;:::-;101519:16;;101416:70;;-1:-1:-1;101416:70:0;-1:-1:-1;101499:17:0;101589:14;101585:101;;101632:4;101620:16;;101585:101;101715:38;101743:9;101715:23;:13;101733:4;101715:17;:23::i;:38::-;101698:55;;101786:14;101768;:32;101764:430;;101817:18;101838:34;:14;101857;101838:18;:34::i;:::-;101903:6;;:31;;-1:-1:-1;;;101903:31:0;;101817:55;;-1:-1:-1;101887:13:0;;101903:6;;;;-1:-1:-1;;;;;101903:6:0;;-1:-1:-1;;101903:31:0;;101928:4;;101903:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101887:47;;101961:1;101953:5;:9;101949:234;;;102000:7;101987:10;:20;101983:185;;;102032:6;;:35;;-1:-1:-1;;;102032:35:0;;:6;;;;-1:-1:-1;;;;;102032:6:0;;-1:-1:-1;;102032:35:0;;102056:10;;102032:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;101983:185;;;102116:6;;:32;;-1:-1:-1;;;102116:32:0;;:6;;;;-1:-1:-1;;;;;102116:6:0;;-1:-1:-1;;102116:32:0;;102140:7;;102116:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;101983:185;101764:430;;;102210:16;;:21;:70;;;;-1:-1:-1;102258:4:0;;102267:13;;102235:29;;-1:-1:-1;;;;;102258:4:0;102235:14;:29::i;:::-;:45;102210:70;102206:136;;;102297:6;;:33;;-1:-1:-1;;;102297:33:0;;:6;;;;-1:-1:-1;;;;;102297:6:0;;:18;;:33;;102316:13;;102297:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;102206:136;100110:2239;;;;;;;;;:::o;17426:106::-;17484:7;17515:1;17511;:5;:13;;17523:1;17511:13;;;-1:-1:-1;17519:1:0;;17426:106;-1:-1:-1;17426:106:0:o;102847:1774::-;102927:16;102945:12;103022:16;103040:15;103059:17;:15;:17::i;:::-;103021:55;;-1:-1:-1;103021:55:0;-1:-1:-1;103171:22:0;103196:21;103021:55;;103196:12;:21::i;:::-;103171:46;;103475:21;103515:3;103511:258;;;103551:27;:14;103570:7;103551:18;:27::i;:::-;103535:43;;103511:258;;;103625:14;103615:7;:24;103611:89;;;103670:14;103660:24;;103611:89;103730:27;:14;103749:7;103730:18;:27::i;:::-;103714:43;;103511:258;103806:11;103820:35;103838:16;;103820:13;:17;;:35;;;;:::i;:::-;103806:49;;103866:11;103880:35;103898:16;;103888:4;103880:17;;:35;;;;:::i;:::-;103866:49;-1:-1:-1;103928:21:0;103952:12;:3;103866:49;103952:7;:12::i;:::-;103928:36;;103995:3;103979:13;:19;103975:140;;;104081:22;:13;104099:3;104081:17;:22::i;:::-;104065:38;;103975:140;104320:7;104304:13;:23;104300:314;;;104354:4;;-1:-1:-1;104384:26:0;:7;104396:13;104384:11;:26::i;:::-;104373:37;;104300:314;;;104545:5;;-1:-1:-1;104576:26:0;:13;104594:7;104576:17;:26::i;:::-;104565:37;;104300:314;102847:1774;;;;;;;;;;;;:::o;109121:795::-;109188:14;109328:12;109342:16;109362:20;:18;:20::i;:::-;109327:55;;;;109472:8;109484:1;109472:13;:24;;;;;109489:7;109472:24;109468:65;;;109520:1;109513:8;;;;;;109468:65;109611:6;;109586:33;;-1:-1:-1;;;109586:33:0;;109548:32;;83139:42;;-1:-1:-1;;109586:33:0;;109611:6;;;;-1:-1:-1;;;;;109611:6:0;;109586:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;109545:74;;;;109636:7;109632:217;;;109669:64;109687:3;109692:4;109698:8;109708:24;109669:17;:64::i;:::-;109660:73;;109632:217;;;109775:62;109791:3;109796:4;109802:8;109812:24;109775:15;:62::i;:::-;109766:71;;109632:217;109866:42;109875:3;109880:6;109888:7;109905:1;109866:42;;;;;;;;;:::i;:::-;;;;;;;;109121:795;;;;;;;:::o;112738:190::-;112898:4;;112905:14;;112841:79;;-1:-1:-1;;;112841:79:0;;112814:7;;112841:12;;-1:-1:-1;;112841:79:0;;112866:7;;112875:13;;-1:-1:-1;;;;;112898:4:0;;;;112841:79;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;106584:237::-;106630:13;;;;106626:52;;;106660:7;;106626:52;106714:16;;;106728:1;106714:16;;;;;;;;;106688:23;;106714:16;;;;;;;;;-1:-1:-1;;106753:6:0;;106741:9;;;;-1:-1:-1;106753:6:0;;;-1:-1:-1;;;;;106753:6:0;;106741:9;;-1:-1:-1;106748:1:0;;106741:9;;;;-1:-1:-1;;;;;106741:18:0;;;;:9;;;;;;;;;;;:18;106772:41;;-1:-1:-1;;;106772:41:0;;83139:42;;106772:18;;:41;;106799:4;;106806:6;;106772:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106855:485;106901:13;106917:20;83255:42;106917:14;:20::i;:::-;106901:36;;106960:13;;106952:5;:21;106948:60;;;106990:7;;;106948:60;107024:8;;-1:-1:-1;;;107024:8:0;;;;107020:313;;;107074:103;;;;;;;;;107140:4;;83948:42;;107049:24;;107074:103;;107108:38;;83255:42;;-1:-1:-1;;;;;107140:4:0;107108:17;:38::i;:::-;107074:103;;;;107156:4;-1:-1:-1;;;;;107074:103:0;;;;;107163:3;107074:103;;;;107168:5;107074:103;;;;107175:1;107074:103;;;107049:129;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;107020:313::-;107211:15;;107294:4;;-1:-1:-1;;;;;107211:15:0;;;;:40;;107252:5;;107211:15;;107262:38;;83255:42;;107294:4;107262:17;:38::i;:::-;107310:4;107317:3;107211:110;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;107211:110:0;;;;;;;;;;;;:::i;84750:138::-;84827:53;-1:-1:-1;;;;;84827:25:0;;84853:7;-1:-1:-1;;84827:25:0;:53::i;8768:619::-;8828:4;9296:20;;9139:66;9336:23;;;;;;:42;;-1:-1:-1;;9363:15:0;;;9328:51;-1:-1:-1;;8768:619:0:o;109978:1289::-;110142:25;;110320:16;;110316:102;;110371:35;110394:11;110371:18;:8;110384:4;110371:12;:18::i;:35::-;110353:53;;110316:102;110448:25;:4;110457:15;110448:8;:25::i;:::-;110428:45;;110511:8;110490:17;:29;110486:90;;110556:8;110536:28;;110486:90;110611:13;110590:17;:34;110586:100;;110661:13;110641:33;;110586:100;110725:6;;:27;;;-1:-1:-1;;;110725:27:0;;;;110696:26;;110725:6;;;-1:-1:-1;;;;;110725:6:0;;:25;;:27;;;;;;;;;;;;;;:6;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;110696:56;-1:-1:-1;110696:56:0;110916:27;:17;110938:4;110916:21;:27::i;:::-;:49;;:75;;;;;110989:2;110969:17;:22;110916:75;110912:348;;;111028:34;:17;111058:2;111028:21;:34::i;:::-;111077:6;;:42;;-1:-1:-1;;;111077:42:0;;111008:54;;-1:-1:-1;111077:6:0;;;-1:-1:-1;;;;;111077:6:0;;-1:-1:-1;;111077:42:0;;111008:54;;111077:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;111211:6:0;;:37;;-1:-1:-1;;;111211:37:0;;:6;;;;-1:-1:-1;;;;;111211:6:0;;:18;;:37;;111230:17;;111211:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;109978:1289;;;;;;;;:::o;111331:644::-;111491:23;;111555:31;111581:4;111555:21;:4;111564:11;111555:8;:21::i;:31::-;111527:59;-1:-1:-1;111617:31:0;111527:59;111639:8;111617:21;:31::i;:::-;111599:49;;111684:11;111665:15;:30;111661:92;;111730:11;111712:29;;111661:92;111785:2;111767:15;:20;111763:205;;;111822:32;:15;111850:2;111822:19;:32::i;:::-;111869:6;;:30;;-1:-1:-1;;;111869:30:0;;111804:50;;-1:-1:-1;111869:6:0;;;-1:-1:-1;;;;;111869:6:0;;:13;;:30;;111804:50;;111869:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;111914:6:0;;111949:4;;-1:-1:-1;;;;;111914:6:0;;;;;;;:11;;111926:29;;111949:4;111926:14;:29::i;:::-;111914:42;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;111763:205::-;111331:644;;;;;;;:::o;107796:405::-;107926:4;;107883:18;;-1:-1:-1;;;;;107926:4:0;83336:42;107918:21;107914:280;;;107989:8;108000:17;;;;;;;;;;;83336:42;107964:69;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;107956:77;;107914:280;;;108110:17;;108074:108;;;;108099:8;;108110:17;-1:-1:-1;;;108110:17:0;;;;;83336:42;;-1:-1:-1;;;108144:17:0;;;;;;;108171:9;;108074:108;;;:::i;:::-;;;;;;;;;;;;;108066:116;;107796: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;4035:128::-;4101:20;;43875:8;43864:20;;47668:34;;47658:2;;47716:1;;47706:12;4585:241;;4689:2;4677:9;4668:7;4664:23;4660:32;4657:2;;;-1:-1;;4695:12;4657:2;85:6;72:20;97:33;124:5;97:33;:::i;4833:263::-;;4948:2;4936:9;4927:7;4923:23;4919:32;4916:2;;;-1:-1;;4954:12;4916:2;226:6;220:13;238:33;265:5;238:33;:::i;5103:366::-;;;5224:2;5212:9;5203:7;5199:23;5195:32;5192:2;;;-1:-1;;5230:12;5192:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5282:63;-1:-1;5382:2;5421:22;;72:20;97:33;72:20;97:33;:::i;:::-;5390:63;;;;5186:283;;;;;:::o;5476:491::-;;;;5614:2;5602:9;5593:7;5589:23;5585:32;5582:2;;;-1:-1;;5620:12;5582:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5672:63;-1:-1;5772:2;5811:22;;72:20;97:33;72:20;97:33;:::i;:::-;5576:391;;5780:63;;-1:-1;;;5880:2;5919:22;;;;4237:20;;5576:391::o;5974:867::-;;;;;;;6165:3;6153:9;6144:7;6140:23;6136:33;6133:2;;;-1:-1;;6172:12;6133:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;6224:63;-1:-1;6324:2;6363:22;;72:20;97:33;72:20;97:33;:::i;:::-;6332:63;-1:-1;6432:2;6471:22;;4237:20;;-1:-1;6540:2;6579:22;;4237:20;;-1:-1;6676:3;6661:19;;6648:33;6701:18;6690:30;;6687:2;;;-1:-1;;6723:12;6687:2;6761:64;6817:7;6808:6;6797:9;6793:22;6761:64;:::i;:::-;6127:714;;;;-1:-1;6127:714;;-1:-1;6127:714;;6743:82;;6127:714;-1:-1;;;6127:714::o;6848:392::-;;6988:2;;6976:9;6967:7;6963:23;6959:32;6956:2;;;-1:-1;;6994:12;6956:2;7045:17;7039:24;7083:18;7075:6;7072:30;7069:2;;;-1:-1;;7105:12;7069:2;7192: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;;;4385:13;;893:61;;847:1;840:9;;;;;968:14;;;;996;;800:217;;;-1:-1;7125:99;6950:290;-1:-1;;;;;;;6950:290::o;7247:235::-;;7348:2;7336:9;7327:7;7323:23;7319:32;7316:2;;;-1:-1;;7354:12;7316:2;1108:6;1095:20;1120:30;1144:5;1120:30;:::i;7489:257::-;;7601:2;7589:9;7580:7;7576:23;7572:32;7569:2;;;-1:-1;;7607:12;7569:2;1243:6;1237:13;1255:30;1279:5;1255:30;:::i;7753:360::-;;;7871:2;7859:9;7850:7;7846:23;7842:32;7839:2;;;-1:-1;;7877:12;7839:2;1108:6;1095:20;1120:30;1144:5;1120:30;:::i;:::-;7929:60;8026:2;8065:22;;;;4237:20;;-1:-1;;;7833:280::o;8120:523::-;;;;8263:2;8251:9;8242:7;8238:23;8234:32;8231:2;;;-1:-1;;8269:12;8231:2;1243:6;1237:13;1255:30;1279:5;1255:30;:::i;:::-;8429:2;8479:22;;4385:13;8548:2;8595:22;;1237:13;8321:71;;-1:-1;4385:13;-1:-1;1255:30;1237:13;1255:30;:::i;:::-;8556:71;;;;8225:418;;;;;:::o;8650:263::-;;8765:2;8753:9;8744:7;8740:23;8736:32;8733:2;;;-1:-1;;8771:12;8733:2;-1:-1;1375:13;;8727:186;-1:-1;8727:186::o;9224:367::-;;;9348:2;9336:9;9327:7;9323:23;9319:32;9316:2;;;-1:-1;;9354:12;9316:2;9412:17;9399:31;9450:18;9442:6;9439:30;9436:2;;;-1:-1;;9472:12;9436:2;9510:65;9567:7;9558:6;9547:9;9543:22;9510:65;:::i;:::-;9492:83;;;;-1:-1;9310:281;-1:-1;;;;9310:281::o;9598:324::-;;9743:3;;9731:9;9722:7;9718:23;9714:33;9711:2;;;-1:-1;;9750:12;9711:2;2527:22;9743:3;2527:22;:::i;:::-;2518:31;;2673:22;4385:13;2623:16;2616:86;2769:2;2838:9;2834:22;4385:13;2769:2;2788:5;2784:16;2777:86;2929:2;2998:9;2994:22;4385:13;2929:2;2948:5;2944:16;2937:86;3097:2;3166:9;3162:22;4385:13;3097:2;3116:5;3112:16;3105:86;3265:3;3335:9;3331:22;4385:13;3265:3;3285:5;3281:16;3274:86;3427:3;3497:9;3493:22;4385:13;3427:3;3447:5;3443:16;3436:86;3588:3;3658:9;3654:22;4385:13;3588:3;3608:5;3604:16;3597:86;3749:3;3819:9;3815:22;4385:13;3749:3;3769:5;3765:16;3758:86;3910:3;;3982:9;3978:22;4385:13;3910:3;3930:5;3926:18;3919:88;;9802:104;;;;9705:217;;;;:::o;9929:362::-;;;10048:2;10036:9;10027:7;10023:23;10019:32;10016:2;;;-1:-1;;10054:12;10016:2;10116:52;10160:7;10136:22;10116:52;:::i;:::-;10106:62;;10223:52;10267:7;10205:2;10247:9;10243:22;10223:52;:::i;:::-;10213:62;;10010:281;;;;;:::o;10298:241::-;;10402:2;10390:9;10381:7;10377:23;10373:32;10370:2;;;-1:-1;;10408:12;10370:2;-1:-1;4237:20;;10364:175;-1:-1;10364:175::o;10816:672::-;;;;;10982:3;10970:9;10961:7;10957:23;10953:33;10950:2;;;-1:-1;;10989:12;10950:2;-1:-1;;4385:13;;11152:2;11202:22;;4385:13;11271:2;11321:22;;4385:13;11390:2;11440:22;;;4385:13;;;;;-1:-1;4385:13;;-1:-1;10944:544;-1:-1;10944:544::o;11495:259::-;;11608:2;11596:9;11587:7;11583:23;11579:32;11576:2;;;-1:-1;;11614:12;11576:2;4530:6;4524:13;44046:4;47939:5;44035:16;47916:5;47913:33;47903:2;;-1:-1;;47950:12;12854:690;;13047:5;41914:12;42749:6;42744:3;42737:19;42786:4;;42781:3;42777:14;13059:93;;42786:4;13223:5;41594:14;-1:-1;13262:260;13287:6;13284:1;13281:13;13262:260;;;13348:13;;-1:-1;;;;;43737:54;12367:37;;11915:14;;;;42461;;;;-1:-1;13302:9;13262:260;;;-1:-1;13528:10;;12978:566;-1:-1;;;;;12978:566::o;14720:323::-;;14852:5;41914:12;42749:6;42744:3;42737:19;14935:52;14980:6;42786:4;42781:3;42777:14;42786:4;14961:5;14957:16;14935:52;:::i;:::-;46859:7;46843:14;-1:-1;;46839:28;14999:39;;;;42786:4;14999:39;;14800:243;-1:-1;;14800:243::o;23459:526::-;47058:2;47054:14;;;-1:-1;;47054:14;;;12753:58;;46951:15;;;;;-1:-1;;;;;;46951:15;23738:2;23729:12;;23033:56;47054:14;;;23838:11;;;12753:58;23948:12;;;23629:356::o;23992:799::-;-1:-1;;47058:2;47054:14;;;;;12753:58;;-1:-1;;;;;;;46951:15;;;;;24325:2;24316:12;;23033:56;47054:14;;;;;24425:11;;;12753:58;46951:15;;;;;;;24535:12;;;23033:56;47054:14;;;;;24644:11;;;12753:58;24754:12;;;24216:575::o;24798:271::-;;15210:5;41914:12;15321:52;15366:6;15361:3;15354:4;15347:5;15343:16;15321:52;:::i;:::-;15385:16;;;;;24932:137;-1:-1;;24932:137::o;25076:222::-;-1:-1;;;;;43737:54;;;;12367:37;;25203:2;25188:18;;25174:124::o;25305:333::-;-1:-1;;;;;43737:54;;;12367:37;;43737:54;;25624:2;25609:18;;12367:37;25460:2;25445:18;;25431:207::o;25645:513::-;-1:-1;;;;;43737:54;;;12367:37;;25866:2;25984;25969:18;;;25962:48;;;41914:12;;25851:18;;;42737:19;;;-1:-1;;41594:14;;;;-1:-1;;25984:2;42777:14;;;;-1:-1;14048:292;14073:6;14070:1;14067:13;14048:292;;;14134:13;;43737:54;;15500:66;;42461:14;;;;12129;;;;14095:1;14088:9;14048:292;;;-1:-1;26016:132;;25837:321;-1:-1;;;;;;;;25837:321::o;26165:349::-;-1:-1;;;;;43737:54;;;;12367:37;;26500:2;26485:18;;16500:58;26328:2;26313:18;;26299:215::o;26861:370::-;;27038:2;27059:17;27052:47;27113:108;27038:2;27027:9;27023:18;27207:6;27113:108;:::i;27238:210::-;43455:13;;43448:21;14435:34;;27359:2;27344:18;;27330:118::o;27455:584::-;43455:13;;43448:21;14435:34;;27843:2;27828:18;;14671:37;;;;-1:-1;;;;;43737:54;27934:2;27919:18;;12367:37;28025:2;28010:18;;14671:37;27668:3;27653:19;;27639:400::o;28046:616::-;43455:13;;43448:21;14435:34;;28450:2;28435:18;;14671:37;;;;28541:2;28526:18;;14671:37;-1:-1;;;;;43737:54;28648:2;28633:18;;15500:66;28275:3;28260:19;;28246:416::o;28669:222::-;14671:37;;;28796:2;28781:18;;28767:124::o;29962:330::-;;30119:2;30140:17;30133:47;42749:6;30119:2;30108:9;30104:18;42737:19;46132:6;46127:3;42777:14;30108:9;42777:14;46109:30;46170:16;;;42777:14;46170:16;;;46163:27;;;;46859:7;46843:14;;;-1:-1;;46839:28;16850:39;;;30090:202;-1:-1;30090:202::o;30299:310::-;;30446:2;30467:17;30460:47;30521:78;30446:2;30435:9;30431:18;30585:6;30521:78;:::i;30616:416::-;30816:2;30830:47;;;17482:2;30801:18;;;42737:19;-1:-1;;;42777:14;;;17498:34;17551:12;;;30787:245::o;31039:416::-;31239:2;31253:47;;;17802:1;31224:18;;;42737:19;-1:-1;;;42777:14;;;17817:28;17864:12;;;31210:245::o;31462:416::-;31662:2;31676:47;;;18115:2;31647:18;;;42737:19;18151:29;42777:14;;;18131:50;18200:12;;;31633:245::o;31885:416::-;32085:2;32099:47;;;18451:2;32070:18;;;42737:19;-1:-1;;;42777:14;;;18467:35;18521:12;;;32056:245::o;32308:416::-;32508:2;32522:47;;;18772:2;32493:18;;;42737:19;18808:30;42777:14;;;18788:51;18858:12;;;32479:245::o;32731:416::-;32931:2;32945:47;;;19109:2;32916:18;;;42737:19;19145:34;42777:14;;;19125:55;-1:-1;;;19200:12;;;19193:25;19237:12;;;32902:245::o;33154:416::-;33354:2;33368:47;;;19488:1;33339:18;;;42737:19;-1:-1;;;42777:14;;;19503:29;19551:12;;;33325:245::o;33577:416::-;33777:2;33791:47;;;19802:1;33762:18;;;42737:19;-1:-1;;;42777:14;;;19817:30;19866:12;;;33748:245::o;34000:416::-;34200:2;34214:47;;;20117:2;34185:18;;;42737:19;20153:31;42777:14;;;20133:52;20204:12;;;34171:245::o;34423:416::-;34623:2;34637:47;;;20455:2;34608:18;;;42737:19;-1:-1;;;42777:14;;;20471:34;20524:12;;;34594:245::o;34846:416::-;35046:2;35060:47;;;20775:2;35031:18;;;42737:19;20811:34;42777:14;;;20791:55;-1:-1;;;20866:12;;;20859:34;20912:12;;;35017:245::o;35269:416::-;35469:2;35483:47;;;21163:2;35454:18;;;42737:19;-1:-1;;;42777:14;;;21179:33;21231:12;;;35440:245::o;35692:416::-;35892:2;35906:47;;;21482:2;35877:18;;;42737:19;21518:34;42777:14;;;21498:55;-1:-1;;;21573:12;;;21566:46;21631:12;;;35863:245::o;36115:406::-;;36310:2;36331:17;36324:47;21989:16;21983:23;21917:4;36310:2;36299:9;36295:18;22019:38;22072:71;21908:14;36299:9;21908:14;22124:12;22072:71;:::i;:::-;22064:79;;1644:18;;43748:42;;;36310:2;22226:5;22222:16;22216:23;43737:54;22293:14;36299:9;22293:14;12367:37;22293:14;22384:5;22380:16;22374:23;22451:14;36299:9;22451:14;14671:37;22451:14;22542:5;22538:16;22532:23;22609:14;36299:9;22609:14;14671:37;22609:14;22708:5;22704:16;22698:23;21917:4;36299:9;22775:14;14671:37;36377:134;;;;36281:240;;;;:::o;36528:218::-;43875:8;43864:20;;;;22898:36;;36653:2;36638:18;;36624:122::o;36982:481::-;;14701:5;14678:3;14671:37;37187:2;37305;37294:9;37290:18;37283:48;37345:108;37187:2;37176:9;37172:18;37439:6;37345:108;:::i;37470:832::-;;14701:5;14678:3;14671:37;45771:24;37940:2;37929:9;37925:18;16500:58;37767:3;37977:2;37966:9;37962:18;37955:48;38017:108;37767:3;37756:9;37752:19;38111:6;38017:108;:::i;:::-;-1:-1;;;;;43737:54;;;;38204:2;38189:18;;12367:37;-1:-1;38287:3;38272:19;14671:37;43737:54;38009:116;-1:-1;;;37738:564::o;38309:333::-;14671:37;;;38628:2;38613:18;;14671:37;38464:2;38449:18;;38435:207::o;38649:560::-;14671:37;;;39027:2;39012:18;;14671:37;;;;43455:13;43448:21;39104:2;39089:18;;14435:34;-1:-1;;;;;43737:54;39195:2;39180:18;;12236:58;38862:3;38847:19;;38833:376::o;39216:444::-;14671:37;;;39563:2;39548:18;;14671:37;;;;39646:2;39631:18;;14671:37;39399:2;39384:18;;39370:290::o;39667:556::-;14671:37;;;40043:2;40028:18;;14671:37;;;;40126:2;40111:18;;14671:37;40209:2;40194:18;;14671:37;39878:3;39863:19;;39849:374::o;40230:668::-;14671:37;;;40634:2;40619:18;;14671:37;;;;40717:2;40702:18;;14671:37;;;;40800:2;40785:18;;14671:37;40883:3;40868:19;;14671:37;40469:3;40454:19;;40440:458::o;40905:256::-;40967:2;40961:9;40993:17;;;41068:18;41053:34;;41089:22;;;41050:62;41047:2;;;41125:1;;41115:12;41047:2;40967;41134:22;40945:216;;-1:-1;40945:216::o;41168:304::-;;41327:18;41319:6;41316:30;41313:2;;;-1:-1;;41349:12;41313:2;-1:-1;41394:4;41382:17;;;41447:15;;41250:222::o;46205:268::-;46270:1;46277:101;46291:6;46288:1;46285:13;46277:101;;;46358:11;;;46352:18;46339:11;;;46332:39;46313:2;46306:10;46277:101;;;46393:6;46390:1;46387:13;46384:2;;;-1:-1;;46270:1;46440:16;;46433:27;46254:219::o;47086:117::-;-1:-1;;;;;43737:54;;47145:35;;47135:2;;47194:1;;47184:12;47210:111;47291:5;43455:13;43448:21;47269:5;47266:32;47256:2;;47312:1;;47302:12
Swarm Source
ipfs://4fbe1f6c346640ade3ea6687ce05bc5b2469b59584aa4a7c2a914b6f2ecc4d9d
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ 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.