Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 2 internal transactions
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
13579629 | 1072 days ago | Contract Creation | 0 ETH | |||
12911458 | 1176 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-07-12 */ // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.6.12; pragma experimental ABIEncoderV2; // Global Enums and Structs struct Rebase { uint128 elastic; uint128 base; } struct StrategyParams { uint256 performanceFee; uint256 activation; uint256 debtRatio; uint256 minDebtPerHarvest; uint256 maxDebtPerHarvest; uint256 lastReport; uint256 totalDebt; uint256 totalGain; uint256 totalLoss; } // Part: BIERC20 interface BIERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval( address indexed owner, address indexed spender, uint256 value ); /// @notice EIP 2612 function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; } // Part: BoringMath /// @notice A library for performing overflow-/underflow-safe math, /// updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math). library BoringMath { function add(uint256 a, uint256 b) internal pure returns (uint256 c) { require((c = a + b) >= b, "BoringMath: Add Overflow"); } function sub(uint256 a, uint256 b) internal pure returns (uint256 c) { require((c = a - b) <= a, "BoringMath: Underflow"); } function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { require(b == 0 || (c = a * b) / b == a, "BoringMath: Mul Overflow"); } function to128(uint256 a) internal pure returns (uint128 c) { require(a <= uint128(-1), "BoringMath: uint128 Overflow"); c = uint128(a); } function to64(uint256 a) internal pure returns (uint64 c) { require(a <= uint64(-1), "BoringMath: uint64 Overflow"); c = uint64(a); } function to32(uint256 a) internal pure returns (uint32 c) { require(a <= uint32(-1), "BoringMath: uint32 Overflow"); c = uint32(a); } } // Part: BoringMath128 /// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint128. library BoringMath128 { function add(uint128 a, uint128 b) internal pure returns (uint128 c) { require((c = a + b) >= b, "BoringMath: Add Overflow"); } function sub(uint128 a, uint128 b) internal pure returns (uint128 c) { require((c = a - b) <= a, "BoringMath: Underflow"); } } // Part: IMasterChef interface IMasterChef { struct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. } struct PoolInfo { address lpToken; // Address of LP token contract. uint256 allocPoint; // How many allocation points assigned to this pool. SUSHI to distribute per block. uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs. uint256 accSushiPerShare; // Accumulated SUSHI per share, times 1e12. See below. } function poolInfo(uint256 pid) external view returns (IMasterChef.PoolInfo memory); function totalAllocPoint() external view returns (uint256); function deposit(uint256 _pid, uint256 _amount) external; function withdraw(uint256 _pid, uint256 _amount) external; function emergencyWithdraw(uint256 _pid) external; function userInfo(uint256 _pid, address user) external view returns (IMasterChef.UserInfo memory); function pendingSushi(uint256 _pid, address _user) external view returns (uint256); } // Part: IOracle interface IOracle { /// @notice Get the latest exchange rate. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return success if no valid (recent) rate is available, return false else true. /// @return rate The rate of the requested asset / pair / pool. function get(bytes calldata data) external returns (bool success, uint256 rate); /// @notice Check the last exchange rate without any state changes. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return success if no valid (recent) rate is available, return false else true. /// @return rate The rate of the requested asset / pair / pool. function peek(bytes calldata data) external view returns (bool success, uint256 rate); /// @notice Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek(). /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return rate The rate of the requested asset / pair / pool. function peekSpot(bytes calldata data) external view returns (uint256 rate); /// @notice Returns a human readable (short) name about this oracle. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return (string) A human readable symbol name about this oracle. function symbol(bytes calldata data) external view returns (string memory); /// @notice Returns a human readable name about this oracle. /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. /// For example: /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256)); /// @return (string) A human readable name about this oracle. function name(bytes calldata data) external view returns (string memory); } // Part: IStrategy interface IStrategy { // Send the assets to the Strategy and call skim to invest them function skim(uint256 amount) external; // Harvest any profits made converted to the asset and pass them to the caller function harvest(uint256 balance, address sender) external returns (int256 amountAdded); // Withdraw assets. The returned amount can differ from the requested amount due to rounding. // The actualAmount should be very close to the amount. The difference should NOT be used to report a loss. That's what harvest is for. function withdraw(uint256 amount) external returns (uint256 actualAmount); // Withdraw all assets in the safest way possible. This shouldn't fail. function exit(uint256 balance) external returns (int256 amountAdded); } // 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: 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: IBatchFlashBorrower interface IBatchFlashBorrower { function onBatchFlashLoan( address sender, BIERC20[] calldata tokens, uint256[] calldata amounts, uint256[] calldata fees, bytes calldata data ) external; } // Part: IFlashBorrower interface IFlashBorrower { function onFlashLoan( address sender, BIERC20 token, uint256 amount, uint256 fee, bytes calldata data ) external; } // Part: ISwapper interface ISwapper { /// @notice Withdraws 'amountFrom' of token 'from' from the BentoBox account for this swapper. /// Swaps it for at least 'amountToMin' of token 'to'. /// Transfers the swapped tokens of 'to' into the BentoBox using a plain ERC20 transfer. /// Returns the amount of tokens 'to' transferred to BentoBox. /// (The BentoBox skim function will be used by the caller to get the swapped funds). function swap( BIERC20 fromToken, BIERC20 toToken, address recipient, uint256 shareToMin, uint256 shareFrom ) external returns (uint256 extraShare, uint256 shareReturned); /// @notice Calculates the amount of token 'from' needed to complete the swap (amountFrom), /// this should be less than or equal to amountFromMax. /// Withdraws 'amountFrom' of token 'from' from the BentoBox account for this swapper. /// Swaps it for exactly 'exactAmountTo' of token 'to'. /// Transfers the swapped tokens of 'to' into the BentoBox using a plain ERC20 transfer. /// Transfers allocated, but unused 'from' tokens within the BentoBox to 'refundTo' (amountFromMax - amountFrom). /// Returns the amount of 'from' tokens withdrawn from BentoBox (amountFrom). /// (The BentoBox skim function will be used by the caller to get the swapped funds). function swapExact( BIERC20 fromToken, BIERC20 toToken, address recipient, address refundTo, uint256 shareFromSupplied, uint256 shareToExact ) external returns (uint256 shareUsed, uint256 shareReturned); } // 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: 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: RebaseLibrary /// @notice A rebasing library using overflow-/underflow-safe math. library RebaseLibrary { using BoringMath for uint256; using BoringMath128 for uint128; /// @notice Calculates the base value in relationship to `elastic` and `total`. function toBase( Rebase memory total, uint256 elastic, bool roundUp ) internal pure returns (uint256 base) { if (total.elastic == 0) { base = elastic; } else { base = elastic.mul(total.base) / total.elastic; if (roundUp && base.mul(total.elastic) / total.base < elastic) { base = base.add(1); } } } /// @notice Calculates the elastic value in relationship to `base` and `total`. function toElastic( Rebase memory total, uint256 base, bool roundUp ) internal pure returns (uint256 elastic) { if (total.base == 0) { elastic = base; } else { elastic = base.mul(total.elastic) / total.base; if (roundUp && elastic.mul(total.base) / total.elastic < base) { elastic = elastic.add(1); } } } /// @notice Add `elastic` to `total` and doubles `total.base`. /// @return (Rebase) The new total. /// @return base in relationship to `elastic`. function add( Rebase memory total, uint256 elastic, bool roundUp ) internal pure returns (Rebase memory, uint256 base) { base = toBase(total, elastic, roundUp); total.elastic = total.elastic.add(elastic.to128()); total.base = total.base.add(base.to128()); return (total, base); } /// @notice Sub `base` from `total` and update `total.elastic`. /// @return (Rebase) The new total. /// @return elastic in relationship to `base`. function sub( Rebase memory total, uint256 base, bool roundUp ) internal pure returns (Rebase memory, uint256 elastic) { elastic = toElastic(total, base, roundUp); total.elastic = total.elastic.sub(elastic.to128()); total.base = total.base.sub(base.to128()); return (total, elastic); } /// @notice Add `elastic` and `base` to `total`. function add( Rebase memory total, uint256 elastic, uint256 base ) internal pure returns (Rebase memory) { total.elastic = total.elastic.add(elastic.to128()); total.base = total.base.add(base.to128()); return total; } /// @notice Subtract `elastic` and `base` to `total`. function sub( Rebase memory total, uint256 elastic, uint256 base ) internal pure returns (Rebase memory) { total.elastic = total.elastic.sub(elastic.to128()); total.base = total.base.sub(base.to128()); return total; } /// @notice Add `elastic` to `total` and update storage. /// @return newElastic Returns updated `elastic`. function addElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) { newElastic = total.elastic = total.elastic.add(elastic.to128()); } /// @notice Subtract `elastic` from `total` and update storage. /// @return newElastic Returns updated `elastic`. function subElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) { newElastic = total.elastic = total.elastic.sub(elastic.to128()); } } // 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: IBentoBoxV1 (Alias import as IBentoBox) interface IBentoBox { event LogDeploy( address indexed masterContract, bytes data, address indexed cloneAddress ); event LogDeposit( address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share ); event LogFlashLoan( address indexed borrower, address indexed token, uint256 amount, uint256 feeAmount, address indexed receiver ); event LogRegisterProtocol(address indexed protocol); event LogSetMasterContractApproval( address indexed masterContract, address indexed user, bool approved ); event LogStrategyDivest(address indexed token, uint256 amount); event LogStrategyInvest(address indexed token, uint256 amount); event LogStrategyLoss(address indexed token, uint256 amount); event LogStrategyProfit(address indexed token, uint256 amount); event LogStrategyQueued(address indexed token, address indexed strategy); event LogStrategySet(address indexed token, address indexed strategy); event LogStrategyTargetPercentage( address indexed token, uint256 targetPercentage ); event LogTransfer( address indexed token, address indexed from, address indexed to, uint256 share ); event LogWhiteListMasterContract( address indexed masterContract, bool approved ); event LogWithdraw( address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share ); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); function balanceOf(BIERC20, address) external view returns (uint256); function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results); function batchFlashLoan( IBatchFlashBorrower borrower, address[] calldata receivers, BIERC20[] calldata tokens, uint256[] calldata amounts, bytes calldata data ) external; function claimOwnership() external; function deploy( address masterContract, bytes calldata data, bool useCreate2 ) external payable; function deposit( BIERC20 token_, address from, address to, uint256 amount, uint256 share ) external payable returns (uint256 amountOut, uint256 shareOut); function flashLoan( IFlashBorrower borrower, address receiver, BIERC20 token, uint256 amount, bytes calldata data ) external; function harvest( BIERC20 token, bool balance, uint256 maxChangeAmount ) external; function masterContractApproved(address, address) external view returns (bool); function masterContractOf(address) external view returns (address); function nonces(address) external view returns (uint256); function owner() external view returns (address); function pendingOwner() external view returns (address); function pendingStrategy(BIERC20) external view returns (IStrategy); function permitToken( BIERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function registerProtocol() external; function setMasterContractApproval( address user, address masterContract, bool approved, uint8 v, bytes32 r, bytes32 s ) external; function setStrategy(BIERC20 token, IStrategy newStrategy) external; function setStrategyTargetPercentage( BIERC20 token, uint64 targetPercentage_ ) external; function strategy(BIERC20) external view returns (IStrategy); function strategyData(BIERC20) external view returns ( uint64 strategyStartDate, uint64 targetPercentage, uint128 balance ); function toAmount( BIERC20 token, uint256 share, bool roundUp ) external view returns (uint256 amount); function toShare( BIERC20 token, uint256 amount, bool roundUp ) external view returns (uint256 share); function totals(BIERC20) external view returns (Rebase memory totals_); function transfer( BIERC20 token, address from, address to, uint256 share ) external; function transferMultiple( BIERC20 token, address from, address[] calldata tos, uint256[] calldata shares ) external; function transferOwnership( address newOwner, bool direct, bool renounce ) external; function whitelistMasterContract(address masterContract, bool approved) external; function whitelistedMasterContracts(address) external view returns (bool); function withdraw( BIERC20 token_, address from, address to, uint256 amount, uint256 share ) external returns (uint256 amountOut, uint256 shareOut); } // Part: IBentoBoxV1 interface IBentoBoxV1 { event LogDeploy( address indexed masterContract, bytes data, address indexed cloneAddress ); event LogDeposit( address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share ); event LogFlashLoan( address indexed borrower, address indexed token, uint256 amount, uint256 feeAmount, address indexed receiver ); event LogRegisterProtocol(address indexed protocol); event LogSetMasterContractApproval( address indexed masterContract, address indexed user, bool approved ); event LogStrategyDivest(address indexed token, uint256 amount); event LogStrategyInvest(address indexed token, uint256 amount); event LogStrategyLoss(address indexed token, uint256 amount); event LogStrategyProfit(address indexed token, uint256 amount); event LogStrategyQueued(address indexed token, address indexed strategy); event LogStrategySet(address indexed token, address indexed strategy); event LogStrategyTargetPercentage( address indexed token, uint256 targetPercentage ); event LogTransfer( address indexed token, address indexed from, address indexed to, uint256 share ); event LogWhiteListMasterContract( address indexed masterContract, bool approved ); event LogWithdraw( address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share ); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); function balanceOf(BIERC20, address) external view returns (uint256); function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results); function batchFlashLoan( IBatchFlashBorrower borrower, address[] calldata receivers, BIERC20[] calldata tokens, uint256[] calldata amounts, bytes calldata data ) external; function claimOwnership() external; function deploy( address masterContract, bytes calldata data, bool useCreate2 ) external payable; function deposit( BIERC20 token_, address from, address to, uint256 amount, uint256 share ) external payable returns (uint256 amountOut, uint256 shareOut); function flashLoan( IFlashBorrower borrower, address receiver, BIERC20 token, uint256 amount, bytes calldata data ) external; function harvest( BIERC20 token, bool balance, uint256 maxChangeAmount ) external; function masterContractApproved(address, address) external view returns (bool); function masterContractOf(address) external view returns (address); function nonces(address) external view returns (uint256); function owner() external view returns (address); function pendingOwner() external view returns (address); function pendingStrategy(BIERC20) external view returns (IStrategy); function permitToken( BIERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function registerProtocol() external; function setMasterContractApproval( address user, address masterContract, bool approved, uint8 v, bytes32 r, bytes32 s ) external; function setStrategy(BIERC20 token, IStrategy newStrategy) external; function setStrategyTargetPercentage( BIERC20 token, uint64 targetPercentage_ ) external; function strategy(BIERC20) external view returns (IStrategy); function strategyData(BIERC20) external view returns ( uint64 strategyStartDate, uint64 targetPercentage, uint128 balance ); function toAmount( BIERC20 token, uint256 share, bool roundUp ) external view returns (uint256 amount); function toShare( BIERC20 token, uint256 amount, bool roundUp ) external view returns (uint256 share); function totals(BIERC20) external view returns (Rebase memory totals_); function transfer( BIERC20 token, address from, address to, uint256 share ) external; function transferMultiple( BIERC20 token, address from, address[] calldata tos, uint256[] calldata shares ) external; function transferOwnership( address newOwner, bool direct, bool renounce ) external; function whitelistMasterContract(address masterContract, bool approved) external; function whitelistedMasterContracts(address) external view returns (bool); function withdraw( BIERC20 token_, address from, address to, uint256 amount, uint256 share ) external returns (uint256 amountOut, uint256 shareOut); } // 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: IKashiPair interface IKashiPair { event Approval( address indexed _owner, address indexed _spender, uint256 _value ); event LogAccrue( uint256 accruedAmount, uint256 feeFraction, uint64 rate, uint256 utilization ); event LogAddAsset( address indexed from, address indexed to, uint256 share, uint256 fraction ); event LogAddCollateral( address indexed from, address indexed to, uint256 share ); event LogBorrow( address indexed from, address indexed to, uint256 amount, uint256 part ); event LogExchangeRate(uint256 rate); event LogFeeTo(address indexed newFeeTo); event LogRemoveAsset( address indexed from, address indexed to, uint256 share, uint256 fraction ); event LogRemoveCollateral( address indexed from, address indexed to, uint256 share ); event LogRepay( address indexed from, address indexed to, uint256 amount, uint256 part ); event LogWithdrawFees(address indexed feeTo, uint256 feesEarnedFraction); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); event Transfer(address indexed _from, address indexed _to, uint256 _value); function DOMAIN_SEPARATOR() external view returns (bytes32); function accrue() external; function accrueInfo() external view returns ( uint64 interestPerBlock, uint64 lastBlockAccrued, uint128 feesEarnedFraction ); function addAsset( address to, bool skim, uint256 share ) external returns (uint256 fraction); function addCollateral( address to, bool skim, uint256 share ) external; function allowance(address, address) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function asset() external view returns (BIERC20); function balanceOf(address) external view returns (uint256); function bentoBox() external view returns (IBentoBoxV1); function borrow(address to, uint256 amount) external returns (uint256 part, uint256 share); function claimOwnership() external; function collateral() external view returns (BIERC20); function cook( uint8[] calldata actions, uint256[] calldata values, bytes[] calldata datas ) external payable returns (uint256 value1, uint256 value2); function decimals() external view returns (uint8); function exchangeRate() external view returns (uint256); function feeTo() external view returns (address); function getInitData( BIERC20 collateral_, BIERC20 asset_, IOracle oracle_, bytes calldata oracleData_ ) external pure returns (bytes memory data); function init(bytes calldata data) external payable; function isSolvent(address user, bool open) external view returns (bool); function liquidate( address[] calldata users, uint256[] calldata borrowParts, address to, ISwapper swapper, bool open ) external; function masterContract() external view returns (address); function name() external view returns (string memory); function nonces(address) external view returns (uint256); function oracle() external view returns (IOracle); function oracleData() external view returns (bytes memory); function owner() external view returns (address); function pendingOwner() external view returns (address); function permit( address owner_, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function removeAsset(address to, uint256 fraction) external returns (uint256 share); function removeCollateral(address to, uint256 share) external; function repay( address to, bool skim, uint256 part ) external returns (uint256 amount); function setFeeTo(address newFeeTo) external; function setSwapper(ISwapper swapper, bool enable) external; function swappers(ISwapper) external view returns (bool); function symbol() external view returns (string memory); function totalAsset() external view returns (Rebase memory); function totalBorrow() external view returns (Rebase memory); function totalCollateralShare() external view returns (uint256); function totalSupply() external view returns (uint256); function transfer(address to, uint256 amount) external returns (bool); function transferFrom( address from, address to, uint256 amount ) external returns (bool); function transferOwnership( address newOwner, bool direct, bool renounce ) external; function updateExchangeRate() external returns (bool updated, uint256 rate); function userBorrowPart(address) external view returns (uint256); function userCollateralShare(address) external view returns (uint256); function withdrawFees() external; } // File: Strategy.sol contract Strategy is BaseStrategy { using SafeERC20 for IERC20; using Address for address; using SafeMath for uint256; using RebaseLibrary for Rebase; struct KashiPairInfo { IKashiPair kashiPair; uint256 pid; } bool internal isOriginal = true; uint256 internal constant MAX_PAIRS = 5; uint256 internal constant MAX_BPS = 1e4; // Kashi constants (apply to MediumRiskPairs) uint256 internal constant KASHI_MINIMUM_TARGET_UTILIZATION = 7e17; // 70% uint256 internal constant KASHI_MAXIMUM_TARGET_UTILIZATION = 8e17; // 80% uint256 internal constant KASHI_UTILIZATION_PRECISION = 1e18; IERC20 internal constant weth = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); IERC20 internal constant sushi = IERC20(0x6B3595068778DD592e39A122f4f5a5cF09C90fE2); IMasterChef public constant masterChef = IMasterChef(0xc2EdaD668740f1aA35E4D8f227fB8E17dcA888Cd); IUniswapV2Router02 public constant sushiRouter = IUniswapV2Router02(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); IBentoBox public bentoBox; KashiPairInfo[] public kashiPairs; uint256 public dustThreshold = 2; // Path for swaps address[] private path; string private strategyName; constructor( address _vault, address _bentoBox, address[] memory _kashiPairs, uint256[] memory _pids, string memory _strategyName ) public BaseStrategy(_vault) { _initializeStrat(_bentoBox, _kashiPairs, _pids, _strategyName); } function initialize( address _vault, address _strategist, address _rewards, address _keeper, address _bentoBox, address[] memory _kashiPairs, uint256[] memory _pids, string memory _strategyName ) public { _initialize(_vault, _strategist, _rewards, _keeper); _initializeStrat(_bentoBox, _kashiPairs, _pids, _strategyName); } event Cloned(address indexed clone); function cloneKashiLender( address _vault, address _strategist, address _rewards, address _keeper, address _bentoBox, address[] memory _kashiPairs, uint256[] memory _pids, string memory _strategyName ) external returns (address newStrategy) { require(isOriginal); // Copied from https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol bytes20 addressBytes = bytes20(address(this)); assembly { // EIP-1167 bytecode let clone_code := mload(0x40) mstore( clone_code, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 ) mstore(add(clone_code, 0x14), addressBytes) mstore( add(clone_code, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000 ) newStrategy := create(0, clone_code, 0x37) } Strategy(newStrategy).initialize( _vault, _strategist, _rewards, _keeper, _bentoBox, _kashiPairs, _pids, _strategyName ); emit Cloned(newStrategy); } function _initializeStrat( address _bentoBox, address[] memory _kashiPairs, uint256[] memory _pids, string memory _strategyName ) internal { require(address(bentoBox) == address(0)); // Check if previously initialized require(_kashiPairs.length <= MAX_PAIRS); // Must not exceed the max length require(_kashiPairs.length == _pids.length); // Pairs length must match pids length strategyName = bytes(_strategyName).length == 0 ? "StrategyKashiMultiPairLender" : _strategyName; bentoBox = IBentoBox(_bentoBox); healthCheck = address(0xDDCea799fF1699e98EDF118e0629A974Df7DF012); // health.ychad.eth for (uint256 i = 0; i < _kashiPairs.length; i++) { kashiPairs.push( KashiPairInfo(IKashiPair(_kashiPairs[i]), _pids[i]) ); // kashiPair must use the right bentoBox require(address(kashiPairs[i].kashiPair.bentoBox()) == _bentoBox); // kashiPair asset must match want require(address(kashiPairs[i].kashiPair.asset()) == address(want)); if (_pids[i] != 0) { // the masterChef pid token must match the kashiPair require( address(masterChef.poolInfo(_pids[i]).lpToken) == _kashiPairs[i] ); IERC20(_kashiPairs[i]).safeApprove( address(masterChef), type(uint256).max ); } } want.safeApprove(_bentoBox, type(uint256).max); sushi.safeApprove(address(sushiRouter), type(uint256).max); // Initialize the swap path path = new address[](3); path[0] = address(sushi); path[1] = address(weth); path[2] = address(want); } function name() external view override returns (string memory) { return strategyName; } function estimatedTotalAssets() public view override returns (uint256) { uint256 totalShares = sharesInBento(); for (uint256 i = 0; i < kashiPairs.length; i++) { KashiPairInfo memory kashiPairInfo = kashiPairs[i]; totalShares = totalShares.add( kashiFractionToBentoShares( kashiPairInfo.kashiPair, kashiFractionTotal( kashiPairInfo.kashiPair, kashiPairInfo.pid ) ) ); } return balanceOfWant().add(bentoSharesToWant(totalShares)); } function kashiPairEstimatedAssets(uint256 i) public view returns (uint256) { KashiPairInfo memory kashiPairInfo = kashiPairs[i]; return bentoSharesToWant( kashiFractionToBentoShares( kashiPairInfo.kashiPair, kashiFractionTotal( kashiPairInfo.kashiPair, kashiPairInfo.pid ) ) ); } function prepareReturn(uint256 _debtOutstanding) internal override returns ( uint256 _profit, uint256 _loss, uint256 _debtPayment ) { for (uint256 i = 0; i < kashiPairs.length; i++) { KashiPairInfo memory kashiPairInfo = kashiPairs[i]; if ( kashiFractionTotal( kashiPairInfo.kashiPair, kashiPairInfo.pid ) == 0 ) continue; // skip the pair has no assets accrueInterest(kashiPairInfo.kashiPair); depositKashiInMasterChef( kashiPairInfo.kashiPair, kashiPairInfo.pid ); // claim and deposit loose } sell(); uint256 assets = estimatedTotalAssets(); uint256 wantBal = balanceOfWant(); uint256 debt = vault.strategies(address(this)).totalDebt; if (assets >= debt) { _profit = assets.sub(debt); } else { _loss = debt.sub(assets); } _debtPayment = _debtOutstanding; uint256 amountToFree = _debtPayment.add(_profit); if (amountToFree > 0 && wantBal < amountToFree) { (uint256 newLoose, ) = liquidatePosition(amountToFree); // if we didnt free enough money, prioritize paying down debt before taking profit if (newLoose < amountToFree) { if (newLoose <= _debtPayment) { _profit = 0; _debtPayment = newLoose; } else { _profit = newLoose.sub(_debtPayment); } } } } function adjustPosition(uint256 _debtOutstanding) internal override { if (emergencyExit) { return; } uint256 wantBalance = balanceOfWant(); uint256 shares = 0; if (wantBalance > dustThreshold) { (, shares) = depositInBento(wantBalance); } uint256 sharesInBento = sharesInBento(); if (sharesInBento > wantToBentoShares(dustThreshold)) { // Get highest interest rate pair (IKashiPair highestPair, uint256 highestPid) = highestInterestPair(sharesInBento); depositInKashiPair(highestPair, highestPid, sharesInBento); } } function liquidatePosition(uint256 _amountNeeded) internal override returns (uint256 _liquidatedAmount, uint256 _loss) { uint256 wantBalance = balanceOfWant(); if (_amountNeeded <= wantBalance) { return (_amountNeeded, 0); } uint256 amountToFree = _amountNeeded.sub(wantBalance); uint256 deposited = estimatedTotalAssets().sub(wantBalance); if (amountToFree.add(dustThreshold) > deposited) { amountToFree = deposited; } if (amountToFree > 0) { uint256 sharesNeeded = wantToBentoShares(amountToFree); uint256 bentoShares = sharesInBento(); if (sharesNeeded > bentoShares) { uint256 sharesToFreeFromKashi = sharesNeeded.sub(bentoShares); uint256 sharesFreedFromKashi = 0; // Find the lowest apr pair with at least the lesser of // - the amount to free // - the mean assets per pair (IKashiPair lowestPair, uint256 lowestPid) = lowestInterestPair( Math.min( sharesToFreeFromKashi, wantToBentoShares( estimatedTotalAssets().div(kashiPairs.length) ) ) ); if (address(lowestPair) != address(0)) { sharesFreedFromKashi = liquidateKashiPair( lowestPair, lowestPid, sharesToFreeFromKashi ); } for ( uint256 i = 0; i < kashiPairs.length && sharesFreedFromKashi.add(dustThreshold) < sharesToFreeFromKashi; i++ ) { KashiPairInfo memory kashiPairInfo = kashiPairs[i]; if (address(kashiPairInfo.kashiPair) == address(lowestPair)) continue; // we already visited this sharesFreedFromKashi = sharesFreedFromKashi.add( liquidateKashiPair( kashiPairInfo.kashiPair, kashiPairInfo.pid, sharesToFreeFromKashi.sub(sharesFreedFromKashi) ) ); } } bentoBox.withdraw( BIERC20(address(want)), address(this), address(this), 0, sharesInBento() ); } _liquidatedAmount = Math.min(balanceOfWant(), _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 (_liquidatedAmount < _amountNeeded) { uint256 diff = _amountNeeded.sub(_liquidatedAmount); if (diff <= dustThreshold) { _loss = diff; } } } function liquidateAllPositions() internal override returns (uint256 _liquidatedAmount) { (_liquidatedAmount, ) = liquidatePosition(estimatedTotalAssets()); } // new strategy **must** have the same kashiPairs attached function prepareMigration(address _newStrategy) internal override { for (uint256 i = 0; i < kashiPairs.length; i++) { KashiPairInfo memory kashiPairInfo = kashiPairs[i]; if (kashiPairInfo.pid != 0) { masterChef.withdraw( kashiPairInfo.pid, kashiFactionInMasterChef(kashiPairInfo.pid) ); } kashiPairs[i].kashiPair.transfer( _newStrategy, kashiFractionInPair(kashiPairInfo.kashiPair) ); } } function addKashiPair(address _newKashiPair, uint256 _newPid) external onlyGovernance { // cannot exceed max pair length require(kashiPairs.length < MAX_PAIRS); // must use the correct bentobox require( address(IKashiPair(_newKashiPair).bentoBox()) == address(bentoBox) ); // kashPair asset must match want require(IKashiPair(_newKashiPair).asset() == BIERC20(address(want))); if (_newPid != 0) { // masterChef pid token must match the kashiPair require( address(masterChef.poolInfo(_newPid).lpToken) == _newKashiPair ); } for (uint256 i = 0; i < kashiPairs.length; i++) { // kashiPair must not already be attached require(_newKashiPair != address(kashiPairs[i].kashiPair)); } kashiPairs.push(KashiPairInfo(IKashiPair(_newKashiPair), _newPid)); if (_newPid != 0) { IERC20(_newKashiPair).safeApprove( address(masterChef), type(uint256).max ); } } function removeKashiPair( address _remKashiPair, uint256 _remIndex, bool _force ) external onlyEmergencyAuthorized { KashiPairInfo memory kashiPairInfo = kashiPairs[_remIndex]; require(_remKashiPair == address(kashiPairInfo.kashiPair)); liquidateKashiPair( kashiPairInfo.kashiPair, kashiPairInfo.pid, type(uint256).max // liquidateAll ); if (!_force) { // must have liquidated all but dust require( kashiFractionTotal( kashiPairInfo.kashiPair, kashiPairInfo.pid ) <= dustThreshold ); } if (kashiPairInfo.pid != 0) { IERC20(_remKashiPair).safeApprove(address(masterChef), 0); } kashiPairs[_remIndex] = kashiPairs[kashiPairs.length - 1]; kashiPairs.pop(); } function adjustKashiPairRatios(uint256[] calldata _ratios) external onlyAuthorized { // length of ratios must match number of pairs require(_ratios.length == kashiPairs.length); uint256 totalRatio; for (uint256 i = 0; i < kashiPairs.length; i++) { // We must accrue all pairs to ensure we get an accurate estimate of assets accrueInterest(kashiPairs[i].kashiPair); totalRatio += _ratios[i]; } require(totalRatio == MAX_BPS); //ratios must add to 10000 bps uint256 wantBalance = balanceOfWant(); if (wantBalance > dustThreshold) { depositInBento(wantBalance); } uint256 totalAssets = estimatedTotalAssets(); uint256[] memory kashiPairsIncreasedAllocation = new uint256[](kashiPairs.length); for (uint256 i = 0; i < kashiPairs.length; i++) { KashiPairInfo memory kashiPairInfo = kashiPairs[i]; uint256 pairTotalAssets = bentoSharesToWant( kashiFractionToBentoShares( kashiPairInfo.kashiPair, kashiFractionTotal( kashiPairInfo.kashiPair, kashiPairInfo.pid ) ) ); uint256 targetAssets = (_ratios[i] * totalAssets) / MAX_BPS; if (targetAssets < pairTotalAssets) { uint256 toLiquidate = pairTotalAssets.sub(targetAssets); liquidateKashiPair( kashiPairInfo.kashiPair, kashiPairInfo.pid, wantToBentoShares(toLiquidate) ); } else if (targetAssets > pairTotalAssets) { kashiPairsIncreasedAllocation[i] = targetAssets.sub( pairTotalAssets ); } } for (uint256 i = 0; i < kashiPairs.length; i++) { if (kashiPairsIncreasedAllocation[i] == 0) continue; KashiPairInfo memory kashiPairInfo = kashiPairs[i]; uint256 sharesInBento = sharesInBento(); uint256 sharesToAdd = wantToBentoShares(kashiPairsIncreasedAllocation[i]); if (sharesToAdd > sharesInBento) { sharesToAdd = sharesInBento; } depositInKashiPair( kashiPairInfo.kashiPair, kashiPairInfo.pid, sharesToAdd ); } } function depositInKashiPair( IKashiPair kashiPair, uint256 pid, uint256 sharesToDeposit ) internal { transferBento(address(kashiPair), sharesToDeposit); uint256 depositedFraction = kashiPair.addAsset(address(this), true, sharesToDeposit); depositKashiInMasterChef(kashiPair, pid); } function depositKashiInMasterChef(IKashiPair kashiPair, uint256 pid) internal { if (pid == 0) return; uint256 fractionsToStake = kashiFractionInPair(kashiPair); masterChef.deposit(pid, fractionsToStake); } function depositInBento(uint256 wantToDeposit) internal returns (uint256 amountOut, uint256 shareOut) { return bentoBox.deposit( BIERC20(address(want)), address(this), address(this), wantToDeposit, 0 ); } function transferBento(address to, uint256 shares) internal { bentoBox.transfer( BIERC20(address(want)), address(this), address(to), shares ); } function liquidateKashiPair( IKashiPair kashiPair, uint256 pid, uint256 sharesToFree ) internal returns (uint256 _shareLiquidated) { // We need to call accrue to accurately calculate totalAssets accrueInterest(kashiPair); uint256 liquidShares = kashiPairLiquidShares(kashiPair); if (sharesToFree > liquidShares) { sharesToFree = liquidShares; } if (sharesToFree == 0) return 0; uint256 fractionsToFree = bentoSharesToKashiFraction(kashiPair, sharesToFree); // Remove from masterChef if there is a non-zero pid if (pid != 0) { uint256 fractionInMc = kashiFactionInMasterChef(pid); uint256 fractionsToFreeFromMc = fractionsToFree; if (fractionsToFreeFromMc.add(dustThreshold) > fractionInMc) { fractionsToFreeFromMc = fractionInMc; } masterChef.withdraw(pid, fractionsToFreeFromMc); } uint256 fractionBalance = kashiFractionInPair(kashiPair); if (fractionsToFree.add(dustThreshold) > fractionBalance) { fractionsToFree = fractionBalance; } _shareLiquidated = kashiPair.removeAsset( address(this), fractionsToFree ); // Redeposit into the masterChef if there's some spare change depositKashiInMasterChef(kashiPair, pid); } // sell all function function sell() internal { uint256 sushiBal = balanceOfSushi(); if (sushiBal == 0) { return; } sushiRouter.swapExactTokensForTokens( sushiBal, uint256(0), path, address(this), now ); } function accrueInterest(IKashiPair kashiPair) internal { (, uint256 lastAccrued, ) = kashiPair.accrueInfo(); // Accure interest if (block.timestamp > lastAccrued) { kashiPair.accrue(); } } function setDustThreshold(uint256 _newDustThreshold) external onlyAuthorized { dustThreshold = _newDustThreshold; } function setPath(address[] calldata _path) external onlyGovernance { path = _path; } function balanceOfWant() internal view returns (uint256) { return want.balanceOf(address(this)); } function balanceOfSushi() internal view returns (uint256) { return sushi.balanceOf(address(this)); } function sharesInBento() internal view returns (uint256) { return bentoBox.balanceOf(BIERC20(address(want)), address(this)); } function kashiFractionTotal(IKashiPair kashiPair, uint256 pid) internal view returns (uint256) { return kashiFactionInMasterChef(pid).add(kashiFractionInPair(kashiPair)); } function kashiFactionInMasterChef(uint256 pid) internal view returns (uint256 _kashiFraction) { if (pid != 0) { _kashiFraction = masterChef.userInfo(pid, address(this)).amount; } } function kashiFractionInPair(IKashiPair kashiPair) internal view returns (uint256) { return kashiPair.balanceOf(address(this)); } function kashiPairLiquidShares(IKashiPair kashiPair) internal view returns (uint256) { return kashiPair.totalAsset().elastic; } // highestInterestIndex finds the best pair to invest the given deposit function highestInterestPair(uint256 sharesToDeposit) internal view returns (IKashiPair _highestPair, uint256 _highestPid) { uint256 highestInterest = 0; uint256 highestUtilization = 0; for (uint256 i = 0; i < kashiPairs.length; i++) { KashiPairInfo memory kashiPairInfo = kashiPairs[i]; (uint256 interestPerBlock, , ) = kashiPairInfo.kashiPair.accrueInfo(); uint256 utilization = kashiPairUtilization(kashiPairInfo.kashiPair, sharesToDeposit); // A pair is highest (really best) if either // - It's utilization is higher, and either // - It is above the max target util // - The existing choice is below the min util target // - Compare APR directly only if both are between the min and max if ( (utilization > highestUtilization && (utilization > KASHI_MAXIMUM_TARGET_UTILIZATION || highestUtilization < KASHI_MINIMUM_TARGET_UTILIZATION)) || (interestPerBlock > highestInterest && utilization < KASHI_MAXIMUM_TARGET_UTILIZATION && utilization > KASHI_MINIMUM_TARGET_UTILIZATION && highestUtilization < KASHI_MAXIMUM_TARGET_UTILIZATION && highestUtilization > KASHI_MINIMUM_TARGET_UTILIZATION) ) { highestInterest = interestPerBlock; highestUtilization = utilization; _highestPair = kashiPairInfo.kashiPair; _highestPid = kashiPairInfo.pid; } } } function lowestInterestPair(uint256 minLiquidShares) internal view returns (IKashiPair _lowestPair, uint256 _lowestPid) { uint256 lowestInterest = type(uint256).max; uint256 lowestUtilization = KASHI_UTILIZATION_PRECISION; for (uint256 i = 0; i < kashiPairs.length; i++) { KashiPairInfo memory kashiPairInfo = kashiPairs[i]; (uint256 interestPerBlock, , ) = kashiPairInfo.kashiPair.accrueInfo(); uint256 utilization = kashiPairUtilization(kashiPairInfo.kashiPair, 0); // A pair is lowest if either // - It's utilization is lower, and either // - It is below the min taget util // - The existing choice is above the max target util // - Compare APR directly only if both are between the min and max if ( ((utilization < lowestUtilization && (lowestUtilization > KASHI_MAXIMUM_TARGET_UTILIZATION || utilization < KASHI_MINIMUM_TARGET_UTILIZATION)) || (interestPerBlock < lowestInterest && utilization < KASHI_MAXIMUM_TARGET_UTILIZATION && utilization > KASHI_MINIMUM_TARGET_UTILIZATION && lowestUtilization < KASHI_MAXIMUM_TARGET_UTILIZATION && lowestUtilization > KASHI_MINIMUM_TARGET_UTILIZATION)) && kashiFractionTotal(kashiPairInfo.kashiPair, kashiPairInfo.pid) > dustThreshold && kashiPairLiquidShares(kashiPairInfo.kashiPair) >= minLiquidShares ) { lowestInterest = interestPerBlock; _lowestPair = kashiPairInfo.kashiPair; _lowestPid = kashiPairInfo.pid; } } } function kashiPairUtilization(IKashiPair kashiPair, uint256 sharesToDeposit) internal view returns (uint256) { uint256 totalAssetShares = kashiPair.totalAsset().elastic; uint256 totalBorrowAmount = kashiPair.totalBorrow().elastic; uint256 fullAssetAmount = bentoBox .toAmount( BIERC20(address(this)), totalAssetShares.add(sharesToDeposit), false ) .add(totalBorrowAmount); return uint256(totalBorrowAmount).mul(KASHI_UTILIZATION_PRECISION).div( fullAssetAmount ); } function wantToBentoShares(uint256 wantAmount) internal view returns (uint256) { if (wantAmount == 0) return 0; return bentoBox.toShare(BIERC20(address(this)), wantAmount, true); } function bentoSharesToWant(uint256 bentoShares) internal view returns (uint256) { if (bentoShares == 0) return 0; return bentoBox.toAmount(BIERC20(address(this)), bentoShares, true); } function bentoSharesToKashiFraction( IKashiPair kashiPair, uint256 bentoShares ) internal view returns (uint256 _kashiFraction) { // Adapted from https://github.com/sushiswap/kashi-lending/blob/b6e3521d8628a835935c94a9039cfd192044d66b/contracts/KashiPair.sol#L320-L323 Rebase memory totalAsset = kashiPair.totalAsset(); Rebase memory totalBorrow = kashiPair.totalBorrow(); uint256 allShare = uint256(totalAsset.elastic).add( wantToBentoShares(totalBorrow.elastic) ); _kashiFraction = allShare == 0 ? bentoShares : bentoShares.mul(totalAsset.base).div(allShare); } function kashiFractionToBentoShares( IKashiPair kashiPair, uint256 _kashiFraction ) internal view returns (uint256 bentoShares) { // Adapted from https://github.com/sushiswap/kashi-lending/blob/b6e3521d8628a835935c94a9039cfd192044d66b/contracts/KashiPair.sol#L351-L353 Rebase memory totalAsset = kashiPair.totalAsset(); Rebase memory totalBorrow = kashiPair.totalBorrow(); uint256 allShare = uint256(totalAsset.elastic).add( wantToBentoShares(totalBorrow.elastic) ); bentoShares = _kashiFraction.mul(allShare).div(totalAsset.base); } function protectedTokens() internal view override returns (address[] memory) {} function ethToWant(uint256 _amtInWei) public view virtual override returns (uint256) { // TODO create an accurate price oracle return _amtInWei; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_bentoBox","type":"address"},{"internalType":"address[]","name":"_kashiPairs","type":"address[]"},{"internalType":"uint256[]","name":"_pids","type":"uint256[]"},{"internalType":"string","name":"_strategyName","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clone","type":"address"}],"name":"Cloned","type":"event"},{"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":"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":[{"internalType":"address","name":"_newKashiPair","type":"address"},{"internalType":"uint256","name":"_newPid","type":"uint256"}],"name":"addKashiPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ratios","type":"uint256[]"}],"name":"adjustKashiPairRatios","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"apiVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"bentoBox","outputs":[{"internalType":"contract IBentoBox","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_strategist","type":"address"},{"internalType":"address","name":"_rewards","type":"address"},{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"address","name":"_bentoBox","type":"address"},{"internalType":"address[]","name":"_kashiPairs","type":"address[]"},{"internalType":"uint256[]","name":"_pids","type":"uint256[]"},{"internalType":"string","name":"_strategyName","type":"string"}],"name":"cloneKashiLender","outputs":[{"internalType":"address","name":"newStrategy","type":"address"}],"stateMutability":"nonpayable","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":"dustThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":"_strategist","type":"address"},{"internalType":"address","name":"_rewards","type":"address"},{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"address","name":"_bentoBox","type":"address"},{"internalType":"address[]","name":"_kashiPairs","type":"address[]"},{"internalType":"uint256[]","name":"_pids","type":"uint256[]"},{"internalType":"string","name":"_strategyName","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"}],"name":"kashiPairEstimatedAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"kashiPairs","outputs":[{"internalType":"contract IKashiPair","name":"kashiPair","type":"address"},{"internalType":"uint256","name":"pid","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"masterChef","outputs":[{"internalType":"contract IMasterChef","name":"","type":"address"}],"stateMutability":"view","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":"minReportDelay","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":"profitFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_remKashiPair","type":"address"},{"internalType":"uint256","name":"_remIndex","type":"uint256"},{"internalType":"bool","name":"_force","type":"bool"}],"name":"removeKashiPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":"uint256","name":"_newDustThreshold","type":"uint256"}],"name":"setDustThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setEmergencyExit","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":"_delay","type":"uint256"}],"name":"setMinReportDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_path","type":"address[]"}],"name":"setPath","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":"strategist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sushiRouter","outputs":[{"internalType":"contract IUniswapV2Router02","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":"callCostInWei","type":"uint256"}],"name":"tendTrigger","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":[{"internalType":"uint256","name":"_amountNeeded","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"_loss","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052600b805461ff0019166101001790556002600d553480156200002557600080fd5b5060405162006e4c38038062006e4c833981016040819052620000489162000d10565b84620000578133808062000071565b50620000668484848462000255565b5050505050620010fc565b6006546001600160a01b031615620000a65760405162461bcd60e51b81526004016200009d9062000f4b565b60405180910390fd5b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b1580156200010357600080fd5b505afa15801562000118573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200013e919062000cea565b600680546001600160a01b0319166001600160a01b0392831617908190556200017891168560001962000814602090811b62002b7217901c565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b393620001f893911691600019910162000efd565b602060405180830381600087803b1580156200021357600080fd5b505af115801562000228573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200024e919062000e33565b5050505050565b600b546201000090046001600160a01b0316156200027257600080fd5b6005835111156200028257600080fd5b81518351146200029157600080fd5b805115620002a05780620002d7565b6040518060400160405280601c81526020017f53747261746567794b617368694d756c7469506169724c656e646572000000008152505b8051620002ed91600f9160209091019062000ae3565b50600b805462010000600160b01b031916620100006001600160a01b0387160217905560018054610100600160a81b03191674ddcea799ff1699e98edf118e0629a974df7df0120017905560005b83518110156200068e57600c60405180604001604052808684815181106200035f57fe5b60200260200101516001600160a01b031681526020018584815181106200038257fe5b602090810291909101810151909152825460018082018555600094855293829020835160029092020180546001600160a01b0319166001600160a01b0392831617815592909101519190920155600c80549187169183908110620003e257fe5b60009182526020918290206002909102015460408051636b2ace8760e01b815290516001600160a01b0390921692636b2ace8792600480840193829003018186803b1580156200043157600080fd5b505afa15801562000446573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200046c919062000cea565b6001600160a01b0316146200048057600080fd5b600654600c80546001600160a01b0390921691839081106200049e57fe5b600091825260209182902060029091020154604080516338d52e0f60e01b815290516001600160a01b03909216926338d52e0f92600480840193829003018186803b158015620004ed57600080fd5b505afa15801562000502573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000528919062000cea565b6001600160a01b0316146200053c57600080fd5b8281815181106200054957fe5b602002602001015160001462000685578381815181106200056657fe5b60200260200101516001600160a01b031673c2edad668740f1aa35e4d8f227fb8e17dca888cd6001600160a01b0316631526fe27858481518110620005a757fe5b60200260200101516040518263ffffffff1660e01b8152600401620005cd919062001060565b60806040518083038186803b158015620005e657600080fd5b505afa158015620005fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000621919062000e55565b516001600160a01b0316146200063657600080fd5b6200068573c2edad668740f1aa35e4d8f227fb8e17dca888cd6000198684815181106200065f57fe5b60200260200101516001600160a01b03166200081460201b62002b72179092919060201c565b6001016200033b565b50600654620006b6906001600160a01b03168560001962000814602090811b62002b7217901c565b620006f9736b3595068778dd592e39a122f4f5a5cf09c90fe273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f60001962000814602090811b62002b7217901c565b604080516003808252608082019092529060208201606080368337505081516200072b92600e92506020019062000b68565b50736b3595068778dd592e39a122f4f5a5cf09c90fe2600e6000815481106200075057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2600e600181548110620007a257fe5b600091825260209091200180546001600160a01b0319166001600160a01b03928316179055600654600e80549190921691906002908110620007e057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555050505050565b801580620008a35750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906200084d903090869060040162000ee3565b60206040518083038186803b1580156200086657600080fd5b505afa1580156200087b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008a1919062000eac565b155b620008c25760405162461bcd60e51b81526004016200009d9062001003565b6200091d8363095ea7b360e01b8484604051602401620008e492919062000efd565b60408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b03938416179052906200092216565b505050565b60606200097e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620009be60201b62002c6c179092919060201c565b8051909150156200091d57808060200190518101906200099f919062000e33565b6200091d5760405162461bcd60e51b81526004016200009d9062000fb9565b6060620009cf8484600085620009d7565b949350505050565b6060620009e48562000aa9565b62000a035760405162461bcd60e51b81526004016200009d9062000f82565b60006060866001600160a01b0316858760405162000a22919062000ec5565b60006040518083038185875af1925050503d806000811462000a61576040519150601f19603f3d011682016040523d82523d6000602084013e62000a66565b606091505b5091509150811562000a7c579150620009cf9050565b80511562000a8d5780518082602001fd5b8360405162461bcd60e51b81526004016200009d919062000f16565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590620009cf575050151592915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1062000b2657805160ff191683800117855562000b56565b8280016001018555821562000b56579182015b8281111562000b5657825182559160200191906001019062000b39565b5062000b6492915062000bce565b5090565b82805482825590600052602060002090810192821562000bc0579160200282015b8281111562000bc057825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019062000b89565b5062000b6492915062000be5565b5b8082111562000b64576000815560010162000bcf565b5b8082111562000b645780546001600160a01b031916815560010162000be6565b600082601f83011262000c17578081fd5b815162000c2e62000c288262001090565b62001069565b81815291506020808301908481018184028601820187101562000c5057600080fd5b60005b8481101562000c715781518452928201929082019060010162000c53565b505050505092915050565b600082601f83011262000c8d578081fd5b81516001600160401b0381111562000ca3578182fd5b62000cb8601f8201601f191660200162001069565b915080825283602082850101111562000cd057600080fd5b62000ce3816020840160208601620010b0565b5092915050565b60006020828403121562000cfc578081fd5b815162000d0981620010e3565b9392505050565b600080600080600060a0868803121562000d28578081fd5b855162000d3581620010e3565b8095505060208087015162000d4a81620010e3565b60408801519095506001600160401b038082111562000d67578384fd5b818901915089601f83011262000d7b578384fd5b815162000d8c62000c288262001090565b81815284810190848601868402860187018e101562000da9578788fd5b8795505b8386101562000dd857805162000dc381620010e3565b83526001959095019491860191860162000dad565b5060608c0151909850945050508083111562000df2578384fd5b62000e008a848b0162000c06565b9450608089015192508083111562000e16578384fd5b505062000e268882890162000c7c565b9150509295509295909350565b60006020828403121562000e45578081fd5b8151801515811462000d09578182fd5b60006080828403121562000e67578081fd5b62000e73608062001069565b825162000e8081620010e3565b808252506020830151602082015260408301516040820152606083015160608201528091505092915050565b60006020828403121562000ebe578081fd5b5051919050565b6000825162000ed9818460208701620010b0565b9190910192915050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b600060208252825180602084015262000f37816040850160208701620010b0565b601f01601f19169190910160400192915050565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606082015260800190565b90815260200190565b6040518181016001600160401b03811182821017156200108857600080fd5b604052919050565b60006001600160401b03821115620010a6578081fd5b5060209081020190565b60005b83811015620010cd578181015183820152602001620010b3565b83811115620010dd576000848401525b50505050565b6001600160a01b0381168114620010f957600080fd5b50565b615d40806200110c6000396000f3fe608060405234801561001057600080fd5b50600436106102d65760003560e01c80636d13582c11610182578063ad7e55ba116100e9578063ec38a862116100a2578063f017c92f1161007c578063f017c92f14610595578063fa9b9545146105a8578063fbfa77cf146105bb578063fcf2d0ad146105c3576102d6565b8063ec38a86214610567578063ed882c2b1461057a578063efbb5cb01461058d576102d6565b8063ad7e55ba1461050b578063b252720b1461051e578063c7b9d53014610526578063c812daa914610539578063ce5494bb1461054c578063e8462e8f1461055f576102d6565b80638e6350e21161013b5780638e6350e2146104c557806391397ab4146104cd57806395e80c50146104e05780639ec5a894146104e8578063ac00ff26146104f0578063aced166114610503576102d6565b80636d13582c1461045b578063748747e614610463578063750521f5146104765780637795d5bc14610489578063780022a0146104aa5780638cdfe166146104bd576102d6565b80632e1a7d4d116102415780635641ec03116101fa578063650d1880116101d4578063650d1880146104255780636718835f14610438578063686ca00d146104405780636b2ace8714610453576102d6565b80635641ec0314610402578063575a86b21461040a5780635a4775ef14610412576102d6565b80632e1a7d4d146103a65780632e430638146103b9578063324b91dd146103cc57806339a172a8146103df578063440368a3146103f25780634641257d146103fa576102d6565b80631d12f28b116102935780631d12f28b1461034f5780631f1fcd51146103645780631fe4a6861461037957806322f3e2d414610381578063258294101461039657806328b7ccf71461039e576102d6565b806301681a62146102db57806303ee438c146102f0578063048be65d1461030e57806306fdde03146103215780630f969b871461032957806311bc82451461033c575b600080fd5b6102ee6102e93660046151bc565b6105cb565b005b6102f861076a565b60405161030591906158df565b60405180910390f35b6102ee61031c3660046152fb565b6107f8565b6102f8610af1565b6102ee6103373660046155f1565b610b87565b6102ee61034a3660046151bc565b610c14565b610357610d15565b6040516103059190615b6c565b61036c610d1b565b6040516103059190615712565b61036c610d2a565b610389610d39565b6040516103059190615824565b6102f8610ddb565b610357610dfa565b6103576103b43660046155f1565b610e00565b61036c6103c73660046151f4565b610e5b565b6102ee6103da36600461533c565b610f6a565b6102ee6103ed3660046155f1565b611286565b6102ee611308565b6102ee611531565b610389611a0a565b61036c611a13565b6102ee6104203660046152d0565b611a2b565b6103896104333660046155f1565b611d62565b610389611d6a565b6102ee61044e36600461533c565b611d73565b61036c611dbc565b61036c611dd1565b6102ee6104713660046151bc565b611de9565b6102ee610484366004615442565b611e94565b61049c6104973660046155f1565b611f2b565b60405161030592919061580b565b6103576104b83660046155f1565b611f60565b610357611f63565b610357611f69565b6102ee6104db3660046155f1565b611f6e565b610357611ff0565b61036c611ff6565b6102ee6104fe36600461540a565b612005565b61036c6120f1565b6102ee6105193660046155f1565b612100565b61036c612152565b6102ee6105343660046151bc565b612166565b6102ee6105473660046151f4565b612211565b6102ee61055a3660046151bc565b612233565b610357612381565b6102ee6105753660046151bc565b612387565b6103896105883660046155f1565b61251a565b6103576127a4565b6102ee6105a33660046155f1565b612852565b6103576105b63660046155f1565b6128d4565b61036c61293e565b6102ee61294d565b6105d3612c83565b6001600160a01b0316336001600160a01b03161461060c5760405162461bcd60e51b815260040161060390615a83565b60405180910390fd5b6006546001600160a01b038281169116141561063a5760405162461bcd60e51b815260040161060390615917565b6002546001600160a01b03828116911614156106685760405162461bcd60e51b815260040161060390615a2b565b6060610672612d00565b905060005b81518110156106cd5781818151811061068c57fe5b60200260200101516001600160a01b0316836001600160a01b031614156106c55760405162461bcd60e51b815260040161060390615af2565b600101610677565b506107666106d9612c83565b6040516370a0823160e01b81526001600160a01b038516906370a0823190610705903090600401615712565b60206040518083038186803b15801561071d57600080fd5b505afa158015610731573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107559190615609565b6001600160a01b0385169190612d05565b5050565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107f05780601f106107c5576101008083540402835291602001916107f0565b820191906000526020600020905b8154815290600101906020018083116107d357829003601f168201915b505050505081565b6003546001600160a01b03163314806108295750610814612c83565b6001600160a01b0316336001600160a01b0316145b806108ca5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561087d57600080fd5b505afa158015610891573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b591906151d8565b6001600160a01b0316336001600160a01b0316145b8061096b5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561091e57600080fd5b505afa158015610932573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095691906151d8565b6001600160a01b0316336001600160a01b0316145b6109875760405162461bcd60e51b815260040161060390615a83565b61098f614dde565b600c838154811061099c57fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b0390811680845260019092015493830193909352909250908516146109e457600080fd5b6109f981600001518260200151600019612d24565b5081610a1f57600d54610a1482600001518360200151612ec5565b1115610a1f57600080fd5b602081015115610a5257610a526001600160a01b03851673c2edad668740f1aa35e4d8f227fb8e17dca888cd6000612b72565b600c80546000198101908110610a6457fe5b9060005260206000209060020201600c8481548110610a7f57fe5b60009182526020909120825460029092020180546001600160a01b0319166001600160a01b03909216919091178155600191820154910155600c805480610ac257fe5b60008281526020812060026000199093019283020180546001600160a01b031916815560010155905550505050565b600f8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b7d5780601f10610b5257610100808354040283529160200191610b7d565b820191906000526020600020905b815481529060010190602001808311610b6057829003601f168201915b5050505050905090565b6003546001600160a01b0316331480610bb85750610ba3612c83565b6001600160a01b0316336001600160a01b0316145b610bd45760405162461bcd60e51b815260040161060390615a83565b600a8190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a860090610c09908390615b6c565b60405180910390a150565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6257600080fd5b505afa158015610c76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9a91906151d8565b6001600160a01b0316336001600160a01b03161480610cd15750610cbc612c83565b6001600160a01b0316336001600160a01b0316145b610ced5760405162461bcd60e51b815260040161060390615a83565b600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600a5481565b6006546001600160a01b031681565b6003546001600160a01b031681565b6002546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610d6e903090600401615712565b6101206040518083038186803b158015610d8757600080fd5b505afa158015610d9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbf9190615540565b604001511180610dd657506000610dd46127a4565b115b905090565b604080518082019091526005815264302e342e3360d81b602082015290565b60085481565b6002546000906001600160a01b03163314610e2d5760405162461bcd60e51b815260040161060390615a0b565b6000610e3883612ee5565b600654909350909150610e55906001600160a01b03163383612d05565b50919050565b600b54600090610100900460ff16610e7257600080fd5b604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81523060601b601482018190526e5af43d82803e903d91602b57fd5bf360881b6028830152906037816000f060405163c812daa960e01b81529093506001600160a01b038416915063c812daa990610ef7908d908d908d908d908d908d908d908d90600401615740565b600060405180830381600087803b158015610f1157600080fd5b505af1158015610f25573d6000803e3d6000fd5b50506040516001600160a01b03851692507f783540fb4221a3238720dc7038937d0d79982bcf895274aa6ad179f82cf0d53c9150600090a25098975050505050505050565b6003546001600160a01b0316331480610f9b5750610f86612c83565b6001600160a01b0316336001600160a01b0316145b610fb75760405162461bcd60e51b815260040161060390615a83565b600c548114610fc557600080fd5b6000805b600c5481101561102457611002600c8281548110610fe357fe5b60009182526020909120600290910201546001600160a01b0316613176565b83838281811061100e57fe5b6020029190910135929092019150600101610fc9565b50612710811461103357600080fd5b600061103d613255565b9050600d5481111561105557611052816132d6565b50505b600061105f6127a4565b600c549091506060906001600160401b038111801561107d57600080fd5b506040519080825280602002602001820160405280156110a7578160200160208202803683370190505b50905060005b600c548110156111b4576110bf614dde565b600c82815481106110cc57fe5b600091825260208083206040805180820190915260029093020180546001600160a01b03168084526001909101549183018290529193506111209161111b91611116908290612ec5565b613375565b6134c0565b90506000612710868b8b8781811061113457fe5b90506020020135028161114357fe5b0490508181101561117e57600061115a8383613559565b9050611177846000015185602001516111728461359b565b612d24565b50506111a9565b818111156111a9576111908183613559565b85858151811061119c57fe5b6020026020010181815250505b5050506001016110ad565b5060005b600c5481101561127d578181815181106111ce57fe5b6020026020010151600014156111e357611275565b6111eb614dde565b600c82815481106111f857fe5b600091825260208083206040805180820190915260029093020180546001600160a01b03168352600101549082015291506112316135e4565b9050600061125185858151811061124457fe5b602002602001015161359b565b90508181111561125e5750805b6112718360000151846020015183613624565b5050505b6001016111b8565b50505050505050565b6003546001600160a01b03163314806112b757506112a2612c83565b6001600160a01b0316336001600160a01b0316145b6112d35760405162461bcd60e51b815260040161060390615a83565b60078190556040517fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190610c09908390615b6c565b6005546001600160a01b031633148061132b57506003546001600160a01b031633145b8061134e5750611339612c83565b6001600160a01b0316336001600160a01b0316145b806113ef5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156113a257600080fd5b505afa1580156113b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113da91906151d8565b6001600160a01b0316336001600160a01b0316145b806114905750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561144357600080fd5b505afa158015611457573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147b91906151d8565b6001600160a01b0316336001600160a01b0316145b6114ac5760405162461bcd60e51b815260040161060390615a83565b6002546040805163bf3759b560e01b8152905161152f926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b1580156114f257600080fd5b505afa158015611506573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152a9190615609565b6136c5565b565b6005546001600160a01b031633148061155457506003546001600160a01b031633145b806115775750611562612c83565b6001600160a01b0316336001600160a01b0316145b806116185750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156115cb57600080fd5b505afa1580156115df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160391906151d8565b6001600160a01b0316336001600160a01b0316145b806116b95750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561166c57600080fd5b505afa158015611680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a491906151d8565b6001600160a01b0316336001600160a01b0316145b6116d55760405162461bcd60e51b815260040161060390615a83565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561172857600080fd5b505afa15801561173c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117609190615609565b600b5490915060009060ff16156117bd57600061177b613733565b9050828110156117965761178f8382613559565b93506117ab565b828111156117ab576117a88184613559565b94505b6117b58385613559565b9150506117ce565b6117c682613745565b919550935090505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf823906117ff903090600401615712565b6101206040518083038186803b15801561181857600080fd5b505afa15801561182c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118509190615540565b60c001516002546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc9061188990889088908790600401615c0d565b602060405180830381600087803b1580156118a357600080fd5b505af11580156118b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118db9190615609565b92506118e6836136c5565b60015460ff168015611907575060015461010090046001600160a01b031615155b156119b95760015460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b906119489088908890879089908890600401615c3e565b60206040518083038186803b15801561196057600080fd5b505afa158015611974573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119989190615426565b6119b45760405162461bcd60e51b81526004016106039061596d565b6119c6565b6001805460ff1916811790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d509858584866040516119fb9493929190615c23565b60405180910390a15050505050565b600b5460ff1681565b73c2edad668740f1aa35e4d8f227fb8e17dca888cd81565b611a33612c83565b6001600160a01b0316336001600160a01b031614611a635760405162461bcd60e51b815260040161060390615a83565b600c54600511611a7257600080fd5b600b60029054906101000a90046001600160a01b03166001600160a01b0316826001600160a01b0316636b2ace876040518163ffffffff1660e01b815260040160206040518083038186803b158015611aca57600080fd5b505afa158015611ade573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0291906151d8565b6001600160a01b031614611b1557600080fd5b600654604080516338d52e0f60e01b815290516001600160a01b03928316928516916338d52e0f916004808301926020929190829003018186803b158015611b5c57600080fd5b505afa158015611b70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9491906151d8565b6001600160a01b031614611ba757600080fd5b8015611c5357604051631526fe2760e01b81526001600160a01b0383169073c2edad668740f1aa35e4d8f227fb8e17dca888cd90631526fe2790611bef908590600401615b6c565b60806040518083038186803b158015611c0757600080fd5b505afa158015611c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3f91906154ae565b516001600160a01b031614611c5357600080fd5b60005b600c54811015611c9e57600c8181548110611c6d57fe5b60009182526020909120600290910201546001600160a01b0384811691161415611c9657600080fd5b600101611c56565b50604080518082019091526001600160a01b03838116825260208201838152600c805460018101825560009190915292517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7600290940293840180546001600160a01b0319169190931617909155517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8909101558015610766576107666001600160a01b03831673c2edad668740f1aa35e4d8f227fb8e17dca888cd600019612b72565b60005b919050565b60015460ff1681565b611d7b612c83565b6001600160a01b0316336001600160a01b031614611dab5760405162461bcd60e51b815260040161060390615a83565b611db7600e8383614df5565b505050565b600b546201000090046001600160a01b031681565b73d9e1ce17f2641f24ae83637ab66a2cca9c378b9f81565b6003546001600160a01b0316331480611e1a5750611e05612c83565b6001600160a01b0316336001600160a01b0316145b611e365760405162461bcd60e51b815260040161060390615a83565b6001600160a01b038116611e4957600080fd5b600580546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490610c09908390615712565b6003546001600160a01b0316331480611ec55750611eb0612c83565b6001600160a01b0316336001600160a01b0316145b611ee15760405162461bcd60e51b815260040161060390615a83565b611eed60008383614e58565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda68282604051611f1f9291906158b0565b60405180910390a15050565b600c8181548110611f3857fe5b6000918252602090912060029091020180546001909101546001600160a01b03909116915082565b90565b60095481565b600090565b6003546001600160a01b0316331480611f9f5750611f8a612c83565b6001600160a01b0316336001600160a01b0316145b611fbb5760405162461bcd60e51b815260040161060390615a83565b60098190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec29890610c09908390615b6c565b60075481565b6004546001600160a01b031681565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561205357600080fd5b505afa158015612067573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208b91906151d8565b6001600160a01b0316336001600160a01b031614806120c257506120ad612c83565b6001600160a01b0316336001600160a01b0316145b6120de5760405162461bcd60e51b815260040161060390615a83565b6001805460ff1916911515919091179055565b6005546001600160a01b031681565b6003546001600160a01b0316331480612131575061211c612c83565b6001600160a01b0316336001600160a01b0316145b61214d5760405162461bcd60e51b815260040161060390615a83565b600d55565b60015461010090046001600160a01b031681565b6003546001600160a01b03163314806121975750612182612c83565b6001600160a01b0316336001600160a01b0316145b6121b35760405162461bcd60e51b815260040161060390615a83565b6001600160a01b0381166121c657600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490610c09908390615712565b61221d88888888613915565b61222984848484613ad5565b5050505050505050565b6002546001600160a01b0316331461224a57600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b15801561229157600080fd5b505afa1580156122a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c991906151d8565b6001600160a01b0316146122dc57600080fd5b6122e581614049565b6006546040516370a0823160e01b815261237e9183916001600160a01b03909116906370a082319061231b903090600401615712565b60206040518083038186803b15801561233357600080fd5b505afa158015612347573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236b9190615609565b6006546001600160a01b03169190612d05565b50565b600d5481565b6003546001600160a01b031633146123b15760405162461bcd60e51b8152600401610603906158f2565b6001600160a01b0381166123c457600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b3936123fb93909116916000910161580b565b602060405180830381600087803b15801561241557600080fd5b505af1158015612429573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244d9190615426565b50600480546001600160a01b0319166001600160a01b038381169190911780835560025460405163095ea7b360e01b81529083169363095ea7b393612498931691600019910161580b565b602060405180830381600087803b1580156124b257600080fd5b505af11580156124c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ea9190615426565b507fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06981604051610c099190615712565b60008061252683611f60565b9050612530614ed2565b6002546040516339ebf82360e01b81526001600160a01b03909116906339ebf82390612560903090600401615712565b6101206040518083038186803b15801561257957600080fd5b505afa15801561258d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b19190615540565b90508060200151600014156125cb57600092505050611d65565b60075460a08201516125de904290613559565b10156125ef57600092505050611d65565b60085460a0820151612602904290613559565b1061261257600192505050611d65565b6002546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561265757600080fd5b505afa15801561266b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268f9190615609565b9050600a548111156126a75760019350505050611d65565b60006126b16127a4565b90508260c001516126cd600a54836141d490919063ffffffff16565b10156126e0576001945050505050611d65565b60008360c001518211156127015760c08401516126fe908390613559565b90505b6002546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b15801561274657600080fd5b505afa15801561275a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277e9190615609565b905061278a81836141d4565b60095461279790886141f9565b1098975050505050505050565b6000806127af6135e4565b905060005b600c54811015612831576127c6614dde565b600c82815481106127d357fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b03168083526001909101549282018390529092506128269161281f9190611116908290612ec5565b84906141d4565b9250506001016127b4565b5061284c61283e826134c0565b612846613255565b906141d4565b91505090565b6003546001600160a01b0316331480612883575061286e612c83565b6001600160a01b0316336001600160a01b0316145b61289f5760405162461bcd60e51b815260040161060390615a83565b60088190556040517f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590610c09908390615b6c565b60006128de614dde565b600c83815481106128eb57fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b03168083526001909101549282018390529092506129379161111b9190611116908290612ec5565b9392505050565b6002546001600160a01b031681565b6003546001600160a01b031633148061297e5750612969612c83565b6001600160a01b0316336001600160a01b0316145b80612a1f5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156129d257600080fd5b505afa1580156129e6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a0a91906151d8565b6001600160a01b0316336001600160a01b0316145b80612ac05750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015612a7357600080fd5b505afa158015612a87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aab91906151d8565b6001600160a01b0316336001600160a01b0316145b612adc5760405162461bcd60e51b815260040161060390615a83565b600b805460ff191660011790556002546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b158015612b2f57600080fd5b505af1158015612b43573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b801580612bfa5750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e90612ba89030908690600401615726565b60206040518083038186803b158015612bc057600080fd5b505afa158015612bd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf89190615609565b155b612c165760405162461bcd60e51b815260040161060390615b16565b611db78363095ea7b360e01b8484604051602401612c3592919061580b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614233565b6060612c7b84846000856142c2565b949350505050565b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b158015612cc857600080fd5b505afa158015612cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd691906151d8565b606090565b611db78363a9059cbb60e01b8484604051602401612c3592919061580b565b6000612d2f84613176565b6000612d3a85614386565b905080831115612d48578092505b82612d57576000915050612937565b6000612d638685614408565b90508415612e02576000612d7686614554565b600d5490915082908290612d8b9083906141d4565b1115612d945750805b604051630441a3e760e41b815273c2edad668740f1aa35e4d8f227fb8e17dca888cd9063441a3e7090612dcd908a908590600401615b8c565b600060405180830381600087803b158015612de757600080fd5b505af1158015612dfb573d6000803e3d6000fd5b5050505050505b6000612e0d876145eb565b905080612e25600d54846141d490919063ffffffff16565b1115612e2f578091505b604051632317ef6760e01b81526001600160a01b03881690632317ef6790612e5d903090869060040161580b565b602060405180830381600087803b158015612e7757600080fd5b505af1158015612e8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eaf9190615609565b9350612ebb878761461a565b5050509392505050565b6000612edc612ed3846145eb565b61284684614554565b90505b92915050565b6000806000612ef2613255565b9050808411612f08578360009250925050613171565b6000612f148583613559565b90506000612f2a83612f246127a4565b90613559565b905080612f42600d54846141d490919063ffffffff16565b1115612f4c578091505b8115613135576000612f5d8361359b565b90506000612f696135e4565b905080821115613094576000612f7f8383613559565b905060008080612fb5612fb085612fab612fa6600c80549050612fa06127a4565b90614699565b61359b565b6146db565b6146f1565b90925090506001600160a01b03821615612fd757612fd4828286612d24565b92505b60005b600c5481108015612ffe575084612ffc600d54866141d490919063ffffffff16565b105b1561308e5761300b614dde565b600c828154811061301857fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b039081168084526001909201549383019390935290925090851614156130625750613086565b805160208201516130829161307b916111728a8a613559565b86906141d4565b9450505b600101612fda565b50505050505b600b546006546001600160a01b03620100009092048216916397da6d309116308060006130bf6135e4565b6040518663ffffffff1660e01b81526004016130df95949392919061582f565b6040805180830381600087803b1580156130f857600080fd5b505af115801561310c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131309190615621565b505050505b613146613140613255565b876146db565b94508585101561316d57600061315c8787613559565b9050600d54811161316b578094505b505b5050505b915091565b6000816001600160a01b031663b27c0e746040518163ffffffff1660e01b815260040160606040518083038186803b1580156131b157600080fd5b505afa1580156131c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e99190615644565b506001600160401b03169150508042111561076657816001600160a01b031663f8ba4cff6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561323957600080fd5b505af115801561324d573d6000803e3d6000fd5b505050505050565b6006546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613286903090600401615712565b60206040518083038186803b15801561329e57600080fd5b505afa1580156132b2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd69190615609565b600b5460065460405162ae511b60e21b815260009283926001600160a01b03620100009092048216926302b9446c9261331b921690309081908990889060040161582f565b6040805180830381600087803b15801561333457600080fd5b505af1158015613348573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061336c9190615621565b91509150915091565b600061337f614dde565b836001600160a01b031663f9557ccb6040518163ffffffff1660e01b8152600401604080518083038186803b1580156133b757600080fd5b505afa1580156133cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133ef9190615500565b90506133f9614dde565b846001600160a01b0316638285ef406040518163ffffffff1660e01b8152600401604080518083038186803b15801561343157600080fd5b505afa158015613445573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134699190615500565b9050600061349761348683600001516001600160801b031661359b565b84516001600160801b0316906141d4565b60208401519091506134b6906001600160801b0316612fa087846141f9565b9695505050505050565b6000816134cf57506000611d65565b600b54604051630acc462360e31b8152620100009091046001600160a01b031690635662311890613509903090869060019060040161588d565b60206040518083038186803b15801561352157600080fd5b505afa158015613535573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612edf9190615609565b6000612edc83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506148bc565b6000816135aa57506000611d65565b600b54604051636d289ce560e11b8152620100009091046001600160a01b03169063da5139ca90613509903090869060019060040161588d565b600b54600654604051633de222bb60e21b81526000926201000090046001600160a01b039081169263f7888aec9261328692909116903090600401615726565b61362e83826148e8565b604051626d47a560e61b81526000906001600160a01b03851690631b51e9409061366190309060019087906004016157ea565b602060405180830381600087803b15801561367b57600080fd5b505af115801561368f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136b39190615609565b90506136bf848461461a565b50505050565b600b5460ff16156136d55761237e565b60006136df613255565b90506000600d548211156136fa576136f6826132d6565b9150505b60006137046135e4565b9050613711600d5461359b565b8111156136bf5760008061372483614942565b9150915061324d828285613624565b6000610e556137406127a4565b612ee5565b60008080805b600c548110156137dc5761375d614dde565b600c828154811061376a57fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b03168083526001909101549282018390529092506137ab91612ec5565b6137b557506137d4565b80516137c090613176565b6137d28160000151826020015161461a565b505b60010161374b565b506137e5614ad1565b60006137ef6127a4565b905060006137fb613255565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf82390613831903090600401615712565b6101206040518083038186803b15801561384a57600080fd5b505afa15801561385e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138829190615540565b60c0015190508083106138a0576138998382613559565b95506138ad565b6138aa8184613559565b94505b86935060006138bc85886141d4565b90506000811180156138cd57508083105b1561390a5760006138dd82612ee5565b50905081811015613908578581116138fb5760009750809550613908565b6139058187613559565b97505b505b505050509193909250565b6006546001600160a01b03161561393e5760405162461bcd60e51b815260040161060390615993565b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b15801561399a57600080fd5b505afa1580156139ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139d291906151d8565b600680546001600160a01b0319166001600160a01b0392831617908190556139fe911685600019612b72565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b393613a7c93911691600019910161580b565b602060405180830381600087803b158015613a9657600080fd5b505af1158015613aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ace9190615426565b5050505050565b600b546201000090046001600160a01b031615613af157600080fd5b600583511115613b0057600080fd5b8151835114613b0e57600080fd5b805115613b1b5780613b52565b6040518060400160405280601c81526020017f53747261746567794b617368694d756c7469506169724c656e646572000000008152505b8051613b6691600f91602090910190614f1e565b50600b805462010000600160b01b031916620100006001600160a01b0387160217905560018054610100600160a81b03191674ddcea799ff1699e98edf118e0629a974df7df0120017905560005b8351811015613ee457600c6040518060400160405280868481518110613bd657fe5b60200260200101516001600160a01b03168152602001858481518110613bf857fe5b602090810291909101810151909152825460018082018555600094855293829020835160029092020180546001600160a01b0319166001600160a01b0392831617815592909101519190920155600c80549187169183908110613c5757fe5b60009182526020918290206002909102015460408051636b2ace8760e01b815290516001600160a01b0390921692636b2ace8792600480840193829003018186803b158015613ca557600080fd5b505afa158015613cb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cdd91906151d8565b6001600160a01b031614613cf057600080fd5b600654600c80546001600160a01b039092169183908110613d0d57fe5b600091825260209182902060029091020154604080516338d52e0f60e01b815290516001600160a01b03909216926338d52e0f92600480840193829003018186803b158015613d5b57600080fd5b505afa158015613d6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d9391906151d8565b6001600160a01b031614613da657600080fd5b828181518110613db257fe5b6020026020010151600014613edc57838181518110613dcd57fe5b60200260200101516001600160a01b031673c2edad668740f1aa35e4d8f227fb8e17dca888cd6001600160a01b0316631526fe27858481518110613e0d57fe5b60200260200101516040518263ffffffff1660e01b8152600401613e319190615b6c565b60806040518083038186803b158015613e4957600080fd5b505afa158015613e5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e8191906154ae565b516001600160a01b031614613e9557600080fd5b613edc73c2edad668740f1aa35e4d8f227fb8e17dca888cd600019868481518110613ebc57fe5b60200260200101516001600160a01b0316612b729092919063ffffffff16565b600101613bb4565b50600654613efe906001600160a01b031685600019612b72565b613f33736b3595068778dd592e39a122f4f5a5cf09c90fe273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f600019612b72565b60408051600380825260808201909252906020820160608036833750508151613f6392600e925060200190614f8c565b50736b3595068778dd592e39a122f4f5a5cf09c90fe2600e600081548110613f8757fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2600e600181548110613fd857fe5b600091825260209091200180546001600160a01b0319166001600160a01b03928316179055600654600e8054919092169190600290811061401557fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555050505050565b60005b600c548110156107665761405e614dde565b600c828154811061406b57fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b031682526001015491810182905291501561411e57602081015173c2edad668740f1aa35e4d8f227fb8e17dca888cd9063441a3e70906140ce81614554565b6040518363ffffffff1660e01b81526004016140eb929190615b8c565b600060405180830381600087803b15801561410557600080fd5b505af1158015614119573d6000803e3d6000fd5b505050505b600c828154811061412b57fe5b600091825260209091206002909102015481516001600160a01b039091169063a9059cbb90859061415b906145eb565b6040518363ffffffff1660e01b815260040161417892919061580b565b602060405180830381600087803b15801561419257600080fd5b505af11580156141a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141ca9190615426565b505060010161404c565b600082820183811015612edc5760405162461bcd60e51b815260040161060390615936565b60008261420857506000612edf565b8282028284828161421557fe5b0414612edc5760405162461bcd60e51b8152600401610603906159ca565b6060614288826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612c6c9092919063ffffffff16565b805190915015611db757808060200190518101906142a69190615426565b611db75760405162461bcd60e51b815260040161060390615aa8565b60606142cd85614b7f565b6142e95760405162461bcd60e51b815260040161060390615a4c565b60006060866001600160a01b0316858760405161430691906156f6565b60006040518083038185875af1925050503d8060008114614343576040519150601f19603f3d011682016040523d82523d6000602084013e614348565b606091505b5091509150811561435c579150612c7b9050565b80511561436c5780518082602001fd5b8360405162461bcd60e51b815260040161060391906158df565b6000816001600160a01b031663f9557ccb6040518163ffffffff1660e01b8152600401604080518083038186803b1580156143c057600080fd5b505afa1580156143d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143f89190615500565b516001600160801b031692915050565b6000614412614dde565b836001600160a01b031663f9557ccb6040518163ffffffff1660e01b8152600401604080518083038186803b15801561444a57600080fd5b505afa15801561445e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144829190615500565b905061448c614dde565b846001600160a01b0316638285ef406040518163ffffffff1660e01b8152600401604080518083038186803b1580156144c457600080fd5b505afa1580156144d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144fc9190615500565b9050600061451961348683600001516001600160801b031661359b565b9050801561454a5761454581612fa085602001516001600160801b0316886141f990919063ffffffff16565b6134b6565b5092949350505050565b60008115611d65576040516393f1a40b60e01b815273c2edad668740f1aa35e4d8f227fb8e17dca888cd906393f1a40b906145959085903090600401615b75565b604080518083038186803b1580156145ac57600080fd5b505afa1580156145c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145e491906155be565b5192915050565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190613509903090600401615712565b8061462457610766565b600061462f836145eb565b604051631c57762b60e31b815290915073c2edad668740f1aa35e4d8f227fb8e17dca888cd9063e2bbb1589061466b9085908590600401615b8c565b600060405180830381600087803b15801561468557600080fd5b505af115801561127d573d6000803e3d6000fd5b6000612edc83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614bb8565b60008183106146ea5781612edc565b5090919050565b600080600019670de0b6b3a7640000825b600c5481101561316d57614714614dde565b600c828154811061472157fe5b60009182526020808320604080518082018252600290940290910180546001600160a01b0316808552600190910154928401929092528051632c9f039d60e21b81529051929450909163b27c0e7491600480820192606092909190829003018186803b15801561479057600080fd5b505afa1580156147a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147c89190615644565b50506001600160401b0316905060006147e683600001516000614bef565b9050848110801561480f5750670b1a2bc2ec50000085118061480f57506709b6e64a8ec6000081105b806148645750858210801561482b5750670b1a2bc2ec50000081105b801561483e57506709b6e64a8ec6000081115b80156148515750670b1a2bc2ec50000085105b801561486457506709b6e64a8ec6000085115b80156148825750600d5461488084600001518560200151612ec5565b115b801561489a5750886148978460000151614386565b10155b156148b15781955082600001519750826020015196505b505050600101614702565b600081848411156148e05760405162461bcd60e51b815260040161060391906158df565b505050900390565b600b54600654604051633c6340f360e21b81526001600160a01b036201000090930483169263f18d03cc9261492892911690309087908790600401615863565b600060405180830381600087803b15801561323957600080fd5b60008060008060005b600c5481101561316d5761495d614dde565b600c828154811061496a57fe5b60009182526020808320604080518082018252600290940290910180546001600160a01b0316808552600190910154928401929092528051632c9f039d60e21b81529051929450909163b27c0e7491600480820192606092909190829003018186803b1580156149d957600080fd5b505afa1580156149ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a119190615644565b50506001600160401b031690506000614a2e83600001518a614bef565b90508481118015614a575750670b1a2bc2ec500000811180614a5757506709b6e64a8ec6000085105b80614aac57508582118015614a735750670b1a2bc2ec50000081105b8015614a8657506709b6e64a8ec6000081115b8015614a995750670b1a2bc2ec50000085105b8015614aac57506709b6e64a8ec6000085115b15614ac65781955080945082600001519750826020015196505b50505060010161494b565b6000614adb614da4565b905080614ae8575061152f565b6040516338ed173960e01b815273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f906338ed173990614b29908490600090600e9030904290600401615b9a565b600060405180830381600087803b158015614b4357600080fd5b505af1158015614b57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610766919081019061537b565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612c7b575050151592915050565b60008183614bd95760405162461bcd60e51b815260040161060391906158df565b506000838581614be557fe5b0495945050505050565b600080836001600160a01b031663f9557ccb6040518163ffffffff1660e01b8152600401604080518083038186803b158015614c2a57600080fd5b505afa158015614c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c629190615500565b600001516001600160801b031690506000846001600160a01b0316638285ef406040518163ffffffff1660e01b8152600401604080518083038186803b158015614cab57600080fd5b505afa158015614cbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ce39190615500565b51600b546001600160801b039091169150600090614d8c9083906201000090046001600160a01b0316635662311830614d1c888b6141d4565b60006040518463ffffffff1660e01b8152600401614d3c9392919061588d565b60206040518083038186803b158015614d5457600080fd5b505afa158015614d68573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128469190615609565b90506134b681612fa084670de0b6b3a76400006141f9565b6040516370a0823160e01b8152600090736b3595068778dd592e39a122f4f5a5cf09c90fe2906370a0823190613286903090600401615712565b604080518082019091526000808252602082015290565b828054828255906000526020600020908101928215614e48579160200282015b82811115614e485781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190614e15565b50614e54929150614fe1565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614e995782800160ff19823516178555614ec6565b82800160010185558215614ec6579182015b82811115614ec6578235825591602001919060010190614eab565b50614e54929150615000565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614f5f57805160ff1916838001178555614ec6565b82800160010185558215614ec6579182015b82811115614ec6578251825591602001919060010190614f71565b828054828255906000526020600020908101928215614e48579160200282015b82811115614e4857825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614fac565b5b80821115614e545780546001600160a01b0319168155600101614fe2565b5b80821115614e545760008155600101615001565b8035612edf81615cd2565b60008083601f840112615031578182fd5b5081356001600160401b03811115615047578182fd5b602083019150836020808302850101111561506157600080fd5b9250929050565b600082601f830112615078578081fd5b813561508b61508682615c87565b615c61565b8181529150602080830190848101818402860182018710156150ac57600080fd5b60005b848110156150d45781356150c281615cd2565b845292820192908201906001016150af565b505050505092915050565b600082601f8301126150ef578081fd5b81356150fd61508682615c87565b81815291506020808301908481018184028601820187101561511e57600080fd5b60005b848110156150d457813584529282019290820190600101615121565b600082601f83011261514d578081fd5b81356001600160401b03811115615162578182fd5b615175601f8201601f1916602001615c61565b915080825283602082850101111561518c57600080fd5b8060208401602084013760009082016020015292915050565b80516001600160801b0381168114612edf57600080fd5b6000602082840312156151cd578081fd5b8135612edc81615cd2565b6000602082840312156151e9578081fd5b8151612edc81615cd2565b600080600080600080600080610100898b031215615210578384fd5b61521a8a8a615015565b97506152298a60208b01615015565b96506152388a60408b01615015565b95506152478a60608b01615015565b94506152568a60808b01615015565b935060a08901356001600160401b0380821115615271578485fd5b61527d8c838d01615068565b945060c08b0135915080821115615292578384fd5b61529e8c838d016150df565b935060e08b01359150808211156152b3578283fd5b506152c08b828c0161513d565b9150509295985092959890939650565b600080604083850312156152e2578182fd5b82356152ed81615cd2565b946020939093013593505050565b60008060006060848603121561530f578081fd5b833561531a81615cd2565b925060208401359150604084013561533181615ce7565b809150509250925092565b6000806020838503121561534e578182fd5b82356001600160401b03811115615363578283fd5b61536f85828601615020565b90969095509350505050565b6000602080838503121561538d578182fd5b82516001600160401b038111156153a2578283fd5b8301601f810185136153b2578283fd5b80516153c061508682615c87565b81815283810190838501858402850186018910156153dc578687fd5b8694505b838510156153fe5780518352600194909401939185019185016153e0565b50979650505050505050565b60006020828403121561541b578081fd5b8135612edc81615ce7565b600060208284031215615437578081fd5b8151612edc81615ce7565b60008060208385031215615454578182fd5b82356001600160401b038082111561546a578384fd5b818501915085601f83011261547d578384fd5b81358181111561548b578485fd5b86602082850101111561549c578485fd5b60209290920196919550909350505050565b6000608082840312156154bf578081fd5b6154c96080615c61565b82516154d481615cd2565b808252506020830151602082015260408301516040820152606083015160608201528091505092915050565b600060408284031215615511578081fd5b61551b6040615c61565b61552584846151a5565b815261553484602085016151a5565b60208201529392505050565b6000610120808385031215615553578182fd5b61555c81615c61565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b6000604082840312156155cf578081fd5b6155d96040615c61565b82518152602083015160208201528091505092915050565b600060208284031215615602578081fd5b5035919050565b60006020828403121561561a578081fd5b5051919050565b60008060408385031215615633578182fd5b505080516020909101519092909150565b600080600060608486031215615658578081fd5b835161566381615cf5565b602085015190935061567481615cf5565b60408501519092506001600160801b0381168114615331578182fd5b6000815180845260208085019450808401835b838110156156bf578151875295820195908201906001016156a3565b509495945050505050565b600081518084526156e2816020860160208601615ca6565b601f01601f19169290920160200192915050565b60008251615708818460208701615ca6565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03898116825288811660208084019190915288821660408401528782166060840152868216608084015261010060a08401819052865190840181905260009261012085019288810192855b818110156157b0578451841686529482019493820193600101615792565b505050505082810360c08401526157c78186615690565b905082810360e08401526157db81856156ca565b9b9a5050505050505050505050565b6001600160a01b039390931683529015156020830152604082015260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6001600160a01b03958616815293851660208501529190931660408301526060820192909252608081019190915260a00190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b6001600160a01b0393909316835260208301919091521515604082015260600190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b600060208252612edc60208301846156ca565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b90815260200190565b9182526001600160a01b0316602082015260400190565b918252602082015260400190565b600060a082018783526020878185015260a0604085015281875480845260c0860191508885528285209350845b81811015615bec5784546001600160a01b031683526001948501949284019201615bc7565b50506001600160a01b03969096166060850152505050608001529392505050565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b6040518181016001600160401b0381118282101715615c7f57600080fd5b604052919050565b60006001600160401b03821115615c9c578081fd5b5060209081020190565b60005b83811015615cc1578181015183820152602001615ca9565b838111156136bf5750506000910152565b6001600160a01b038116811461237e57600080fd5b801515811461237e57600080fd5b6001600160401b038116811461237e57600080fdfea2646970667358221220249666e07c860f2875a5a98b68433e73d3b70707c81e2b4b5e773ea92814810364736f6c634300060c0033000000000000000000000000da816459f1ab5631232fe5e97a05bbbb94970c95000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd64396600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000418bc3ff0ba33ad64931160a91c92fa26b35acb00000000000000000000000005f92e4300024c447a103c161614e6918e794c7640000000000000000000000000ea032decbfbea581d77d4a9b9c5e9db7c102a7c00000000000000000000000077f3a4fa35bac0ea6cfac69037ac4d3a757240a1000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010a00000000000000000000000000000000000000000000000000000000000000f60000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102d65760003560e01c80636d13582c11610182578063ad7e55ba116100e9578063ec38a862116100a2578063f017c92f1161007c578063f017c92f14610595578063fa9b9545146105a8578063fbfa77cf146105bb578063fcf2d0ad146105c3576102d6565b8063ec38a86214610567578063ed882c2b1461057a578063efbb5cb01461058d576102d6565b8063ad7e55ba1461050b578063b252720b1461051e578063c7b9d53014610526578063c812daa914610539578063ce5494bb1461054c578063e8462e8f1461055f576102d6565b80638e6350e21161013b5780638e6350e2146104c557806391397ab4146104cd57806395e80c50146104e05780639ec5a894146104e8578063ac00ff26146104f0578063aced166114610503576102d6565b80636d13582c1461045b578063748747e614610463578063750521f5146104765780637795d5bc14610489578063780022a0146104aa5780638cdfe166146104bd576102d6565b80632e1a7d4d116102415780635641ec03116101fa578063650d1880116101d4578063650d1880146104255780636718835f14610438578063686ca00d146104405780636b2ace8714610453576102d6565b80635641ec0314610402578063575a86b21461040a5780635a4775ef14610412576102d6565b80632e1a7d4d146103a65780632e430638146103b9578063324b91dd146103cc57806339a172a8146103df578063440368a3146103f25780634641257d146103fa576102d6565b80631d12f28b116102935780631d12f28b1461034f5780631f1fcd51146103645780631fe4a6861461037957806322f3e2d414610381578063258294101461039657806328b7ccf71461039e576102d6565b806301681a62146102db57806303ee438c146102f0578063048be65d1461030e57806306fdde03146103215780630f969b871461032957806311bc82451461033c575b600080fd5b6102ee6102e93660046151bc565b6105cb565b005b6102f861076a565b60405161030591906158df565b60405180910390f35b6102ee61031c3660046152fb565b6107f8565b6102f8610af1565b6102ee6103373660046155f1565b610b87565b6102ee61034a3660046151bc565b610c14565b610357610d15565b6040516103059190615b6c565b61036c610d1b565b6040516103059190615712565b61036c610d2a565b610389610d39565b6040516103059190615824565b6102f8610ddb565b610357610dfa565b6103576103b43660046155f1565b610e00565b61036c6103c73660046151f4565b610e5b565b6102ee6103da36600461533c565b610f6a565b6102ee6103ed3660046155f1565b611286565b6102ee611308565b6102ee611531565b610389611a0a565b61036c611a13565b6102ee6104203660046152d0565b611a2b565b6103896104333660046155f1565b611d62565b610389611d6a565b6102ee61044e36600461533c565b611d73565b61036c611dbc565b61036c611dd1565b6102ee6104713660046151bc565b611de9565b6102ee610484366004615442565b611e94565b61049c6104973660046155f1565b611f2b565b60405161030592919061580b565b6103576104b83660046155f1565b611f60565b610357611f63565b610357611f69565b6102ee6104db3660046155f1565b611f6e565b610357611ff0565b61036c611ff6565b6102ee6104fe36600461540a565b612005565b61036c6120f1565b6102ee6105193660046155f1565b612100565b61036c612152565b6102ee6105343660046151bc565b612166565b6102ee6105473660046151f4565b612211565b6102ee61055a3660046151bc565b612233565b610357612381565b6102ee6105753660046151bc565b612387565b6103896105883660046155f1565b61251a565b6103576127a4565b6102ee6105a33660046155f1565b612852565b6103576105b63660046155f1565b6128d4565b61036c61293e565b6102ee61294d565b6105d3612c83565b6001600160a01b0316336001600160a01b03161461060c5760405162461bcd60e51b815260040161060390615a83565b60405180910390fd5b6006546001600160a01b038281169116141561063a5760405162461bcd60e51b815260040161060390615917565b6002546001600160a01b03828116911614156106685760405162461bcd60e51b815260040161060390615a2b565b6060610672612d00565b905060005b81518110156106cd5781818151811061068c57fe5b60200260200101516001600160a01b0316836001600160a01b031614156106c55760405162461bcd60e51b815260040161060390615af2565b600101610677565b506107666106d9612c83565b6040516370a0823160e01b81526001600160a01b038516906370a0823190610705903090600401615712565b60206040518083038186803b15801561071d57600080fd5b505afa158015610731573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107559190615609565b6001600160a01b0385169190612d05565b5050565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107f05780601f106107c5576101008083540402835291602001916107f0565b820191906000526020600020905b8154815290600101906020018083116107d357829003601f168201915b505050505081565b6003546001600160a01b03163314806108295750610814612c83565b6001600160a01b0316336001600160a01b0316145b806108ca5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561087d57600080fd5b505afa158015610891573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b591906151d8565b6001600160a01b0316336001600160a01b0316145b8061096b5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561091e57600080fd5b505afa158015610932573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095691906151d8565b6001600160a01b0316336001600160a01b0316145b6109875760405162461bcd60e51b815260040161060390615a83565b61098f614dde565b600c838154811061099c57fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b0390811680845260019092015493830193909352909250908516146109e457600080fd5b6109f981600001518260200151600019612d24565b5081610a1f57600d54610a1482600001518360200151612ec5565b1115610a1f57600080fd5b602081015115610a5257610a526001600160a01b03851673c2edad668740f1aa35e4d8f227fb8e17dca888cd6000612b72565b600c80546000198101908110610a6457fe5b9060005260206000209060020201600c8481548110610a7f57fe5b60009182526020909120825460029092020180546001600160a01b0319166001600160a01b03909216919091178155600191820154910155600c805480610ac257fe5b60008281526020812060026000199093019283020180546001600160a01b031916815560010155905550505050565b600f8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b7d5780601f10610b5257610100808354040283529160200191610b7d565b820191906000526020600020905b815481529060010190602001808311610b6057829003601f168201915b5050505050905090565b6003546001600160a01b0316331480610bb85750610ba3612c83565b6001600160a01b0316336001600160a01b0316145b610bd45760405162461bcd60e51b815260040161060390615a83565b600a8190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a860090610c09908390615b6c565b60405180910390a150565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6257600080fd5b505afa158015610c76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9a91906151d8565b6001600160a01b0316336001600160a01b03161480610cd15750610cbc612c83565b6001600160a01b0316336001600160a01b0316145b610ced5760405162461bcd60e51b815260040161060390615a83565b600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600a5481565b6006546001600160a01b031681565b6003546001600160a01b031681565b6002546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610d6e903090600401615712565b6101206040518083038186803b158015610d8757600080fd5b505afa158015610d9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbf9190615540565b604001511180610dd657506000610dd46127a4565b115b905090565b604080518082019091526005815264302e342e3360d81b602082015290565b60085481565b6002546000906001600160a01b03163314610e2d5760405162461bcd60e51b815260040161060390615a0b565b6000610e3883612ee5565b600654909350909150610e55906001600160a01b03163383612d05565b50919050565b600b54600090610100900460ff16610e7257600080fd5b604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81523060601b601482018190526e5af43d82803e903d91602b57fd5bf360881b6028830152906037816000f060405163c812daa960e01b81529093506001600160a01b038416915063c812daa990610ef7908d908d908d908d908d908d908d908d90600401615740565b600060405180830381600087803b158015610f1157600080fd5b505af1158015610f25573d6000803e3d6000fd5b50506040516001600160a01b03851692507f783540fb4221a3238720dc7038937d0d79982bcf895274aa6ad179f82cf0d53c9150600090a25098975050505050505050565b6003546001600160a01b0316331480610f9b5750610f86612c83565b6001600160a01b0316336001600160a01b0316145b610fb75760405162461bcd60e51b815260040161060390615a83565b600c548114610fc557600080fd5b6000805b600c5481101561102457611002600c8281548110610fe357fe5b60009182526020909120600290910201546001600160a01b0316613176565b83838281811061100e57fe5b6020029190910135929092019150600101610fc9565b50612710811461103357600080fd5b600061103d613255565b9050600d5481111561105557611052816132d6565b50505b600061105f6127a4565b600c549091506060906001600160401b038111801561107d57600080fd5b506040519080825280602002602001820160405280156110a7578160200160208202803683370190505b50905060005b600c548110156111b4576110bf614dde565b600c82815481106110cc57fe5b600091825260208083206040805180820190915260029093020180546001600160a01b03168084526001909101549183018290529193506111209161111b91611116908290612ec5565b613375565b6134c0565b90506000612710868b8b8781811061113457fe5b90506020020135028161114357fe5b0490508181101561117e57600061115a8383613559565b9050611177846000015185602001516111728461359b565b612d24565b50506111a9565b818111156111a9576111908183613559565b85858151811061119c57fe5b6020026020010181815250505b5050506001016110ad565b5060005b600c5481101561127d578181815181106111ce57fe5b6020026020010151600014156111e357611275565b6111eb614dde565b600c82815481106111f857fe5b600091825260208083206040805180820190915260029093020180546001600160a01b03168352600101549082015291506112316135e4565b9050600061125185858151811061124457fe5b602002602001015161359b565b90508181111561125e5750805b6112718360000151846020015183613624565b5050505b6001016111b8565b50505050505050565b6003546001600160a01b03163314806112b757506112a2612c83565b6001600160a01b0316336001600160a01b0316145b6112d35760405162461bcd60e51b815260040161060390615a83565b60078190556040517fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190610c09908390615b6c565b6005546001600160a01b031633148061132b57506003546001600160a01b031633145b8061134e5750611339612c83565b6001600160a01b0316336001600160a01b0316145b806113ef5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156113a257600080fd5b505afa1580156113b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113da91906151d8565b6001600160a01b0316336001600160a01b0316145b806114905750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561144357600080fd5b505afa158015611457573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147b91906151d8565b6001600160a01b0316336001600160a01b0316145b6114ac5760405162461bcd60e51b815260040161060390615a83565b6002546040805163bf3759b560e01b8152905161152f926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b1580156114f257600080fd5b505afa158015611506573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152a9190615609565b6136c5565b565b6005546001600160a01b031633148061155457506003546001600160a01b031633145b806115775750611562612c83565b6001600160a01b0316336001600160a01b0316145b806116185750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156115cb57600080fd5b505afa1580156115df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160391906151d8565b6001600160a01b0316336001600160a01b0316145b806116b95750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561166c57600080fd5b505afa158015611680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a491906151d8565b6001600160a01b0316336001600160a01b0316145b6116d55760405162461bcd60e51b815260040161060390615a83565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561172857600080fd5b505afa15801561173c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117609190615609565b600b5490915060009060ff16156117bd57600061177b613733565b9050828110156117965761178f8382613559565b93506117ab565b828111156117ab576117a88184613559565b94505b6117b58385613559565b9150506117ce565b6117c682613745565b919550935090505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf823906117ff903090600401615712565b6101206040518083038186803b15801561181857600080fd5b505afa15801561182c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118509190615540565b60c001516002546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc9061188990889088908790600401615c0d565b602060405180830381600087803b1580156118a357600080fd5b505af11580156118b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118db9190615609565b92506118e6836136c5565b60015460ff168015611907575060015461010090046001600160a01b031615155b156119b95760015460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b906119489088908890879089908890600401615c3e565b60206040518083038186803b15801561196057600080fd5b505afa158015611974573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119989190615426565b6119b45760405162461bcd60e51b81526004016106039061596d565b6119c6565b6001805460ff1916811790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d509858584866040516119fb9493929190615c23565b60405180910390a15050505050565b600b5460ff1681565b73c2edad668740f1aa35e4d8f227fb8e17dca888cd81565b611a33612c83565b6001600160a01b0316336001600160a01b031614611a635760405162461bcd60e51b815260040161060390615a83565b600c54600511611a7257600080fd5b600b60029054906101000a90046001600160a01b03166001600160a01b0316826001600160a01b0316636b2ace876040518163ffffffff1660e01b815260040160206040518083038186803b158015611aca57600080fd5b505afa158015611ade573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0291906151d8565b6001600160a01b031614611b1557600080fd5b600654604080516338d52e0f60e01b815290516001600160a01b03928316928516916338d52e0f916004808301926020929190829003018186803b158015611b5c57600080fd5b505afa158015611b70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9491906151d8565b6001600160a01b031614611ba757600080fd5b8015611c5357604051631526fe2760e01b81526001600160a01b0383169073c2edad668740f1aa35e4d8f227fb8e17dca888cd90631526fe2790611bef908590600401615b6c565b60806040518083038186803b158015611c0757600080fd5b505afa158015611c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3f91906154ae565b516001600160a01b031614611c5357600080fd5b60005b600c54811015611c9e57600c8181548110611c6d57fe5b60009182526020909120600290910201546001600160a01b0384811691161415611c9657600080fd5b600101611c56565b50604080518082019091526001600160a01b03838116825260208201838152600c805460018101825560009190915292517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7600290940293840180546001600160a01b0319169190931617909155517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8909101558015610766576107666001600160a01b03831673c2edad668740f1aa35e4d8f227fb8e17dca888cd600019612b72565b60005b919050565b60015460ff1681565b611d7b612c83565b6001600160a01b0316336001600160a01b031614611dab5760405162461bcd60e51b815260040161060390615a83565b611db7600e8383614df5565b505050565b600b546201000090046001600160a01b031681565b73d9e1ce17f2641f24ae83637ab66a2cca9c378b9f81565b6003546001600160a01b0316331480611e1a5750611e05612c83565b6001600160a01b0316336001600160a01b0316145b611e365760405162461bcd60e51b815260040161060390615a83565b6001600160a01b038116611e4957600080fd5b600580546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490610c09908390615712565b6003546001600160a01b0316331480611ec55750611eb0612c83565b6001600160a01b0316336001600160a01b0316145b611ee15760405162461bcd60e51b815260040161060390615a83565b611eed60008383614e58565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda68282604051611f1f9291906158b0565b60405180910390a15050565b600c8181548110611f3857fe5b6000918252602090912060029091020180546001909101546001600160a01b03909116915082565b90565b60095481565b600090565b6003546001600160a01b0316331480611f9f5750611f8a612c83565b6001600160a01b0316336001600160a01b0316145b611fbb5760405162461bcd60e51b815260040161060390615a83565b60098190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec29890610c09908390615b6c565b60075481565b6004546001600160a01b031681565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561205357600080fd5b505afa158015612067573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208b91906151d8565b6001600160a01b0316336001600160a01b031614806120c257506120ad612c83565b6001600160a01b0316336001600160a01b0316145b6120de5760405162461bcd60e51b815260040161060390615a83565b6001805460ff1916911515919091179055565b6005546001600160a01b031681565b6003546001600160a01b0316331480612131575061211c612c83565b6001600160a01b0316336001600160a01b0316145b61214d5760405162461bcd60e51b815260040161060390615a83565b600d55565b60015461010090046001600160a01b031681565b6003546001600160a01b03163314806121975750612182612c83565b6001600160a01b0316336001600160a01b0316145b6121b35760405162461bcd60e51b815260040161060390615a83565b6001600160a01b0381166121c657600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490610c09908390615712565b61221d88888888613915565b61222984848484613ad5565b5050505050505050565b6002546001600160a01b0316331461224a57600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b15801561229157600080fd5b505afa1580156122a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c991906151d8565b6001600160a01b0316146122dc57600080fd5b6122e581614049565b6006546040516370a0823160e01b815261237e9183916001600160a01b03909116906370a082319061231b903090600401615712565b60206040518083038186803b15801561233357600080fd5b505afa158015612347573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236b9190615609565b6006546001600160a01b03169190612d05565b50565b600d5481565b6003546001600160a01b031633146123b15760405162461bcd60e51b8152600401610603906158f2565b6001600160a01b0381166123c457600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b3936123fb93909116916000910161580b565b602060405180830381600087803b15801561241557600080fd5b505af1158015612429573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244d9190615426565b50600480546001600160a01b0319166001600160a01b038381169190911780835560025460405163095ea7b360e01b81529083169363095ea7b393612498931691600019910161580b565b602060405180830381600087803b1580156124b257600080fd5b505af11580156124c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ea9190615426565b507fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06981604051610c099190615712565b60008061252683611f60565b9050612530614ed2565b6002546040516339ebf82360e01b81526001600160a01b03909116906339ebf82390612560903090600401615712565b6101206040518083038186803b15801561257957600080fd5b505afa15801561258d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b19190615540565b90508060200151600014156125cb57600092505050611d65565b60075460a08201516125de904290613559565b10156125ef57600092505050611d65565b60085460a0820151612602904290613559565b1061261257600192505050611d65565b6002546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561265757600080fd5b505afa15801561266b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268f9190615609565b9050600a548111156126a75760019350505050611d65565b60006126b16127a4565b90508260c001516126cd600a54836141d490919063ffffffff16565b10156126e0576001945050505050611d65565b60008360c001518211156127015760c08401516126fe908390613559565b90505b6002546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b15801561274657600080fd5b505afa15801561275a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277e9190615609565b905061278a81836141d4565b60095461279790886141f9565b1098975050505050505050565b6000806127af6135e4565b905060005b600c54811015612831576127c6614dde565b600c82815481106127d357fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b03168083526001909101549282018390529092506128269161281f9190611116908290612ec5565b84906141d4565b9250506001016127b4565b5061284c61283e826134c0565b612846613255565b906141d4565b91505090565b6003546001600160a01b0316331480612883575061286e612c83565b6001600160a01b0316336001600160a01b0316145b61289f5760405162461bcd60e51b815260040161060390615a83565b60088190556040517f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590610c09908390615b6c565b60006128de614dde565b600c83815481106128eb57fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b03168083526001909101549282018390529092506129379161111b9190611116908290612ec5565b9392505050565b6002546001600160a01b031681565b6003546001600160a01b031633148061297e5750612969612c83565b6001600160a01b0316336001600160a01b0316145b80612a1f5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156129d257600080fd5b505afa1580156129e6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a0a91906151d8565b6001600160a01b0316336001600160a01b0316145b80612ac05750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015612a7357600080fd5b505afa158015612a87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aab91906151d8565b6001600160a01b0316336001600160a01b0316145b612adc5760405162461bcd60e51b815260040161060390615a83565b600b805460ff191660011790556002546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b158015612b2f57600080fd5b505af1158015612b43573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b801580612bfa5750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e90612ba89030908690600401615726565b60206040518083038186803b158015612bc057600080fd5b505afa158015612bd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf89190615609565b155b612c165760405162461bcd60e51b815260040161060390615b16565b611db78363095ea7b360e01b8484604051602401612c3592919061580b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614233565b6060612c7b84846000856142c2565b949350505050565b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b158015612cc857600080fd5b505afa158015612cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd691906151d8565b606090565b611db78363a9059cbb60e01b8484604051602401612c3592919061580b565b6000612d2f84613176565b6000612d3a85614386565b905080831115612d48578092505b82612d57576000915050612937565b6000612d638685614408565b90508415612e02576000612d7686614554565b600d5490915082908290612d8b9083906141d4565b1115612d945750805b604051630441a3e760e41b815273c2edad668740f1aa35e4d8f227fb8e17dca888cd9063441a3e7090612dcd908a908590600401615b8c565b600060405180830381600087803b158015612de757600080fd5b505af1158015612dfb573d6000803e3d6000fd5b5050505050505b6000612e0d876145eb565b905080612e25600d54846141d490919063ffffffff16565b1115612e2f578091505b604051632317ef6760e01b81526001600160a01b03881690632317ef6790612e5d903090869060040161580b565b602060405180830381600087803b158015612e7757600080fd5b505af1158015612e8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eaf9190615609565b9350612ebb878761461a565b5050509392505050565b6000612edc612ed3846145eb565b61284684614554565b90505b92915050565b6000806000612ef2613255565b9050808411612f08578360009250925050613171565b6000612f148583613559565b90506000612f2a83612f246127a4565b90613559565b905080612f42600d54846141d490919063ffffffff16565b1115612f4c578091505b8115613135576000612f5d8361359b565b90506000612f696135e4565b905080821115613094576000612f7f8383613559565b905060008080612fb5612fb085612fab612fa6600c80549050612fa06127a4565b90614699565b61359b565b6146db565b6146f1565b90925090506001600160a01b03821615612fd757612fd4828286612d24565b92505b60005b600c5481108015612ffe575084612ffc600d54866141d490919063ffffffff16565b105b1561308e5761300b614dde565b600c828154811061301857fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b039081168084526001909201549383019390935290925090851614156130625750613086565b805160208201516130829161307b916111728a8a613559565b86906141d4565b9450505b600101612fda565b50505050505b600b546006546001600160a01b03620100009092048216916397da6d309116308060006130bf6135e4565b6040518663ffffffff1660e01b81526004016130df95949392919061582f565b6040805180830381600087803b1580156130f857600080fd5b505af115801561310c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131309190615621565b505050505b613146613140613255565b876146db565b94508585101561316d57600061315c8787613559565b9050600d54811161316b578094505b505b5050505b915091565b6000816001600160a01b031663b27c0e746040518163ffffffff1660e01b815260040160606040518083038186803b1580156131b157600080fd5b505afa1580156131c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e99190615644565b506001600160401b03169150508042111561076657816001600160a01b031663f8ba4cff6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561323957600080fd5b505af115801561324d573d6000803e3d6000fd5b505050505050565b6006546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613286903090600401615712565b60206040518083038186803b15801561329e57600080fd5b505afa1580156132b2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd69190615609565b600b5460065460405162ae511b60e21b815260009283926001600160a01b03620100009092048216926302b9446c9261331b921690309081908990889060040161582f565b6040805180830381600087803b15801561333457600080fd5b505af1158015613348573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061336c9190615621565b91509150915091565b600061337f614dde565b836001600160a01b031663f9557ccb6040518163ffffffff1660e01b8152600401604080518083038186803b1580156133b757600080fd5b505afa1580156133cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133ef9190615500565b90506133f9614dde565b846001600160a01b0316638285ef406040518163ffffffff1660e01b8152600401604080518083038186803b15801561343157600080fd5b505afa158015613445573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134699190615500565b9050600061349761348683600001516001600160801b031661359b565b84516001600160801b0316906141d4565b60208401519091506134b6906001600160801b0316612fa087846141f9565b9695505050505050565b6000816134cf57506000611d65565b600b54604051630acc462360e31b8152620100009091046001600160a01b031690635662311890613509903090869060019060040161588d565b60206040518083038186803b15801561352157600080fd5b505afa158015613535573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612edf9190615609565b6000612edc83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506148bc565b6000816135aa57506000611d65565b600b54604051636d289ce560e11b8152620100009091046001600160a01b03169063da5139ca90613509903090869060019060040161588d565b600b54600654604051633de222bb60e21b81526000926201000090046001600160a01b039081169263f7888aec9261328692909116903090600401615726565b61362e83826148e8565b604051626d47a560e61b81526000906001600160a01b03851690631b51e9409061366190309060019087906004016157ea565b602060405180830381600087803b15801561367b57600080fd5b505af115801561368f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136b39190615609565b90506136bf848461461a565b50505050565b600b5460ff16156136d55761237e565b60006136df613255565b90506000600d548211156136fa576136f6826132d6565b9150505b60006137046135e4565b9050613711600d5461359b565b8111156136bf5760008061372483614942565b9150915061324d828285613624565b6000610e556137406127a4565b612ee5565b60008080805b600c548110156137dc5761375d614dde565b600c828154811061376a57fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b03168083526001909101549282018390529092506137ab91612ec5565b6137b557506137d4565b80516137c090613176565b6137d28160000151826020015161461a565b505b60010161374b565b506137e5614ad1565b60006137ef6127a4565b905060006137fb613255565b6002546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf82390613831903090600401615712565b6101206040518083038186803b15801561384a57600080fd5b505afa15801561385e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138829190615540565b60c0015190508083106138a0576138998382613559565b95506138ad565b6138aa8184613559565b94505b86935060006138bc85886141d4565b90506000811180156138cd57508083105b1561390a5760006138dd82612ee5565b50905081811015613908578581116138fb5760009750809550613908565b6139058187613559565b97505b505b505050509193909250565b6006546001600160a01b03161561393e5760405162461bcd60e51b815260040161060390615993565b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b15801561399a57600080fd5b505afa1580156139ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139d291906151d8565b600680546001600160a01b0319166001600160a01b0392831617908190556139fe911685600019612b72565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b393613a7c93911691600019910161580b565b602060405180830381600087803b158015613a9657600080fd5b505af1158015613aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ace9190615426565b5050505050565b600b546201000090046001600160a01b031615613af157600080fd5b600583511115613b0057600080fd5b8151835114613b0e57600080fd5b805115613b1b5780613b52565b6040518060400160405280601c81526020017f53747261746567794b617368694d756c7469506169724c656e646572000000008152505b8051613b6691600f91602090910190614f1e565b50600b805462010000600160b01b031916620100006001600160a01b0387160217905560018054610100600160a81b03191674ddcea799ff1699e98edf118e0629a974df7df0120017905560005b8351811015613ee457600c6040518060400160405280868481518110613bd657fe5b60200260200101516001600160a01b03168152602001858481518110613bf857fe5b602090810291909101810151909152825460018082018555600094855293829020835160029092020180546001600160a01b0319166001600160a01b0392831617815592909101519190920155600c80549187169183908110613c5757fe5b60009182526020918290206002909102015460408051636b2ace8760e01b815290516001600160a01b0390921692636b2ace8792600480840193829003018186803b158015613ca557600080fd5b505afa158015613cb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cdd91906151d8565b6001600160a01b031614613cf057600080fd5b600654600c80546001600160a01b039092169183908110613d0d57fe5b600091825260209182902060029091020154604080516338d52e0f60e01b815290516001600160a01b03909216926338d52e0f92600480840193829003018186803b158015613d5b57600080fd5b505afa158015613d6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d9391906151d8565b6001600160a01b031614613da657600080fd5b828181518110613db257fe5b6020026020010151600014613edc57838181518110613dcd57fe5b60200260200101516001600160a01b031673c2edad668740f1aa35e4d8f227fb8e17dca888cd6001600160a01b0316631526fe27858481518110613e0d57fe5b60200260200101516040518263ffffffff1660e01b8152600401613e319190615b6c565b60806040518083038186803b158015613e4957600080fd5b505afa158015613e5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e8191906154ae565b516001600160a01b031614613e9557600080fd5b613edc73c2edad668740f1aa35e4d8f227fb8e17dca888cd600019868481518110613ebc57fe5b60200260200101516001600160a01b0316612b729092919063ffffffff16565b600101613bb4565b50600654613efe906001600160a01b031685600019612b72565b613f33736b3595068778dd592e39a122f4f5a5cf09c90fe273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f600019612b72565b60408051600380825260808201909252906020820160608036833750508151613f6392600e925060200190614f8c565b50736b3595068778dd592e39a122f4f5a5cf09c90fe2600e600081548110613f8757fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2600e600181548110613fd857fe5b600091825260209091200180546001600160a01b0319166001600160a01b03928316179055600654600e8054919092169190600290811061401557fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555050505050565b60005b600c548110156107665761405e614dde565b600c828154811061406b57fe5b60009182526020918290206040805180820190915260029092020180546001600160a01b031682526001015491810182905291501561411e57602081015173c2edad668740f1aa35e4d8f227fb8e17dca888cd9063441a3e70906140ce81614554565b6040518363ffffffff1660e01b81526004016140eb929190615b8c565b600060405180830381600087803b15801561410557600080fd5b505af1158015614119573d6000803e3d6000fd5b505050505b600c828154811061412b57fe5b600091825260209091206002909102015481516001600160a01b039091169063a9059cbb90859061415b906145eb565b6040518363ffffffff1660e01b815260040161417892919061580b565b602060405180830381600087803b15801561419257600080fd5b505af11580156141a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141ca9190615426565b505060010161404c565b600082820183811015612edc5760405162461bcd60e51b815260040161060390615936565b60008261420857506000612edf565b8282028284828161421557fe5b0414612edc5760405162461bcd60e51b8152600401610603906159ca565b6060614288826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612c6c9092919063ffffffff16565b805190915015611db757808060200190518101906142a69190615426565b611db75760405162461bcd60e51b815260040161060390615aa8565b60606142cd85614b7f565b6142e95760405162461bcd60e51b815260040161060390615a4c565b60006060866001600160a01b0316858760405161430691906156f6565b60006040518083038185875af1925050503d8060008114614343576040519150601f19603f3d011682016040523d82523d6000602084013e614348565b606091505b5091509150811561435c579150612c7b9050565b80511561436c5780518082602001fd5b8360405162461bcd60e51b815260040161060391906158df565b6000816001600160a01b031663f9557ccb6040518163ffffffff1660e01b8152600401604080518083038186803b1580156143c057600080fd5b505afa1580156143d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143f89190615500565b516001600160801b031692915050565b6000614412614dde565b836001600160a01b031663f9557ccb6040518163ffffffff1660e01b8152600401604080518083038186803b15801561444a57600080fd5b505afa15801561445e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144829190615500565b905061448c614dde565b846001600160a01b0316638285ef406040518163ffffffff1660e01b8152600401604080518083038186803b1580156144c457600080fd5b505afa1580156144d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144fc9190615500565b9050600061451961348683600001516001600160801b031661359b565b9050801561454a5761454581612fa085602001516001600160801b0316886141f990919063ffffffff16565b6134b6565b5092949350505050565b60008115611d65576040516393f1a40b60e01b815273c2edad668740f1aa35e4d8f227fb8e17dca888cd906393f1a40b906145959085903090600401615b75565b604080518083038186803b1580156145ac57600080fd5b505afa1580156145c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145e491906155be565b5192915050565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190613509903090600401615712565b8061462457610766565b600061462f836145eb565b604051631c57762b60e31b815290915073c2edad668740f1aa35e4d8f227fb8e17dca888cd9063e2bbb1589061466b9085908590600401615b8c565b600060405180830381600087803b15801561468557600080fd5b505af115801561127d573d6000803e3d6000fd5b6000612edc83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614bb8565b60008183106146ea5781612edc565b5090919050565b600080600019670de0b6b3a7640000825b600c5481101561316d57614714614dde565b600c828154811061472157fe5b60009182526020808320604080518082018252600290940290910180546001600160a01b0316808552600190910154928401929092528051632c9f039d60e21b81529051929450909163b27c0e7491600480820192606092909190829003018186803b15801561479057600080fd5b505afa1580156147a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147c89190615644565b50506001600160401b0316905060006147e683600001516000614bef565b9050848110801561480f5750670b1a2bc2ec50000085118061480f57506709b6e64a8ec6000081105b806148645750858210801561482b5750670b1a2bc2ec50000081105b801561483e57506709b6e64a8ec6000081115b80156148515750670b1a2bc2ec50000085105b801561486457506709b6e64a8ec6000085115b80156148825750600d5461488084600001518560200151612ec5565b115b801561489a5750886148978460000151614386565b10155b156148b15781955082600001519750826020015196505b505050600101614702565b600081848411156148e05760405162461bcd60e51b815260040161060391906158df565b505050900390565b600b54600654604051633c6340f360e21b81526001600160a01b036201000090930483169263f18d03cc9261492892911690309087908790600401615863565b600060405180830381600087803b15801561323957600080fd5b60008060008060005b600c5481101561316d5761495d614dde565b600c828154811061496a57fe5b60009182526020808320604080518082018252600290940290910180546001600160a01b0316808552600190910154928401929092528051632c9f039d60e21b81529051929450909163b27c0e7491600480820192606092909190829003018186803b1580156149d957600080fd5b505afa1580156149ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a119190615644565b50506001600160401b031690506000614a2e83600001518a614bef565b90508481118015614a575750670b1a2bc2ec500000811180614a5757506709b6e64a8ec6000085105b80614aac57508582118015614a735750670b1a2bc2ec50000081105b8015614a8657506709b6e64a8ec6000081115b8015614a995750670b1a2bc2ec50000085105b8015614aac57506709b6e64a8ec6000085115b15614ac65781955080945082600001519750826020015196505b50505060010161494b565b6000614adb614da4565b905080614ae8575061152f565b6040516338ed173960e01b815273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f906338ed173990614b29908490600090600e9030904290600401615b9a565b600060405180830381600087803b158015614b4357600080fd5b505af1158015614b57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610766919081019061537b565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612c7b575050151592915050565b60008183614bd95760405162461bcd60e51b815260040161060391906158df565b506000838581614be557fe5b0495945050505050565b600080836001600160a01b031663f9557ccb6040518163ffffffff1660e01b8152600401604080518083038186803b158015614c2a57600080fd5b505afa158015614c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c629190615500565b600001516001600160801b031690506000846001600160a01b0316638285ef406040518163ffffffff1660e01b8152600401604080518083038186803b158015614cab57600080fd5b505afa158015614cbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ce39190615500565b51600b546001600160801b039091169150600090614d8c9083906201000090046001600160a01b0316635662311830614d1c888b6141d4565b60006040518463ffffffff1660e01b8152600401614d3c9392919061588d565b60206040518083038186803b158015614d5457600080fd5b505afa158015614d68573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128469190615609565b90506134b681612fa084670de0b6b3a76400006141f9565b6040516370a0823160e01b8152600090736b3595068778dd592e39a122f4f5a5cf09c90fe2906370a0823190613286903090600401615712565b604080518082019091526000808252602082015290565b828054828255906000526020600020908101928215614e48579160200282015b82811115614e485781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190614e15565b50614e54929150614fe1565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614e995782800160ff19823516178555614ec6565b82800160010185558215614ec6579182015b82811115614ec6578235825591602001919060010190614eab565b50614e54929150615000565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614f5f57805160ff1916838001178555614ec6565b82800160010185558215614ec6579182015b82811115614ec6578251825591602001919060010190614f71565b828054828255906000526020600020908101928215614e48579160200282015b82811115614e4857825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614fac565b5b80821115614e545780546001600160a01b0319168155600101614fe2565b5b80821115614e545760008155600101615001565b8035612edf81615cd2565b60008083601f840112615031578182fd5b5081356001600160401b03811115615047578182fd5b602083019150836020808302850101111561506157600080fd5b9250929050565b600082601f830112615078578081fd5b813561508b61508682615c87565b615c61565b8181529150602080830190848101818402860182018710156150ac57600080fd5b60005b848110156150d45781356150c281615cd2565b845292820192908201906001016150af565b505050505092915050565b600082601f8301126150ef578081fd5b81356150fd61508682615c87565b81815291506020808301908481018184028601820187101561511e57600080fd5b60005b848110156150d457813584529282019290820190600101615121565b600082601f83011261514d578081fd5b81356001600160401b03811115615162578182fd5b615175601f8201601f1916602001615c61565b915080825283602082850101111561518c57600080fd5b8060208401602084013760009082016020015292915050565b80516001600160801b0381168114612edf57600080fd5b6000602082840312156151cd578081fd5b8135612edc81615cd2565b6000602082840312156151e9578081fd5b8151612edc81615cd2565b600080600080600080600080610100898b031215615210578384fd5b61521a8a8a615015565b97506152298a60208b01615015565b96506152388a60408b01615015565b95506152478a60608b01615015565b94506152568a60808b01615015565b935060a08901356001600160401b0380821115615271578485fd5b61527d8c838d01615068565b945060c08b0135915080821115615292578384fd5b61529e8c838d016150df565b935060e08b01359150808211156152b3578283fd5b506152c08b828c0161513d565b9150509295985092959890939650565b600080604083850312156152e2578182fd5b82356152ed81615cd2565b946020939093013593505050565b60008060006060848603121561530f578081fd5b833561531a81615cd2565b925060208401359150604084013561533181615ce7565b809150509250925092565b6000806020838503121561534e578182fd5b82356001600160401b03811115615363578283fd5b61536f85828601615020565b90969095509350505050565b6000602080838503121561538d578182fd5b82516001600160401b038111156153a2578283fd5b8301601f810185136153b2578283fd5b80516153c061508682615c87565b81815283810190838501858402850186018910156153dc578687fd5b8694505b838510156153fe5780518352600194909401939185019185016153e0565b50979650505050505050565b60006020828403121561541b578081fd5b8135612edc81615ce7565b600060208284031215615437578081fd5b8151612edc81615ce7565b60008060208385031215615454578182fd5b82356001600160401b038082111561546a578384fd5b818501915085601f83011261547d578384fd5b81358181111561548b578485fd5b86602082850101111561549c578485fd5b60209290920196919550909350505050565b6000608082840312156154bf578081fd5b6154c96080615c61565b82516154d481615cd2565b808252506020830151602082015260408301516040820152606083015160608201528091505092915050565b600060408284031215615511578081fd5b61551b6040615c61565b61552584846151a5565b815261553484602085016151a5565b60208201529392505050565b6000610120808385031215615553578182fd5b61555c81615c61565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b6000604082840312156155cf578081fd5b6155d96040615c61565b82518152602083015160208201528091505092915050565b600060208284031215615602578081fd5b5035919050565b60006020828403121561561a578081fd5b5051919050565b60008060408385031215615633578182fd5b505080516020909101519092909150565b600080600060608486031215615658578081fd5b835161566381615cf5565b602085015190935061567481615cf5565b60408501519092506001600160801b0381168114615331578182fd5b6000815180845260208085019450808401835b838110156156bf578151875295820195908201906001016156a3565b509495945050505050565b600081518084526156e2816020860160208601615ca6565b601f01601f19169290920160200192915050565b60008251615708818460208701615ca6565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03898116825288811660208084019190915288821660408401528782166060840152868216608084015261010060a08401819052865190840181905260009261012085019288810192855b818110156157b0578451841686529482019493820193600101615792565b505050505082810360c08401526157c78186615690565b905082810360e08401526157db81856156ca565b9b9a5050505050505050505050565b6001600160a01b039390931683529015156020830152604082015260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6001600160a01b03958616815293851660208501529190931660408301526060820192909252608081019190915260a00190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b6001600160a01b0393909316835260208301919091521515604082015260600190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b600060208252612edc60208301846156ca565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b90815260200190565b9182526001600160a01b0316602082015260400190565b918252602082015260400190565b600060a082018783526020878185015260a0604085015281875480845260c0860191508885528285209350845b81811015615bec5784546001600160a01b031683526001948501949284019201615bc7565b50506001600160a01b03969096166060850152505050608001529392505050565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b6040518181016001600160401b0381118282101715615c7f57600080fd5b604052919050565b60006001600160401b03821115615c9c578081fd5b5060209081020190565b60005b83811015615cc1578181015183820152602001615ca9565b838111156136bf5750506000910152565b6001600160a01b038116811461237e57600080fd5b801515811461237e57600080fd5b6001600160401b038116811461237e57600080fdfea2646970667358221220249666e07c860f2875a5a98b68433e73d3b70707c81e2b4b5e773ea92814810364736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000da816459f1ab5631232fe5e97a05bbbb94970c95000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd64396600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000418bc3ff0ba33ad64931160a91c92fa26b35acb00000000000000000000000005f92e4300024c447a103c161614e6918e794c7640000000000000000000000000ea032decbfbea581d77d4a9b9c5e9db7c102a7c00000000000000000000000077f3a4fa35bac0ea6cfac69037ac4d3a757240a1000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010a00000000000000000000000000000000000000000000000000000000000000f60000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _vault (address): 0xdA816459F1AB5631232FE5e97a05BBBb94970c95
Arg [1] : _bentoBox (address): 0xF5BCE5077908a1b7370B9ae04AdC565EBd643966
Arg [2] : _kashiPairs (address[]): 0x418BC3ff0Ba33AD64931160A91C92fA26b35aCB0,0x5F92e4300024c447A103c161614E6918E794c764,0x0EA032DEcBfbeA581d77D4A9B9c5E9dB7C102a7c,0x77F3A4Fa35BaC0EA6CfaC69037Ac4d3a757240A1
Arg [3] : _pids (uint256[]): 194,192,266,246
Arg [4] : _strategyName (string):
-----Encoded View---------------
16 Constructor Arguments found :
Arg [0] : 000000000000000000000000da816459f1ab5631232fe5e97a05bbbb94970c95
Arg [1] : 000000000000000000000000f5bce5077908a1b7370b9ae04adc565ebd643966
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [4] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [6] : 000000000000000000000000418bc3ff0ba33ad64931160a91c92fa26b35acb0
Arg [7] : 0000000000000000000000005f92e4300024c447a103c161614e6918e794c764
Arg [8] : 0000000000000000000000000ea032decbfbea581d77d4a9b9c5e9db7c102a7c
Arg [9] : 00000000000000000000000077f3a4fa35bac0ea6cfac69037ac4d3a757240a1
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [11] : 00000000000000000000000000000000000000000000000000000000000000c2
Arg [12] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [13] : 000000000000000000000000000000000000000000000000000000000000010a
Arg [14] : 00000000000000000000000000000000000000000000000000000000000000f6
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
89890:29597:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83833:444;;;;;;:::i;:::-;;:::i;:::-;;55062:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;104310:957;;;;;;:::i;:::-;;:::i;95254:101::-;;;:::i;65435:175::-;;;;;;:::i;:::-;;:::i;61003:118::-;;;;;;:::i;:::-;;:::i;58341:28::-;;;:::i;:::-;;;;;;;:::i;57089:18::-;;;:::i;:::-;;;;;;;:::i;56998:25::-;;;:::i;68837:148::-;;;:::i;:::-;;;;;;;:::i;55461:91::-;;;:::i;57977:29::-;;;:::i;80237:515::-;;;;;;:::i;:::-;;:::i;91987:1333::-;;;;;;:::i;:::-;;:::i;105275:2651::-;;;;;;:::i;:::-;;:::i;63484:154::-;;;;;;:::i;:::-;;:::i;73934:170::-;;;:::i;78413:1580::-;;;:::i;58420:25::-;;;:::i;90767:105::-;;;:::i;103142:1160::-;;;;;;:::i;:::-;;:::i;73173:432::-;;;;;;:::i;:::-;;:::i;55118:25::-;;;:::i;111391:98::-;;;;;;:::i;:::-;;:::i;91008:25::-;;;:::i;90879:120::-;;;:::i;62241:174::-;;;;;;:::i;:::-;;:::i;65913:171::-;;;;;;:::i;:::-;;:::i;91040:33::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;119265:219::-;;;;;;:::i;:::-;;:::i;58163:27::-;;;:::i;56868:94::-;;;:::i;64709:169::-;;;;;;:::i;:::-;;:::i;57826:29::-;;;:::i;57030:22::-;;;:::i;61129:123::-;;;;;;:::i;:::-;;:::i;57059:21::-;;;:::i;111231:152::-;;;;;;:::i;:::-;;:::i;55150:26::-;;;:::i;61485:202::-;;;;;;:::i;:::-;;:::i;91512:423::-;;;;;;:::i;:::-;;:::i;81524:281::-;;;;;;:::i;:::-;;:::i;91082:32::-;;;:::i;62704:263::-;;;;;;:::i;:::-;;:::i;75871:1736::-;;;;;;:::i;:::-;;:::i;95363:664::-;;;:::i;64155:154::-;;;;;;:::i;:::-;;:::i;96035:477::-;;;;;;:::i;:::-;;:::i;56970:21::-;;;:::i;82234:173::-;;;:::i;83833:444::-;59046:12;:10;:12::i;:::-;-1:-1:-1;;;;;59032:26:0;:10;-1:-1:-1;;;;;59032:26:0;;59024:50;;;;-1:-1:-1;;;59024:50:0;;;;;;;:::i;:::-;;;;;;;;;83925:4:::1;::::0;-1:-1:-1;;;;;83907:23:0;;::::1;83925:4:::0;::::1;83907:23;;83899:41;;;;-1:-1:-1::0;;;83899:41:0::1;;;;;;;:::i;:::-;83977:5;::::0;-1:-1:-1;;;;;83959:24:0;;::::1;83977:5:::0;::::1;83959:24;;83951:44;;;;-1:-1:-1::0;;;83951:44:0::1;;;;;;;:::i;:::-;84008:33;84044:17;:15;:17::i;:::-;84008:53;;84077:9;84072:102;84092:16;:23;84088:1;:27;84072:102;;;84140:16;84157:1;84140:19;;;;;;;;;;;;;;-1:-1:-1::0;;;;;84130:29:0::1;:6;-1:-1:-1::0;;;;;84130:29:0::1;;;84122:52;;;;-1:-1:-1::0;;;84122:52:0::1;;;;;;;:::i;:::-;84117:3;;84072:102;;;;84187:82;84215:12;:10;:12::i;:::-;84229:39;::::0;-1:-1:-1;;;84229:39:0;;-1:-1:-1;;;;;84229:24:0;::::1;::::0;::::1;::::0;:39:::1;::::0;84262:4:::1;::::0;84229:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;84187:27:0;::::1;::::0;:82;:27:::1;:82::i;:::-;59085:1;83833:444:::0;:::o;55062:25::-;;;;;;;;;;;;;;;-1:-1:-1;;55062:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;104310:957::-;58697:10;;-1:-1:-1;;;;;58697:10:0;58683;:24;;:54;;;58725:12;:10;:12::i;:::-;-1:-1:-1;;;;;58711:26:0;:10;-1:-1:-1;;;;;58711:26:0;;58683:54;:88;;;;58755:5;;;;;;;;;-1:-1:-1;;;;;58755:5:0;-1:-1:-1;;;;;58755:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;58741:30:0;:10;-1:-1:-1;;;;;58741:30:0;;58683:88;:124;;;;58789:5;;;;;;;;;-1:-1:-1;;;;;58789:5:0;-1:-1:-1;;;;;58789:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;58775:32:0;:10;-1:-1:-1;;;;;58775:32:0;;58683:124;58661:185;;;;-1:-1:-1;;;58661:185:0;;;;;;;:::i;:::-;104468:34:::1;;:::i;:::-;104505:10;104516:9;104505:21;;;;;;;;;::::0;;;::::1;::::0;;;;104468:58:::1;::::0;;;;::::1;::::0;;;104505:21:::1;::::0;;::::1;;104468:58:::0;;-1:-1:-1;;;;;104468:58:0;;::::1;::::0;;;;;;::::1;::::0;;;::::1;::::0;;;;;;-1:-1:-1;104547:49:0;;::::1;;104539:58;;;::::0;::::1;;104610:147;104643:13;:23;;;104681:13;:17;;;-1:-1:-1::0;;104610:18:0::1;:147::i;:::-;;104775:6;104770:271;;105001:13;;104874:123;104915:13;:23;;;104961:13;:17;;;104874:18;:123::i;:::-;:140;;104848:181;;;::::0;::::1;;105057:17;::::0;::::1;::::0;:22;105053:112:::1;;105096:57;-1:-1:-1::0;;;;;105096:33:0;::::1;90829:42;105151:1;105096:33;:57::i;:::-;105199:10;105210:17:::0;;-1:-1:-1;;105210:21:0;;;105199:33;::::1;;;;;;;;;;;;;;;105175:10;105186:9;105175:21;;;;;;;;;::::0;;;::::1;::::0;;;:57;;:21:::1;::::0;;::::1;;:57:::0;;-1:-1:-1;;;;;;105175:57:0::1;-1:-1:-1::0;;;;;105175:57:0;;::::1;::::0;;;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;105243:10:::1;:16:::0;;;::::1;;;;;::::0;;;::::1;::::0;;::::1;-1:-1:-1::0;;105243:16:0;;;;;::::1;;::::0;;-1:-1:-1;;;;;;105243:16:0::1;::::0;;::::1;;::::0;;;-1:-1:-1;;;;104310:957:0:o;95254:101::-;95335:12;95328:19;;;;;;;;-1:-1:-1;;95328:19:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95302:13;;95328:19;;95335:12;;95328:19;;95335:12;95328:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95254:101;:::o;65435:175::-;58531:10;;-1:-1:-1;;;;;58531:10:0;58517;:24;;:54;;;58559:12;:10;:12::i;:::-;-1:-1:-1;;;;;58545:26:0;:10;-1:-1:-1;;;;;58545:26:0;;58517:54;58509:78;;;;-1:-1:-1;;;58509:78:0;;;;;;;:::i;:::-;65520:13:::1;:30:::0;;;65566:36:::1;::::0;::::1;::::0;::::1;::::0;65536:14;;65566:36:::1;:::i;:::-;;;;;;;;65435:175:::0;:::o;61003:118::-;59503:5;;;;;;;;;-1:-1:-1;;;;;59503:5:0;-1:-1:-1;;;;;59503:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;59489:32:0;:10;-1:-1:-1;;;;;59489:32:0;;:62;;;;59539:12;:10;:12::i;:::-;-1:-1:-1;;;;;59525:26:0;:10;-1:-1:-1;;;;;59525:26:0;;59489:62;59481:86;;;;-1:-1:-1;;;59481:86:0;;;;;;;:::i;:::-;61087:11:::1;:26:::0;;-1:-1:-1;;;;;61087:26:0;;::::1;;;-1:-1:-1::0;;;;;;61087:26:0;;::::1;::::0;;;::::1;::::0;;61003:118::o;58341:28::-;;;;:::o;57089:18::-;;;-1:-1:-1;;;;;57089:18:0;;:::o;56998:25::-;;;-1:-1:-1;;;;;56998:25:0;;:::o;68837:148::-;68902:5;;:31;;-1:-1:-1;;;68902:31:0;;68878:4;;;;-1:-1:-1;;;;;68902:5:0;;;;:16;;:31;;68927:4;;68902:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;:45;:75;;;;68976:1;68951:22;:20;:22::i;:::-;:26;68902:75;68895:82;;68837:148;:::o;55461:91::-;55530:14;;;;;;;;;;;;-1:-1:-1;;;55530:14:0;;;;55461:91;:::o;57977:29::-;;;;:::o;80237:515::-;80352:5;;80296:13;;-1:-1:-1;;;;;80352:5:0;80330:10;:28;80322:47;;;;-1:-1:-1;;;80322:47:0;;;;;;;:::i;:::-;80455:19;80508:32;80526:13;80508:17;:32::i;:::-;80632:4;;80485:55;;-1:-1:-1;80485:55:0;;-1:-1:-1;80632:42:0;;-1:-1:-1;;;;;80632:4:0;80650:10;80485:55;80632:17;:42::i;:::-;80237:515;;;;:::o;91987:1333::-;92324:10;;92284:19;;92324:10;;;;;92316:19;;;;;;92592:4;92586:11;-1:-1:-1;;;92611:135:0;;92493:4;92477:22;;92783:4;92767:21;;92760:43;;;-1:-1:-1;;;92858:4:0;92842:21;;92817:146;92477:22;93014:4;92586:11;92454:20;92992:27;93042:233;;-1:-1:-1;;;93042:233:0;;92977:42;;-1:-1:-1;;;;;;93042:32:0;;;-1:-1:-1;93042:32:0;;:233;;93089:6;;93110:11;;93136:8;;93159:7;;93181:9;;93205:11;;93231:5;;93251:13;;93042:233;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;93293:19:0;;-1:-1:-1;;;;;93293:19:0;;;-1:-1:-1;93293:19:0;;-1:-1:-1;93293:19:0;;;91987:1333;;;;;;;;;;;:::o;105275:2651::-;58531:10;;-1:-1:-1;;;;;58531:10:0;58517;:24;;:54;;;58559:12;:10;:12::i;:::-;-1:-1:-1;;;;;58545:26:0;:10;-1:-1:-1;;;;;58545:26:0;;58517:54;58509:78;;;;-1:-1:-1;;;58509:78:0;;;;;;;:::i;:::-;105474:10:::1;:17:::0;105456:35;::::1;105448:44;;;::::0;::::1;;105505:18;::::0;105536:242:::1;105560:10;:17:::0;105556:21;::::1;105536:242;;;105688:39;105703:10;105714:1;105703:13;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;;::::1;;:23:::0;-1:-1:-1;;;;;105703:23:0::1;105688:14;:39::i;:::-;105756:7;;105764:1;105756:10;;;;;;;;;::::0;;;::::1;;105742:24:::0;;;::::1;::::0;-1:-1:-1;105579:3:0::1;;105536:242;;;;90278:3;105798:10;:21;105790:30;;;::::0;::::1;;105864:19;105886:15;:13;:15::i;:::-;105864:37;;105930:13;;105916:11;:27;105912:87;;;105960:27;105975:11;105960:14;:27::i;:::-;;;105912:87;106011:19;106033:22;:20;:22::i;:::-;106142:10;:17:::0;106011:44;;-1:-1:-1;106066:46:0::1;::::0;-1:-1:-1;;;;;106128:32:0;::::1;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;106128:32:0::1;;106066:94;;106178:9;106173:1111;106197:10;:17:::0;106193:21;::::1;106173:1111;;;106236:34;;:::i;:::-;106273:10;106284:1;106273:13;;;;;;;;;::::0;;;::::1;::::0;;;106236:50:::1;::::0;;;;::::1;::::0;;;106273:13:::1;::::0;;::::1;;106236:50:::0;;-1:-1:-1;;;;;106236:50:0::1;::::0;;;;;;::::1;::::0;;;::::1;::::0;;;;;-1:-1:-1;106346:332:0::1;::::0;106386:273:::1;::::0;106489:147:::1;::::0;106236:50;;106489:18:::1;:147::i;:::-;106386:26;:273::i;:::-;106346:17;:332::i;:::-;106303:375;;106693:20;90278:3;106730:11;106717:7;;106725:1;106717:10;;;;;;;;;;;;;:24;106716:36;;;;;;106693:59;;106786:15;106771:12;:30;106767:506;;;106822:19;106844:33;:15:::0;106864:12;106844:19:::1;:33::i;:::-;106822:55;;106896:176;106937:13;:23;;;106983:13;:17;;;107023:30;107041:11;107023:17;:30::i;:::-;106896:18;:176::i;:::-;;106767:506;;;;107113:15;107098:12;:30;107094:179;;;107184:73;:12:::0;107223:15;107184:16:::1;:73::i;:::-;107149:29;107179:1;107149:32;;;;;;;;;;;;;:108;;;::::0;::::1;107094:179;-1:-1:-1::0;;;106216:3:0::1;;106173:1111;;;;107301:9;107296:623;107320:10;:17:::0;107316:21;::::1;107296:623;;;107363:29;107393:1;107363:32;;;;;;;;;;;;;;107399:1;107363:37;107359:51;;;107402:8;;107359:51;107427:34;;:::i;:::-;107464:10;107475:1;107464:13;;;;;;;;;::::0;;;::::1;::::0;;;107427:50:::1;::::0;;;;::::1;::::0;;;107464:13:::1;::::0;;::::1;;107427:50:::0;;-1:-1:-1;;;;;107427:50:0::1;::::0;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;107518:15:0::1;:13;:15::i;:::-;107494:39;;107548:19;107587:51;107605:29;107635:1;107605:32;;;;;;;;;;;;;;107587:17;:51::i;:::-;107548:90;;107673:13;107659:11;:27;107655:95;;;-1:-1:-1::0;107721:13:0;107655:95:::1;107766:141;107803:13;:23;;;107845:13;:17;;;107881:11;107766:18;:141::i;:::-;107296:623;;;;107339:3;;107296:623;;;;58598:1;;;;105275:2651:::0;;:::o;63484:154::-;58531:10;;-1:-1:-1;;;;;58531:10:0;58517;:24;;:54;;;58559:12;:10;:12::i;:::-;-1:-1:-1;;;;;58545:26:0;:10;-1:-1:-1;;;;;58545:26:0;;58517:54;58509:78;;;;-1:-1:-1;;;58509:78:0;;;;;;;:::i;:::-;63562:14:::1;:23:::0;;;63601:29:::1;::::0;::::1;::::0;::::1;::::0;63579:6;;63601:29:::1;:::i;73934:170::-:0;59172:6;;-1:-1:-1;;;;;59172:6:0;59158:10;:20;;:65;;-1:-1:-1;59213:10:0;;-1:-1:-1;;;;;59213:10:0;59199;:24;59158:65;:112;;;;59258:12;:10;:12::i;:::-;-1:-1:-1;;;;;59244:26:0;:10;-1:-1:-1;;;;;59244:26:0;;59158:112;:163;;;;59305:5;;;;;;;;;-1:-1:-1;;;;;59305:5:0;-1:-1:-1;;;;;59305:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;59291:30:0;:10;-1:-1:-1;;;;;59291:30:0;;59158:163;:216;;;;59356:5;;;;;;;;;-1:-1:-1;;;;;59356:5:0;-1:-1:-1;;;;;59356:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;59342:32:0;:10;-1:-1:-1;;;;;59342:32:0;;59158:216;59136:277;;;;-1:-1:-1;;;59136:277:0;;;;;;;:::i;:::-;74072:5:::1;::::0;:23:::1;::::0;;-1:-1:-1;;;74072:23:0;;;;74057:39:::1;::::0;-1:-1:-1;;;;;74072:5:0::1;::::0;:21:::1;::::0;:23:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:5;:23;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74057:14;:39::i;:::-;73934:170::o:0;78413:1580::-;59172:6;;-1:-1:-1;;;;;59172:6:0;59158:10;:20;;:65;;-1:-1:-1;59213:10:0;;-1:-1:-1;;;;;59213:10:0;59199;:24;59158:65;:112;;;;59258:12;:10;:12::i;:::-;-1:-1:-1;;;;;59244:26:0;:10;-1:-1:-1;;;;;59244:26:0;;59158:112;:163;;;;59305:5;;;;;;;;;-1:-1:-1;;;;;59305:5:0;-1:-1:-1;;;;;59305:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;59291:30:0;:10;-1:-1:-1;;;;;59291:30:0;;59158:163;:216;;;;59356:5;;;;;;;;;-1:-1:-1;;;;;59356:5:0;-1:-1:-1;;;;;59356:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;59342:32:0;:10;-1:-1:-1;;;;;59342:32:0;;59158:216;59136:277;;;;-1:-1:-1;;;59136:277:0;;;;;;;:::i;:::-;78464:14:::1;78493:12:::0;78520:23:::1;78546:5;;;;;;;;;-1:-1:-1::0;;;;;78546:5:0::1;-1:-1:-1::0;;;;;78546:21:0::1;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78618:13;::::0;78520:49;;-1:-1:-1;78580:19:0::1;::::0;78618:13:::1;;78614:580;;;78700:19;78722:23;:21;:23::i;:::-;78700:45;;78778:15;78764:11;:29;78760:226;;;78821:32;:15:::0;78841:11;78821:19:::1;:32::i;:::-;78814:39;;78760:226;;;78893:15;78879:11;:29;78875:111;;;78938:32;:11:::0;78954:15;78938::::1;:32::i;:::-;78929:41;;78875:111;79014:25;:15:::0;79034:4;79014:19:::1;:25::i;:::-;79000:39;;78614:580;;;;79152:30;79166:15;79152:13;:30::i;:::-;79122:60:::0;;-1:-1:-1;79122:60:0;-1:-1:-1;79122:60:0;-1:-1:-1;78614:580:0::1;79410:5;::::0;:31:::1;::::0;-1:-1:-1;;;79410:31:0;;79390:17:::1;::::0;-1:-1:-1;;;;;79410:5:0::1;::::0;:16:::1;::::0;:31:::1;::::0;79435:4:::1;::::0;79410:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;::::0;79480:5:::1;::::0;:39:::1;::::0;-1:-1:-1;;;79480:39:0;;79410:41;;-1:-1:-1;;;;;;79480:5:0::1;::::0;:12:::1;::::0;:39:::1;::::0;79493:6;;79501:4;;79507:11;;79480:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;79462:57;;79595:31;79610:15;79595:14;:31::i;:::-;79681:13;::::0;::::1;;:42:::0;::::1;;;-1:-1:-1::0;79698:11:0::1;::::0;::::1;::::0;::::1;-1:-1:-1::0;;;;;79698:11:0::1;:25:::0;::::1;79681:42;79677:238;;;79760:11;::::0;79748:85:::1;::::0;-1:-1:-1;;;79748:85:0;;79760:11:::1;::::0;;::::1;-1:-1:-1::0;;;;;79760:11:0::1;::::0;79748:30:::1;::::0;:85:::1;::::0;79779:6;;79787:4;;79793:11;;79806:15;;79823:9;;79748:85:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;79740:110;;;;-1:-1:-1::0;;;79740:110:0::1;;;;;;;:::i;:::-;79677:238;;;79899:4;79883:20:::0;;-1:-1:-1;;79883:20:0::1;::::0;::::1;::::0;;79677:238:::1;79932:53;79942:6;79950:4;79956:11;79969:15;79932:53;;;;;;;;;:::i;:::-;;;;;;;;59424:1;;;;;78413:1580::o:0;58420:25::-;;;;;;:::o;90767:105::-;90829:42;90767:105;:::o;103142:1160::-;59046:12;:10;:12::i;:::-;-1:-1:-1;;;;;59032:26:0;:10;-1:-1:-1;;;;;59032:26:0;;59024:50;;;;-1:-1:-1;;;59024:50:0;;;;;;;:::i;:::-;103312:10:::1;:17:::0;90234:1:::1;-1:-1:-1::0;103304:38:0::1;;;::::0;::::1;;103474:8;;;;;;;;;-1:-1:-1::0;;;;;103474:8:0::1;-1:-1:-1::0;;;;;103417:66:0::1;103436:13;-1:-1:-1::0;;;;;103425:34:0::1;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;103417:66:0::1;;103395:99;;;::::0;::::1;;103609:4;::::0;103556:33:::1;::::0;;-1:-1:-1;;;103556:33:0;;;;-1:-1:-1;;;;;103609:4:0;;::::1;::::0;103556:31;::::1;::::0;::::1;::::0;:33:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:31;:33;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;103556:59:0::1;;103548:68;;;::::0;::::1;;103631:12:::0;;103627:210:::1;;103756:28;::::0;-1:-1:-1;;;103756:28:0;;-1:-1:-1;;;;;103748:62:0;::::1;::::0;90829:42:::1;::::0;103756:19:::1;::::0;:28:::1;::::0;103776:7;;103756:28:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:36:::0;-1:-1:-1;;;;;103748:62:0::1;;103722:103;;;::::0;::::1;;103854:9;103849:188;103873:10;:17:::0;103869:21;::::1;103849:188;;;104000:10;104011:1;104000:13;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;;::::1;;:23:::0;-1:-1:-1;;;;;103975:49:0;;::::1;104000:23:::0;::::1;103975:49;;103967:58;;;::::0;::::1;;103892:3;;103849:188;;;-1:-1:-1::0;104065:49:0::1;::::0;;;;::::1;::::0;;;-1:-1:-1;;;;;104065:49:0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;104049:10:::1;:66:::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;104049:66:0;;;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;-1:-1:-1;;;;;;104049:66:0::1;::::0;;;::::1;;::::0;;;;;;;;;104132:12;;104128:167:::1;;104161:122;-1:-1:-1::0;;;;;104161:33:0;::::1;90829:42;-1:-1:-1::0;;104161:33:0::1;:122::i;73173:432::-:0;73246:4;73173:432;;;;:::o;55118:25::-;;;;;;:::o;111391:98::-;59046:12;:10;:12::i;:::-;-1:-1:-1;;;;;59032:26:0;:10;-1:-1:-1;;;;;59032:26:0;;59024:50;;;;-1:-1:-1;;;59024:50:0;;;;;;;:::i;:::-;111469:12:::1;:4;111476:5:::0;;111469:12:::1;:::i;:::-;;111391:98:::0;;:::o;91008:25::-;;;;;;-1:-1:-1;;;;;91008:25:0;;:::o;90879:120::-;90956:42;90879:120;:::o;62241:174::-;58531:10;;-1:-1:-1;;;;;58531:10:0;58517;:24;;:54;;;58559:12;:10;:12::i;:::-;-1:-1:-1;;;;;58545:26:0;:10;-1:-1:-1;;;;;58545:26:0;;58517:54;58509:78;;;;-1:-1:-1;;;58509:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;62320:21:0;::::1;62312:30;;;::::0;::::1;;62353:6;:16:::0;;-1:-1:-1;;;;;;62353:16:0::1;-1:-1:-1::0;;;;;62353:16:0;::::1;;::::0;;62385:22:::1;::::0;::::1;::::0;::::1;::::0;62353:16;;62385:22:::1;:::i;65913:171::-:0;58531:10;;-1:-1:-1;;;;;58531:10:0;58517;:24;;:54;;;58559:12;:10;:12::i;:::-;-1:-1:-1;;;;;58545:26:0;:10;-1:-1:-1;;;;;58545:26:0;;58517:54;58509:78;;;;-1:-1:-1;;;58509:78:0;;;;;;;:::i;:::-;66002:26:::1;:11;66016:12:::0;;66002:26:::1;:::i;:::-;;66044:32;66063:12;;66044:32;;;;;;;:::i;:::-;;;;;;;;65913:171:::0;;:::o;91040:33::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;91040:33:0;;;;-1:-1:-1;91040:33:0;:::o;119265:219::-;119467:9;119265:219::o;58163:27::-;;;;:::o;56868:94::-;56926:7;56868:94;:::o;64709:169::-;58531:10;;-1:-1:-1;;;;;58531:10:0;58517;:24;;:54;;;58559:12;:10;:12::i;:::-;-1:-1:-1;;;;;58545:26:0;:10;-1:-1:-1;;;;;58545:26:0;;58517:54;58509:78;;;;-1:-1:-1;;;58509:78:0;;;;;;;:::i;:::-;64792:12:::1;:28:::0;;;64836:34:::1;::::0;::::1;::::0;::::1;::::0;64807:13;;64836:34:::1;:::i;57826:29::-:0;;;;:::o;57030:22::-;;;-1:-1:-1;;;;;57030:22:0;;:::o;61129:123::-;59503:5;;;;;;;;;-1:-1:-1;;;;;59503:5:0;-1:-1:-1;;;;;59503:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;59489:32:0;:10;-1:-1:-1;;;;;59489:32:0;;:62;;;;59539:12;:10;:12::i;:::-;-1:-1:-1;;;;;59525:26:0;:10;-1:-1:-1;;;;;59525:26:0;;59489:62;59481:86;;;;-1:-1:-1;;;59481:86:0;;;;;;;:::i;:::-;61214:13:::1;:30:::0;;-1:-1:-1;;61214:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;61129:123::o;57059:21::-;;;-1:-1:-1;;;;;57059:21:0;;:::o;111231:152::-;58531:10;;-1:-1:-1;;;;;58531:10:0;58517;:24;;:54;;;58559:12;:10;:12::i;:::-;-1:-1:-1;;;;;58545:26:0;:10;-1:-1:-1;;;;;58545:26:0;;58517:54;58509:78;;;;-1:-1:-1;;;58509:78:0;;;;;;;:::i;:::-;111342:13:::1;:33:::0;111231:152::o;55150:26::-;;;;;;-1:-1:-1;;;;;55150:26:0;;:::o;61485:202::-;58531:10;;-1:-1:-1;;;;;58531:10:0;58517;:24;;:54;;;58559:12;:10;:12::i;:::-;-1:-1:-1;;;;;58545:26:0;:10;-1:-1:-1;;;;;58545:26:0;;58517:54;58509:78;;;;-1:-1:-1;;;58509:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;61572:25:0;::::1;61564:34;;;::::0;::::1;;61609:10;:24:::0;;-1:-1:-1;;;;;;61609:24:0::1;-1:-1:-1::0;;;;;61609:24:0;::::1;;::::0;;61649:30:::1;::::0;::::1;::::0;::::1;::::0;61609:24;;61649:30:::1;:::i;91512:423::-:0;91803:51;91815:6;91823:11;91836:8;91846:7;91803:11;:51::i;:::-;91865:62;91882:9;91893:11;91906:5;91913:13;91865:16;:62::i;:::-;91512:423;;;;;;;;:::o;81524:281::-;81613:5;;-1:-1:-1;;;;;81613:5:0;81591:10;:28;81583:37;;;;;;81677:5;;81639:34;;;-1:-1:-1;;;81639:34:0;;;;-1:-1:-1;;;;;81677:5:0;;;;81639:32;;;;;:34;;;;;;;;;;;;;;:32;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;81639:43:0;;81631:52;;;;;;81694:30;81711:12;81694:16;:30::i;:::-;81767:4;;:29;;-1:-1:-1;;;81767:29:0;;81735:62;;81753:12;;-1:-1:-1;;;;;81767:4:0;;;;:14;;:29;;81790:4;;81767:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81735:4;;-1:-1:-1;;;;;81735:4:0;;:62;:17;:62::i;:::-;81524:281;:::o;91082:32::-;;;;:::o;62704:263::-;58933:10;;-1:-1:-1;;;;;58933:10:0;58919;:24;58911:48;;;;-1:-1:-1;;;58911:48:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;62785:22:0;::::1;62777:31;;;::::0;::::1;;62819:5;::::0;62833:7:::1;::::0;;62819:25:::1;::::0;-1:-1:-1;;;62819:25:0;;-1:-1:-1;;;;;62819:5:0;;::::1;::::0;:13:::1;::::0;:25:::1;::::0;62833:7;;::::1;::::0;62819:5:::1;::::0;:25:::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;62855:7:0::1;:18:::0;;-1:-1:-1;;;;;;62855:18:0::1;-1:-1:-1::0;;;;;62855:18:0;;::::1;::::0;;;::::1;::::0;;;62884:5:::1;::::0;:35:::1;::::0;-1:-1:-1;;;62884:35:0;;:5;;::::1;::::0;:13:::1;::::0;:35:::1;::::0;62898:7:::1;::::0;-1:-1:-1;;62915:2:0;62884:35:::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;62935:24;62950:8;62935:24;;;;;;:::i;75871:1736::-:0;75947:4;75964:16;75983:24;75993:13;75983:9;:24::i;:::-;75964:43;;76018:28;;:::i;:::-;76049:5;;:31;;-1:-1:-1;;;76049:31:0;;-1:-1:-1;;;;;76049:5:0;;;;:16;;:31;;76074:4;;76049:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;76018:62;;76157:6;:17;;;76178:1;76157:22;76153:40;;;76188:5;76181:12;;;;;;76153:40;76338:14;;76317:17;;;;76297:38;;:15;;:19;:38::i;:::-;:55;76293:73;;;76361:5;76354:12;;;;;;76293:73;76485:14;;76463:17;;;;76443:38;;:15;;:19;:38::i;:::-;:56;76439:73;;76508:4;76501:11;;;;;;76439:73;76942:5;;:23;;;-1:-1:-1;;;76942:23:0;;;;76920:19;;-1:-1:-1;;;;;76942:5:0;;:21;;:23;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;76920:45;;76994:13;;76980:11;:27;76976:44;;;77016:4;77009:11;;;;;;;76976:44;77074:13;77090:22;:20;:22::i;:::-;77074:38;;77202:6;:16;;;77175:24;77185:13;;77175:5;:9;;:24;;;;:::i;:::-;:43;77171:60;;;77227:4;77220:11;;;;;;;;77171:60;77244:14;77285:6;:16;;;77277:5;:24;77273:66;;;77322:16;;;;77312:27;;:5;;:9;:27::i;:::-;77303:36;;77273:66;77509:5;;:23;;;-1:-1:-1;;;77509:23:0;;;;77492:14;;-1:-1:-1;;;;;77509:5:0;;:21;;:23;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77492:40;-1:-1:-1;77580:18:0;77492:40;77591:6;77580:10;:18::i;:::-;77551:12;;:26;;77568:8;77551:16;:26::i;:::-;:47;;75871:1736;-1:-1:-1;;;;;;;;75871:1736:0:o;95363:664::-;95425:7;95445:19;95467:15;:13;:15::i;:::-;95445:37;;95500:9;95495:454;95519:10;:17;95515:21;;95495:454;;;95558:34;;:::i;:::-;95595:10;95606:1;95595:13;;;;;;;;;;;;;;;;;95558:50;;;;;;;;;95595:13;;;;;95558:50;;-1:-1:-1;;;;;95558:50:0;;;;;;;;;;;;;;;;;-1:-1:-1;95639:298:0;;95673:249;;95558:50;95768:135;;95558:50;;95768:18;:135::i;95673:249::-;95639:11;;:15;:298::i;:::-;95625:312;-1:-1:-1;;95538:3:0;;95495:454;;;;95968:51;95988:30;96006:11;95988:17;:30::i;:::-;95968:15;:13;:15::i;:::-;:19;;:51::i;:::-;95961:58;;;95363:664;:::o;64155:154::-;58531:10;;-1:-1:-1;;;;;58531:10:0;58517;:24;;:54;;;58559:12;:10;:12::i;:::-;-1:-1:-1;;;;;58545:26:0;:10;-1:-1:-1;;;;;58545:26:0;;58517:54;58509:78;;;;-1:-1:-1;;;58509:78:0;;;;;;;:::i;:::-;64233:14:::1;:23:::0;;;64272:29:::1;::::0;::::1;::::0;::::1;::::0;64250:6;;64272:29:::1;:::i;96035:477::-:0;96101:7;96121:34;;:::i;:::-;96158:10;96169:1;96158:13;;;;;;;;;;;;;;;;;96121:50;;;;;;;;;96158:13;;;;;96121:50;;-1:-1:-1;;;;;96121:50:0;;;;;;;;;;;;;;;;;-1:-1:-1;96204:300:0;;96240:249;;96121:50;96335:135;;96121:50;;96335:18;:135::i;96204:300::-;96184:320;96035:477;-1:-1:-1;;;96035:477:0:o;56970:21::-;;;-1:-1:-1;;;;;56970:21:0;;:::o;82234:173::-;58697:10;;-1:-1:-1;;;;;58697:10:0;58683;:24;;:54;;;58725:12;:10;:12::i;:::-;-1:-1:-1;;;;;58711:26:0;:10;-1:-1:-1;;;;;58711:26:0;;58683:54;:88;;;;58755:5;;;;;;;;;-1:-1:-1;;;;;58755:5:0;-1:-1:-1;;;;;58755:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;58741:30:0;:10;-1:-1:-1;;;;;58741:30:0;;58683:88;:124;;;;58789:5;;;;;;;;;-1:-1:-1;;;;;58789:5:0;-1:-1:-1;;;;;58789:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;58775:32:0;:10;-1:-1:-1;;;;;58775:32:0;;58683:124;58661:185;;;;-1:-1:-1;;;58661:185:0;;;;;;;:::i;:::-;82306:13:::1;:20:::0;;-1:-1:-1;;82306:20:0::1;82322:4;82306:20;::::0;;82337:5:::1;::::0;:22:::1;::::0;;-1:-1:-1;;;82337:22:0;;;;-1:-1:-1;;;;;82337:5:0;;::::1;::::0;:20:::1;::::0;:22:::1;::::0;;::::1;::::0;82306:13:::1;::::0;82337:22;;;;;;;;82306:13;82337:5;:22;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;82377:22:0::1;::::0;::::1;::::0;-1:-1:-1;82377:22:0;;-1:-1:-1;82377:22:0::1;82234:173::o:0;32486:622::-;32856:10;;;32855:62;;-1:-1:-1;32872:39:0;;-1:-1:-1;;;32872:39:0;;-1:-1:-1;;;;;32872:15:0;;;;;:39;;32896:4;;32903:7;;32872:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;32855:62;32847:152;;;;-1:-1:-1;;;32847:152:0;;;;;;;:::i;:::-;33010:90;33030:5;33060:22;;;33084:7;33093:5;33037:62;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;33037:62:0;;;;;;;;;;;;;;-1:-1:-1;;;;;33037:62:0;-1:-1:-1;;;;;;33037:62:0;;;;;;;;;;33010:19;:90::i;16040:196::-;16143:12;16175:53;16198:6;16206:4;16212:1;16215:12;16175:22;:53::i;:::-;16168:60;16040:196;-1:-1:-1;;;;16040:196:0:o;66238:98::-;66310:5;;:18;;;-1:-1:-1;;;66310:18:0;;;;66283:7;;-1:-1:-1;;;;;66310:5:0;;:16;;:18;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;119137:120::-;119232:16;119137:120;:::o;31827:177::-;31910:86;31930:5;31960:23;;;31985:2;31989:5;31937:58;;;;;;;;;:::i;109153:1472::-;109290:24;109398:25;109413:9;109398:14;:25::i;:::-;109436:20;109459:32;109481:9;109459:21;:32::i;:::-;109436:55;;109521:12;109506;:27;109502:87;;;109565:12;109550:27;;109502:87;109605:17;109601:31;;109631:1;109624:8;;;;;109601:31;109645:23;109684:51;109711:9;109722:12;109684:26;:51::i;:::-;109645:90;-1:-1:-1;109814:8:0;;109810:363;;109839:20;109862:29;109887:3;109862:24;:29::i;:::-;109998:13;;109839:52;;-1:-1:-1;109938:15:0;;109839:52;;109972:40;;109938:15;;109972:25;:40::i;:::-;:55;109968:132;;;-1:-1:-1;110072:12:0;109968:132;110114:47;;-1:-1:-1;;;110114:47:0;;90829:42;;110114:19;;:47;;110134:3;;110139:21;;110114:47;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109810:363;;;110185:23;110211:30;110231:9;110211:19;:30::i;:::-;110185:56;;110295:15;110258:34;110278:13;;110258:15;:19;;:34;;;;:::i;:::-;:52;110254:118;;;110345:15;110327:33;;110254:118;110403:90;;-1:-1:-1;;;110403:90:0;;-1:-1:-1;;;;;110403:21:0;;;;;:90;;110447:4;;110467:15;;110403:90;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;110384:109;;110577:40;110602:9;110613:3;110577:24;:40::i;:::-;109153:1472;;;;;;;;:::o;111887:231::-;112000:7;112045:65;112079:30;112099:9;112079:19;:30::i;:::-;112045:29;112070:3;112045:24;:29::i;:65::-;112025:85;;111887:231;;;;;:::o;98980:3281::-;99084:25;99111:13;99142:19;99164:15;:13;:15::i;:::-;99142:37;;99213:11;99196:13;:28;99192:86;;99249:13;99264:1;99241:25;;;;;;;99192:86;99290:20;99313:30;:13;99331:11;99313:17;:30::i;:::-;99290:53;;99354:17;99374:39;99401:11;99374:22;:20;:22::i;:::-;:26;;:39::i;:::-;99354:59;;99464:9;99430:31;99447:13;;99430:12;:16;;:31;;;;:::i;:::-;:43;99426:100;;;99505:9;99490:24;;99426:100;99542:16;;99538:2262;;99575:20;99598:31;99616:12;99598:17;:31::i;:::-;99575:54;;99644:19;99666:15;:13;:15::i;:::-;99644:37;;99717:11;99702:12;:26;99698:1883;;;99749:29;99781;:12;99798:11;99781:16;:29::i;:::-;99749:61;;99829:28;100048:21;100071:17;100113:314;100158:246;100197:21;100249:128;100301:45;100328:10;:17;;;;100301:22;:20;:22::i;:::-;:26;;:45::i;:::-;100249:17;:128::i;:::-;100158:8;:246::i;:::-;100113:18;:314::i;:::-;100047:380;;-1:-1:-1;100047:380:0;-1:-1:-1;;;;;;100450:33:0;;;100446:267;;100531:162;100576:10;100613:9;100649:21;100531:18;:162::i;:::-;100508:185;;100446:267;100760:9;100733:833;100800:10;:17;100796:21;;:138;;;;;100913:21;100846:39;100871:13;;100846:20;:24;;:39;;;;:::i;:::-;:88;100796:138;100733:833;;;101003:34;;:::i;:::-;101040:10;101051:1;101040:13;;;;;;;;;;;;;;;;;101003:50;;;;;;;;;101040:13;;;;;101003:50;;-1:-1:-1;;;;;101003:50:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;101082:55:0;;;;101078:94;;;101164:8;;;101078:94;101347:23;;101401:17;;;;101247:299;;101298:225;;101449:47;:21;101475:20;101449:25;:47::i;101298:225::-;101247:20;;:24;:299::i;:::-;101224:322;;100733:833;;100957:3;;100733:833;;;;99698:1883;;;;;101597:8;;101649:4;;-1:-1:-1;;;;;101597:8:0;;;;;;;:17;;101649:4;101682;;101649;101758:15;:13;:15::i;:::-;101597:191;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;99538:2262;;;101832:40;101841:15;:13;:15::i;:::-;101858:13;101832:8;:40::i;:::-;101812:60;;102073:13;102053:17;:33;102049:205;;;102103:12;102118:36;:13;102136:17;102118;:36::i;:::-;102103:51;;102181:13;;102173:4;:21;102169:74;;102223:4;102215:12;;102169:74;102049:205;;98980:3281;;;;;;;:::o;110981:242::-;111050:19;111075:9;-1:-1:-1;;;;;111075:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;111047:50;-1:-1:-1;;;;;111047:50:0;;;;111158:11;111140:15;:29;111136:80;;;111186:9;-1:-1:-1;;;;;111186:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110981:242;;:::o;111497:112::-;111572:4;;:29;;-1:-1:-1;;;111572:29:0;;111545:7;;-1:-1:-1;;;;;111572:4:0;;:14;;:29;;111595:4;;111572:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;108566:352::-;108722:8;;108773:4;;108722:188;;-1:-1:-1;;;108722:188:0;;108649:17;;;;-1:-1:-1;;;;;108722:8:0;;;;;;;:16;;:188;;108773:4;;108806;;;;108862:13;;108649:17;;108722:188;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;108702:208;;;;108566:352;;;:::o;118480:649::-;118610:19;118790:24;;:::i;:::-;118817:9;-1:-1:-1;;;;;118817:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118790:49;;118850:25;;:::i;:::-;118878:9;-1:-1:-1;;;;;118878:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118850:51;;118912:16;118944:103;118994:38;119012:11;:19;;;-1:-1:-1;;;;;118994:38:0;:17;:38::i;:::-;118952:18;;-1:-1:-1;;;;;118944:27:0;;:31;:103::i;:::-;119105:15;;;;118912:135;;-1:-1:-1;119072:49:0;;-1:-1:-1;;;;;119072:49:0;:28;:14;118912:135;119072:18;:28::i;:49::-;119058:63;118480:649;-1:-1:-1;;;;;;118480:649:0:o;117520:239::-;117618:7;117647:16;117643:30;;-1:-1:-1;117672:1:0;117665:8;;117643:30;117691:8;;:60;;-1:-1:-1;;;117691:60:0;;:8;;;;-1:-1:-1;;;;;117691:8:0;;:17;;:60;;117725:4;;117733:11;;117746:4;;117691:60;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;23375:136::-;23433:7;23460:43;23464:1;23467;23460:43;;;;;;;;;;;;;;;;;:3;:43::i;117277:235::-;117374:7;117403:15;117399:29;;-1:-1:-1;117427:1:0;117420:8;;117399:29;117446:8;;:58;;-1:-1:-1;;;117446:58:0;;:8;;;;-1:-1:-1;;;;;117446:8:0;;:16;;:58;;117479:4;;117487:10;;117499:4;;117446:58;;;:::i;111739:140::-;111814:8;;111849:4;;111814:57;;-1:-1:-1;;;111814:57:0;;111787:7;;111814:8;;;-1:-1:-1;;;;;111814:8:0;;;;:18;;:57;;111849:4;;;;111865;;111814:57;;;:::i;107934:363::-;108076:50;108098:9;108110:15;108076:13;:50::i;:::-;108180:56;;-1:-1:-1;;;108180:56:0;;108139:25;;-1:-1:-1;;;;;108180:18:0;;;;;:56;;108207:4;;108214;;108220:15;;108180:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;108139:97;;108249:40;108274:9;108285:3;108249:24;:40::i;:::-;107934:363;;;;:::o;98276:696::-;98359:13;;;;98355:52;;;98389:7;;98355:52;98419:19;98441:15;:13;:15::i;:::-;98419:37;;98469:14;98518:13;;98504:11;:27;98500:100;;;98561:27;98576:11;98561:14;:27::i;:::-;98548:40;-1:-1:-1;;98500:100:0;98612:21;98636:15;:13;:15::i;:::-;98612:39;;98684:32;98702:13;;98684:17;:32::i;:::-;98668:13;:48;98664:301;;;98781:22;98805:18;98844:34;98864:13;98844:19;:34::i;:::-;98780:98;;;;98895:58;98914:11;98927:10;98939:13;98895:18;:58::i;102269:203::-;102356:25;102423:41;102441:22;:20;:22::i;:::-;102423:17;:41::i;96520:1748::-;96637:15;;;;96743:558;96767:10;:17;96763:21;;96743:558;;;96806:34;;:::i;:::-;96843:10;96854:1;96843:13;;;;;;;;;;;;;;;;;96806:50;;;;;;;;;96843:13;;;;;96806:50;;-1:-1:-1;;;;;96806:50:0;;;;;;;;;;;;;;;;;-1:-1:-1;96893:123:0;;:18;:123::i;:::-;96871:174;;97037:8;;;96871:174;97106:23;;97091:39;;:14;:39::i;:::-;97145:117;97188:13;:23;;;97230:13;:17;;;97145:24;:117::i;:::-;96743:558;;96786:3;;96743:558;;;;97313:6;:4;:6::i;:::-;97332:14;97349:22;:20;:22::i;:::-;97332:39;;97382:15;97400;:13;:15::i;:::-;97443:5;;:31;;-1:-1:-1;;;97443:31:0;;97382:33;;-1:-1:-1;97428:12:0;;-1:-1:-1;;;;;97443:5:0;;;;:16;;:31;;97468:4;;97443:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;97428:56;;97511:4;97501:6;:14;97497:130;;97542:16;:6;97553:4;97542:10;:16::i;:::-;97532:26;;97497:130;;;97599:16;:4;97608:6;97599:8;:16::i;:::-;97591:24;;97497:130;97654:16;;-1:-1:-1;97681:20:0;97704:25;97654:16;97721:7;97704:16;:25::i;:::-;97681:48;;97761:1;97746:12;:16;:42;;;;;97776:12;97766:7;:22;97746:42;97742:519;;;97806:16;97828:31;97846:12;97828:17;:31::i;:::-;97805:54;;;97987:12;97976:8;:23;97972:278;;;98036:12;98024:8;:24;98020:215;;98083:1;98073:11;;98122:8;98107:23;;98020:215;;;98189:26;:8;98202:12;98189;:26::i;:::-;98179:36;;98020:215;97742:519;;96520:1748;;;;;;;;;:::o;60268:727::-;60440:4;;-1:-1:-1;;;;;60440:4:0;60432:27;60424:68;;;;-1:-1:-1;;;60424:68:0;;;;;;;:::i;:::-;60505:5;:24;;-1:-1:-1;;;;;;60505:24:0;-1:-1:-1;;;;;60505:24:0;;;;;;;;;;;60554:13;;;-1:-1:-1;;;60554:13:0;;;;:5;;;;;:11;;:13;;;;;;;;;;;;;;;:5;:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60540:4;:28;;-1:-1:-1;;;;;;60540:28:0;-1:-1:-1;;;;;60540:28:0;;;;;;;;60579:37;;:4;60596:6;-1:-1:-1;;60579:16:0;:37::i;:::-;60675:10;:24;;-1:-1:-1;;;;;60675:24:0;;;-1:-1:-1;;;;;;60675:24:0;;;;;;;60710:7;:18;;;;;;;;;;;;60739:6;:16;;;;;;;;;;;;;;60675:10;60801:14;:18;;;60847:5;60830:14;:22;60878:3;60863:12;:18;60892:13;:17;60922:5;;:35;;-1:-1:-1;;;60922:35:0;;:5;;;;:13;;:35;;60936:7;;;-1:-1:-1;;;60922:35:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;60268:727;;;;:::o;93328:1918::-;93535:8;;;;;-1:-1:-1;;;;;93535:8:0;93527:31;93519:40;;;;;;90234:1;93613:11;:18;:31;;93605:40;;;;;;93720:5;:12;93698:11;:18;:34;93690:43;;;;;;93800:27;;:32;:107;;93894:13;93800:107;;;;;;;;;;;;;;;;;;;;;93785:122;;;;:12;;:122;;;;;;:::i;:::-;-1:-1:-1;93920:8:0;:31;;-1:-1:-1;;;;;;93920:31:0;;-1:-1:-1;;;;;93920:31:0;;;;;;-1:-1:-1;93964:65:0;;-1:-1:-1;;;;;;93964:65:0;;;;;-1:-1:-1;94062:873:0;94086:11;:18;94082:1;:22;94062:873;;;94126:10;94160:51;;;;;;;;94185:11;94197:1;94185:14;;;;;;;;;;;;;;-1:-1:-1;;;;;94160:51:0;;;;;94202:5;94208:1;94202:8;;;;;;;;;;;;;;;;;;;94160:51;;;94126:100;;;;;;;;-1:-1:-1;94126:100:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;94126:100:0;-1:-1:-1;;;;;94126:100:0;;;;;;;;;;;;;;;;94311:10;:13;;94303:56;;;;94322:1;;94311:13;;;;;;;;;;;;;;;;;;;;:23;:34;;;-1:-1:-1;;;94311:34:0;;;;-1:-1:-1;;;;;94311:23:0;;;;:32;;:34;;;;;;;;;;:23;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;94303:56:0;;94295:65;;;;;;94483:4;;94439:10;:13;;-1:-1:-1;;;;;94483:4:0;;;;94450:1;;94439:13;;;;;;;;;;;;;;;;;;;;:23;:31;;;-1:-1:-1;;;94439:31:0;;;;-1:-1:-1;;;;;94439:23:0;;;;:29;;:31;;;;;;;;;;:23;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;94431:57:0;;94423:66;;;;;;94510:5;94516:1;94510:8;;;;;;;;;;;;;;94522:1;94510:13;94506:418;;94719:11;94731:1;94719:14;;;;;;;;;;;;;;-1:-1:-1;;;;;94644:89:0;90829:42;-1:-1:-1;;;;;94652:19:0;;94672:5;94678:1;94672:8;;;;;;;;;;;;;;94652:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:37;-1:-1:-1;;;;;94644:89:0;;94614:138;;;;;;94773:135;90829:42;-1:-1:-1;;94780:11:0;94792:1;94780:14;;;;;;;;;;;;;;-1:-1:-1;;;;;94773:34:0;;;:135;;;;;:::i;:::-;94106:3;;94062:873;;;-1:-1:-1;94947:4:0;;:46;;-1:-1:-1;;;;;94947:4:0;94964:9;-1:-1:-1;;94947:16:0;:46::i;:::-;95004:58;90715:42;90956;-1:-1:-1;;95004:17:0;:58::i;:::-;95119:16;;;95133:1;95119:16;;;;;;;;;;;;;;;;;;-1:-1:-1;;95112:23:0;;;;:4;;-1:-1:-1;95112:23:0;;;;:::i;:::-;;90715:42;95146:4;95151:1;95146:7;;;;;;;;;;;;;;;;:24;;;;;-1:-1:-1;;;;;95146:24:0;;;;;-1:-1:-1;;;;;95146:24:0;;;;;;90616:42;95181:4;95186:1;95181:7;;;;;;;;;;;;;;;;;:23;;-1:-1:-1;;;;;;95181:23:0;-1:-1:-1;;;;;95181:23:0;;;;;;95233:4;;95215;:7;;95233:4;;;;;95215;95220:1;;95215:7;;;;;;;;;;;;;;:23;;;;;-1:-1:-1;;;;;95215:23:0;;;;;-1:-1:-1;;;;;95215:23:0;;;;;;93328:1918;;;;:::o;102544:590::-;102626:9;102621:506;102645:10;:17;102641:21;;102621:506;;;102684:34;;:::i;:::-;102721:10;102732:1;102721:13;;;;;;;;;;;;;;;;;102684:50;;;;;;;;;102721:13;;;;;102684:50;;-1:-1:-1;;;;;102684:50:0;;;;;;;;;;;;;-1:-1:-1;102755:22:0;102751:207;;102840:17;;;;90829:42;;102798:19;;102880:43;102840:17;102880:24;:43::i;:::-;102798:144;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102751:207;102974:10;102985:1;102974:13;;;;;;;;;;;;;;;;;;;;;:23;103076;;-1:-1:-1;;;;;102974:23:0;;;;:32;;103025:12;;103056:44;;:19;:44::i;:::-;102974:141;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;102664:3:0;;102621:506;;22911:181;22969:7;23001:5;;;23025:6;;;;23017:46;;;;-1:-1:-1;;;23017:46:0;;;;;;;:::i;24265:471::-;24323:7;24568:6;24564:47;;-1:-1:-1;24598:1:0;24591:8;;24564:47;24635:5;;;24639:1;24635;:5;:1;24659:5;;;;;:10;24651:56;;;;-1:-1:-1;;;24651:56:0;;;;;;;:::i;34132:761::-;34556:23;34582:69;34610:4;34582:69;;;;;;;;;;;;;;;;;34590:5;-1:-1:-1;;;;;34582:27:0;;;:69;;;;;:::i;:::-;34666:17;;34556:95;;-1:-1:-1;34666:21:0;34662:224;;34808:10;34797:30;;;;;;;;;;;;:::i;:::-;34789:85;;;;-1:-1:-1;;;34789:85:0;;;;;;;:::i;17417:979::-;17547:12;17580:18;17591:6;17580:10;:18::i;:::-;17572:60;;;;-1:-1:-1;;;17572:60:0;;;;;;;:::i;:::-;17706:12;17720:23;17747:6;-1:-1:-1;;;;;17747:11:0;17767:8;17778:4;17747:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17705:78;;;;17798:7;17794:595;;;17829:10;-1:-1:-1;17822:17:0;;-1:-1:-1;17822:17:0;17794:595;17943:17;;:21;17939:439;;18206:10;18200:17;18267:15;18254:10;18250:2;18246:19;18239:44;18154:148;18349:12;18342:20;;-1:-1:-1;;;18342:20:0;;;;;;;;:::i;112565:173::-;112668:7;112700:9;-1:-1:-1;;;;;112700:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:30;-1:-1:-1;;;;;112693:37:0;;112565:173;-1:-1:-1;;112565:173:0:o;117767:705::-;117894:22;118077:24;;:::i;:::-;118104:9;-1:-1:-1;;;;;118104:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118077:49;;118137:25;;:::i;:::-;118165:9;-1:-1:-1;;;;;118165:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118137:51;;118199:16;118231:103;118281:38;118299:11;:19;;;-1:-1:-1;;;;;118281:38:0;:17;:38::i;118231:103::-;118199:135;-1:-1:-1;118362:13:0;;:102;;118418:46;118455:8;118418:32;118434:10;:15;;;-1:-1:-1;;;;;118418:32:0;:11;:15;;:32;;;;:::i;:46::-;118362:102;;;-1:-1:-1;118391:11:0;;118345:119;-1:-1:-1;;;;117767:705:0:o;112126:248::-;112223:22;112267:8;;112263:104;;112309:39;;-1:-1:-1;;;112309:39:0;;90829:42;;112309:19;;:39;;112329:3;;112342:4;;112309:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:46;;112126:248;-1:-1:-1;;112126:248:0:o;112382:175::-;112515:34;;-1:-1:-1;;;112515:34:0;;112483:7;;-1:-1:-1;;;;;112515:19:0;;;;;:34;;112543:4;;112515:34;;;:::i;108305:253::-;108412:8;108408:21;;108422:7;;108408:21;108441:24;108468:30;108488:9;108468:19;:30::i;:::-;108509:41;;-1:-1:-1;;;108509:41:0;;108441:57;;-1:-1:-1;90829:42:0;;108509:18;;:41;;108528:3;;108441:57;;108509:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25212:132;25270:7;25297:39;25301:1;25304;25297:39;;;;;;;;;;;;;;;;;:3;:39::i;21583:106::-;21641:7;21672:1;21668;:5;:13;;21680:1;21668:13;;;-1:-1:-1;21676:1:0;;21583:106;-1:-1:-1;21583:106:0:o;114605:1962::-;114708:22;;-1:-1:-1;;90555:4:0;114708:22;114889:1671;114913:10;:17;114909:21;;114889:1671;;;114952:34;;:::i;:::-;114989:10;115000:1;114989:13;;;;;;;;;;;;;;;;114952:50;;;;;;;;114989:13;;;;;;;114952:50;;-1:-1:-1;;;;;114952:50:0;;;;;;;;;;;;;;;;115069:36;;-1:-1:-1;;;115069:36:0;;;;114952:50;;-1:-1:-1;114952:50:0;;115069:34;;:36;;;;;;;;;;;;;;;114952:50;115069:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;115019:86;;-1:-1:-1;;;;;115019:86:0;;;115122:19;115161:48;115182:13;:23;;;115207:1;115161:20;:48::i;:::-;115122:87;;115571:17;115557:11;:31;:185;;;;;90481:4;115614:17;:52;:127;;;;90402:4;115695:11;:46;115614:127;115556:584;;;;115788:14;115769:16;:33;:108;;;;;90481:4;115831:11;:46;115769:108;:183;;;;;90402:4;115906:11;:46;115769:183;:264;;;;;90481:4;115981:17;:52;115769:264;:370;;;;;90402:4;116062:17;:77;115769:370;115555:702;;;;;116244:13;;116162:62;116181:13;:23;;;116206:13;:17;;;116162:18;:62::i;:::-;:95;115555:702;:805;;;;;116345:15;116278:46;116300:13;:23;;;116278:21;:46::i;:::-;:82;;115555:805;115533:1016;;;116412:16;116395:33;;116461:13;:23;;;116447:37;;116516:13;:17;;;116503:30;;115533:1016;-1:-1:-1;;;114932:3:0;;114889:1671;;23814:192;23900:7;23936:12;23928:6;;;;23920:29;;;;-1:-1:-1;;;23920:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;23972:5:0;;;23814:192::o;108926:219::-;108997:8;;109045:4;;108997:140;;-1:-1:-1;;;108997:140:0;;-1:-1:-1;;;;;108997:8:0;;;;;;;:17;;:140;;109045:4;;;109074;;109102:2;;109120:6;;108997:140;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;112823:1774;112927:23;112952:19;112989:23;113027:26;113075:9;113070:1520;113094:10;:17;113090:21;;113070:1520;;;113133:34;;:::i;:::-;113170:10;113181:1;113170:13;;;;;;;;;;;;;;;;113133:50;;;;;;;;113170:13;;;;;;;113133:50;;-1:-1:-1;;;;;113133:50:0;;;;;;;;;;;;;;;;113250:36;;-1:-1:-1;;;113250:36:0;;;;113133:50;;-1:-1:-1;113133:50:0;;113250:34;;:36;;;;;;;;;;;;;;;113133:50;113250:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;113200:86;;-1:-1:-1;;;;;113200:86:0;;;113303:19;113342:62;113363:13;:23;;;113388:15;113342:20;:62::i;:::-;113303:101;;113782:18;113768:11;:32;:212;;;;;90481:4;113826:11;:46;:153;;;;90402:4;113901:18;:78;113826:153;113767:569;;;;114022:15;114003:16;:34;:105;;;;;90481:4;114062:11;:46;114003:105;:176;;;;;90402:4;114133:11;:46;114003:176;:254;;;;;90481:4;114204:18;:53;114003:254;:332;;;;;90402:4;114282:18;:53;114003:332;113745:834;;;114389:16;114371:34;;114445:11;114424:32;;114490:13;:23;;;114475:38;;114546:13;:17;;;114532:31;;113745:834;-1:-1:-1;;;113113:3:0;;113070:1520;;110659:314;110695:16;110714;:14;:16::i;:::-;110695:35;-1:-1:-1;110745:13:0;110741:52;;110775:7;;;110741:52;110805:160;;-1:-1:-1;;;110805:160:0;;90956:42;;110805:36;;:160;;110856:8;;110887:1;;110904:4;;110931;;110951:3;;110805:160;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;110805:160:0;;;;;;;;;;;;:::i;12925:619::-;12985:4;13453:20;;13296:66;13493:23;;;;;;:42;;-1:-1:-1;;13520:15:0;;;13485:51;-1:-1:-1;;12925:619:0:o;25840:278::-;25926:7;25961:12;25954:5;25946:28;;;;-1:-1:-1;;;25946:28:0;;;;;;;;:::i;:::-;;25985:9;26001:1;25997;:5;;;;;;;25840:278;-1:-1:-1;;;;;25840:278:0:o;116575:694::-;116702:7;116727:24;116754:9;-1:-1:-1;;;;;116754:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:30;;;-1:-1:-1;;;;;116727:57:0;;;116795:25;116823:9;-1:-1:-1;;;;;116823:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:31;116904:8;;-1:-1:-1;;;;;116795:59:0;;;;-1:-1:-1;116823:31:0;;116904:212;;116795:59;;116904:8;;;-1:-1:-1;;;;;116904:8:0;:35;116974:4;116999:37;:16;117020:15;116999:20;:37::i;:::-;117055:5;116904:171;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:212::-;116865:251;-1:-1:-1;117149:112:0;116865:251;117149:59;117157:17;90555:4;117149:30;:59::i;111617:114::-;111693:30;;-1:-1:-1;;;111693:30:0;;111666:7;;90715:42;;111693:15;;:30;;111717:4;;111693:30;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:130;72:20;;97:33;72:20;97:33;:::i;301:352::-;;;431:3;424:4;416:6;412:17;408:27;398:2;;-1:-1;;439:12;398:2;-1:-1;469:20;;-1:-1;;;;;498:30;;495:2;;;-1:-1;;531:12;495:2;575:4;567:6;563:17;551:29;;626:3;575:4;;610:6;606:17;567:6;592:32;;589:41;586:2;;;643:1;;633:12;586:2;391:262;;;;;:::o;679:707::-;;796:3;789:4;781:6;777:17;773:27;763:2;;-1:-1;;804:12;763:2;851:6;838:20;873:80;888:64;945:6;888:64;:::i;:::-;873:80;:::i;:::-;981:21;;;864:89;-1:-1;1025:4;1038:14;;;;1013:17;;;1127;;;1118:27;;;;1115:36;-1:-1;1112:2;;;1164:1;;1154:12;1112:2;1189:1;1174:206;1199:6;1196:1;1193:13;1174:206;;;85:6;72:20;97:33;124:5;97:33;:::i;:::-;1267:50;;1331:14;;;;1359;;;;1221:1;1214:9;1174:206;;;1178:14;;;;;756:630;;;;:::o;1790:707::-;;1907:3;1900:4;1892:6;1888:17;1884:27;1874:2;;-1:-1;;1915:12;1874:2;1962:6;1949:20;1984:80;1999:64;2056:6;1999:64;:::i;1984:80::-;2092:21;;;1975:89;-1:-1;2136:4;2149:14;;;;2124:17;;;2238;;;2229:27;;;;2226:36;-1:-1;2223:2;;;2275:1;;2265:12;2223:2;2300:1;2285:206;2310:6;2307:1;2304:13;2285:206;;;8725:20;;2378:50;;2442:14;;;;2470;;;;2332:1;2325:9;2285:206;;4405:442;;4507:3;4500:4;4492:6;4488:17;4484:27;4474:2;;-1:-1;;4515:12;4474:2;4562:6;4549:20;-1:-1;;;;;46400:6;46397:30;46394:2;;;-1:-1;;46430:12;46394:2;4584:65;46503:9;46484:17;;-1:-1;;46480:33;46571:4;46561:15;4584:65;:::i;:::-;4575:74;;4669:6;4662:5;4655:21;4773:3;46571:4;4764:6;4697;4755:16;;4752:25;4749:2;;;4790:1;;4780:12;4749:2;52222:6;46571:4;4697:6;4693:17;46571:4;4731:5;4727:16;52199:30;52278:1;52260:16;;;46571:4;52260:16;52253:27;4731:5;4467:380;-1:-1;;4467:380::o;8517:134::-;8595:13;;-1:-1;;;;;49561:46;;53874:35;;53864:2;;53923:1;;53913:12;9075:241;;9179:2;9167:9;9158:7;9154:23;9150:32;9147:2;;;-1:-1;;9185:12;9147:2;85:6;72:20;97:33;124:5;97:33;:::i;9323:263::-;;9438:2;9426:9;9417:7;9413:23;9409:32;9406:2;;;-1:-1;;9444:12;9406:2;226:6;220:13;238:33;265:5;238:33;:::i;9593:1499::-;;;;;;;;;9876:3;9864:9;9855:7;9851:23;9847:33;9844:2;;;-1:-1;;9883:12;9844:2;9945:53;9990:7;9966:22;9945:53;:::i;:::-;9935:63;;10053:53;10098:7;10035:2;10078:9;10074:22;10053:53;:::i;:::-;10043:63;;10161:53;10206:7;10143:2;10186:9;10182:22;10161:53;:::i;:::-;10151:63;;10269:53;10314:7;10251:2;10294:9;10290:22;10269:53;:::i;:::-;10259:63;;10378:53;10423:7;10359:3;10403:9;10399:22;10378:53;:::i;:::-;10368:63;;10496:3;10485:9;10481:19;10468:33;-1:-1;;;;;10521:18;10513:6;10510:30;10507:2;;;-1:-1;;10543:12;10507:2;10573:78;10643:7;10634:6;10623:9;10619:22;10573:78;:::i;:::-;10563:88;;10716:3;10705:9;10701:19;10688:33;10674:47;;10521:18;10733:6;10730:30;10727:2;;;-1:-1;;10763:12;10727:2;10793:78;10863:7;10854:6;10843:9;10839:22;10793:78;:::i;:::-;10783:88;;10936:3;10925:9;10921:19;10908:33;10894:47;;10521:18;10953:6;10950:30;10947:2;;;-1:-1;;10983:12;10947:2;;11013:63;11068:7;11059:6;11048:9;11044:22;11013:63;:::i;:::-;11003:73;;;9838:1254;;;;;;;;;;;:::o;11099:366::-;;;11220:2;11208:9;11199:7;11195:23;11191:32;11188:2;;;-1:-1;;11226:12;11188:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;11278:63;11378:2;11417:22;;;;8725:20;;-1:-1;;;11182:283::o;11472:485::-;;;;11607:2;11595:9;11586:7;11582:23;11578:32;11575:2;;;-1:-1;;11613:12;11575:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;11665:63;-1:-1;11765:2;11804:22;;8725:20;;-1:-1;11873:2;11909:22;;3317:20;3342:30;3317:20;3342:30;:::i;:::-;11881:60;;;;11569:388;;;;;:::o;11964:397::-;;;12103:2;12091:9;12082:7;12078:23;12074:32;12071:2;;;-1:-1;;12109:12;12071:2;12167:17;12154:31;-1:-1;;;;;12197:6;12194:30;12191:2;;;-1:-1;;12227:12;12191:2;12265:80;12337:7;12328:6;12317:9;12313:22;12265:80;:::i;:::-;12247:98;;;;-1:-1;12065:296;-1:-1;;;;12065:296::o;12772:392::-;;12912:2;;12900:9;12891:7;12887:23;12883:32;12880:2;;;-1:-1;;12918:12;12880:2;12969:17;12963:24;-1:-1;;;;;12999:6;12996:30;12993:2;;;-1:-1;;13029:12;12993:2;13116:22;;2644:4;2632:17;;2628:27;-1:-1;2618:2;;-1:-1;;2659:12;2618:2;2699:6;2693:13;2721:80;2736:64;2793:6;2736:64;:::i;2721:80::-;2829:21;;;2886:14;;;;2861:17;;;2975;;;2966:27;;;;2963:36;-1:-1;2960:2;;;-1:-1;;3002:12;2960:2;-1:-1;3028:10;;3022:217;3047:6;3044:1;3041:13;3022:217;;;8873:13;;3115:61;;3069:1;3062:9;;;;;3190:14;;;;3218;;3022:217;;;-1:-1;13049:99;12874:290;-1:-1;;;;;;;12874:290::o;13171:235::-;;13272:2;13260:9;13251:7;13247:23;13243:32;13240:2;;;-1:-1;;13278:12;13240:2;3330:6;3317:20;3342:30;3366:5;3342:30;:::i;13413:257::-;;13525:2;13513:9;13504:7;13500:23;13496:32;13493:2;;;-1:-1;;13531:12;13493:2;3465:6;3459:13;3477:30;3501:5;3477:30;:::i;14589:367::-;;;14713:2;14701:9;14692:7;14688:23;14684:32;14681:2;;;-1:-1;;14719:12;14681:2;14777:17;14764:31;-1:-1;;;;;14815:18;14807:6;14804:30;14801:2;;;-1:-1;;14837:12;14801:2;14923:6;14912:9;14908:22;;;4174:3;4167:4;4159:6;4155:17;4151:27;4141:2;;-1:-1;;4182:12;4141:2;4225:6;4212:20;14815:18;4244:6;4241:30;4238:2;;;-1:-1;;4274:12;4238:2;4369:3;14713:2;4349:17;4310:6;4335:32;;4332:41;4329:2;;;-1:-1;;4376:12;4329:2;14713;4306:17;;;;;14857:83;;-1:-1;14675:281;;-1:-1;;;;14675:281::o;14963:314::-;;15103:3;15091:9;15082:7;15078:23;15074:33;15071:2;;;-1:-1;;15110:12;15071:2;5050:20;15103:3;5050:20;:::i;:::-;226:6;220:13;238:33;265:5;238:33;:::i;:::-;5155:60;5137:16;5130:86;;5283:2;5352:9;5348:22;8873:13;5283:2;5302:5;5298:16;5291:86;5449:2;5518:9;5514:22;8873:13;5449:2;5468:5;5464:16;5457:86;5616:2;5685:9;5681:22;8873:13;5616:2;5635:5;5631:16;5624:86;15162:99;;;;15065:212;;;;:::o;15284:305::-;;15420:2;15408:9;15399:7;15395:23;15391:32;15388:2;;;-1:-1;;15426:12;15388:2;5915:20;15420:2;5915:20;:::i;:::-;6020:60;6076:3;6052:22;6020:60;:::i;:::-;6002:16;5995:86;6175:60;6231:3;6142:2;6211:9;6207:22;6175:60;:::i;:::-;6142:2;6157:16;;6150:86;6161:5;15382:207;-1:-1;;;15382:207::o;15596:324::-;;15741:3;;15729:9;15720:7;15716:23;15712:33;15709:2;;;-1:-1;;15748:12;15709:2;6460:22;15741:3;6460:22;:::i;:::-;6451:31;;6606:22;8873:13;6556:16;6549:86;6702:2;6771:9;6767:22;8873:13;6702:2;6721:5;6717:16;6710:86;6862:2;6931:9;6927:22;8873:13;6862:2;6881:5;6877:16;6870:86;7030:2;7099:9;7095:22;8873:13;7030:2;7049:5;7045:16;7038:86;7198:3;7268:9;7264:22;8873:13;7198:3;7218:5;7214:16;7207:86;7360:3;7430:9;7426:22;8873:13;7360:3;7380:5;7376:16;7369:86;7521:3;7591:9;7587:22;8873:13;7521:3;7541:5;7537:16;7530:86;7682:3;7752:9;7748:22;8873:13;7682:3;7702:5;7698:16;7691:86;7843:3;;7915:9;7911:22;8873:13;7843:3;7863:5;7859:18;7852:88;;15800:104;;;;15703:217;;;;:::o;15927:313::-;;16067:2;16055:9;16046:7;16042:23;16038:32;16035:2;;;-1:-1;;16073:12;16035:2;8163:20;16067:2;8163:20;:::i;:::-;8299:22;8873:13;8249:16;8242:86;8395:2;8464:9;8460:22;8873:13;8395:2;8414:5;8410:16;8403:86;16125:99;;;;16029:211;;;;:::o;16247:241::-;;16351:2;16339:9;16330:7;16326:23;16322:32;16319:2;;;-1:-1;;16357:12;16319:2;-1:-1;8725:20;;16313:175;-1:-1;16313:175::o;16495:263::-;;16610:2;16598:9;16589:7;16585:23;16581:32;16578:2;;;-1:-1;;16616:12;16578:2;-1:-1;8873:13;;16572:186;-1:-1;16572:186::o;16765:399::-;;;16897:2;16885:9;16876:7;16872:23;16868:32;16865:2;;;-1:-1;;16903:12;16865:2;-1:-1;;8873:13;;17066:2;17116:22;;;8873:13;;;;;-1:-1;16859:305::o;17171:531::-;;;;17318:2;17306:9;17297:7;17293:23;17289:32;17286:2;;;-1:-1;;17324:12;17286:2;9019:6;9013:13;9031:32;9057:5;9031:32;:::i;:::-;17486:2;17535:22;;9013:13;17376:73;;-1:-1;9031:32;9013:13;9031:32;:::i;:::-;17604:2;17654:22;;8595:13;17494:73;;-1:-1;;;;;;49561:46;;53874:35;;53864:2;;-1:-1;;53913:12;19811:690;;20004:5;47192:12;48255:6;48250:3;48243:19;48292:4;;48287:3;48283:14;20016:93;;48292:4;20180:5;46708:14;-1:-1;20219:260;20244:6;20241:1;20238:13;20219:260;;;20305:13;;27469:37;;18045:14;;;;47871;;;;20266:1;20259:9;20219:260;;;-1:-1;20485:10;;19935:566;-1:-1;;;;;19935:566::o;22654:347::-;;22799:5;47192:12;48255:6;48250:3;48243:19;22893:52;22938:6;48292:4;48287:3;48283:14;48292:4;22919:5;22915:16;22893:52;:::i;:::-;46503:9;52952:14;-1:-1;;52948:28;22957:39;;;;48292:4;22957:39;;22746:255;-1:-1;;22746:255::o;27638:271::-;;20780:5;47192:12;20891:52;20936:6;20931:3;20924:4;20917:5;20913:16;20891:52;:::i;:::-;20955:16;;;;;27772:137;-1:-1;;27772:137::o;27916:222::-;-1:-1;;;;;48898:54;;;;18134:37;;28043:2;28028:18;;28014:124::o;28145:333::-;-1:-1;;;;;48898:54;;;18134:37;;48898:54;;28464:2;28449:18;;18134:37;28300:2;28285:18;;28271:207::o;28485:1388::-;-1:-1;;;;;48898:54;;;18134:37;;48898:54;;;29093:2;29078:18;;;18134:37;;;;48898:54;;;29176:2;29161:18;;18134:37;48898:54;;;29259:2;29244:18;;18134:37;48898:54;;;29342:3;29327:19;;18134:37;28928:3;48909:42;29365:19;;29358:49;;;47192:12;;28913:19;;;48243;;;28485:1388;;48283:14;;;;46708;;;;28485:1388;18742:260;18767:6;18764:1;18761:13;18742:260;;;18828:13;;48898:54;;18134:37;;17863:14;;;;47871;;;;18789:1;18782:9;18742:260;;;18746:14;;;;;29578:9;29572:4;29568:20;29562:3;29551:9;29547:19;29540:49;29603:108;29706:4;29697:6;29603:108;:::i;:::-;29595:116;;29760:9;29754:4;29750:20;29744:3;29733:9;29729:19;29722:49;29785:78;29858:4;29849:6;29785:78;:::i;:::-;29777:86;28899:974;-1:-1;;;;;;;;;;;28899:974::o;29880:432::-;-1:-1;;;;;48898:54;;;;18134:37;;49128:13;;49121:21;30215:2;30200:18;;20574:34;30298:2;30283:18;;27469:37;30057:2;30042:18;;30028:284::o;30319:349::-;-1:-1;;;;;48898:54;;;;18134:37;;30654:2;30639:18;;22251:58;30482:2;30467:18;;30453:215::o;31015:210::-;49128:13;;49121:21;20574:34;;31136:2;31121:18;;31107:118::o;31600:712::-;-1:-1;;;;;48898:54;;;21068:64;;48898:54;;;32040:2;32025:18;;18134:37;48898:54;;;;32123:2;32108:18;;18134:37;32214:2;32199:18;;22251:58;;;;32297:3;32282:19;;27469:37;;;;31861:3;31846:19;;31832:480::o;32319:584::-;-1:-1;;;;;48898:54;;;21068:64;;48898:54;;;32723:2;32708:18;;18134:37;48898:54;;32806:2;32791:18;;18134:37;32889:2;32874:18;;27469:37;;;;32544:3;32529:19;;32515:388::o;33629:460::-;-1:-1;;;;;48898:54;;;;21068:64;;33998:2;33983:18;;27469:37;;;;49128:13;49121:21;34075:2;34060:18;;20574:34;33820:2;33805:18;;33791:298::o;35811:330::-;;35968:2;35989:17;35982:47;48255:6;35968:2;35957:9;35953:18;48243:19;52222:6;52217:3;48283:14;35957:9;48283:14;52199:30;52260:16;;;48283:14;52260:16;;;52253:27;;;;46503:9;52952:14;;;-1:-1;;52948:28;22601:39;;;35939:202;-1:-1;35939:202::o;36148:310::-;;36295:2;36316:17;36309:47;36370:78;36295:2;36284:9;36280:18;36434:6;36370:78;:::i;36465:416::-;36665:2;36679:47;;;23233:2;36650:18;;;48243:19;-1:-1;;;48283:14;;;23249:34;23302:12;;;36636:245::o;36888:416::-;37088:2;37102:47;;;23553:1;37073:18;;;48243:19;-1:-1;;;48283:14;;;23568:28;23615:12;;;37059:245::o;37311:416::-;37511:2;37525:47;;;23866:2;37496:18;;;48243:19;23902:29;48283:14;;;23882:50;23951:12;;;37482:245::o;37734:416::-;37934:2;37948:47;;;24202:2;37919:18;;;48243:19;-1:-1;;;48283:14;;;24218:35;24272:12;;;37905:245::o;38157:416::-;38357:2;38371:47;;;24523:2;38342:18;;;48243:19;24559:30;48283:14;;;24539:51;24609:12;;;38328:245::o;38580:416::-;38780:2;38794:47;;;24860:2;38765:18;;;48243:19;24896:34;48283:14;;;24876:55;-1:-1;;;24951:12;;;24944:25;24988:12;;;38751:245::o;39003:416::-;39203:2;39217:47;;;25239:1;39188:18;;;48243:19;-1:-1;;;48283:14;;;25254:29;25302:12;;;39174:245::o;39426:416::-;39626:2;39640:47;;;25553:1;39611:18;;;48243:19;-1:-1;;;48283:14;;;25568:30;25617:12;;;39597:245::o;39849:416::-;40049:2;40063:47;;;25868:2;40034:18;;;48243:19;25904:31;48283:14;;;25884:52;25955:12;;;40020:245::o;40272:416::-;40472:2;40486:47;;;26206:2;40457:18;;;48243:19;-1:-1;;;48283:14;;;26222:34;26275:12;;;40443:245::o;40695:416::-;40895:2;40909:47;;;26526:2;40880:18;;;48243:19;26562:34;48283:14;;;26542:55;-1:-1;;;26617:12;;;26610:34;26663:12;;;40866:245::o;41118:416::-;41318:2;41332:47;;;26914:2;41303:18;;;48243:19;-1:-1;;;48283:14;;;26930:33;26982:12;;;41289:245::o;41541:416::-;41741:2;41755:47;;;27233:2;41726:18;;;48243:19;27269:34;48283:14;;;27249:55;-1:-1;;;27324:12;;;27317:46;27382:12;;;41712:245::o;41964:222::-;27469:37;;;42091:2;42076:18;;42062:124::o;42193:333::-;27469:37;;;-1:-1;;;;;48898:54;42512:2;42497:18;;18134:37;42348:2;42333:18;;42319:207::o;42533:333::-;27469:37;;;42852:2;42837:18;;27469:37;42688:2;42673:18;;42659:207::o;42873:810::-;;43159:3;43148:9;43144:19;27499:5;27476:3;27469:37;43324:2;27499:5;43324:2;43313:9;43309:18;27469:37;43159:3;43361:2;43350:9;43346:18;43339:48;43401:105;19250:5;47339:12;48255:6;48250:3;48243:19;48283:14;43148:9;48283:14;19262:93;;46871:3;-1:-1;46861:14;43324:2;-1:-1;46890:18;19435:21;;-1:-1;19462:288;19487:6;19484:1;19481:13;19462:288;;;52860:11;;-1:-1;;;;;48898:54;18134:37;;509:18;47983:14;;;;17863;;;;19502:9;19462:288;;;-1:-1;;;;;;;48898:54;;;;43585:2;43570:18;;18134:37;-1:-1;;;43668:3;43653:19;27469:37;43393:113;43130:553;-1:-1;;;43130:553::o;43690:444::-;27469:37;;;44037:2;44022:18;;27469:37;;;;44120:2;44105:18;;27469:37;43873:2;43858:18;;43844:290::o;44141:556::-;27469:37;;;44517:2;44502:18;;27469:37;;;;44600:2;44585:18;;27469:37;44683:2;44668:18;;27469:37;44352:3;44337:19;;44323:374::o;44704:668::-;27469:37;;;45108:2;45093:18;;27469:37;;;;45191:2;45176:18;;27469:37;;;;45274:2;45259:18;;27469:37;45357:3;45342:19;;27469:37;44943:3;44928:19;;44914:458::o;45379:256::-;45441:2;45435:9;45467:17;;;-1:-1;;;;;45527:34;;45563:22;;;45524:62;45521:2;;;45599:1;;45589:12;45521:2;45441;45608:22;45419:216;;-1:-1;45419:216::o;45642:304::-;;-1:-1;;;;;45793:6;45790:30;45787:2;;;-1:-1;;45823:12;45787:2;-1:-1;45868:4;45856:17;;;45921:15;;45724:222::o;52295:268::-;52360:1;52367:101;52381:6;52378:1;52375:13;52367:101;;;52448:11;;;52442:18;52429:11;;;52422:39;52403:2;52396:10;52367:101;;;52483:6;52480:1;52477:13;52474:2;;;-1:-1;;52360:1;52530:16;;52523:27;52344:219::o;53099:117::-;-1:-1;;;;;48898:54;;53158:35;;53148:2;;53207:1;;53197:12;53223:111;53304:5;49128:13;49121:21;53282:5;53279:32;53269:2;;53325:1;;53315:12;54063:115;-1:-1;;;;;54148:5;49887:30;54124:5;54121:34;54111:2;;54169:1;;54159:12
Swarm Source
ipfs://249666e07c860f2875a5a98b68433e73d3b70707c81e2b4b5e773ea928148103
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 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.