Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 13378586 | 1003 days ago | IN | Create: Strategy | 0 ETH | 0.46716275 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
13516171 | 982 days ago | 17,431.82930435 ETH | ||||
13516171 | 982 days ago | 17,431.82930435 ETH | ||||
13516171 | 982 days ago | 17,431.82930435 ETH | ||||
13516171 | 982 days ago | 17,431.82930435 ETH | ||||
13516171 | 982 days ago | 17,431.82930435 ETH | ||||
13516171 | 982 days ago | 17,431.82930435 ETH | ||||
13516171 | 982 days ago | 17,431.82930435 ETH | ||||
13516171 | 982 days ago | 17,431.82930435 ETH | ||||
13513706 | 982 days ago | 1,671.69192176 ETH | ||||
13513706 | 982 days ago | 1,671.69192176 ETH | ||||
13513706 | 982 days ago | 1,671.69192176 ETH | ||||
13513706 | 982 days ago | 1,671.69192176 ETH | ||||
13509215 | 983 days ago | 0 ETH | ||||
13509215 | 983 days ago | 0 ETH | ||||
13509215 | 983 days ago | 0 ETH | ||||
13509215 | 983 days ago | 0 ETH | ||||
13505955 | 983 days ago | 184.64468216 ETH | ||||
13505955 | 983 days ago | 184.64468216 ETH | ||||
13505955 | 983 days ago | 184.64468216 ETH | ||||
13505955 | 983 days ago | 184.64468216 ETH | ||||
13502638 | 984 days ago | 2.08930785 ETH | ||||
13502638 | 984 days ago | 2.08930785 ETH | ||||
13502638 | 984 days ago | 2.08930785 ETH | ||||
13502638 | 984 days ago | 2.08930785 ETH | ||||
13502638 | 984 days ago | 20,608.87672654 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Strategy
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-10-08 */ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.6.12; pragma experimental ABIEncoderV2; // Global Enums and Structs struct StrategyParams { uint256 performanceFee; uint256 activation; uint256 debtRatio; uint256 rateLimit; uint256 lastReport; uint256 totalDebt; uint256 totalGain; uint256 totalLoss; } // Part: Account library Account { enum Status {Normal, Liquid, Vapor} struct Info { address owner; // The address that owns the account uint256 number; // A nonce that allows a single address to control many accounts } struct Storage { mapping(uint256 => Types.Par) balances; // Mapping from marketId to principal Status status; } } // Part: Actions library Actions { enum ActionType { Deposit, // supply tokens Withdraw, // borrow tokens Transfer, // transfer balance between accounts Buy, // buy an amount of some token (publicly) Sell, // sell an amount of some token (publicly) Trade, // trade tokens against another account Liquidate, // liquidate an undercollateralized or expiring account Vaporize, // use excess tokens to zero-out a completely negative account Call // send arbitrary data to an address } enum AccountLayout {OnePrimary, TwoPrimary, PrimaryAndSecondary} enum MarketLayout {ZeroMarkets, OneMarket, TwoMarkets} struct ActionArgs { ActionType actionType; uint256 accountId; Types.AssetAmount amount; uint256 primaryMarketId; uint256 secondaryMarketId; address otherAddress; uint256 otherAccountId; bytes data; } struct DepositArgs { Types.AssetAmount amount; Account.Info account; uint256 market; address from; } struct WithdrawArgs { Types.AssetAmount amount; Account.Info account; uint256 market; address to; } struct TransferArgs { Types.AssetAmount amount; Account.Info accountOne; Account.Info accountTwo; uint256 market; } struct BuyArgs { Types.AssetAmount amount; Account.Info account; uint256 makerMarket; uint256 takerMarket; address exchangeWrapper; bytes orderData; } struct SellArgs { Types.AssetAmount amount; Account.Info account; uint256 takerMarket; uint256 makerMarket; address exchangeWrapper; bytes orderData; } struct TradeArgs { Types.AssetAmount amount; Account.Info takerAccount; Account.Info makerAccount; uint256 inputMarket; uint256 outputMarket; address autoTrader; bytes tradeData; } struct LiquidateArgs { Types.AssetAmount amount; Account.Info solidAccount; Account.Info liquidAccount; uint256 owedMarket; uint256 heldMarket; } struct VaporizeArgs { Types.AssetAmount amount; Account.Info solidAccount; Account.Info vaporAccount; uint256 owedMarket; uint256 heldMarket; } struct CallArgs { Account.Info account; address callee; bytes data; } } library Decimal { struct D256 { uint256 value; } } library Interest { struct Rate { uint256 value; } struct Index { uint96 borrow; uint96 supply; uint32 lastUpdate; } } library Monetary { struct Price { uint256 value; } struct Value { uint256 value; } } library Storage { // All information necessary for tracking a market struct Market { // Contract address of the associated ERC20 token address token; // Total aggregated supply and borrow amount of the entire market Types.TotalPar totalPar; // Interest index of the market Interest.Index index; // Contract address of the price oracle for this market address priceOracle; // Contract address of the interest setter for this market address interestSetter; // Multiplier on the marginRatio for this market Decimal.D256 marginPremium; // Multiplier on the liquidationSpread for this market Decimal.D256 spreadPremium; // Whether additional borrows are allowed for this market bool isClosing; } // The global risk parameters that govern the health and security of the system struct RiskParams { // Required ratio of over-collateralization Decimal.D256 marginRatio; // Percentage penalty incurred by liquidated accounts Decimal.D256 liquidationSpread; // Percentage of the borrower's interest fee that gets passed to the suppliers Decimal.D256 earningsRate; // The minimum absolute borrow value of an account // There must be sufficient incentivize to liquidate undercollateralized accounts Monetary.Value minBorrowedValue; } // The maximum RiskParam values that can be set struct RiskLimits { uint64 marginRatioMax; uint64 liquidationSpreadMax; uint64 earningsRateMax; uint64 marginPremiumMax; uint64 spreadPremiumMax; uint128 minBorrowedValueMax; } // The entire storage state of Solo struct State { // number of markets uint256 numMarkets; // marketId => Market mapping(uint256 => Market) markets; // owner => account number => Account mapping(address => mapping(uint256 => Account.Storage)) accounts; // Addresses that can control other users accounts mapping(address => mapping(address => bool)) operators; // Addresses that can control all users accounts mapping(address => bool) globalOperators; // mutable risk parameters of the system RiskParams riskParams; // immutable risk limits of the system RiskLimits riskLimits; } } // Part: ICallee /** * @title ICallee * @author dYdX * * Interface that Callees for Solo must implement in order to ingest data. */ interface ICallee { // ============ Public Functions ============ /** * Allows users to send this contract arbitrary data. * * @param sender The msg.sender to Solo * @param accountInfo The account from which the data is being sent * @param data Arbitrary data given by the sender */ function callFunction( address sender, Account.Info memory accountInfo, bytes memory data ) external; } // Part: ISoloMargin interface ISoloMargin { struct OperatorArg { address operator1; bool trusted; } function ownerSetSpreadPremium(uint256 marketId, Decimal.D256 memory spreadPremium) external; function getIsGlobalOperator(address operator1) external view returns (bool); function getMarketTokenAddress(uint256 marketId) external view returns (address); function ownerSetInterestSetter(uint256 marketId, address interestSetter) external; function getAccountValues(Account.Info memory account) external view returns (Monetary.Value memory, Monetary.Value memory); function getMarketPriceOracle(uint256 marketId) external view returns (address); function getMarketInterestSetter(uint256 marketId) external view returns (address); function getMarketSpreadPremium(uint256 marketId) external view returns (Decimal.D256 memory); function getNumMarkets() external view returns (uint256); function ownerWithdrawUnsupportedTokens(address token, address recipient) external returns (uint256); function ownerSetMinBorrowedValue(Monetary.Value memory minBorrowedValue) external; function ownerSetLiquidationSpread(Decimal.D256 memory spread) external; function ownerSetEarningsRate(Decimal.D256 memory earningsRate) external; function getIsLocalOperator(address owner, address operator1) external view returns (bool); function getAccountPar(Account.Info memory account, uint256 marketId) external view returns (Types.Par memory); function ownerSetMarginPremium(uint256 marketId, Decimal.D256 memory marginPremium) external; function getMarginRatio() external view returns (Decimal.D256 memory); function getMarketCurrentIndex(uint256 marketId) external view returns (Interest.Index memory); function getMarketIsClosing(uint256 marketId) external view returns (bool); function getRiskParams() external view returns (Storage.RiskParams memory); function getAccountBalances(Account.Info memory account) external view returns ( address[] memory, Types.Par[] memory, Types.Wei[] memory ); function renounceOwnership() external; function getMinBorrowedValue() external view returns (Monetary.Value memory); function setOperators(OperatorArg[] memory args) external; function getMarketPrice(uint256 marketId) external view returns (address); function owner() external view returns (address); function isOwner() external view returns (bool); function ownerWithdrawExcessTokens(uint256 marketId, address recipient) external returns (uint256); function ownerAddMarket( address token, address priceOracle, address interestSetter, Decimal.D256 memory marginPremium, Decimal.D256 memory spreadPremium ) external; function operate(Account.Info[] memory accounts, Actions.ActionArgs[] memory actions) external; function getMarketWithInfo(uint256 marketId) external view returns ( Storage.Market memory, Interest.Index memory, Monetary.Price memory, Interest.Rate memory ); function ownerSetMarginRatio(Decimal.D256 memory ratio) external; function getLiquidationSpread() external view returns (Decimal.D256 memory); function getAccountWei(Account.Info memory account, uint256 marketId) external view returns (Types.Wei memory); function getMarketTotalPar(uint256 marketId) external view returns (Types.TotalPar memory); function getLiquidationSpreadForPair(uint256 heldMarketId, uint256 owedMarketId) external view returns (Decimal.D256 memory); function getNumExcessTokens(uint256 marketId) external view returns (Types.Wei memory); function getMarketCachedIndex(uint256 marketId) external view returns (Interest.Index memory); function getAccountStatus(Account.Info memory account) external view returns (uint8); function getEarningsRate() external view returns (Decimal.D256 memory); function ownerSetPriceOracle(uint256 marketId, address priceOracle) external; function getRiskLimits() external view returns (Storage.RiskLimits memory); function getMarket(uint256 marketId) external view returns (Storage.Market memory); function ownerSetIsClosing(uint256 marketId, bool isClosing) external; function ownerSetGlobalOperator(address operator1, bool approved) external; function transferOwnership(address newOwner) external; function getAdjustedAccountValues(Account.Info memory account) external view returns (Monetary.Value memory, Monetary.Value memory); function getMarketMarginPremium(uint256 marketId) external view returns (Decimal.D256 memory); function getMarketInterestRate(uint256 marketId) external view returns (Interest.Rate memory); } // Part: IUniswapAnchoredView interface IUniswapAnchoredView { function price(string memory) external returns (uint); } // Part: IUniswapV2Router01 interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns ( uint256 amountA, uint256 amountB, uint256 liquidity ); function addLiquidityETH( address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external payable returns ( uint256 amountToken, uint256 amountETH, uint256 liquidity ); function removeLiquidity( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETH( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountToken, uint256 amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETHWithPermit( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountToken, uint256 amountETH); function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapTokensForExactTokens( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactETHForTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable returns (uint256[] memory amounts); function swapTokensForExactETH( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactTokensForETH( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapETHForExactTokens( uint256 amountOut, address[] calldata path, address to, uint256 deadline ) external payable returns (uint256[] memory amounts); function quote( uint256 amountA, uint256 reserveA, uint256 reserveB ) external pure returns (uint256 amountB); function getAmountOut( uint256 amountIn, uint256 reserveIn, uint256 reserveOut ) external pure returns (uint256 amountOut); function getAmountIn( uint256 amountOut, uint256 reserveIn, uint256 reserveOut ) external pure returns (uint256 amountIn); function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts); } // Part: IUniswapV3SwapCallback /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; } // Part: InterestRateModel interface InterestRateModel { /** * @notice Calculates the current borrow interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @return The borrow rate per block (as a percentage, and scaled by 1e18) */ function getBorrowRate( uint256 cash, uint256 borrows, uint256 reserves ) external view returns (uint256, uint256); /** * @notice Calculates the current supply interest rate per block * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @param reserveFactorMantissa The current reserve factor the market has * @return The supply rate per block (as a percentage, and scaled by 1e18) */ function getSupplyRate( uint256 cash, uint256 borrows, uint256 reserves, uint256 reserveFactorMantissa ) external view returns (uint256); } // Part: OpenZeppelin/[email protected]/Address /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // Part: OpenZeppelin/[email protected]/IERC20 /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // Part: OpenZeppelin/[email protected]/Math /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } } // Part: OpenZeppelin/[email protected]/SafeMath /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // Part: Types library Types { enum AssetDenomination { Wei, // the amount is denominated in wei Par // the amount is denominated in par } enum AssetReference { Delta, // the amount is given as a delta from the current value Target // the amount is given as an exact number to end up at } struct AssetAmount { bool sign; // true if positive AssetDenomination denomination; AssetReference ref; uint256 value; } struct TotalPar { uint128 borrow; uint128 supply; } struct Par { bool sign; // true if positive uint128 value; } struct Wei { bool sign; // true if positive uint256 value; } } // Part: iearn-finance/[email protected]/HealthCheck interface HealthCheck { function check( uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding, uint256 totalDebt ) external view returns (bool); } // Part: CTokenI interface CTokenI { /*** Market Events ***/ /** * @notice Event emitted when interest is accrued */ event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows); /** * @notice Event emitted when tokens are minted */ event Mint(address minter, uint256 mintAmount, uint256 mintTokens); /** * @notice Event emitted when tokens are redeemed */ event Redeem(address redeemer, uint256 redeemAmount, uint256 redeemTokens); /** * @notice Event emitted when underlying is borrowed */ event Borrow(address borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows); /** * @notice Event emitted when a borrow is repaid */ event RepayBorrow(address payer, address borrower, uint256 repayAmount, uint256 accountBorrows, uint256 totalBorrows); /** * @notice Event emitted when a borrow is liquidated */ event LiquidateBorrow(address liquidator, address borrower, uint256 repayAmount, address cTokenCollateral, uint256 seizeTokens); /*** Admin Events ***/ /** * @notice Event emitted when pendingAdmin is changed */ event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); /** * @notice Event emitted when pendingAdmin is accepted, which means admin is updated */ event NewAdmin(address oldAdmin, address newAdmin); /** * @notice Event emitted when the reserve factor is changed */ event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa); /** * @notice Event emitted when the reserves are added */ event ReservesAdded(address benefactor, uint256 addAmount, uint256 newTotalReserves); /** * @notice Event emitted when the reserves are reduced */ event ReservesReduced(address admin, uint256 reduceAmount, uint256 newTotalReserves); /** * @notice EIP20 Transfer event */ event Transfer(address indexed from, address indexed to, uint256 amount); /** * @notice EIP20 Approval event */ event Approval(address indexed owner, address indexed spender, uint256 amount); /** * @notice Failure event */ event Failure(uint256 error, uint256 info, uint256 detail); function transfer(address dst, uint256 amount) external returns (bool); function transferFrom( address src, address dst, uint256 amount ) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function balanceOfUnderlying(address owner) external returns (uint256); function getAccountSnapshot(address account) external view returns ( uint256, uint256, uint256, uint256 ); function borrowRatePerBlock() external view returns (uint256); function supplyRatePerBlock() external view returns (uint256); function totalBorrowsCurrent() external returns (uint256); function borrowBalanceCurrent(address account) external returns (uint256); function borrowBalanceStored(address account) external view returns (uint256); function exchangeRateCurrent() external returns (uint256); function accrualBlockNumber() external view returns (uint256); function exchangeRateStored() external view returns (uint256); function getCash() external view returns (uint256); function accrueInterest() external returns (uint256); function interestRateModel() external view returns (InterestRateModel); function totalReserves() external view returns (uint256); function reserveFactorMantissa() external view returns (uint256); function seize( address liquidator, address borrower, uint256 seizeTokens ) external returns (uint256); function totalBorrows() external view returns (uint256); function totalSupply() external view returns (uint256); } // Part: IERC20Extended interface IERC20Extended is IERC20 { function decimals() external view returns (uint8); function name() external view returns (string memory); function symbol() external view returns (string memory); } // Part: IUniswapV2Router02 interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; } // Part: IUniswapV3Router /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface IUniswapV3Router is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); } // Part: IWETH interface IWETH is IERC20 { function deposit() payable external; function withdraw(uint256) 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: iearn-finance/[email protected]/VaultAPI interface VaultAPI is IERC20 { function apiVersion() external view returns (string memory); function withdraw(uint256 shares, address recipient) external; function token() external view returns (address); function strategies(address _strategy) external view returns (StrategyParams memory); /** * 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); } // Part: CErc20I interface CErc20I is CTokenI { function mint(uint256 mintAmount) external returns (uint256); function redeem(uint256 redeemTokens) external returns (uint256); function redeemUnderlying(uint256 redeemAmount) external returns (uint256); function borrow(uint256 borrowAmount) external returns (uint256); function repayBorrow(uint256 repayAmount) external returns (uint256); function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256); function liquidateBorrow( address borrower, uint256 repayAmount, CTokenI cTokenCollateral ) external returns (uint256); function underlying() external view returns (address); } // Part: CEtherI interface CEtherI is CTokenI { function redeemUnderlying(uint256 redeemAmount) external returns (uint256); function redeem(uint256 redeemTokens) external returns (uint256); function liquidateBorrow(address borrower, CTokenI cTokenCollateral) external payable; function borrow(uint256 borrowAmount) external returns (uint); function mint() external payable; function repayBorrow() external payable; } // Part: ComptrollerI interface ComptrollerI { function enterMarkets(address[] calldata cTokens) external returns (uint256[] memory); function exitMarket(address cToken) external returns (uint256); /*** Policy Hooks ***/ function mintAllowed( address cToken, address minter, uint256 mintAmount ) external returns (uint256); function mintVerify( address cToken, address minter, uint256 mintAmount, uint256 mintTokens ) external; function redeemAllowed( address cToken, address redeemer, uint256 redeemTokens ) external returns (uint256); function redeemVerify( address cToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens ) external; function borrowAllowed( address cToken, address borrower, uint256 borrowAmount ) external returns (uint256); function borrowVerify( address cToken, address borrower, uint256 borrowAmount ) external; function repayBorrowAllowed( address cToken, address payer, address borrower, uint256 repayAmount ) external returns (uint256); function repayBorrowVerify( address cToken, address payer, address borrower, uint256 repayAmount, uint256 borrowerIndex ) external; function liquidateBorrowAllowed( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint256 repayAmount ) external returns (uint256); function liquidateBorrowVerify( address cTokenBorrowed, address cTokenCollateral, address liquidator, address borrower, uint256 repayAmount, uint256 seizeTokens ) external; function seizeAllowed( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint256 seizeTokens ) external returns (uint256); function seizeVerify( address cTokenCollateral, address cTokenBorrowed, address liquidator, address borrower, uint256 seizeTokens ) external; function transferAllowed( address cToken, address src, address dst, uint256 transferTokens ) external returns (uint256); function transferVerify( address cToken, address src, address dst, uint256 transferTokens ) external; /*** Liquidity/Liquidation Calculations ***/ function liquidateCalculateSeizeTokens( address cTokenBorrowed, address cTokenCollateral, uint256 repayAmount ) external view returns (uint256, uint256); function getAccountLiquidity(address account) external view returns ( uint256, uint256, uint256 ); /*** Comp claims ****/ function claimComp(address holder) external; function claimComp(address holder, CTokenI[] memory cTokens) external; function markets(address ctoken) external view returns ( bool, uint256, bool ); function compSpeeds(address ctoken) external view returns (uint256); // will be deprecated function compSupplySpeeds(address ctoken) external view returns (uint256); function compBorrowSpeeds(address ctoken) external view returns (uint256); function oracle() external view returns (address); } // Part: iearn-finance/[email protected]/BaseStrategy /** * @title Yearn Base Strategy * @author yearn.finance * @notice * BaseStrategy implements all of the required functionality to interoperate * closely with the Vault contract. This contract should be inherited and the * abstract methods implemented to adapt the Strategy to the particular needs * it has to create a return. * * Of special interest is the relationship between `harvest()` and * `vault.report()'. `harvest()` may be called simply because enough time has * elapsed since the last report, and not because any funds need to be moved * or positions adjusted. This is critical so that the Vault may maintain an * accurate picture of the Strategy's performance. See `vault.report()`, * `harvest()`, and `harvestTrigger()` for further details. */ abstract contract BaseStrategy { using SafeMath for uint256; // 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.3.0"; } /** * @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 virtual view 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. * @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 virtual view 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 UpdatedReportDelay(uint256 delay); event UpdatedProfitFactor(uint256 profitFactor); event UpdatedDebtThreshold(uint256 debtThreshold); event EmergencyExitEnabled(); // The maximum number of seconds between harvest calls. See // `setMaxReportDelay()` for more details. uint256 public maxReportDelay = 86400; // ~ once a day // The minimum multiple that `callCost` must be above the credit/profit to // be "justifiable". See `setProfitFactor()` for more details. uint256 public profitFactor = 100; // Use this to adjust the threshold at which running a debt causes a // harvest trigger. See `setDebtThreshold()` for more details. uint256 public debtThreshold = 0; // See note on `setEmergencyExit()`. bool public emergencyExit; // modifiers modifier onlyAuthorized() { require(msg.sender == strategist || msg.sender == governance(), "!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(), "!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. */ 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.approve(_vault, uint256(-1)); // Give Vault unlimited access (might save gas) strategist = _strategist; rewards = _rewards; keeper = _keeper; vault.approve(rewards, uint256(-1)); // Allow rewards to be pulled } function setHealthCheck(address _healthCheck) external onlyGovernance { healthCheck = _healthCheck; } function setDoHealthCheck(bool _doHealthCheck) external onlyGovernance { 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`. Any distributed rewards will cease flowing * to the old address and begin flowing to this address once the change * is in effect. * * This may only be called by the strategist. * @param _rewards The address to use for collecting rewards. */ function setRewards(address _rewards) external onlyStrategist { require(_rewards != address(0)); rewards = _rewards; emit UpdatedRewards(_rewards); } /** * @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 UpdatedReportDelay(_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); } /** * 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 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 virtual view 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 - _loss`). * * `_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). This function is used during emergency exit instead of * `prepareReturn()` to liquidate all of the Strategy's positions back to the Vault. * * NOTE: The invariant `_amountFreed + _loss <= _amountNeeded` should always be maintained */ function liquidatePosition(uint256 _amountNeeded) internal virtual returns (uint256 _liquidatedAmount, uint256 _loss); /** * `Harvest()` calls this function after shares are created during * `vault.report()`. You can customize this function to any share * distribution mechanism you want. * * See `vault.report()` for further details. */ function distributeRewards() internal virtual { // Transfer 100% of newly-minted shares awarded to this contract to the rewards address. uint256 balance = vault.balanceOf(address(this)); if (balance > 0) { vault.transfer(rewards, balance); } } /** * @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 * `callCost` must be priced in terms of `want`. * * This call and `harvestTrigger()` should never return `true` at the same * time. * @param callCost The keeper's estimated cast cost to call `tend()`. * @return `true` if `tend()` should be called, `false` otherwise. */ function tendTrigger(uint256 callCost) public virtual view 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. 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 * `callCost` must be priced in terms of `want`. * * This call and `tendTrigger` should never return `true` at the * same time. * * See `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/master/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 callCost The keeper's estimated cast cost to call `harvest()`. * @return `true` if `harvest()` should be called, `false` otherwise. */ function harvestTrigger(uint256 callCost) public virtual view returns (bool) { StrategyParams memory params = vault.strategies(address(this)); // Should not trigger if Strategy is not activated if (params.activation == 0) 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 totalAssets = estimatedTotalAssets(); // NOTE: use the larger of total assets or debt outstanding to book losses properly (debtPayment, loss) = liquidatePosition(totalAssets > debtOutstanding ? totalAssets : debtOutstanding); // NOTE: take up any remainder here as profit if (debtPayment > debtOutstanding) { profit = debtPayment.sub(debtOutstanding); debtPayment = debtOutstanding; } } 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); // Distribute any reward shares earned by the strategy on this report distributeRewards(); // 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 `_amount` uint256 amountFreed; (amountFreed, _loss) = liquidatePosition(_amountNeeded); // sanity check require(_amountNeeded == amountFreed.add(_loss), "!withdraw"); // Send it directly back (NOTE: Using `msg.sender` saves some gas here) want.transfer(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 governance or the Vault. * @dev * The new Strategy's Vault must be the same as this Strategy's Vault. * @param _newStrategy The Strategy to migrate to. */ function migrate(address _newStrategy) external { require(msg.sender == address(vault) || msg.sender == governance()); require(BaseStrategy(_newStrategy).vault() == vault); prepareMigration(_newStrategy); want.transfer(_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 onlyAuthorized { 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 virtual view 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).transfer(governance(), IERC20(_token).balanceOf(address(this))); } } // Part: FlashLoanLib library FlashLoanLib { using SafeMath for uint256; event Leverage(uint256 amountRequested, uint256 amountGiven, bool deficit, address flashLoan); uint256 constant private PRICE_DECIMALS = 1e6; uint256 constant private WETH_DECIMALS = 1e18; uint256 constant private COLLAT_RATIO_ETH = 0.74 ether; address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address private constant WBTC = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599; ComptrollerI private constant COMP = ComptrollerI(0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B); ISoloMargin public constant SOLO = ISoloMargin(0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e); CEtherI public constant CETH = CEtherI(0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5); function doDyDxFlashLoan(bool deficit, uint256 amountDesired, address want) public returns (uint256) { if(amountDesired == 0){ return 0; } // calculate amount of ETH we need (uint256 requiredETH, uint256 amountWant)= getFlashLoanParams(want, amountDesired); // Array of actions to be done during FlashLoan Actions.ActionArgs[] memory operations = new Actions.ActionArgs[](3); // 1. Take FlashLoan operations[0] = _getWithdrawAction(0, requiredETH); // hardcoded market ID to 0 (ETH) // 2. Encode arguments of functions and create action for calling it bytes memory data = abi.encode(deficit, amountWant); operations[1] = _getCallAction( data ); // 3. Repay FlashLoan operations[2] = _getDepositAction(0, requiredETH.add(2)); // Create Account Info Account.Info[] memory accountInfos = new Account.Info[](1); accountInfos[0] = _getAccountInfo(); SOLO.operate(accountInfos, operations); emit Leverage(amountDesired, requiredETH, deficit, address(SOLO)); return amountWant; // we need to return the amount of Want we have changed our position in } function getFlashLoanParams(address want, uint256 amountDesired) internal returns (uint256 requiredETH, uint256 amountWant) { (uint256 priceETHWant, uint256 decimalsDifference, uint256 _requiredETH) = getPriceETHWant(want, amountDesired); // to avoid stack too deep requiredETH = _requiredETH; amountWant = amountDesired; // Not enough want in DyDx. So we take all we can uint256 dxdyLiquidity = IERC20(WETH).balanceOf(address(SOLO)); if(requiredETH > dxdyLiquidity) { requiredETH = dxdyLiquidity; // NOTE: if we cap amountETH, we reduce amountWant we are taking too amountWant = requiredETH.mul(COLLAT_RATIO_ETH).div(priceETHWant).div(1e18).div(decimalsDifference); } } function getPriceETHWant(address want, uint256 amountDesired) internal returns (uint256 priceETHWant, uint256 decimalsDifference, uint256 requiredETH) { uint256 wantDecimals = 10 ** uint256(IERC20Extended(want).decimals()); decimalsDifference = WETH_DECIMALS > wantDecimals ? WETH_DECIMALS.div(wantDecimals) : wantDecimals.div(WETH_DECIMALS); if(want == WETH) { requiredETH = amountDesired.mul(1e18).div(COLLAT_RATIO_ETH); priceETHWant = 1e6; // 1:1 } else { priceETHWant = getOraclePrice(WETH).mul(PRICE_DECIMALS).div(getOraclePrice(want)); // requiredETH = desiredWantInETH / COLLAT_RATIO_ETH // desiredWBTCInETH = (desiredWant / priceETHWant) // NOTE: decimals need adjustment (e.g. BTC: 8 / ETH: 18) requiredETH = amountDesired.mul(PRICE_DECIMALS).mul(1e18).mul(decimalsDifference).div(priceETHWant).div(COLLAT_RATIO_ETH); } } function getOraclePrice(address token) internal returns (uint256) { string memory symbol = IERC20Extended(token).symbol(); // Symbol for WBTC is BTC in oracle if(token == WBTC) { symbol = "BTC"; } else if (token == WETH) { symbol = "ETH"; } IUniswapAnchoredView oracle = IUniswapAnchoredView(COMP.oracle()); return oracle.price(symbol); } function loanLogic( bool deficit, uint256 amount, CErc20I cToken ) public { uint256 wethBal = IERC20(WETH).balanceOf(address(this)); // NOTE: weth balance should always be > amount/0.75 require(wethBal >= amount, "!bal"); // to stop malicious calls uint256 wethBalance = IERC20(WETH).balanceOf(address(this)); // 0. Unwrap WETH IWETH(WETH).withdraw(wethBalance); // 1. Deposit ETH in Compound as collateral // will revert if it fails CETH.mint{value: wethBalance}(); //if in deficit we repay amount and then withdraw if (deficit) { // 2a. if in deficit withdraw amount and repay it require(cToken.redeemUnderlying(amount) == 0, "!redeem_down"); require(cToken.repayBorrow(IERC20(cToken.underlying()).balanceOf(address(this))) == 0, "!repay_down"); } else { // 2b. if levering up borrow and deposit require(cToken.borrow(amount) == 0, "!borrow_up"); require(cToken.mint(IERC20(cToken.underlying()).balanceOf(address(this))) == 0, "!mint_up"); } // 3. Redeem collateral (ETH borrowed from DyDx) from Compound require(CETH.redeemUnderlying(wethBalance) == 0, "!redeem"); // 4. Wrap ETH into WETH IWETH(WETH).deposit{value: address(this).balance}(); // NOTE: after this, WETH will be taken by DyDx } function _getAccountInfo() internal view returns (Account.Info memory) { return Account.Info({owner: address(this), number: 1}); } function _getWithdrawAction(uint256 marketId, uint256 amount) internal view returns (Actions.ActionArgs memory) { return Actions.ActionArgs({ actionType: Actions.ActionType.Withdraw, accountId: 0, amount: Types.AssetAmount({ sign: false, denomination: Types.AssetDenomination.Wei, ref: Types.AssetReference.Delta, value: amount }), primaryMarketId: marketId, secondaryMarketId: 0, otherAddress: address(this), otherAccountId: 0, data: "" }); } function _getCallAction(bytes memory data) internal view returns (Actions.ActionArgs memory) { return Actions.ActionArgs({ actionType: Actions.ActionType.Call, accountId: 0, amount: Types.AssetAmount({sign: false, denomination: Types.AssetDenomination.Wei, ref: Types.AssetReference.Delta, value: 0}), primaryMarketId: 0, secondaryMarketId: 0, otherAddress: address(this), otherAccountId: 0, data: data }); } function _getDepositAction(uint256 marketId, uint256 amount) internal view returns (Actions.ActionArgs memory) { return Actions.ActionArgs({ actionType: Actions.ActionType.Deposit, accountId: 0, amount: Types.AssetAmount({ sign: true, denomination: Types.AssetDenomination.Wei, ref: Types.AssetReference.Delta, value: amount }), primaryMarketId: marketId, secondaryMarketId: 0, otherAddress: address(this), otherAccountId: 0, data: "" }); } } // File: Strategy.sol /******************** * * A lender optimisation strategy for any erc20 asset * https://github.com/Grandthrax/yearnV2-generic-lender-strat * v0.4.2 * ********************* */ contract Strategy is BaseStrategy, ICallee { using SafeERC20 for IERC20; using Address for address; using SafeMath for uint256; // @notice emitted when trying to do Flash Loan. flashLoan address is 0x00 when no flash loan used event Leverage(uint256 amountRequested, uint256 amountGiven, bool deficit, address flashLoan); // Comptroller address for compound.finance ComptrollerI private constant compound = ComptrollerI(0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B); //Only three tokens we use address private constant comp = 0xc00e94Cb662C3520282E6f5717214004A7f26888; address private constant weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; CErc20I public cToken; bool public useUniV3; // fee pool to use in UniV3 in basis points(default: 0.3% = 3000) uint24 public compToWethSwapFee; uint24 public wethToWantSwapFee; IUniswapV2Router02 public currentV2Router; IUniswapV2Router02 private constant UNI_V2_ROUTER = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); IUniswapV2Router02 private constant SUSHI_V2_ROUTER = IUniswapV2Router02(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); IUniswapV3Router private constant UNI_V3_ROUTER = IUniswapV3Router(0xE592427A0AEce92De3Edee1F18E0157C05861564); uint256 public collateralTarget; // total borrow / total supply ratio we are targeting (100% = 1e18) uint256 public blocksToLiquidationDangerZone; // minimum number of blocks before liquidation uint256 public minWant; // minimum amount of want to act on // Rewards handling bool public dontClaimComp; // enable/disables COMP claiming uint256 public minCompToSell; // minimum amount of COMP to be sold bool public DyDxActive; // To deactivate flash loan provider if needed bool public forceMigrate; constructor(address _vault, address _cToken) public BaseStrategy(_vault) { _initializeThis(_cToken); } function approveTokenMax(address token, address spender) internal { IERC20(token).safeApprove(spender, type(uint256).max); } // To receive ETH from compound and WETH contract receive() external payable {} function name() external override view returns (string memory){ return "GenLevCompV2"; } function _initializeThis(address _cToken) internal { cToken = CErc20I(address(_cToken)); currentV2Router = SUSHI_V2_ROUTER; //pre-set approvals approveTokenMax(comp, address(UNI_V2_ROUTER)); approveTokenMax(comp, address(SUSHI_V2_ROUTER)); approveTokenMax(comp, address(UNI_V3_ROUTER)); approveTokenMax(address(want), address(cToken)); approveTokenMax(weth, address(FlashLoanLib.SOLO)); // Enter Compound's ETH market to take it into account when using ETH as collateral address[] memory markets = new address[](2); markets[0] = address(FlashLoanLib.CETH); markets[1] = address(cToken); compound.enterMarkets(markets); //comp speed is amount to borrow or deposit (so half the total distribution for want) compToWethSwapFee = 3000; wethToWantSwapFee = 3000; // You can set these parameters on deployment to whatever you want maxReportDelay = 86400; // once per 24 hours profitFactor = 100; // multiple before triggering harvest minCompToSell = 0.1 ether; collateralTarget = 0.74 ether; blocksToLiquidationDangerZone = 46500; DyDxActive = true; } /* * Control Functions */ function setUniV3PathFees(uint24 _compToWethSwapFee, uint24 _wethToWantSwapFee) external management { compToWethSwapFee = _compToWethSwapFee; wethToWantSwapFee = _wethToWantSwapFee; } function setDontClaimComp(bool _dontClaimComp) external management { dontClaimComp = _dontClaimComp; } function setUseUniV3(bool _useUniV3) external management { useUniV3 = _useUniV3; } function setToggleV2Router() external management { currentV2Router = currentV2Router == SUSHI_V2_ROUTER ? UNI_V2_ROUTER : SUSHI_V2_ROUTER; } function setDyDx(bool _dydx) external management { DyDxActive = _dydx; } function setForceMigrate(bool _force) external onlyGovernance { forceMigrate = _force; } function setMinCompToSell(uint256 _minCompToSell) external management { minCompToSell = _minCompToSell; } function setMinWant(uint256 _minWant) external management { minWant = _minWant; } function setCollateralTarget(uint256 _collateralTarget) external management { (, uint256 collateralFactorMantissa, ) = compound.markets(address(cToken)); require(collateralFactorMantissa > _collateralTarget); collateralTarget = _collateralTarget; } /* * Base External Facing Functions */ /* * An accurate estimate for the total amount of assets (principle + return) * that this strategy is currently managing, denominated in terms of want tokens. */ function estimatedTotalAssets() public override view returns (uint256) { (uint256 deposits, uint256 borrows) = getCurrentPosition(); uint256 _claimableComp = predictCompAccrued(); uint256 currentComp = balanceOfToken(comp); // Use touch price. it doesnt matter if we are wrong as this is not used for decision making uint256 estimatedWant = priceCheck(comp, address(want),_claimableComp.add(currentComp)); uint256 conservativeWant = estimatedWant.mul(9).div(10); //10% pessimist return balanceOfToken(address(want)).add(deposits).add(conservativeWant).sub(borrows); } function balanceOfToken(address token) internal view returns (uint256) { return IERC20(token).balanceOf(address(this)); } //predicts our profit at next report function expectedReturn() public view returns (uint256) { uint256 estimateAssets = estimatedTotalAssets(); uint256 debt = vault.strategies(address(this)).totalDebt; if (debt > estimateAssets) { return 0; } else { return estimateAssets.sub(debt); } } /* * Provide a signal to the keeper that `tend()` should be called. * (keepers are always reimbursed by yEarn) * * NOTE: this call and `harvestTrigger` should never return `true` at the same time. * tendTrigger should be called with same gasCost as harvestTrigger */ function tendTrigger(uint256 gasCost) public override view returns (bool) { if (harvestTrigger(gasCost)) { //harvest takes priority return false; } return getblocksUntilLiquidation() <= blocksToLiquidationDangerZone; } //WARNING. manipulatable and simple routing. Only use for safe functions function priceCheck(address start, address end, uint256 _amount) public view returns (uint256) { if (_amount == 0) { return 0; } uint256[] memory amounts = currentV2Router.getAmountsOut(_amount, getTokenOutPathV2(start, end)); return amounts[amounts.length - 1]; } /***************** * Public non-base function ******************/ //Calculate how many blocks until we are in liquidation based on current interest rates //WARNING does not include compounding so the estimate becomes more innacurate the further ahead we look //equation. Compound doesn't include compounding for most blocks //((deposits*colateralThreshold - borrows) / (borrows*borrowrate - deposits*colateralThreshold*interestrate)); function getblocksUntilLiquidation() public view returns (uint256) { (, uint256 collateralFactorMantissa, ) = compound.markets(address(cToken)); (uint256 deposits, uint256 borrows) = getCurrentPosition(); uint256 borrrowRate = cToken.borrowRatePerBlock(); uint256 supplyRate = cToken.supplyRatePerBlock(); uint256 collateralisedDeposit1 = deposits.mul(collateralFactorMantissa).div(1e18); uint256 collateralisedDeposit = collateralisedDeposit1; uint256 denom1 = borrows.mul(borrrowRate); uint256 denom2 = collateralisedDeposit.mul(supplyRate); if (denom2 >= denom1) { return type(uint256).max; } else { uint256 numer = collateralisedDeposit.sub(borrows); uint256 denom = denom1.sub(denom2); //minus 1 for this block return numer.mul(1e18).div(denom); } } // This function makes a prediction on how much comp is accrued // It is not 100% accurate as it uses current balances in Compound to predict into the past function predictCompAccrued() public view returns (uint256) { (uint256 deposits, uint256 borrows) = getCurrentPosition(); if (deposits == 0) { return 0; // should be impossible to have 0 balance and positive comp accrued } uint256 distributionPerBlockSupply = compound.compSupplySpeeds(address(cToken)); uint256 distributionPerBlockBorrow = compound.compBorrowSpeeds(address(cToken)); uint256 totalBorrow = cToken.totalBorrows(); //total supply needs to be echanged to underlying using exchange rate uint256 totalSupplyCtoken = cToken.totalSupply(); uint256 totalSupply = totalSupplyCtoken.mul(cToken.exchangeRateStored()).div(1e18); uint256 blockShareSupply = 0; if(totalSupply > 0) { blockShareSupply = deposits.mul(distributionPerBlockSupply).div(totalSupply); } uint256 blockShareBorrow = 0; if(totalBorrow > 0) { blockShareBorrow = borrows.mul(distributionPerBlockBorrow).div(totalBorrow); } //how much we expect to earn per block uint256 blockShare = blockShareSupply.add(blockShareBorrow); //last time we ran harvest uint256 lastReport = vault.strategies(address(this)).lastReport; uint256 blocksSinceLast= (block.timestamp.sub(lastReport)).div(13); //roughly 13 seconds per block return blocksSinceLast.mul(blockShare); } //Returns the current position //WARNING - this returns just the balance at last time someone touched the cToken token. Does not accrue interst in between //cToken is very active so not normally an issue. function getCurrentPosition() public view returns (uint256 deposits, uint256 borrows) { (, uint256 ctokenBalance, uint256 borrowBalance, uint256 exchangeRate) = cToken.getAccountSnapshot(address(this)); borrows = borrowBalance; deposits = ctokenBalance.mul(exchangeRate).div(1e18); } //statechanging version function getLivePosition() public returns (uint256 deposits, uint256 borrows) { deposits = cToken.balanceOfUnderlying(address(this)); //we can use non state changing now because we updated state with balanceOfUnderlying call borrows = cToken.borrowBalanceStored(address(this)); } //Same warning as above function netBalanceLent() public view returns (uint256) { (uint256 deposits, uint256 borrows) = getCurrentPosition(); return deposits.sub(borrows); } /*********** * internal core logic *********** */ /* * A core method. * Called at beggining of harvest before providing report to owner * 1 - claim accrued comp * 2 - if enough to be worth it we sell * 3 - because we lose money on our loans we need to offset profit from comp. */ function prepareReturn(uint256 _debtOutstanding) internal override returns ( uint256 _profit, uint256 _loss, uint256 _debtPayment ) { _profit = 0; _loss = 0; //for clarity. also reduces bytesize if (balanceOfToken(address(cToken)) == 0) { uint256 wantBalance = balanceOfToken(address(want)); //no position to harvest //but we may have some debt to return //it is too expensive to free more debt in this method so we do it in adjust position _debtPayment = Math.min(wantBalance, _debtOutstanding); return (_profit, _loss, _debtPayment); } (uint256 deposits, uint256 borrows) = getLivePosition(); //claim comp accrued _claimComp(); //sell comp _disposeOfComp(); uint256 wantBalance = balanceOfToken(address(want)); uint256 investedBalance = deposits.sub(borrows); uint256 balance = investedBalance.add(wantBalance); uint256 debt = vault.strategies(address(this)).totalDebt; //Balance - Total Debt is profit if (balance > debt) { _profit = balance.sub(debt); if (wantBalance < _profit) { //all reserve is profit _profit = wantBalance; } else if (wantBalance > _profit.add(_debtOutstanding)) { _debtPayment = _debtOutstanding; } else { _debtPayment = wantBalance.sub(_profit); } } else { //we will lose money until we claim comp then we will make money //this has an unintended side effect of slowly lowering our total debt allowed _loss = debt.sub(balance); _debtPayment = Math.min(wantBalance, _debtOutstanding); } } /* * Second core function. Happens after report call. * * Similar to deposit function from V1 strategy */ function adjustPosition(uint256 _debtOutstanding) internal override { //emergency exit is dealt with in prepareReturn if (emergencyExit) { return; } //we are spending all our cash unless we have debt outstanding uint256 _wantBal = balanceOfToken(address(want)); if(_wantBal < _debtOutstanding){ //this is graceful withdrawal. dont use backup //we use more than 1 because withdrawunderlying causes problems with 1 token due to different decimals if(balanceOfToken(address(cToken)) > 1){ _withdrawSome(_debtOutstanding.sub(_wantBal)); } return; } (uint256 position, bool deficit) = _calculateDesiredPosition(_wantBal - _debtOutstanding, true); //if we are below minimun want change it is not worth doing //need to be careful in case this pushes to liquidation if (position > minWant) { //if dydx is not active we just try our best with basic leverage if (!DyDxActive) { uint i = 0; while(position > 0){ position = position.sub(_noFlashLoan(position, deficit)); if(i >= 6){ break; } i++; } } else { //if there is huge position to improve we want to do normal leverage. it is quicker if (position > want.balanceOf(address(FlashLoanLib.SOLO))) { position = position.sub(_noFlashLoan(position, deficit)); } //flash loan to position if(position > minWant){ doDyDxFlashLoan(deficit, position); } } } } /************* * Very important function * Input: amount we want to withdraw and whether we are happy to pay extra for Aave. * cannot be more than we have * Returns amount we were able to withdraw. notall if user has some balance left * * Deleverage position -> redeem our cTokens ******************** */ function _withdrawSome(uint256 _amount) internal returns (bool notAll) { (uint256 position, bool deficit) = _calculateDesiredPosition(_amount, false); //If there is no deficit we dont need to adjust position //if the position change is tiny do nothing if (deficit && position > minWant) { //we do a flash loan to give us a big gap. from here on out it is cheaper to use normal deleverage. Use Aave for extremely large loans if (DyDxActive) { position = position.sub(doDyDxFlashLoan(deficit, position)); } uint8 i = 0; //position will equal 0 unless we haven't been able to deleverage enough with flash loan //if we are not in deficit we dont need to do flash loan while (position > minWant.add(100)) { position = position.sub(_noFlashLoan(position, true)); i++; //A limit set so we don't run out of gas if (i >= 5) { notAll = true; break; } } } //now withdraw //if we want too much we just take max //This part makes sure our withdrawal does not force us into liquidation (uint256 depositBalance, uint256 borrowBalance) = getCurrentPosition(); uint256 tempColla = collateralTarget; uint256 reservedAmount = 0; if(tempColla == 0){ tempColla = 1e15; // 0.001 * 1e18. lower we have issues } reservedAmount = borrowBalance.mul(1e18).div(tempColla); if(depositBalance >= reservedAmount){ uint256 redeemable = depositBalance.sub(reservedAmount); if (redeemable < _amount) { cToken.redeemUnderlying(redeemable); } else { cToken.redeemUnderlying(_amount); } } if(collateralTarget == 0 && balanceOfToken(address(want)) > borrowBalance){ cToken.repayBorrow(borrowBalance); } } /*********** * This is the main logic for calculating how to change our lends and borrows * Input: balance. The net amount we are going to deposit/withdraw. * Input: dep. Is it a deposit or withdrawal * Output: position. The amount we want to change our current borrow position. * Output: deficit. True if we are reducing position size * * For instance deficit =false, position 100 means increase borrowed balance by 100 ****** */ function _calculateDesiredPosition(uint256 balance, bool dep) internal returns (uint256 position, bool deficit) { //we want to use statechanging for safety (uint256 deposits, uint256 borrows) = getLivePosition(); //When we unwind we end up with the difference between borrow and supply uint256 unwoundDeposit = deposits.sub(borrows); //we want to see how close to collateral target we are. //So we take our unwound deposits and add or remove the balance we are are adding/removing. //This gives us our desired future undwoundDeposit (desired supply) uint256 desiredSupply = 0; if (dep) { desiredSupply = unwoundDeposit.add(balance); } else { if(balance > unwoundDeposit) balance = unwoundDeposit; desiredSupply = unwoundDeposit.sub(balance); } //(ds *c)/(1-c) uint256 num = desiredSupply.mul(collateralTarget); uint256 den = uint256(1e18).sub(collateralTarget); uint256 desiredBorrow = num.div(den); if (desiredBorrow > 1e5) { //stop us going right up to the wire desiredBorrow = desiredBorrow.sub(1e5); } //now we see if we want to add or remove balance // if the desired borrow is less than our current borrow we are in deficit. so we want to reduce position if (desiredBorrow < borrows) { deficit = true; position = borrows.sub(desiredBorrow); //safemath check done in if statement } else { //otherwise we want to increase position deficit = false; position = desiredBorrow.sub(borrows); } } /* * Liquidate as many assets as possible to `want`, irregardless of slippage, * up to `_amount`. Any excess should be re-invested here as well. */ function liquidatePosition(uint256 _amountNeeded) internal override returns (uint256 _amountFreed, uint256 _loss) { uint256 _balance = balanceOfToken(address(want)); uint256 assets = netBalanceLent().add(_balance); uint256 debtOutstanding = vault.debtOutstanding(); if(debtOutstanding > assets){ _loss = debtOutstanding.sub(assets); } if (assets < _amountNeeded) { //if we cant afford to withdraw we take all we can //withdraw all we can (uint256 deposits, uint256 borrows) = getLivePosition(); //1 token causes rounding error with withdrawUnderlying if(balanceOfToken(address(cToken)) > 1){ _withdrawSome(deposits.sub(borrows)); } _amountFreed = Math.min(_amountNeeded, balanceOfToken(address(want))); } else { if (_balance < _amountNeeded) { _withdrawSome(_amountNeeded.sub(_balance)); //overflow error if we return more than asked for _amountFreed = Math.min(_amountNeeded, balanceOfToken(address(want))); }else{ _amountFreed = _amountNeeded; } } } function _claimComp() internal { if(dontClaimComp) { return; } CTokenI[] memory tokens = new CTokenI[](1); tokens[0] = cToken; compound.claimComp(address(this), tokens); } //sell comp function function _disposeOfComp() internal { uint256 _comp = balanceOfToken(comp); if (_comp < minCompToSell) { return; } if (useUniV3) { UNI_V3_ROUTER.exactInput( IUniswapV3Router.ExactInputParams( getTokenOutPathV3(comp, address(want)), address(this), now, _comp, 0 ) ); } else { currentV2Router.swapExactTokensForTokens( _comp, 0, getTokenOutPathV2(comp, address(want)), address(this), now ); } } function getTokenOutPathV2(address _tokenIn, address _tokenOut) internal pure returns (address[] memory _path) { bool isWeth = _tokenIn == address(weth) || _tokenOut == address(weth); _path = new address[](isWeth ? 2 : 3); _path[0] = _tokenIn; if (isWeth) { _path[1] = _tokenOut; } else { _path[1] = address(weth); _path[2] = _tokenOut; } } function getTokenOutPathV3(address _tokenIn, address _tokenOut) internal view returns (bytes memory _path) { if (address(want) == weth) { _path = abi.encodePacked( address(_tokenIn), compToWethSwapFee, address(weth) ); } else { _path = abi.encodePacked( address(_tokenIn), compToWethSwapFee, address(weth), wethToWantSwapFee, address(_tokenOut) ); } } //lets leave //if we can't deleverage in one go set collateralFactor to 0 and call harvest multiple times until delevered function prepareMigration(address _newStrategy) internal override { if(!forceMigrate){ (uint256 deposits, uint256 borrows) = getLivePosition(); _withdrawSome(deposits.sub(borrows)); (, , uint256 borrowBalance, ) = cToken.getAccountSnapshot(address(this)); require(borrowBalance < 10_000); IERC20 _comp = IERC20(comp); uint _compB = balanceOfToken(address(_comp)); if(_compB > 0){ _comp.safeTransfer(_newStrategy, _compB); } } } //Three functions covering normal leverage and deleverage situations // max is the max amount we want to increase our borrowed balance // returns the amount we actually did function _noFlashLoan(uint256 max, bool deficit) internal returns (uint256 amount) { //we can use non-state changing because this function is always called after _calculateDesiredPosition (uint256 lent, uint256 borrowed) = getCurrentPosition(); //if we have nothing borrowed then we can't deleverage any more if (borrowed == 0 && deficit) { return 0; } (, uint256 collateralFactorMantissa, ) = compound.markets(address(cToken)); if (deficit) { amount = _normalDeleverage(max, lent, borrowed, collateralFactorMantissa); } else { amount = _normalLeverage(max, lent, borrowed, collateralFactorMantissa); } emit Leverage(max, amount, deficit, address(0)); } //maxDeleverage is how much we want to reduce by function _normalDeleverage( uint256 maxDeleverage, uint256 lent, uint256 borrowed, uint256 collatRatio ) internal returns (uint256 deleveragedAmount) { uint256 theoreticalLent = 0; //collat ration should never be 0. if it is something is very wrong... but just incase if(collatRatio != 0){ theoreticalLent = borrowed.mul(1e18).div(collatRatio); } deleveragedAmount = lent.sub(theoreticalLent); if (deleveragedAmount >= borrowed) { deleveragedAmount = borrowed; } if (deleveragedAmount >= maxDeleverage) { deleveragedAmount = maxDeleverage; } uint256 exchangeRateStored = cToken.exchangeRateStored(); //redeemTokens = redeemAmountIn *1e18 / exchangeRate. must be more than 0 //a rounding error means we need another small addition if(deleveragedAmount.mul(1e18) >= exchangeRateStored && deleveragedAmount > 10){ deleveragedAmount = deleveragedAmount.sub(uint256(10)); cToken.redeemUnderlying(deleveragedAmount); //our borrow has been increased by no more than maxDeleverage cToken.repayBorrow(deleveragedAmount); } } //maxDeleverage is how much we want to increase by function _normalLeverage( uint256 maxLeverage, uint256 lent, uint256 borrowed, uint256 collatRatio ) internal returns (uint256 leveragedAmount) { uint256 theoreticalBorrow = lent.mul(collatRatio).div(1e18); leveragedAmount = theoreticalBorrow.sub(borrowed); if (leveragedAmount >= maxLeverage) { leveragedAmount = maxLeverage; } if(leveragedAmount > 10){ leveragedAmount = leveragedAmount.sub(uint256(10)); cToken.borrow(leveragedAmount); cToken.mint(balanceOfToken(address(want))); } } //emergency function that we can use to deleverage manually if something is broken function manualDeleverage(uint256 amount) external management{ require(cToken.redeemUnderlying(amount) == 0); require(cToken.repayBorrow(amount) == 0); } //emergency function that we can use to deleverage manually if something is broken function manualReleaseWant(uint256 amount) external onlyGovernance{ require(cToken.redeemUnderlying(amount) ==0); } function protectedTokens() internal override view returns (address[] memory) { } /****************** * Flash loan stuff ****************/ // Flash loan DXDY // amount desired is how much we are willing for position to change function doDyDxFlashLoan(bool deficit, uint256 amountDesired) internal returns (uint256) { return FlashLoanLib.doDyDxFlashLoan(deficit, amountDesired, address(want)); } //returns our current collateralisation ratio. Should be compared with collateralTarget function storedCollateralisation() public view returns (uint256 collat) { (uint256 lend, uint256 borrow) = getCurrentPosition(); if (lend == 0) { return 0; } collat = uint256(1e18).mul(borrow).div(lend); } //DyDx calls this function after doing flash loan function callFunction( address sender, Account.Info memory account, bytes memory data ) public override { (bool deficit, uint256 amount) = abi.decode(data, (bool, uint256)); require(msg.sender == address(FlashLoanLib.SOLO)); require(sender == address(this)); FlashLoanLib.loanLogic(deficit, amount, cToken); } // -- Internal Helper functions -- // function mgtm_check() internal { require(msg.sender == governance() || msg.sender == strategist); } modifier management() { mgtm_check(); _; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_cToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"EmergencyExitEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loss","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtPayment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtOutstanding","type":"uint256"}],"name":"Harvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amountRequested","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountGiven","type":"uint256"},{"indexed":false,"internalType":"bool","name":"deficit","type":"bool"},{"indexed":false,"internalType":"address","name":"flashLoan","type":"address"}],"name":"Leverage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"debtThreshold","type":"uint256"}],"name":"UpdatedDebtThreshold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newKeeper","type":"address"}],"name":"UpdatedKeeper","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profitFactor","type":"uint256"}],"name":"UpdatedProfitFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"delay","type":"uint256"}],"name":"UpdatedReportDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"rewards","type":"address"}],"name":"UpdatedRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newStrategist","type":"address"}],"name":"UpdatedStrategist","type":"event"},{"inputs":[],"name":"DyDxActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"apiVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"blocksToLiquidationDangerZone","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cToken","outputs":[{"internalType":"contract CErc20I","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"number","type":"uint256"}],"internalType":"struct Account.Info","name":"account","type":"tuple"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"callFunction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateralTarget","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"compToWethSwapFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentV2Router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delegatedAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"doHealthCheck","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dontClaimComp","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyExit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"estimatedTotalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"expectedReturn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"forceMigrate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentPosition","outputs":[{"internalType":"uint256","name":"deposits","type":"uint256"},{"internalType":"uint256","name":"borrows","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLivePosition","outputs":[{"internalType":"uint256","name":"deposits","type":"uint256"},{"internalType":"uint256","name":"borrows","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getblocksUntilLiquidation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"callCost","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":[],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"manualDeleverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"manualReleaseWant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxReportDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newStrategy","type":"address"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minCompToSell","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minWant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"netBalanceLent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"predictCompAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"start","type":"address"},{"internalType":"address","name":"end","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"priceCheck","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"profitFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralTarget","type":"uint256"}],"name":"setCollateralTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debtThreshold","type":"uint256"}],"name":"setDebtThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_doHealthCheck","type":"bool"}],"name":"setDoHealthCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_dontClaimComp","type":"bool"}],"name":"setDontClaimComp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_dydx","type":"bool"}],"name":"setDyDx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setEmergencyExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_force","type":"bool"}],"name":"setForceMigrate","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":"uint256","name":"_minCompToSell","type":"uint256"}],"name":"setMinCompToSell","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minWant","type":"uint256"}],"name":"setMinWant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_profitFactor","type":"uint256"}],"name":"setProfitFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewards","type":"address"}],"name":"setRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategist","type":"address"}],"name":"setStrategist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setToggleV2Router","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"_compToWethSwapFee","type":"uint24"},{"internalType":"uint24","name":"_wethToWantSwapFee","type":"uint24"}],"name":"setUniV3PathFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_useUniV3","type":"bool"}],"name":"setUseUniV3","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"storedCollateralisation","outputs":[{"internalType":"uint256","name":"collat","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"gasCost","type":"uint256"}],"name":"tendTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"useUniV3","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract VaultAPI","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"want","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wethToWantSwapFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountNeeded","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"_loss","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405262015180600655606460075560006008553480156200002257600080fd5b5060405162005d9d38038062005d9d833981016040819052620000459162000884565b81620000548133808062000068565b5062000060816200029c565b505062000c18565b6005546001600160a01b0316156200009d5760405162461bcd60e51b8152600401620000949062000a70565b60405180910390fd5b600180546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b158015620000fa57600080fd5b505afa1580156200010f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000135919062000854565b600580546001600160a01b0319166001600160a01b03928316179081905560405163095ea7b360e01b815291169063095ea7b3906200017d90879060001990600401620009d3565b602060405180830381600087803b1580156200019857600080fd5b505af1158015620001ad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001d3919062000960565b50600280546001600160a01b038086166001600160a01b03199283161790925560038054858416908316179081905560048054858516931692909217825560015460405163095ea7b360e01b81529084169363095ea7b3936200023f93909116916000199101620009d3565b602060405180830381600087803b1580156200025a57600080fd5b505af11580156200026f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000295919062000960565b5050505050565b600980546001600160a01b03831661010002610100600160a81b0319909116179055600a80546001600160a01b03191673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f1790556200031873c00e94cb662c3520282e6f5717214004a7f26888737a250d5630b4cf539739df2c5dacb4c659f2488d6200055a565b6200034c73c00e94cb662c3520282e6f5717214004a7f2688873d9e1ce17f2641f24ae83637ab66a2cca9c378b9f6200055a565b6200038073c00e94cb662c3520282e6f5717214004a7f2688873e592427a0aece92de3edee1f18e0157c058615646200055a565b600554600954620003a3916001600160a01b03908116916101009004166200055a565b620003d773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2731e0447b19bb6ecfdae1e4ae1694b0c3659614e4e6200055a565b6040805160028082526060808301845292602083019080368337019050509050734ddc2d193948926d02f9b1fe9e1daa0718270ed5816000815181106200041a57fe5b6001600160a01b039283166020918202929092010152600954825161010090910490911690829060019081106200044d57fe5b6001600160a01b0390921660209283029190910190910152604051631853304760e31b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b9063c2998238906200049e908490600401620009ec565b600060405180830381600087803b158015620004b957600080fd5b505af1158015620004ce573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620004f89190810190620008c2565b50506009805462ffffff60b01b191661017760b31b1762ffffff60c81b191661017760cb1b1790555062015180600655606460075567016345785d8a0000600f55670a4502144dca0000600b5561b5a4600c556010805460ff19166001179055565b6200058181600019846001600160a01b03166200058560201b62002cdf179092919060201c565b5050565b801580620006145750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e90620005be9030908690600401620009b9565b60206040518083038186803b158015620005d757600080fd5b505afa158015620005ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000612919062000982565b155b620006335760405162461bcd60e51b8152600401620000949062000b28565b6200068e8363095ea7b360e01b848460405160240162000655929190620009d3565b60408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b03938416179052906200069316565b505050565b6060620006ef826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200072f60201b62002dd9179092919060201c565b8051909150156200068e578080602001905181019062000710919062000960565b6200068e5760405162461bcd60e51b8152600401620000949062000ade565b606062000740848460008562000748565b949350505050565b606062000755856200081a565b620007745760405162461bcd60e51b8152600401620000949062000aa7565b60006060866001600160a01b031685876040516200079391906200099b565b60006040518083038185875af1925050503d8060008114620007d2576040519150601f19603f3d011682016040523d82523d6000602084013e620007d7565b606091505b50915091508115620007ed579150620007409050565b805115620007fe5780518082602001fd5b8360405162461bcd60e51b815260040162000094919062000a3b565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159062000740575050151592915050565b60006020828403121562000866578081fd5b81516001600160a01b03811681146200087d578182fd5b9392505050565b6000806040838503121562000897578081fd5b8251620008a48162000bff565b6020840151909250620008b78162000bff565b809150509250929050565b60006020808385031215620008d5578182fd5b82516001600160401b03811115620008eb578283fd5b8301601f81018513620008fc578283fd5b8051620009136200090d8262000bac565b62000b85565b818152838101908385018584028501860189101562000930578687fd5b8694505b838510156200095457805183526001949094019391850191850162000934565b50979650505050505050565b60006020828403121562000972578081fd5b815180151581146200087d578182fd5b60006020828403121562000994578081fd5b5051919050565b60008251620009af81846020870162000bcc565b9190910192915050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b8181101562000a2f5783516001600160a01b03168352928401929184019160010162000a08565b50909695505050505050565b600060208252825180602084015262000a5c81604085016020870162000bcc565b601f01601f19169190910160400192915050565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606082015260800190565b6040518181016001600160401b038111828210171562000ba457600080fd5b604052919050565b60006001600160401b0382111562000bc2578081fd5b5060209081020190565b60005b8381101562000be957818101518382015260200162000bcf565b8381111562000bf9576000848401525b50505050565b6001600160a01b038116811462000c1557600080fd5b50565b6151758062000c286000396000f3fe6080604052600436106103c75760003560e01c8063775d35e5116101f2578063c1bb4b541161010d578063e00425a3116100a0578063efbb5cb01161006f578063efbb5cb014610a21578063f017c92f14610a36578063fbfa77cf14610a56578063fcf2d0ad14610a6b576103ce565b8063e00425a3146109b7578063e0b8c948146109cc578063ec38a862146109e1578063ed882c2b14610a01576103ce565b8063ccce1d7f116100dc578063ccce1d7f1461094d578063ce5494bb14610962578063d3406abd14610982578063db2fd74514610997576103ce565b8063c1bb4b54146108ee578063c598484714610903578063c7b9d53014610918578063cb1965dd14610938576103ce565b80639be8ef1411610185578063aef6679e11610154578063aef6679e14610884578063b252720b146108a4578063b2c5f658146108b9578063b2d0c8e2146108ce576103ce565b80639be8ef14146108255780639ec5a8941461083a578063ac00ff261461084f578063aced16611461086f576103ce565b80638cdfe166116101c15780638cdfe166146107bb5780638e6350e2146107d057806391397ab4146107e55780639a561fbf14610805576103ce565b8063775d35e514610751578063853e0a3b1461076657806389be318a1461077b5780638b4187131461079b576103ce565b80632e1a7d4d116102e25780634641257d116102755780636718835f116102445780636718835f146106e557806369e527da146106fa57806373b382851461070f578063748747e614610731576103ce565b80634641257d1461067b57806354f809e3146106905780635641ec03146106b0578063650d1880146106c5576103ce565b8063396794cd116102b1578063396794cd1461060e57806340f8bc431461062e578063418f35cc14610643578063440368a314610666576103ce565b80632e1a7d4d1461058e5780633042087c146105ae578063341b3eb9146105ce5780633631ad5f146105ee576103ce565b80631d12f28b1161035a57806322f3e2d41161032957806322f3e2d41461053a578063258294101461054f57806327cc1ea21461056457806328b7ccf714610579576103ce565b80631d12f28b146104d95780631f1fcd51146104ee5780631fe4a68614610510578063205409d314610525576103ce565b806306fdde031161039657806306fdde03146104555780630ee08f7b146104775780630f969b871461049957806311bc8245146104b9576103ce565b806301681a62146103d35780630268ff0b146103f557806304324af81461042057806305a82f9a14610435576103ce565b366103ce57005b600080fd5b3480156103df57600080fd5b506103f36103ee36600461474a565b610a80565b005b34801561040157600080fd5b5061040a610c8a565b6040516104179190614f93565b60405180910390f35b34801561042c57600080fd5b5061040a610cae565b34801561044157600080fd5b506103f3610450366004614919565b610cb4565b34801561046157600080fd5b5061046a610ccf565b6040516104179190614cb2565b34801561048357600080fd5b5061048c610cf5565b6040516104179190614c86565b3480156104a557600080fd5b506103f36104b4366004614a66565b610cfe565b3480156104c557600080fd5b506103f36104d436600461474a565b610d8b565b3480156104e557600080fd5b5061040a610deb565b3480156104fa57600080fd5b50610503610df1565b6040516104179190614be3565b34801561051c57600080fd5b50610503610e00565b34801561053157600080fd5b5061040a610e0f565b34801561054657600080fd5b5061048c610e15565b34801561055b57600080fd5b5061046a610eb7565b34801561057057600080fd5b506103f3610ed6565b34801561058557600080fd5b5061040a610f56565b34801561059a57600080fd5b5061040a6105a9366004614a66565b610f5c565b3480156105ba57600080fd5b506103f36105c9366004614a66565b61104b565b3480156105da57600080fd5b506103f36105e9366004614919565b611176565b3480156105fa57600080fd5b506103f3610609366004614a66565b611191565b34801561061a57600080fd5b506103f3610629366004614a66565b61119e565b34801561063a57600080fd5b5061048c61120a565b34801561064f57600080fd5b50610658611213565b604051610417929190614ff1565b34801561067257600080fd5b506103f36112d9565b34801561068757600080fd5b506103f36113c0565b34801561069c57600080fd5b506103f36106ab366004614919565b611759565b3480156106bc57600080fd5b5061048c6117ab565b3480156106d157600080fd5b5061048c6106e0366004614a66565b6117b4565b3480156106f157600080fd5b5061048c6117e1565b34801561070657600080fd5b506105036117ea565b34801561071b57600080fd5b506107246117fe565b6040516104179190614f83565b34801561073d57600080fd5b506103f361074c36600461474a565b611810565b34801561075d57600080fd5b506106586118bb565b34801561077257600080fd5b5061040a6119d2565b34801561078757600080fd5b5061040a610796366004614782565b611c2a565b3480156107a757600080fd5b506103f36107b63660046147c2565b611cee565b3480156107c757600080fd5b5061040a611dc1565b3480156107dc57600080fd5b5061040a611dc7565b3480156107f157600080fd5b506103f3610800366004614a66565b611dcc565b34801561081157600080fd5b506103f3610820366004614a66565b611e4e565b34801561083157600080fd5b5061040a611f07565b34801561084657600080fd5b50610503611f42565b34801561085b57600080fd5b506103f361086a366004614919565b611f51565b34801561087b57600080fd5b50610503611f9c565b34801561089057600080fd5b506103f361089f366004614a32565b611fab565b3480156108b057600080fd5b50610503611feb565b3480156108c557600080fd5b50610724611fff565b3480156108da57600080fd5b506103f36108e9366004614919565b612011565b3480156108fa57600080fd5b5061040a612037565b34801561090f57600080fd5b5061048c61203d565b34801561092457600080fd5b506103f361093336600461474a565b61204d565b34801561094457600080fd5b5061048c6120f8565b34801561095957600080fd5b5061040a612106565b34801561096e57600080fd5b506103f361097d36600461474a565b61210c565b34801561098e57600080fd5b5061040a6122de565b3480156109a357600080fd5b506103f36109b2366004614a66565b61239c565b3480156109c357600080fd5b5061040a6123a9565b3480156109d857600080fd5b506105036127b5565b3480156109ed57600080fd5b506103f36109fc36600461474a565b6127c4565b348015610a0d57600080fd5b5061048c610a1c366004614a66565b61284c565b348015610a2d57600080fd5b5061040a612aa1565b348015610a4257600080fd5b506103f3610a51366004614a66565b612b6a565b348015610a6257600080fd5b50610503612bec565b348015610a7757600080fd5b506103f3612bfb565b610a88612df0565b6001600160a01b0316336001600160a01b031614610ac15760405162461bcd60e51b8152600401610ab890614e42565b60405180910390fd5b6005546001600160a01b0382811691161415610aef5760405162461bcd60e51b8152600401610ab890614cea565b6001546001600160a01b0382811691161415610b1d5760405162461bcd60e51b8152600401610ab890614dea565b6060610b27612e6d565b905060005b8151811015610b8257818181518110610b4157fe5b60200260200101516001600160a01b0316836001600160a01b03161415610b7a5760405162461bcd60e51b8152600401610ab890614eb1565b600101610b2c565b50816001600160a01b031663a9059cbb610b9a612df0565b6040516370a0823160e01b81526001600160a01b038616906370a0823190610bc6903090600401614be3565b60206040518083038186803b158015610bde57600080fd5b505afa158015610bf2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c169190614a7e565b6040518363ffffffff1660e01b8152600401610c33929190614c53565b602060405180830381600087803b158015610c4d57600080fd5b505af1158015610c61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c859190614935565b505050565b6000806000610c97611213565b9092509050610ca68282612e72565b925050505b90565b600f5481565b610cbc612ebd565b600e805460ff1916911515919091179055565b60408051808201909152600c81526b23b2b72632bb21b7b6b82b1960a11b602082015290565b60105460ff1681565b6002546001600160a01b0316331480610d2f5750610d1a612df0565b6001600160a01b0316336001600160a01b0316145b610d4b5760405162461bcd60e51b8152600401610ab890614e42565b60088190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a860090610d80908390614f93565b60405180910390a150565b610d93612df0565b6001600160a01b0316336001600160a01b031614610dc35760405162461bcd60e51b8152600401610ab890614e42565b600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60085481565b6005546001600160a01b031681565b6002546001600160a01b031681565b600d5481565b6001546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610e4a903090600401614be3565b6101006040518083038186803b158015610e6357600080fd5b505afa158015610e77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9b91906149c0565b604001511180610eb257506000610eb0612aa1565b115b905090565b6040805180820190915260058152640302e332e360dc1b602082015290565b610ede612ebd565b600a546001600160a01b031673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f14610f1e5773d9e1ce17f2641f24ae83637ab66a2cca9c378b9f610f34565b737a250d5630b4cf539739df2c5dacb4c659f2488d5b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b60065481565b6001546000906001600160a01b03163314610f895760405162461bcd60e51b8152600401610ab890614dca565b6000610f9483612ef7565b92509050610fa28183613082565b8314610fc05760405162461bcd60e51b8152600401610ab890614d66565b60055460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90610ff29033908590600401614c53565b602060405180830381600087803b15801561100c57600080fd5b505af1158015611020573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110449190614935565b5050919050565b611053612ebd565b60095460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390611087908490600401614f93565b602060405180830381600087803b1580156110a157600080fd5b505af11580156110b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d99190614a7e565b156110e357600080fd5b60095460405163073a938160e11b81526101009091046001600160a01b031690630e75270290611117908490600401614f93565b602060405180830381600087803b15801561113157600080fd5b505af1158015611145573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111699190614a7e565b1561117357600080fd5b50565b61117e612ebd565b6010805460ff1916911515919091179055565b611199612ebd565b600d55565b6111a6612df0565b6001600160a01b0316336001600160a01b0316146111d65760405162461bcd60e51b8152600401610ab890614e42565b60095460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390611117908490600401614f93565b600e5460ff1681565b6009546040516361bfb47160e11b8152600091829182918291829161010090046001600160a01b03169063c37f68e290611251903090600401614be3565b60806040518083038186803b15801561126957600080fd5b505afa15801561127d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a19190614a96565b935093509350508193506112d0670de0b6b3a76400006112ca83866130a790919063ffffffff16565b906130e1565b94505050509091565b6004546001600160a01b03163314806112fc57506002546001600160a01b031633145b8061131f575061130a612df0565b6001600160a01b0316336001600160a01b0316145b61133b5760405162461bcd60e51b8152600401610ab890614e42565b6001546040805163bf3759b560e01b815290516113be926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561138157600080fd5b505afa158015611395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b99190614a7e565b613123565b565b6004546001600160a01b03163314806113e357506002546001600160a01b031633145b8061140657506113f1612df0565b6001600160a01b0316336001600160a01b0316145b6114225760405162461bcd60e51b8152600401610ab890614e42565b6000806000600160009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561147557600080fd5b505afa158015611489573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ad9190614a7e565b60095490915060009060ff16156115035760006114c8612aa1565b90506114e18382116114da57836114dc565b815b612ef7565b94509150828211156114fd576114f78284612e72565b94508291505b50611514565b61150c826132bd565b919550935090505b6001546040516339ebf82360e01b81526000916001600160a01b0316906339ebf82390611545903090600401614be3565b6101006040518083038186803b15801561155e57600080fd5b505afa158015611572573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159691906149c0565b60a001516001546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc906115cf90889088908790600401615025565b602060405180830381600087803b1580156115e957600080fd5b505af11580156115fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116219190614a7e565b925061162b613464565b61163483613123565b60005460ff168015611655575060005461010090046001600160a01b031615155b156117075760005460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b906116969088908890879089908890600401615056565b60206040518083038186803b1580156116ae57600080fd5b505afa1580156116c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e69190614935565b6117025760405162461bcd60e51b8152600401610ab890614d40565b611715565b6000805460ff191660011790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d5098585848660405161174a949392919061503b565b60405180910390a15050505050565b611761612df0565b6001600160a01b0316336001600160a01b0316146117915760405162461bcd60e51b8152600401610ab890614e42565b601080549115156101000261ff0019909216919091179055565b60095460ff1681565b60006117bf8261284c565b156117cc575060006117dc565b600c546117d76119d2565b111590505b919050565b60005460ff1681565b60095461010090046001600160a01b031681565b600954600160c81b900462ffffff1681565b6002546001600160a01b0316331480611841575061182c612df0565b6001600160a01b0316336001600160a01b0316145b61185d5760405162461bcd60e51b8152600401610ab890614e42565b6001600160a01b03811661187057600080fd5b600480546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490610d80908390614be3565b600954604051633af9e66960e01b815260009182916101009091046001600160a01b031690633af9e669906118f4903090600401614be3565b602060405180830381600087803b15801561190e57600080fd5b505af1158015611922573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119469190614a7e565b6009546040516395dd919360e01b815291935061010090046001600160a01b0316906395dd91939061197c903090600401614be3565b60206040518083038186803b15801561199457600080fd5b505afa1580156119a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119cc9190614a7e565b90509091565b600954604051638e8f294b60e01b81526000918291733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91611a1e9161010090046001600160a01b031690600401614be3565b60606040518083038186803b158015611a3657600080fd5b505afa158015611a4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6e919061497e565b50915050600080611a7d611213565b915091506000600960019054906101000a90046001600160a01b03166001600160a01b031663f8f9da286040518163ffffffff1660e01b815260040160206040518083038186803b158015611ad157600080fd5b505afa158015611ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b099190614a7e565b90506000600960019054906101000a90046001600160a01b03166001600160a01b031663ae9d70b06040518163ffffffff1660e01b815260040160206040518083038186803b158015611b5b57600080fd5b505afa158015611b6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b939190614a7e565b90506000611bad670de0b6b3a76400006112ca87896130a7565b9050806000611bbc86866130a7565b90506000611bca83866130a7565b9050818110611be6576000199950505050505050505050610cab565b6000611bf28489612e72565b90506000611c008484612e72565b9050611c18816112ca84670de0b6b3a76400006130a7565b9b505050505050505050505050610cab565b600081611c3957506000611ce7565b600a546060906001600160a01b031663d06ca61f84611c588888613523565b6040518363ffffffff1660e01b8152600401611c75929190614f9c565b60006040518083038186803b158015611c8d57600080fd5b505afa158015611ca1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611cc99190810190614889565b905080600182510381518110611cdb57fe5b60200260200101519150505b9392505050565b60008082806020019051810190611d059190614951565b909250905033731e0447b19bb6ecfdae1e4ae1694b0c3659614e4e14611d2a57600080fd5b6001600160a01b0385163014611d3f57600080fd5b60095460405163be9b32ab60e01b815273698494b9cbcc51d274e7b2046b23a01c5312c7c39163be9b32ab91611d8a918691869161010090046001600160a01b031690600401614c91565b60006040518083038186803b158015611da257600080fd5b505af4158015611db6573d6000803e3d6000fd5b505050505050505050565b60075481565b600090565b6002546001600160a01b0316331480611dfd5750611de8612df0565b6001600160a01b0316336001600160a01b0316145b611e195760405162461bcd60e51b8152600401610ab890614e42565b60078190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec29890610d80908390614f93565b611e56612ebd565b600954604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91611ea1916101009091046001600160a01b031690600401614be3565b60606040518083038186803b158015611eb957600080fd5b505afa158015611ecd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef1919061497e565b50915050818111611f0157600080fd5b50600b55565b6000806000611f14611213565b915091508160001415611f2c57600092505050610cab565b610ca6826112ca670de0b6b3a7640000846130a7565b6003546001600160a01b031681565b611f59612df0565b6001600160a01b0316336001600160a01b031614611f895760405162461bcd60e51b8152600401610ab890614e42565b6000805460ff1916911515919091179055565b6004546001600160a01b031681565b611fb3612ebd565b6009805462ffffff928316600160c81b0262ffffff60c81b1994909316600160b01b0262ffffff60b01b199091161792909216179055565b60005461010090046001600160a01b031681565b600954600160b01b900462ffffff1681565b612019612ebd565b60098054911515600160a81b0260ff60a81b19909216919091179055565b600b5481565b600954600160a81b900460ff1681565b6002546001600160a01b031633148061207e5750612069612df0565b6001600160a01b0316336001600160a01b0316145b61209a5760405162461bcd60e51b8152600401610ab890614e42565b6001600160a01b0381166120ad57600080fd5b600280546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490610d80908390614be3565b601054610100900460ff1681565b600c5481565b6001546001600160a01b031633148061213d5750612128612df0565b6001600160a01b0316336001600160a01b0316145b61214657600080fd5b6001546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b15801561218d57600080fd5b505afa1580156121a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c59190614766565b6001600160a01b0316146121d857600080fd5b6121e1816136a4565b6005546040516370a0823160e01b81526001600160a01b039091169063a9059cbb90839083906370a082319061221b903090600401614be3565b60206040518083038186803b15801561223357600080fd5b505afa158015612247573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226b9190614a7e565b6040518363ffffffff1660e01b8152600401612288929190614c53565b602060405180830381600087803b1580156122a257600080fd5b505af11580156122b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122da9190614935565b5050565b6000806122e9612aa1565b6001546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf8239061231f903090600401614be3565b6101006040518083038186803b15801561233857600080fd5b505afa15801561234c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237091906149c0565b60a0015190508181111561238957600092505050610cab565b6123938282612e72565b92505050610cab565b6123a4612ebd565b600f55565b60008060006123b6611213565b9150915081600014156123ce57600092505050610cab565b600954604051636aa875b560e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91636aa875b591612419916101009091046001600160a01b031690600401614be3565b60206040518083038186803b15801561243157600080fd5b505afa158015612445573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124699190614a7e565b6009546040516303d290cf60e61b8152919250600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b9163f4a433c0916124b69161010090046001600160a01b031690600401614be3565b60206040518083038186803b1580156124ce57600080fd5b505afa1580156124e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125069190614a7e565b90506000600960019054906101000a90046001600160a01b03166001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561255857600080fd5b505afa15801561256c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125909190614a7e565b90506000600960019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156125e257600080fd5b505afa1580156125f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261a9190614a7e565b905060006126ba670de0b6b3a76400006112ca600960019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561267b57600080fd5b505afa15801561268f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b39190614a7e565b85906130a7565b9050600081156126d5576126d2826112ca8a896130a7565b90505b600084156126ee576126eb856112ca8a896130a7565b90505b60006126fa8383613082565b6001546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf82390612730903090600401614be3565b6101006040518083038186803b15801561274957600080fd5b505afa15801561275d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278191906149c0565b6080015190506000612798600d6112ca4285612e72565b90506127a481846130a7565b9c5050505050505050505050505090565b600a546001600160a01b031681565b6002546001600160a01b031633146127ee5760405162461bcd60e51b8152600401610ab890614cc5565b6001600160a01b03811661280157600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06990610d80908390614be3565b60006128566146e7565b6001546040516339ebf82360e01b81526001600160a01b03909116906339ebf82390612886903090600401614be3565b6101006040518083038186803b15801561289f57600080fd5b505afa1580156128b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d791906149c0565b90508060200151600014156128f05760009150506117dc565b6006546080820151612903904290612e72565b106129125760019150506117dc565b6001546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561295757600080fd5b505afa15801561296b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298f9190614a7e565b90506008548111156129a6576001925050506117dc565b60006129b0612aa1565b90508260a001516129cc6008548361308290919063ffffffff16565b10156129de57600193505050506117dc565b60008360a001518211156129ff5760a08401516129fc908390612e72565b90505b6001546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b158015612a4457600080fd5b505afa158015612a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7c9190614a7e565b9050612a888183613082565b600754612a9590896130a7565b10979650505050505050565b6000806000612aae611213565b915091506000612abc6123a9565b90506000612add73c00e94cb662c3520282e6f5717214004a7f268886137ae565b600554909150600090612b139073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b03166107968686613082565b90506000612b27600a6112ca8460096130a7565b9050612b5f85612b5983612b538a612b53600560009054906101000a90046001600160a01b03166137ae565b90613082565b90612e72565b965050505050505090565b6002546001600160a01b0316331480612b9b5750612b86612df0565b6001600160a01b0316336001600160a01b0316145b612bb75760405162461bcd60e51b8152600401610ab890614e42565b60068190556040517f4aaf232568bff365c53cad69bdb6e83014e79df80216ceba8ee01769723dfd6890610d80908390614f93565b6001546001600160a01b031681565b6002546001600160a01b0316331480612c2c5750612c17612df0565b6001600160a01b0316336001600160a01b0316145b612c485760405162461bcd60e51b8152600401610ab890614e42565b6009805460ff19166001908117909155546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b158015612c9c57600080fd5b505af1158015612cb0573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b801580612d675750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e90612d159030908690600401614c6c565b60206040518083038186803b158015612d2d57600080fd5b505afa158015612d41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d659190614a7e565b155b612d835760405162461bcd60e51b8152600401610ab890614ed5565b610c858363095ea7b360e01b8484604051602401612da2929190614c53565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261382d565b6060612de884846000856138bc565b949350505050565b60015460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b158015612e3557600080fd5b505afa158015612e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb29190614766565b606090565b6000612eb483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061398a565b90505b92915050565b612ec5612df0565b6001600160a01b0316336001600160a01b03161480612eee57506002546001600160a01b031633145b6113be57600080fd5b60055460009081908190612f13906001600160a01b03166137ae565b90506000612f2382612b53610c8a565b90506000600160009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b158015612f7557600080fd5b505afa158015612f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fad9190614a7e565b905081811115612fc457612fc18183612e72565b93505b8582101561303e57600080612fd76118bb565b915091506001612ffb600960019054906101000a90046001600160a01b03166137ae565b11156130155761301361300e8383612e72565b6139b6565b505b600554613035908990613030906001600160a01b03166137ae565b613c6a565b9650505061307a565b858310156130765761305361300e8785612e72565b5060055461306f908790613030906001600160a01b03166137ae565b945061307a565b8594505b505050915091565b600082820183811015612eb45760405162461bcd60e51b8152600401610ab890614d09565b6000826130b657506000612eb7565b828202828482816130c357fe5b0414612eb45760405162461bcd60e51b8152600401610ab890614d89565b6000612eb483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613c80565b60095460ff161561313357611173565b60055460009061314b906001600160a01b03166137ae565b90508181101561318d576009546001906131729061010090046001600160a01b03166137ae565b11156131875761318561300e8383612e72565b505b50611173565b60008061319d8484036001613cb7565b91509150600d548211156132b75760105460ff166131ef5760005b82156131e9576131d26131cb8484613da9565b8490612e72565b9250600681106131e1576131e9565b6001016131b8565b506132b7565b6005546040516370a0823160e01b81526001600160a01b03909116906370a082319061323390731e0447b19bb6ecfdae1e4ae1694b0c3659614e4e90600401614be3565b60206040518083038186803b15801561324b57600080fd5b505afa15801561325f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132839190614a7e565b8211156132a15761329e6132978383613da9565b8390612e72565b91505b600d548211156132b7576132b58183613ee5565b505b50505050565b600954600090819081906132de9061010090046001600160a01b03166137ae565b61330e576005546000906132fa906001600160a01b03166137ae565b90506133068186613c6a565b91505061345d565b6000806133196118bb565b91509150613325613f80565b61332d614053565b600554600090613345906001600160a01b03166137ae565b905060006133538484612e72565b905060006133618284613082565b6001546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf82390613397903090600401614be3565b6101006040518083038186803b1580156133b057600080fd5b505afa1580156133c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e891906149c0565b60a0015190508082111561343d576134008282612e72565b98508884101561341257839850613438565b61341c898b613082565b84111561342b57899650613438565b613435848a612e72565b96505b613456565b6134478183612e72565b9750613453848b613c6a565b96505b5050505050505b9193909250565b6001546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613495903090600401614be3565b60206040518083038186803b1580156134ad57600080fd5b505afa1580156134c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e59190614a7e565b905080156111735760015460035460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92612288929116908590600401614c53565b606060006001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2148061356e57506001600160a01b03831673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b90508061357c57600361357f565b60025b60ff1667ffffffffffffffff8111801561359857600080fd5b506040519080825280602002602001820160405280156135c2578160200160208202803683370190505b50915083826000815181106135d357fe5b60200260200101906001600160a01b031690816001600160a01b031681525050801561362c57828260018151811061360757fe5b60200260200101906001600160a01b031690816001600160a01b03168152505061369d565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28260018151811061364e57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050828260028151811061367c57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b5092915050565b601054610100900460ff16611173576000806136be6118bb565b90925090506136d061300e8383612e72565b506009546040516361bfb47160e11b815260009161010090046001600160a01b03169063c37f68e290613707903090600401614be3565b60806040518083038186803b15801561371f57600080fd5b505afa158015613733573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137579190614a96565b5092505050612710811061376a57600080fd5b73c00e94cb662c3520282e6f5717214004a7f26888600061378a826137ae565b905080156137a6576137a66001600160a01b0383168783614232565b505050505050565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906137dd903090600401614be3565b60206040518083038186803b1580156137f557600080fd5b505afa158015613809573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb79190614a7e565b6060613882826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612dd99092919063ffffffff16565b805190915015610c8557808060200190518101906138a09190614935565b610c855760405162461bcd60e51b8152600401610ab890614e67565b60606138c785614251565b6138e35760405162461bcd60e51b8152600401610ab890614e0b565b60006060866001600160a01b031685876040516139009190614bc7565b60006040518083038185875af1925050503d806000811461393d576040519150601f19603f3d011682016040523d82523d6000602084013e613942565b606091505b50915091508115613956579150612de89050565b8051156139665780518082602001fd5b8360405162461bcd60e51b8152600401610ab89190614cb2565b5050949350505050565b600081848411156139ae5760405162461bcd60e51b8152600401610ab89190614cb2565b505050900390565b60008060006139c6846000613cb7565b915091508080156139d85750600d5482115b15613a3e5760105460ff16156139f8576139f56132978284613ee5565b91505b60005b600d54613a09906064613082565b831115613a3c57613a1e6131cb846001613da9565b9250600101600560ff821610613a375760019350613a3c565b6139fb565b505b600080613a49611213565b600b549193509150600081613a635766038d7ea4c6800091505b613a79826112ca85670de0b6b3a76400006130a7565b9050808410613bae576000613a8e8583612e72565b905088811015613b245760095460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390613acc908490600401614f93565b602060405180830381600087803b158015613ae657600080fd5b505af1158015613afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1e9190614a7e565b50613bac565b60095460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390613b58908c90600401614f93565b602060405180830381600087803b158015613b7257600080fd5b505af1158015613b86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613baa9190614a7e565b505b505b600b54158015613bd257506005548390613bd0906001600160a01b03166137ae565b115b15613c5f5760095460405163073a938160e11b81526101009091046001600160a01b031690630e75270290613c0b908690600401614f93565b602060405180830381600087803b158015613c2557600080fd5b505af1158015613c39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c5d9190614a7e565b505b505050505050919050565b6000818310613c795781612eb4565b5090919050565b60008183613ca15760405162461bcd60e51b8152600401610ab89190614cb2565b506000838581613cad57fe5b0495945050505050565b600080600080613cc56118bb565b90925090506000613cd68383612e72565b905060008615613cf157613cea8289613082565b9050613d0a565b81881115613cfd578197505b613d078289612e72565b90505b6000613d21600b54836130a790919063ffffffff16565b90506000613d42600b54670de0b6b3a7640000612e7290919063ffffffff16565b90506000613d5083836130e1565b9050620186a0811115613d6d57613d6a81620186a0612e72565b90505b85811015613d8a5760019750613d838682612e72565b9850613d9b565b60009750613d988187612e72565b98505b505050505050509250929050565b6000806000613db6611213565b91509150806000148015613dc75750835b15613dd757600092505050612eb7565b600954604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91613e22916101009091046001600160a01b031690600401614be3565b60606040518083038186803b158015613e3a57600080fd5b505afa158015613e4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e72919061497e565b509150508415613e8f57613e888684848461428a565b9350613e9e565b613e9b868484846144a3565b93505b7f012a05dea1e4b56be6c250aaa3e6189a1f531f1fd201b35b2a74c56577000bf48685876000604051613ed49493929190614fff565b60405180910390a150505092915050565b600554604051634cab28bb60e11b815260009173698494b9cbcc51d274e7b2046b23a01c5312c7c391639956517691613f3091879187916001600160a01b0390911690600401614c91565b60206040518083038186803b158015613f4857600080fd5b505af4158015613f5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb49190614a7e565b600e5460ff1615613f90576113be565b60408051600180825281830190925260609160208083019080368337019050509050600960019054906101000a90046001600160a01b031681600081518110613fd557fe5b6001600160a01b039092166020928302919091019091015260405162e1ed9760e51b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b90631c3db2e0906140259030908590600401614bf7565b600060405180830381600087803b15801561403f57600080fd5b505af11580156132b5573d6000803e3d6000fd5b600061407273c00e94cb662c3520282e6f5717214004a7f268886137ae565b9050600f5481101561408457506113be565b600954600160a81b900460ff161561417d576040805160a0810190915260055473e592427a0aece92de3edee1f18e0157c058615649163c04b8d599181906140ea9073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b0316614610565b8152602001306001600160a01b0316815260200142815260200184815260200160008152506040518263ffffffff1660e01b815260040161412b9190614f2b565b602060405180830381600087803b15801561414557600080fd5b505af1158015614159573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131879190614a7e565b600a546005546001600160a01b03918216916338ed17399184916000916141ba9173c00e94cb662c3520282e6f5717214004a7f268889116613523565b30426040518663ffffffff1660e01b81526004016141dc959493929190614fb5565b600060405180830381600087803b1580156141f657600080fd5b505af115801561420a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526122da9190810190614889565b610c858363a9059cbb60e01b8484604051602401612da2929190614c53565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612de8575050151592915050565b60008082156142ac576142a9836112ca86670de0b6b3a76400006130a7565b90505b6142b68582612e72565b91508382106142c3578391505b8582106142ce578591505b6000600960019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561431e57600080fd5b505afa158015614332573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143569190614a7e565b90508061436b84670de0b6b3a76400006130a7565b101580156143795750600a83115b156139805761438983600a612e72565b60095460405163852a12e360e01b815291945061010090046001600160a01b03169063852a12e3906143bf908690600401614f93565b602060405180830381600087803b1580156143d957600080fd5b505af11580156143ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144119190614a7e565b5060095460405163073a938160e11b81526101009091046001600160a01b031690630e75270290614446908690600401614f93565b602060405180830381600087803b15801561446057600080fd5b505af1158015614474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144989190614a7e565b505050949350505050565b6000806144bc670de0b6b3a76400006112ca87866130a7565b90506144c88185612e72565b91508582106144d5578591505b600a821115614607576144e982600a612e72565b60095460405163317afabb60e21b815291935061010090046001600160a01b03169063c5ebeaec9061451f908590600401614f93565b602060405180830381600087803b15801561453957600080fd5b505af115801561454d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145719190614a7e565b506009546005546001600160a01b0361010090920482169163a0712d689161459991166137ae565b6040518263ffffffff1660e01b81526004016145b59190614f93565b602060405180830381600087803b1580156145cf57600080fd5b505af11580156145e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139809190614a7e565b50949350505050565b6005546060906001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561468a5782600960169054906101000a900462ffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260405160200161467493929190614b3a565b6040516020818303038152906040529050612eb7565b6009546040516146d091859162ffffff600160b01b830481169273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc292600160c81b909104909116908790602001614b75565b604051602081830303815290604052905092915050565b60405180610100016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b8035612eb78161511c565b803562ffffff81168114612eb757600080fd5b60006020828403121561475b578081fd5b8135612eb48161511c565b600060208284031215614777578081fd5b8151612eb48161511c565b600080600060608486031215614796578182fd5b83356147a18161511c565b925060208401356147b18161511c565b929592945050506040919091013590565b600080600083850360808112156147d7578384fd5b84356147e28161511c565b93506040601f19820112156147f5578283fd5b506148006040615079565b61480d866020870161472c565b8152604085013560208201529150606084013567ffffffffffffffff811115614834578182fd5b8401601f81018613614844578182fd5b8035614857614852826150c0565b615079565b81815287602083850101111561486b578384fd5b61487c8260208301602086016150e4565b8093505050509250925092565b6000602080838503121561489b578182fd5b825167ffffffffffffffff8111156148b1578283fd5b8301601f810185136148c1578283fd5b80516148cf614852826150a0565b81815283810190838501858402850186018910156148eb578687fd5b8694505b8385101561490d5780518352600194909401939185019185016148ef565b50979650505050505050565b60006020828403121561492a578081fd5b8135612eb481615131565b600060208284031215614946578081fd5b8151612eb481615131565b60008060408385031215614963578182fd5b825161496e81615131565b6020939093015192949293505050565b600080600060608486031215614992578283fd5b835161499d81615131565b6020850151604086015191945092506149b581615131565b809150509250925092565b60006101008083850312156149d3578182fd5b6149dc81615079565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201528091505092915050565b60008060408385031215614a44578182fd5b614a4e8484614737565b9150614a5d8460208501614737565b90509250929050565b600060208284031215614a77578081fd5b5035919050565b600060208284031215614a8f578081fd5b5051919050565b60008060008060808587031215614aab578182fd5b505082516020840151604085015160609095015191969095509092509050565b6000815180845260208085019450808401835b83811015614b035781516001600160a01b031687529582019590820190600101614ade565b509495945050505050565b60008151808452614b268160208601602086016150f0565b601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b6001600160e81b0319166014820152921b166017820152602b0190565b6bffffffffffffffffffffffff19606096871b811682526001600160e81b031960e896871b8116601484015294871b811660178301529290941b909216602b840152921b909116602e82015260420190565b60008251614bd98184602087016150f0565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b81811015614c45578551851683529483019491830191600101614c27565b509098975050505050505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b901515815260200190565b921515835260208301919091526001600160a01b0316604082015260600190565b600060208252612eb46020830184614b0e565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b60208082526009908201526821776974686472617760b81b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b600060208252825160a06020840152614f4760c0840182614b0e565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b62ffffff91909116815260200190565b90815260200190565b600083825260406020830152612de86040830184614acb565b600086825285602083015260a06040830152614fd460a0830186614acb565b6001600160a01b0394909416606083015250608001529392505050565b918252602082015260400190565b9384526020840192909252151560408301526001600160a01b0316606082015260800190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff8111828210171561509857600080fd5b604052919050565b600067ffffffffffffffff8211156150b6578081fd5b5060209081020190565b600067ffffffffffffffff8211156150d6578081fd5b50601f01601f191660200190565b82818337506000910152565b60005b8381101561510b5781810151838201526020016150f3565b838111156132b75750506000910152565b6001600160a01b038116811461117357600080fd5b801515811461117357600080fdfea2646970667358221220405a4621a0971844e754f27a47b66af0df795f8a02534d0656a1b3c6a71c33f664736f6c634300060c00330000000000000000000000005f18c75abdae578b483e5f43f12a39cf75b973a900000000000000000000000039aa39c021dfbae8fac545936693ac917d5e7563
Deployed Bytecode
0x6080604052600436106103c75760003560e01c8063775d35e5116101f2578063c1bb4b541161010d578063e00425a3116100a0578063efbb5cb01161006f578063efbb5cb014610a21578063f017c92f14610a36578063fbfa77cf14610a56578063fcf2d0ad14610a6b576103ce565b8063e00425a3146109b7578063e0b8c948146109cc578063ec38a862146109e1578063ed882c2b14610a01576103ce565b8063ccce1d7f116100dc578063ccce1d7f1461094d578063ce5494bb14610962578063d3406abd14610982578063db2fd74514610997576103ce565b8063c1bb4b54146108ee578063c598484714610903578063c7b9d53014610918578063cb1965dd14610938576103ce565b80639be8ef1411610185578063aef6679e11610154578063aef6679e14610884578063b252720b146108a4578063b2c5f658146108b9578063b2d0c8e2146108ce576103ce565b80639be8ef14146108255780639ec5a8941461083a578063ac00ff261461084f578063aced16611461086f576103ce565b80638cdfe166116101c15780638cdfe166146107bb5780638e6350e2146107d057806391397ab4146107e55780639a561fbf14610805576103ce565b8063775d35e514610751578063853e0a3b1461076657806389be318a1461077b5780638b4187131461079b576103ce565b80632e1a7d4d116102e25780634641257d116102755780636718835f116102445780636718835f146106e557806369e527da146106fa57806373b382851461070f578063748747e614610731576103ce565b80634641257d1461067b57806354f809e3146106905780635641ec03146106b0578063650d1880146106c5576103ce565b8063396794cd116102b1578063396794cd1461060e57806340f8bc431461062e578063418f35cc14610643578063440368a314610666576103ce565b80632e1a7d4d1461058e5780633042087c146105ae578063341b3eb9146105ce5780633631ad5f146105ee576103ce565b80631d12f28b1161035a57806322f3e2d41161032957806322f3e2d41461053a578063258294101461054f57806327cc1ea21461056457806328b7ccf714610579576103ce565b80631d12f28b146104d95780631f1fcd51146104ee5780631fe4a68614610510578063205409d314610525576103ce565b806306fdde031161039657806306fdde03146104555780630ee08f7b146104775780630f969b871461049957806311bc8245146104b9576103ce565b806301681a62146103d35780630268ff0b146103f557806304324af81461042057806305a82f9a14610435576103ce565b366103ce57005b600080fd5b3480156103df57600080fd5b506103f36103ee36600461474a565b610a80565b005b34801561040157600080fd5b5061040a610c8a565b6040516104179190614f93565b60405180910390f35b34801561042c57600080fd5b5061040a610cae565b34801561044157600080fd5b506103f3610450366004614919565b610cb4565b34801561046157600080fd5b5061046a610ccf565b6040516104179190614cb2565b34801561048357600080fd5b5061048c610cf5565b6040516104179190614c86565b3480156104a557600080fd5b506103f36104b4366004614a66565b610cfe565b3480156104c557600080fd5b506103f36104d436600461474a565b610d8b565b3480156104e557600080fd5b5061040a610deb565b3480156104fa57600080fd5b50610503610df1565b6040516104179190614be3565b34801561051c57600080fd5b50610503610e00565b34801561053157600080fd5b5061040a610e0f565b34801561054657600080fd5b5061048c610e15565b34801561055b57600080fd5b5061046a610eb7565b34801561057057600080fd5b506103f3610ed6565b34801561058557600080fd5b5061040a610f56565b34801561059a57600080fd5b5061040a6105a9366004614a66565b610f5c565b3480156105ba57600080fd5b506103f36105c9366004614a66565b61104b565b3480156105da57600080fd5b506103f36105e9366004614919565b611176565b3480156105fa57600080fd5b506103f3610609366004614a66565b611191565b34801561061a57600080fd5b506103f3610629366004614a66565b61119e565b34801561063a57600080fd5b5061048c61120a565b34801561064f57600080fd5b50610658611213565b604051610417929190614ff1565b34801561067257600080fd5b506103f36112d9565b34801561068757600080fd5b506103f36113c0565b34801561069c57600080fd5b506103f36106ab366004614919565b611759565b3480156106bc57600080fd5b5061048c6117ab565b3480156106d157600080fd5b5061048c6106e0366004614a66565b6117b4565b3480156106f157600080fd5b5061048c6117e1565b34801561070657600080fd5b506105036117ea565b34801561071b57600080fd5b506107246117fe565b6040516104179190614f83565b34801561073d57600080fd5b506103f361074c36600461474a565b611810565b34801561075d57600080fd5b506106586118bb565b34801561077257600080fd5b5061040a6119d2565b34801561078757600080fd5b5061040a610796366004614782565b611c2a565b3480156107a757600080fd5b506103f36107b63660046147c2565b611cee565b3480156107c757600080fd5b5061040a611dc1565b3480156107dc57600080fd5b5061040a611dc7565b3480156107f157600080fd5b506103f3610800366004614a66565b611dcc565b34801561081157600080fd5b506103f3610820366004614a66565b611e4e565b34801561083157600080fd5b5061040a611f07565b34801561084657600080fd5b50610503611f42565b34801561085b57600080fd5b506103f361086a366004614919565b611f51565b34801561087b57600080fd5b50610503611f9c565b34801561089057600080fd5b506103f361089f366004614a32565b611fab565b3480156108b057600080fd5b50610503611feb565b3480156108c557600080fd5b50610724611fff565b3480156108da57600080fd5b506103f36108e9366004614919565b612011565b3480156108fa57600080fd5b5061040a612037565b34801561090f57600080fd5b5061048c61203d565b34801561092457600080fd5b506103f361093336600461474a565b61204d565b34801561094457600080fd5b5061048c6120f8565b34801561095957600080fd5b5061040a612106565b34801561096e57600080fd5b506103f361097d36600461474a565b61210c565b34801561098e57600080fd5b5061040a6122de565b3480156109a357600080fd5b506103f36109b2366004614a66565b61239c565b3480156109c357600080fd5b5061040a6123a9565b3480156109d857600080fd5b506105036127b5565b3480156109ed57600080fd5b506103f36109fc36600461474a565b6127c4565b348015610a0d57600080fd5b5061048c610a1c366004614a66565b61284c565b348015610a2d57600080fd5b5061040a612aa1565b348015610a4257600080fd5b506103f3610a51366004614a66565b612b6a565b348015610a6257600080fd5b50610503612bec565b348015610a7757600080fd5b506103f3612bfb565b610a88612df0565b6001600160a01b0316336001600160a01b031614610ac15760405162461bcd60e51b8152600401610ab890614e42565b60405180910390fd5b6005546001600160a01b0382811691161415610aef5760405162461bcd60e51b8152600401610ab890614cea565b6001546001600160a01b0382811691161415610b1d5760405162461bcd60e51b8152600401610ab890614dea565b6060610b27612e6d565b905060005b8151811015610b8257818181518110610b4157fe5b60200260200101516001600160a01b0316836001600160a01b03161415610b7a5760405162461bcd60e51b8152600401610ab890614eb1565b600101610b2c565b50816001600160a01b031663a9059cbb610b9a612df0565b6040516370a0823160e01b81526001600160a01b038616906370a0823190610bc6903090600401614be3565b60206040518083038186803b158015610bde57600080fd5b505afa158015610bf2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c169190614a7e565b6040518363ffffffff1660e01b8152600401610c33929190614c53565b602060405180830381600087803b158015610c4d57600080fd5b505af1158015610c61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c859190614935565b505050565b6000806000610c97611213565b9092509050610ca68282612e72565b925050505b90565b600f5481565b610cbc612ebd565b600e805460ff1916911515919091179055565b60408051808201909152600c81526b23b2b72632bb21b7b6b82b1960a11b602082015290565b60105460ff1681565b6002546001600160a01b0316331480610d2f5750610d1a612df0565b6001600160a01b0316336001600160a01b0316145b610d4b5760405162461bcd60e51b8152600401610ab890614e42565b60088190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a860090610d80908390614f93565b60405180910390a150565b610d93612df0565b6001600160a01b0316336001600160a01b031614610dc35760405162461bcd60e51b8152600401610ab890614e42565b600080546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60085481565b6005546001600160a01b031681565b6002546001600160a01b031681565b600d5481565b6001546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610e4a903090600401614be3565b6101006040518083038186803b158015610e6357600080fd5b505afa158015610e77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9b91906149c0565b604001511180610eb257506000610eb0612aa1565b115b905090565b6040805180820190915260058152640302e332e360dc1b602082015290565b610ede612ebd565b600a546001600160a01b031673d9e1ce17f2641f24ae83637ab66a2cca9c378b9f14610f1e5773d9e1ce17f2641f24ae83637ab66a2cca9c378b9f610f34565b737a250d5630b4cf539739df2c5dacb4c659f2488d5b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b60065481565b6001546000906001600160a01b03163314610f895760405162461bcd60e51b8152600401610ab890614dca565b6000610f9483612ef7565b92509050610fa28183613082565b8314610fc05760405162461bcd60e51b8152600401610ab890614d66565b60055460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90610ff29033908590600401614c53565b602060405180830381600087803b15801561100c57600080fd5b505af1158015611020573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110449190614935565b5050919050565b611053612ebd565b60095460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390611087908490600401614f93565b602060405180830381600087803b1580156110a157600080fd5b505af11580156110b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d99190614a7e565b156110e357600080fd5b60095460405163073a938160e11b81526101009091046001600160a01b031690630e75270290611117908490600401614f93565b602060405180830381600087803b15801561113157600080fd5b505af1158015611145573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111699190614a7e565b1561117357600080fd5b50565b61117e612ebd565b6010805460ff1916911515919091179055565b611199612ebd565b600d55565b6111a6612df0565b6001600160a01b0316336001600160a01b0316146111d65760405162461bcd60e51b8152600401610ab890614e42565b60095460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390611117908490600401614f93565b600e5460ff1681565b6009546040516361bfb47160e11b8152600091829182918291829161010090046001600160a01b03169063c37f68e290611251903090600401614be3565b60806040518083038186803b15801561126957600080fd5b505afa15801561127d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a19190614a96565b935093509350508193506112d0670de0b6b3a76400006112ca83866130a790919063ffffffff16565b906130e1565b94505050509091565b6004546001600160a01b03163314806112fc57506002546001600160a01b031633145b8061131f575061130a612df0565b6001600160a01b0316336001600160a01b0316145b61133b5760405162461bcd60e51b8152600401610ab890614e42565b6001546040805163bf3759b560e01b815290516113be926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561138157600080fd5b505afa158015611395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b99190614a7e565b613123565b565b6004546001600160a01b03163314806113e357506002546001600160a01b031633145b8061140657506113f1612df0565b6001600160a01b0316336001600160a01b0316145b6114225760405162461bcd60e51b8152600401610ab890614e42565b6000806000600160009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561147557600080fd5b505afa158015611489573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ad9190614a7e565b60095490915060009060ff16156115035760006114c8612aa1565b90506114e18382116114da57836114dc565b815b612ef7565b94509150828211156114fd576114f78284612e72565b94508291505b50611514565b61150c826132bd565b919550935090505b6001546040516339ebf82360e01b81526000916001600160a01b0316906339ebf82390611545903090600401614be3565b6101006040518083038186803b15801561155e57600080fd5b505afa158015611572573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159691906149c0565b60a001516001546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc906115cf90889088908790600401615025565b602060405180830381600087803b1580156115e957600080fd5b505af11580156115fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116219190614a7e565b925061162b613464565b61163483613123565b60005460ff168015611655575060005461010090046001600160a01b031615155b156117075760005460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b906116969088908890879089908890600401615056565b60206040518083038186803b1580156116ae57600080fd5b505afa1580156116c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e69190614935565b6117025760405162461bcd60e51b8152600401610ab890614d40565b611715565b6000805460ff191660011790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d5098585848660405161174a949392919061503b565b60405180910390a15050505050565b611761612df0565b6001600160a01b0316336001600160a01b0316146117915760405162461bcd60e51b8152600401610ab890614e42565b601080549115156101000261ff0019909216919091179055565b60095460ff1681565b60006117bf8261284c565b156117cc575060006117dc565b600c546117d76119d2565b111590505b919050565b60005460ff1681565b60095461010090046001600160a01b031681565b600954600160c81b900462ffffff1681565b6002546001600160a01b0316331480611841575061182c612df0565b6001600160a01b0316336001600160a01b0316145b61185d5760405162461bcd60e51b8152600401610ab890614e42565b6001600160a01b03811661187057600080fd5b600480546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490610d80908390614be3565b600954604051633af9e66960e01b815260009182916101009091046001600160a01b031690633af9e669906118f4903090600401614be3565b602060405180830381600087803b15801561190e57600080fd5b505af1158015611922573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119469190614a7e565b6009546040516395dd919360e01b815291935061010090046001600160a01b0316906395dd91939061197c903090600401614be3565b60206040518083038186803b15801561199457600080fd5b505afa1580156119a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119cc9190614a7e565b90509091565b600954604051638e8f294b60e01b81526000918291733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91611a1e9161010090046001600160a01b031690600401614be3565b60606040518083038186803b158015611a3657600080fd5b505afa158015611a4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6e919061497e565b50915050600080611a7d611213565b915091506000600960019054906101000a90046001600160a01b03166001600160a01b031663f8f9da286040518163ffffffff1660e01b815260040160206040518083038186803b158015611ad157600080fd5b505afa158015611ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b099190614a7e565b90506000600960019054906101000a90046001600160a01b03166001600160a01b031663ae9d70b06040518163ffffffff1660e01b815260040160206040518083038186803b158015611b5b57600080fd5b505afa158015611b6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b939190614a7e565b90506000611bad670de0b6b3a76400006112ca87896130a7565b9050806000611bbc86866130a7565b90506000611bca83866130a7565b9050818110611be6576000199950505050505050505050610cab565b6000611bf28489612e72565b90506000611c008484612e72565b9050611c18816112ca84670de0b6b3a76400006130a7565b9b505050505050505050505050610cab565b600081611c3957506000611ce7565b600a546060906001600160a01b031663d06ca61f84611c588888613523565b6040518363ffffffff1660e01b8152600401611c75929190614f9c565b60006040518083038186803b158015611c8d57600080fd5b505afa158015611ca1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611cc99190810190614889565b905080600182510381518110611cdb57fe5b60200260200101519150505b9392505050565b60008082806020019051810190611d059190614951565b909250905033731e0447b19bb6ecfdae1e4ae1694b0c3659614e4e14611d2a57600080fd5b6001600160a01b0385163014611d3f57600080fd5b60095460405163be9b32ab60e01b815273698494b9cbcc51d274e7b2046b23a01c5312c7c39163be9b32ab91611d8a918691869161010090046001600160a01b031690600401614c91565b60006040518083038186803b158015611da257600080fd5b505af4158015611db6573d6000803e3d6000fd5b505050505050505050565b60075481565b600090565b6002546001600160a01b0316331480611dfd5750611de8612df0565b6001600160a01b0316336001600160a01b0316145b611e195760405162461bcd60e51b8152600401610ab890614e42565b60078190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec29890610d80908390614f93565b611e56612ebd565b600954604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91611ea1916101009091046001600160a01b031690600401614be3565b60606040518083038186803b158015611eb957600080fd5b505afa158015611ecd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef1919061497e565b50915050818111611f0157600080fd5b50600b55565b6000806000611f14611213565b915091508160001415611f2c57600092505050610cab565b610ca6826112ca670de0b6b3a7640000846130a7565b6003546001600160a01b031681565b611f59612df0565b6001600160a01b0316336001600160a01b031614611f895760405162461bcd60e51b8152600401610ab890614e42565b6000805460ff1916911515919091179055565b6004546001600160a01b031681565b611fb3612ebd565b6009805462ffffff928316600160c81b0262ffffff60c81b1994909316600160b01b0262ffffff60b01b199091161792909216179055565b60005461010090046001600160a01b031681565b600954600160b01b900462ffffff1681565b612019612ebd565b60098054911515600160a81b0260ff60a81b19909216919091179055565b600b5481565b600954600160a81b900460ff1681565b6002546001600160a01b031633148061207e5750612069612df0565b6001600160a01b0316336001600160a01b0316145b61209a5760405162461bcd60e51b8152600401610ab890614e42565b6001600160a01b0381166120ad57600080fd5b600280546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490610d80908390614be3565b601054610100900460ff1681565b600c5481565b6001546001600160a01b031633148061213d5750612128612df0565b6001600160a01b0316336001600160a01b0316145b61214657600080fd5b6001546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b15801561218d57600080fd5b505afa1580156121a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c59190614766565b6001600160a01b0316146121d857600080fd5b6121e1816136a4565b6005546040516370a0823160e01b81526001600160a01b039091169063a9059cbb90839083906370a082319061221b903090600401614be3565b60206040518083038186803b15801561223357600080fd5b505afa158015612247573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226b9190614a7e565b6040518363ffffffff1660e01b8152600401612288929190614c53565b602060405180830381600087803b1580156122a257600080fd5b505af11580156122b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122da9190614935565b5050565b6000806122e9612aa1565b6001546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf8239061231f903090600401614be3565b6101006040518083038186803b15801561233857600080fd5b505afa15801561234c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237091906149c0565b60a0015190508181111561238957600092505050610cab565b6123938282612e72565b92505050610cab565b6123a4612ebd565b600f55565b60008060006123b6611213565b9150915081600014156123ce57600092505050610cab565b600954604051636aa875b560e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91636aa875b591612419916101009091046001600160a01b031690600401614be3565b60206040518083038186803b15801561243157600080fd5b505afa158015612445573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124699190614a7e565b6009546040516303d290cf60e61b8152919250600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b9163f4a433c0916124b69161010090046001600160a01b031690600401614be3565b60206040518083038186803b1580156124ce57600080fd5b505afa1580156124e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125069190614a7e565b90506000600960019054906101000a90046001600160a01b03166001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b15801561255857600080fd5b505afa15801561256c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125909190614a7e565b90506000600960019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156125e257600080fd5b505afa1580156125f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261a9190614a7e565b905060006126ba670de0b6b3a76400006112ca600960019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561267b57600080fd5b505afa15801561268f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b39190614a7e565b85906130a7565b9050600081156126d5576126d2826112ca8a896130a7565b90505b600084156126ee576126eb856112ca8a896130a7565b90505b60006126fa8383613082565b6001546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf82390612730903090600401614be3565b6101006040518083038186803b15801561274957600080fd5b505afa15801561275d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278191906149c0565b6080015190506000612798600d6112ca4285612e72565b90506127a481846130a7565b9c5050505050505050505050505090565b600a546001600160a01b031681565b6002546001600160a01b031633146127ee5760405162461bcd60e51b8152600401610ab890614cc5565b6001600160a01b03811661280157600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06990610d80908390614be3565b60006128566146e7565b6001546040516339ebf82360e01b81526001600160a01b03909116906339ebf82390612886903090600401614be3565b6101006040518083038186803b15801561289f57600080fd5b505afa1580156128b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d791906149c0565b90508060200151600014156128f05760009150506117dc565b6006546080820151612903904290612e72565b106129125760019150506117dc565b6001546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561295757600080fd5b505afa15801561296b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298f9190614a7e565b90506008548111156129a6576001925050506117dc565b60006129b0612aa1565b90508260a001516129cc6008548361308290919063ffffffff16565b10156129de57600193505050506117dc565b60008360a001518211156129ff5760a08401516129fc908390612e72565b90505b6001546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b158015612a4457600080fd5b505afa158015612a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7c9190614a7e565b9050612a888183613082565b600754612a9590896130a7565b10979650505050505050565b6000806000612aae611213565b915091506000612abc6123a9565b90506000612add73c00e94cb662c3520282e6f5717214004a7f268886137ae565b600554909150600090612b139073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b03166107968686613082565b90506000612b27600a6112ca8460096130a7565b9050612b5f85612b5983612b538a612b53600560009054906101000a90046001600160a01b03166137ae565b90613082565b90612e72565b965050505050505090565b6002546001600160a01b0316331480612b9b5750612b86612df0565b6001600160a01b0316336001600160a01b0316145b612bb75760405162461bcd60e51b8152600401610ab890614e42565b60068190556040517f4aaf232568bff365c53cad69bdb6e83014e79df80216ceba8ee01769723dfd6890610d80908390614f93565b6001546001600160a01b031681565b6002546001600160a01b0316331480612c2c5750612c17612df0565b6001600160a01b0316336001600160a01b0316145b612c485760405162461bcd60e51b8152600401610ab890614e42565b6009805460ff19166001908117909155546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b158015612c9c57600080fd5b505af1158015612cb0573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b801580612d675750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e90612d159030908690600401614c6c565b60206040518083038186803b158015612d2d57600080fd5b505afa158015612d41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d659190614a7e565b155b612d835760405162461bcd60e51b8152600401610ab890614ed5565b610c858363095ea7b360e01b8484604051602401612da2929190614c53565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261382d565b6060612de884846000856138bc565b949350505050565b60015460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b158015612e3557600080fd5b505afa158015612e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb29190614766565b606090565b6000612eb483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061398a565b90505b92915050565b612ec5612df0565b6001600160a01b0316336001600160a01b03161480612eee57506002546001600160a01b031633145b6113be57600080fd5b60055460009081908190612f13906001600160a01b03166137ae565b90506000612f2382612b53610c8a565b90506000600160009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b158015612f7557600080fd5b505afa158015612f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fad9190614a7e565b905081811115612fc457612fc18183612e72565b93505b8582101561303e57600080612fd76118bb565b915091506001612ffb600960019054906101000a90046001600160a01b03166137ae565b11156130155761301361300e8383612e72565b6139b6565b505b600554613035908990613030906001600160a01b03166137ae565b613c6a565b9650505061307a565b858310156130765761305361300e8785612e72565b5060055461306f908790613030906001600160a01b03166137ae565b945061307a565b8594505b505050915091565b600082820183811015612eb45760405162461bcd60e51b8152600401610ab890614d09565b6000826130b657506000612eb7565b828202828482816130c357fe5b0414612eb45760405162461bcd60e51b8152600401610ab890614d89565b6000612eb483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613c80565b60095460ff161561313357611173565b60055460009061314b906001600160a01b03166137ae565b90508181101561318d576009546001906131729061010090046001600160a01b03166137ae565b11156131875761318561300e8383612e72565b505b50611173565b60008061319d8484036001613cb7565b91509150600d548211156132b75760105460ff166131ef5760005b82156131e9576131d26131cb8484613da9565b8490612e72565b9250600681106131e1576131e9565b6001016131b8565b506132b7565b6005546040516370a0823160e01b81526001600160a01b03909116906370a082319061323390731e0447b19bb6ecfdae1e4ae1694b0c3659614e4e90600401614be3565b60206040518083038186803b15801561324b57600080fd5b505afa15801561325f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132839190614a7e565b8211156132a15761329e6132978383613da9565b8390612e72565b91505b600d548211156132b7576132b58183613ee5565b505b50505050565b600954600090819081906132de9061010090046001600160a01b03166137ae565b61330e576005546000906132fa906001600160a01b03166137ae565b90506133068186613c6a565b91505061345d565b6000806133196118bb565b91509150613325613f80565b61332d614053565b600554600090613345906001600160a01b03166137ae565b905060006133538484612e72565b905060006133618284613082565b6001546040516339ebf82360e01b81529192506000916001600160a01b03909116906339ebf82390613397903090600401614be3565b6101006040518083038186803b1580156133b057600080fd5b505afa1580156133c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e891906149c0565b60a0015190508082111561343d576134008282612e72565b98508884101561341257839850613438565b61341c898b613082565b84111561342b57899650613438565b613435848a612e72565b96505b613456565b6134478183612e72565b9750613453848b613c6a565b96505b5050505050505b9193909250565b6001546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613495903090600401614be3565b60206040518083038186803b1580156134ad57600080fd5b505afa1580156134c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e59190614a7e565b905080156111735760015460035460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92612288929116908590600401614c53565b606060006001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2148061356e57506001600160a01b03831673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b90508061357c57600361357f565b60025b60ff1667ffffffffffffffff8111801561359857600080fd5b506040519080825280602002602001820160405280156135c2578160200160208202803683370190505b50915083826000815181106135d357fe5b60200260200101906001600160a01b031690816001600160a01b031681525050801561362c57828260018151811061360757fe5b60200260200101906001600160a01b031690816001600160a01b03168152505061369d565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28260018151811061364e57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050828260028151811061367c57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b5092915050565b601054610100900460ff16611173576000806136be6118bb565b90925090506136d061300e8383612e72565b506009546040516361bfb47160e11b815260009161010090046001600160a01b03169063c37f68e290613707903090600401614be3565b60806040518083038186803b15801561371f57600080fd5b505afa158015613733573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137579190614a96565b5092505050612710811061376a57600080fd5b73c00e94cb662c3520282e6f5717214004a7f26888600061378a826137ae565b905080156137a6576137a66001600160a01b0383168783614232565b505050505050565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906137dd903090600401614be3565b60206040518083038186803b1580156137f557600080fd5b505afa158015613809573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb79190614a7e565b6060613882826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612dd99092919063ffffffff16565b805190915015610c8557808060200190518101906138a09190614935565b610c855760405162461bcd60e51b8152600401610ab890614e67565b60606138c785614251565b6138e35760405162461bcd60e51b8152600401610ab890614e0b565b60006060866001600160a01b031685876040516139009190614bc7565b60006040518083038185875af1925050503d806000811461393d576040519150601f19603f3d011682016040523d82523d6000602084013e613942565b606091505b50915091508115613956579150612de89050565b8051156139665780518082602001fd5b8360405162461bcd60e51b8152600401610ab89190614cb2565b5050949350505050565b600081848411156139ae5760405162461bcd60e51b8152600401610ab89190614cb2565b505050900390565b60008060006139c6846000613cb7565b915091508080156139d85750600d5482115b15613a3e5760105460ff16156139f8576139f56132978284613ee5565b91505b60005b600d54613a09906064613082565b831115613a3c57613a1e6131cb846001613da9565b9250600101600560ff821610613a375760019350613a3c565b6139fb565b505b600080613a49611213565b600b549193509150600081613a635766038d7ea4c6800091505b613a79826112ca85670de0b6b3a76400006130a7565b9050808410613bae576000613a8e8583612e72565b905088811015613b245760095460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390613acc908490600401614f93565b602060405180830381600087803b158015613ae657600080fd5b505af1158015613afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1e9190614a7e565b50613bac565b60095460405163852a12e360e01b81526101009091046001600160a01b03169063852a12e390613b58908c90600401614f93565b602060405180830381600087803b158015613b7257600080fd5b505af1158015613b86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613baa9190614a7e565b505b505b600b54158015613bd257506005548390613bd0906001600160a01b03166137ae565b115b15613c5f5760095460405163073a938160e11b81526101009091046001600160a01b031690630e75270290613c0b908690600401614f93565b602060405180830381600087803b158015613c2557600080fd5b505af1158015613c39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c5d9190614a7e565b505b505050505050919050565b6000818310613c795781612eb4565b5090919050565b60008183613ca15760405162461bcd60e51b8152600401610ab89190614cb2565b506000838581613cad57fe5b0495945050505050565b600080600080613cc56118bb565b90925090506000613cd68383612e72565b905060008615613cf157613cea8289613082565b9050613d0a565b81881115613cfd578197505b613d078289612e72565b90505b6000613d21600b54836130a790919063ffffffff16565b90506000613d42600b54670de0b6b3a7640000612e7290919063ffffffff16565b90506000613d5083836130e1565b9050620186a0811115613d6d57613d6a81620186a0612e72565b90505b85811015613d8a5760019750613d838682612e72565b9850613d9b565b60009750613d988187612e72565b98505b505050505050509250929050565b6000806000613db6611213565b91509150806000148015613dc75750835b15613dd757600092505050612eb7565b600954604051638e8f294b60e01b8152600091733d9819210a31b4961b30ef54be2aed79b9c9cd3b91638e8f294b91613e22916101009091046001600160a01b031690600401614be3565b60606040518083038186803b158015613e3a57600080fd5b505afa158015613e4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e72919061497e565b509150508415613e8f57613e888684848461428a565b9350613e9e565b613e9b868484846144a3565b93505b7f012a05dea1e4b56be6c250aaa3e6189a1f531f1fd201b35b2a74c56577000bf48685876000604051613ed49493929190614fff565b60405180910390a150505092915050565b600554604051634cab28bb60e11b815260009173698494b9cbcc51d274e7b2046b23a01c5312c7c391639956517691613f3091879187916001600160a01b0390911690600401614c91565b60206040518083038186803b158015613f4857600080fd5b505af4158015613f5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb49190614a7e565b600e5460ff1615613f90576113be565b60408051600180825281830190925260609160208083019080368337019050509050600960019054906101000a90046001600160a01b031681600081518110613fd557fe5b6001600160a01b039092166020928302919091019091015260405162e1ed9760e51b8152733d9819210a31b4961b30ef54be2aed79b9c9cd3b90631c3db2e0906140259030908590600401614bf7565b600060405180830381600087803b15801561403f57600080fd5b505af11580156132b5573d6000803e3d6000fd5b600061407273c00e94cb662c3520282e6f5717214004a7f268886137ae565b9050600f5481101561408457506113be565b600954600160a81b900460ff161561417d576040805160a0810190915260055473e592427a0aece92de3edee1f18e0157c058615649163c04b8d599181906140ea9073c00e94cb662c3520282e6f5717214004a7f26888906001600160a01b0316614610565b8152602001306001600160a01b0316815260200142815260200184815260200160008152506040518263ffffffff1660e01b815260040161412b9190614f2b565b602060405180830381600087803b15801561414557600080fd5b505af1158015614159573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131879190614a7e565b600a546005546001600160a01b03918216916338ed17399184916000916141ba9173c00e94cb662c3520282e6f5717214004a7f268889116613523565b30426040518663ffffffff1660e01b81526004016141dc959493929190614fb5565b600060405180830381600087803b1580156141f657600080fd5b505af115801561420a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526122da9190810190614889565b610c858363a9059cbb60e01b8484604051602401612da2929190614c53565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612de8575050151592915050565b60008082156142ac576142a9836112ca86670de0b6b3a76400006130a7565b90505b6142b68582612e72565b91508382106142c3578391505b8582106142ce578591505b6000600960019054906101000a90046001600160a01b03166001600160a01b031663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561431e57600080fd5b505afa158015614332573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143569190614a7e565b90508061436b84670de0b6b3a76400006130a7565b101580156143795750600a83115b156139805761438983600a612e72565b60095460405163852a12e360e01b815291945061010090046001600160a01b03169063852a12e3906143bf908690600401614f93565b602060405180830381600087803b1580156143d957600080fd5b505af11580156143ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144119190614a7e565b5060095460405163073a938160e11b81526101009091046001600160a01b031690630e75270290614446908690600401614f93565b602060405180830381600087803b15801561446057600080fd5b505af1158015614474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144989190614a7e565b505050949350505050565b6000806144bc670de0b6b3a76400006112ca87866130a7565b90506144c88185612e72565b91508582106144d5578591505b600a821115614607576144e982600a612e72565b60095460405163317afabb60e21b815291935061010090046001600160a01b03169063c5ebeaec9061451f908590600401614f93565b602060405180830381600087803b15801561453957600080fd5b505af115801561454d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145719190614a7e565b506009546005546001600160a01b0361010090920482169163a0712d689161459991166137ae565b6040518263ffffffff1660e01b81526004016145b59190614f93565b602060405180830381600087803b1580156145cf57600080fd5b505af11580156145e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139809190614a7e565b50949350505050565b6005546060906001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561468a5782600960169054906101000a900462ffffff1673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260405160200161467493929190614b3a565b6040516020818303038152906040529050612eb7565b6009546040516146d091859162ffffff600160b01b830481169273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc292600160c81b909104909116908790602001614b75565b604051602081830303815290604052905092915050565b60405180610100016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b8035612eb78161511c565b803562ffffff81168114612eb757600080fd5b60006020828403121561475b578081fd5b8135612eb48161511c565b600060208284031215614777578081fd5b8151612eb48161511c565b600080600060608486031215614796578182fd5b83356147a18161511c565b925060208401356147b18161511c565b929592945050506040919091013590565b600080600083850360808112156147d7578384fd5b84356147e28161511c565b93506040601f19820112156147f5578283fd5b506148006040615079565b61480d866020870161472c565b8152604085013560208201529150606084013567ffffffffffffffff811115614834578182fd5b8401601f81018613614844578182fd5b8035614857614852826150c0565b615079565b81815287602083850101111561486b578384fd5b61487c8260208301602086016150e4565b8093505050509250925092565b6000602080838503121561489b578182fd5b825167ffffffffffffffff8111156148b1578283fd5b8301601f810185136148c1578283fd5b80516148cf614852826150a0565b81815283810190838501858402850186018910156148eb578687fd5b8694505b8385101561490d5780518352600194909401939185019185016148ef565b50979650505050505050565b60006020828403121561492a578081fd5b8135612eb481615131565b600060208284031215614946578081fd5b8151612eb481615131565b60008060408385031215614963578182fd5b825161496e81615131565b6020939093015192949293505050565b600080600060608486031215614992578283fd5b835161499d81615131565b6020850151604086015191945092506149b581615131565b809150509250925092565b60006101008083850312156149d3578182fd5b6149dc81615079565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201528091505092915050565b60008060408385031215614a44578182fd5b614a4e8484614737565b9150614a5d8460208501614737565b90509250929050565b600060208284031215614a77578081fd5b5035919050565b600060208284031215614a8f578081fd5b5051919050565b60008060008060808587031215614aab578182fd5b505082516020840151604085015160609095015191969095509092509050565b6000815180845260208085019450808401835b83811015614b035781516001600160a01b031687529582019590820190600101614ade565b509495945050505050565b60008151808452614b268160208601602086016150f0565b601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b6001600160e81b0319166014820152921b166017820152602b0190565b6bffffffffffffffffffffffff19606096871b811682526001600160e81b031960e896871b8116601484015294871b811660178301529290941b909216602b840152921b909116602e82015260420190565b60008251614bd98184602087016150f0565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b81811015614c45578551851683529483019491830191600101614c27565b509098975050505050505050565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b901515815260200190565b921515835260208301919091526001600160a01b0316604082015260600190565b600060208252612eb46020830184614b0e565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b60208082526009908201526821776974686472617760b81b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b600060208252825160a06020840152614f4760c0840182614b0e565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b62ffffff91909116815260200190565b90815260200190565b600083825260406020830152612de86040830184614acb565b600086825285602083015260a06040830152614fd460a0830186614acb565b6001600160a01b0394909416606083015250608001529392505050565b918252602082015260400190565b9384526020840192909252151560408301526001600160a01b0316606082015260800190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff8111828210171561509857600080fd5b604052919050565b600067ffffffffffffffff8211156150b6578081fd5b5060209081020190565b600067ffffffffffffffff8211156150d6578081fd5b50601f01601f191660200190565b82818337506000910152565b60005b8381101561510b5781810151838201526020016150f3565b838111156132b75750506000910152565b6001600160a01b038116811461117357600080fd5b801515811461117357600080fdfea2646970667358221220405a4621a0971844e754f27a47b66af0df795f8a02534d0656a1b3c6a71c33f664736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005f18c75abdae578b483e5f43f12a39cf75b973a900000000000000000000000039aa39c021dfbae8fac545936693ac917d5e7563
-----Decoded View---------------
Arg [0] : _vault (address): 0x5f18C75AbDAe578b483E5F43f12a39cF75b973a9
Arg [1] : _cToken (address): 0x39AA39c021dfbaE8faC545936693aC917d5E7563
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000005f18c75abdae578b483e5f43f12a39cf75b973a9
Arg [1] : 00000000000000000000000039aa39c021dfbae8fac545936693ac917d5e7563
Deployed Bytecode Sourcemap
89349:29950:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81881:440;;;;;;;;;;-1:-1:-1;81881:440:0;;;;;:::i;:::-;;:::i;:::-;;100778:172;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;91066:28;;;;;;;;;;;;;:::i;93260:116::-;;;;;;;;;;-1:-1:-1;93260:116:0;;;;;:::i;:::-;;:::i;91613:102::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;91140:22::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;64454:175::-;;;;;;;;;;-1:-1:-1;64454:175:0;;;;;:::i;:::-;;:::i;60725:115::-;;;;;;;;;;-1:-1:-1;60725:115:0;;;;;:::i;:::-;;:::i;59099:32::-;;;;;;;;;;;;;:::i;58075:18::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;57984:25::-;;;;;;;;;;;;;:::i;90909:22::-;;;;;;;;;;;;;:::i;66653:148::-;;;;;;;;;;;;;:::i;56624:91::-;;;;;;;;;;;;;:::i;93488:154::-;;;;;;;;;;;;;:::i;58705:37::-;;;;;;;;;;;;;:::i;78378:602::-;;;;;;;;;;-1:-1:-1;78378:602:0;;;;;:::i;:::-;;:::i;117397:176::-;;;;;;;;;;-1:-1:-1;117397:176:0;;;;;:::i;:::-;;:::i;93650:86::-;;;;;;;;;;-1:-1:-1;93650:86:0;;;;;:::i;:::-;;:::i;93981:95::-;;;;;;;;;;-1:-1:-1;93981:95:0;;;;;:::i;:::-;;:::i;117667:129::-;;;;;;;;;;-1:-1:-1;117667:129:0;;;;;:::i;:::-;;:::i;91001:25::-;;;;;;;;;;;;;:::i;100074:317::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;71903:170::-;;;;;;;;;;;;;:::i;76119:2015::-;;;;;;;;;;;;;:::i;93744:102::-;;;;;;;;;;-1:-1:-1;93744:102:0;;;;;:::i;:::-;;:::i;59182:25::-;;;;;;;;;;;;;:::i;96091:278::-;;;;;;;;;;-1:-1:-1;96091:278:0;;;;;:::i;:::-;;:::i;56281:25::-;;;;;;;;;;;;;:::i;90054:21::-;;;;;;;;;;;;;:::i;90220:31::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;61957:174::-;;;;;;;;;;-1:-1:-1;61957:174:0;;;;;:::i;:::-;;:::i;100428:313::-;;;;;;;;;;;;;:::i;97261:935::-;;;;;;;;;;;;;:::i;96457:322::-;;;;;;;;;;-1:-1:-1;96457:322:0;;;;;:::i;:::-;;:::i;118675:384::-;;;;;;;;;;-1:-1:-1;118675:384:0;;;;;:::i;:::-;;:::i;58915:33::-;;;;;;;;;;;;;:::i;57854:94::-;;;;;;;;;;;;;:::i;63728:169::-;;;;;;;;;;-1:-1:-1;63728:169:0;;;;;:::i;:::-;;:::i;94084:280::-;;;;;;;;;;-1:-1:-1;94084:280:0;;;;;:::i;:::-;;:::i;118353:259::-;;;;;;;;;;;;;:::i;58016:22::-;;;;;;;;;;;;;:::i;60848:120::-;;;;;;;;;;-1:-1:-1;60848:120:0;;;;;:::i;:::-;;:::i;58045:21::-;;;;;;;;;;;;;:::i;93046:206::-;;;;;;;;;;-1:-1:-1;93046:206:0;;;;;:::i;:::-;;:::i;56313:26::-;;;;;;;;;;;;;:::i;90182:31::-;;;;;;;;;;;;;:::i;93384:96::-;;;;;;;;;;-1:-1:-1;93384:96:0;;;;;:::i;:::-;;:::i;90702:31::-;;;;;;;;;;;;;:::i;90084:20::-;;;;;;;;;;;;;:::i;61201:202::-;;;;;;;;;;-1:-1:-1;61201:202:0;;;;;:::i;:::-;;:::i;91218:24::-;;;;;;;;;;;;;:::i;90809:44::-;;;;;;;;;;;;;:::i;79571:307::-;;;;;;;;;;-1:-1:-1;79571:307:0;;;;;:::i;:::-;;:::i;95448:327::-;;;;;;;;;;;;;:::i;93854:119::-;;;;;;;;;;-1:-1:-1;93854:119:0;;;;;:::i;:::-;;:::i;98370:1476::-;;;;;;;;;;;;;:::i;90258:41::-;;;;;;;;;;;;;:::i;62479:181::-;;;;;;;;;;-1:-1:-1;62479:181:0;;;;;:::i;:::-;;:::i;73809:1504::-;;;;;;;;;;-1:-1:-1;73809:1504:0;;;;;:::i;:::-;;:::i;94613:642::-;;;;;;;;;;;;;:::i;63177:151::-;;;;;;;;;;-1:-1:-1;63177:151:0;;;;;:::i;:::-;;:::i;57956:21::-;;;;;;;;;;;;;:::i;80307:164::-;;;;;;;;;;;;;:::i;81881:440::-;59549:12;:10;:12::i;:::-;-1:-1:-1;;;;;59535:26:0;:10;-1:-1:-1;;;;;59535:26:0;;59527:50;;;;-1:-1:-1;;;59527:50:0;;;;;;;:::i;:::-;;;;;;;;;81973:4:::1;::::0;-1:-1:-1;;;;;81955:23:0;;::::1;81973:4:::0;::::1;81955:23;;81947:41;;;;-1:-1:-1::0;;;81947:41:0::1;;;;;;;:::i;:::-;82025:5;::::0;-1:-1:-1;;;;;82007:24:0;;::::1;82025:5:::0;::::1;82007:24;;81999:44;;;;-1:-1:-1::0;;;81999:44:0::1;;;;;;;:::i;:::-;82056:33;82092:17;:15;:17::i;:::-;82056:53;;82125:9;82120:102;82140:16;:23;82136:1;:27;82120:102;;;82188:16;82205:1;82188:19;;;;;;;;;;;;;;-1:-1:-1::0;;;;;82178:29:0::1;:6;-1:-1:-1::0;;;;;82178:29:0::1;;;82170:52;;;;-1:-1:-1::0;;;82170:52:0::1;;;;;;;:::i;:::-;82165:3;;82120:102;;;;82242:6;-1:-1:-1::0;;;;;82235:23:0::1;;82259:12;:10;:12::i;:::-;82273:39;::::0;-1:-1:-1;;;82273:39:0;;-1:-1:-1;;;;;82273:24:0;::::1;::::0;::::1;::::0;:39:::1;::::0;82306:4:::1;::::0;82273:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;82235:78;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;59588:1;81881:440:::0;:::o;100778:172::-;100825:7;100846:16;100864:15;100883:20;:18;:20::i;:::-;100845:58;;-1:-1:-1;100845:58:0;-1:-1:-1;100921:21:0;100845:58;;100921:12;:21::i;:::-;100914:28;;;;100778:172;;:::o;91066:28::-;;;;:::o;93260:116::-;119264:12;:10;:12::i;:::-;93338:13:::1;:30:::0;;-1:-1:-1;;93338:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;93260:116::o;91613:102::-;91686:21;;;;;;;;;;;;-1:-1:-1;;;91686:21:0;;;;91613:102;:::o;91140:22::-;;;;;;:::o;64454:175::-;59293:10;;-1:-1:-1;;;;;59293:10:0;59279;:24;;:54;;;59321:12;:10;:12::i;:::-;-1:-1:-1;;;;;59307:26:0;:10;-1:-1:-1;;;;;59307:26:0;;59279:54;59271:78;;;;-1:-1:-1;;;59271:78:0;;;;;;;:::i;:::-;64539:13:::1;:30:::0;;;64585:36:::1;::::0;::::1;::::0;::::1;::::0;64555:14;;64585:36:::1;:::i;:::-;;;;;;;;64454:175:::0;:::o;60725:115::-;59549:12;:10;:12::i;:::-;-1:-1:-1;;;;;59535:26:0;:10;-1:-1:-1;;;;;59535:26:0;;59527:50;;;;-1:-1:-1;;;59527:50:0;;;;;;;:::i;:::-;60806:11:::1;:26:::0;;-1:-1:-1;;;;;60806:26:0;;::::1;;;-1:-1:-1::0;;;;;;60806:26:0;;::::1;::::0;;;::::1;::::0;;60725:115::o;59099:32::-;;;;:::o;58075:18::-;;;-1:-1:-1;;;;;58075:18:0;;:::o;57984:25::-;;;-1:-1:-1;;;;;57984:25:0;;:::o;90909:22::-;;;;:::o;66653:148::-;66718:5;;:31;;-1:-1:-1;;;66718:31:0;;66694:4;;;;-1:-1:-1;;;;;66718:5:0;;;;:16;;:31;;66743:4;;66718:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;:45;:75;;;;66792:1;66767:22;:20;:22::i;:::-;:26;66718:75;66711:82;;66653:148;:::o;56624:91::-;56693:14;;;;;;;;;;;;-1:-1:-1;;;56693:14:0;;;;56624:91;:::o;93488:154::-;119264:12;:10;:12::i;:::-;93566:15:::1;::::0;-1:-1:-1;;;;;93566:15:0::1;90518:42;93566:34;:68;;90518:42;93566:68;;;90386:42;93566:68;93548:15;:86:::0;;-1:-1:-1;;;;;;93548:86:0::1;-1:-1:-1::0;;;;;93548:86:0;;;::::1;::::0;;;::::1;::::0;;93488:154::o;58705:37::-;;;;:::o;78378:602::-;78493:5;;78437:13;;-1:-1:-1;;;;;78493:5:0;78471:10;:28;78463:47;;;;-1:-1:-1;;;78463:47:0;;;;;;;:::i;:::-;78590:19;78643:32;78661:13;78643:17;:32::i;:::-;78620:55;-1:-1:-1;78620:55:0;-1:-1:-1;78736:22:0;78620:55;;78736:15;:22::i;:::-;78719:13;:39;78711:61;;;;-1:-1:-1;;;78711:61:0;;;;;;;:::i;:::-;78864:4;;:38;;-1:-1:-1;;;78864:38:0;;-1:-1:-1;;;;;78864:4:0;;;;:13;;:38;;78878:10;;78890:11;;78864:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;78378:602;;;;:::o;117397:176::-;119264:12;:10;:12::i;:::-;117477:6:::1;::::0;:31:::1;::::0;-1:-1:-1;;;117477:31:0;;:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;117477:6:0::1;::::0;:23:::1;::::0;:31:::1;::::0;117501:6;;117477:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:36:::0;117469:45:::1;;;::::0;::::1;;117533:6;::::0;:26:::1;::::0;-1:-1:-1;;;117533:26:0;;:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;117533:6:0::1;::::0;:18:::1;::::0;:26:::1;::::0;117552:6;;117533:26:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:31:::0;117525:40:::1;;;::::0;::::1;;117397:176:::0;:::o;93650:86::-;119264:12;:10;:12::i;:::-;93710:10:::1;:18:::0;;-1:-1:-1;;93710:18:0::1;::::0;::::1;;::::0;;;::::1;::::0;;93650:86::o;93981:95::-;119264:12;:10;:12::i;:::-;94050:7:::1;:18:::0;93981:95::o;117667:129::-;59549:12;:10;:12::i;:::-;-1:-1:-1;;;;;59535:26:0;:10;-1:-1:-1;;;;;59535:26:0;;59527:50;;;;-1:-1:-1;;;59527:50:0;;;;;;;:::i;:::-;117752:6:::1;::::0;:31:::1;::::0;-1:-1:-1;;;117752:31:0;;:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;117752:6:0::1;::::0;:23:::1;::::0;:31:::1;::::0;117776:6;;117752:31:::1;;;:::i;91001:25::-:0;;;;;;:::o;100074:317::-;100244:6;;:40;;-1:-1:-1;;;100244:40:0;;100125:16;;;;;;;;;;100244:6;;;-1:-1:-1;;;;;100244:6:0;;:25;;:40;;100278:4;;100244:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100171:113;;;;;;;100305:13;100295:23;;100342:41;100378:4;100342:31;100360:12;100342:13;:17;;:31;;;;:::i;:::-;:35;;:41::i;:::-;100331:52;;100074:317;;;;;:::o;71903:170::-;59661:6;;-1:-1:-1;;;;;59661:6:0;59647:10;:20;;:48;;-1:-1:-1;59685:10:0;;-1:-1:-1;;;;;59685:10:0;59671;:24;59647:48;:78;;;;59713:12;:10;:12::i;:::-;-1:-1:-1;;;;;59699:26:0;:10;-1:-1:-1;;;;;59699:26:0;;59647:78;59639:102;;;;-1:-1:-1;;;59639:102:0;;;;;;;:::i;:::-;72041:5:::1;::::0;:23:::1;::::0;;-1:-1:-1;;;72041:23:0;;;;72026:39:::1;::::0;-1:-1:-1;;;;;72041:5:0::1;::::0;:21:::1;::::0;:23:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:5;:23;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72026:14;:39::i;:::-;71903:170::o:0;76119:2015::-;59661:6;;-1:-1:-1;;;;;59661:6:0;59647:10;:20;;:48;;-1:-1:-1;59685:10:0;;-1:-1:-1;;;;;59685:10:0;59671;:24;59647:48;:78;;;;59713:12;:10;:12::i;:::-;-1:-1:-1;;;;;59699:26:0;:10;-1:-1:-1;;;;;59699:26:0;;59647:78;59639:102;;;;-1:-1:-1;;;59639:102:0;;;;;;;:::i;:::-;76170:14:::1;76199:12:::0;76226:23:::1;76252:5;;;;;;;;;-1:-1:-1::0;;;;;76252:5:0::1;-1:-1:-1::0;;;;;76252:21:0::1;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;76324:13;::::0;76226:49;;-1:-1:-1;76286:19:0::1;::::0;76324:13:::1;;76320:731;;;76406:19;76428:22;:20;:22::i;:::-;76406:44;;76584:80;76616:15;76602:11;:29;:61;;76648:15;76602:61;;;76634:11;76602:61;76584:17;:80::i;:::-;76562:102:::0;-1:-1:-1;76562:102:0;-1:-1:-1;76742:29:0;;::::1;76738:159;;;76801:32;:11:::0;76817:15;76801::::1;:32::i;:::-;76792:41;;76866:15;76852:29;;76738:159;76320:731;;;;77009:30;77023:15;77009:13;:30::i;:::-;76979:60:::0;;-1:-1:-1;76979:60:0;-1:-1:-1;76979:60:0;-1:-1:-1;76320:731:0::1;77267:5;::::0;:31:::1;::::0;-1:-1:-1;;;77267:31:0;;77247:17:::1;::::0;-1:-1:-1;;;;;77267:5:0::1;::::0;:16:::1;::::0;:31:::1;::::0;77292:4:::1;::::0;77267:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;::::0;77337:5:::1;::::0;:39:::1;::::0;-1:-1:-1;;;77337:39:0;;77267:41;;-1:-1:-1;;;;;;77337:5:0::1;::::0;:12:::1;::::0;:39:::1;::::0;77350:6;;77358:4;;77364:11;;77337:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77319:57;;77468:19;:17;:19::i;:::-;77563:31;77578:15;77563:14;:31::i;:::-;77649:13;::::0;::::1;;:42:::0;::::1;;;-1:-1:-1::0;77689:1:0::1;77666:11:::0;::::1;::::0;::::1;-1:-1:-1::0;;;;;77666:11:0::1;:25:::0;::::1;77649:42;77645:411;;;77746:11;::::0;77734:209:::1;::::0;-1:-1:-1;;;77734:209:0;;77746:11:::1;::::0;;::::1;-1:-1:-1::0;;;;;77746:11:0::1;::::0;77734:30:::1;::::0;:209:::1;::::0;77787:6;;77816:4;;77843:11;;77877:15;;77915:9;;77734:209:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77708:283;;;;-1:-1:-1::0;;;77708:283:0::1;;;;;;;:::i;:::-;77645:411;;;78024:13;:20:::0;;-1:-1:-1;;78024:20:0::1;78040:4;78024:20;::::0;;77645:411:::1;78073:53;78083:6;78091:4;78097:11;78110:15;78073:53;;;;;;;;;:::i;:::-;;;;;;;;59752:1;;;;;76119:2015::o:0;93744:102::-;59549:12;:10;:12::i;:::-;-1:-1:-1;;;;;59535:26:0;:10;-1:-1:-1;;;;;59535:26:0;;59527:50;;;;-1:-1:-1;;;59527:50:0;;;;;;;:::i;:::-;93817:12:::1;:21:::0;;;::::1;;;;-1:-1:-1::0;;93817:21:0;;::::1;::::0;;;::::1;::::0;;93744:102::o;59182:25::-;;;;;;:::o;96091:278::-;96159:4;96180:23;96195:7;96180:14;:23::i;:::-;96176:106;;;-1:-1:-1;96265:5:0;96258:12;;96176:106;96332:29;;96301:27;:25;:27::i;:::-;:60;;96294:67;;96091:278;;;;:::o;56281:25::-;;;;;;:::o;90054:21::-;;;;;;-1:-1:-1;;;;;90054:21:0;;:::o;90220:31::-;;;-1:-1:-1;;;90220:31:0;;;;;:::o;61957:174::-;59293:10;;-1:-1:-1;;;;;59293:10:0;59279;:24;;:54;;;59321:12;:10;:12::i;:::-;-1:-1:-1;;;;;59307:26:0;:10;-1:-1:-1;;;;;59307:26:0;;59279:54;59271:78;;;;-1:-1:-1;;;59271:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;62036:21:0;::::1;62028:30;;;::::0;::::1;;62069:6;:16:::0;;-1:-1:-1;;;;;;62069:16:0::1;-1:-1:-1::0;;;;;62069:16:0;::::1;;::::0;;62101:22:::1;::::0;::::1;::::0;::::1;::::0;62069:16;;62101:22:::1;:::i;100428:313::-:0;100528:6;;:41;;-1:-1:-1;;;100528:41:0;;100471:16;;;;100528:6;;;;-1:-1:-1;;;;;100528:6:0;;:26;;:41;;100563:4;;100528:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100692:6;;:41;;-1:-1:-1;;;100692:41:0;;100517:52;;-1:-1:-1;100692:6:0;;;-1:-1:-1;;;;;100692:6:0;;:26;;:41;;100727:4;;100692:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100682:51;;100428:313;;:::o;97261:935::-;97405:6;;97380:33;;-1:-1:-1;;;97380:33:0;;97319:7;;;;89808:42;;97380:16;;:33;;97405:6;;;-1:-1:-1;;;;;97405:6:0;;97380:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97339:74;;;;97427:16;97445:15;97464:20;:18;:20::i;:::-;97426:58;;;;97497:19;97519:6;;;;;;;;;-1:-1:-1;;;;;97519:6:0;-1:-1:-1;;;;;97519:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97497:49;;97559:18;97580:6;;;;;;;;;-1:-1:-1;;;;;97580:6:0;-1:-1:-1;;;;;97580:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97559:48;-1:-1:-1;97620:30:0;97653:48;97696:4;97653:38;:8;97666:24;97653:12;:38::i;:48::-;97620:81;-1:-1:-1;97620:81:0;97712:29;97796:24;:7;97808:11;97796;:24::i;:::-;97779:41;-1:-1:-1;97831:14:0;97848:37;:21;97874:10;97848:25;:37::i;:::-;97831:54;;97912:6;97902;:16;97898:291;;-1:-1:-1;;97935:24:0;;;;;;;;;;;;;97898:291;97992:13;98008:34;:21;98034:7;98008:25;:34::i;:::-;97992:50;-1:-1:-1;98057:13:0;98073:18;:6;98084;98073:10;:18::i;:::-;98057:34;-1:-1:-1;98151:26:0;98057:34;98151:15;:5;98161:4;98151:9;:15::i;:26::-;98144:33;;;;;;;;;;;;;;;96457:322;96543:7;96567:12;96563:53;;-1:-1:-1;96603:1:0;96596:8;;96563:53;96655:15;;96628:24;;-1:-1:-1;;;;;96655:15:0;:29;96685:7;96694:29;96712:5;96719:3;96694:17;:29::i;:::-;96655:69;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;96655:69:0;;;;;;;;;;;;:::i;:::-;96628:96;;96744:7;96769:1;96752:7;:14;:18;96744:27;;;;;;;;;;;;;;96737:34;;;96457:322;;;;;;:::o;118675:384::-;118823:12;118837:14;118866:4;118855:33;;;;;;;;;;;;:::i;:::-;118822:66;;-1:-1:-1;118822:66:0;-1:-1:-1;118907:10:0;82963:42;118907:40;118899:49;;;;;;-1:-1:-1;;;;;118967:23:0;;118985:4;118967:23;118959:32;;;;;;119044:6;;119004:47;;-1:-1:-1;;;119004:47:0;;:12;;:22;;:47;;119027:7;;119036:6;;119044;;;-1:-1:-1;;;;;119044:6:0;;119004:47;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;118675:384;;;;;:::o;58915:33::-;;;;:::o;57854:94::-;57912:7;57854:94;:::o;63728:169::-;59293:10;;-1:-1:-1;;;;;59293:10:0;59279;:24;;:54;;;59321:12;:10;:12::i;:::-;-1:-1:-1;;;;;59307:26:0;:10;-1:-1:-1;;;;;59307:26:0;;59279:54;59271:78;;;;-1:-1:-1;;;59271:78:0;;;;;;;:::i;:::-;63811:12:::1;:28:::0;;;63855:34:::1;::::0;::::1;::::0;::::1;::::0;63826:13;;63855:34:::1;:::i;94084:280::-:0;119264:12;:10;:12::i;:::-;94237:6:::1;::::0;94212:33:::1;::::0;-1:-1:-1;;;94212:33:0;;94174:32:::1;::::0;89808:42:::1;::::0;94212:16:::1;::::0;:33:::1;::::0;94237:6:::1;::::0;;::::1;-1:-1:-1::0;;;;;94237:6:0::1;::::0;94212:33:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94171:74;;;;94291:17;94264:24;:44;94256:53;;;::::0;::::1;;-1:-1:-1::0;94320:16:0::1;:36:::0;94084:280::o;118353:259::-;118409:14;118437:12;118451:14;118469:20;:18;:20::i;:::-;118436:53;;;;118504:4;118512:1;118504:9;118500:50;;;118537:1;118530:8;;;;;;118500:50;118569:35;118599:4;118569:25;118577:4;118587:6;118569:17;:25::i;58016:22::-;;;-1:-1:-1;;;;;58016:22:0;;:::o;60848:120::-;59549:12;:10;:12::i;:::-;-1:-1:-1;;;;;59535:26:0;:10;-1:-1:-1;;;;;59535:26:0;;59527:50;;;;-1:-1:-1;;;59527:50:0;;;;;;;:::i;:::-;60930:13:::1;:30:::0;;-1:-1:-1;;60930:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;60848:120::o;58045:21::-;;;-1:-1:-1;;;;;58045:21:0;;:::o;93046:206::-;119264:12;:10;:12::i;:::-;93157:17:::1;:38:::0;;::::1;93206::::0;;::::1;-1:-1:-1::0;;;93206:38:0::1;-1:-1:-1::0;;;;93157:38:0;;;::::1;-1:-1:-1::0;;;93157:38:0::1;-1:-1:-1::0;;;;93157:38:0;;::::1;;93206::::0;;;::::1;;::::0;;93046:206::o;56313:26::-;;;;;;-1:-1:-1;;;;;56313:26:0;;:::o;90182:31::-;;;-1:-1:-1;;;90182:31:0;;;;;:::o;93384:96::-;119264:12;:10;:12::i;:::-;93452:8:::1;:20:::0;;;::::1;;-1:-1:-1::0;;;93452:20:0::1;-1:-1:-1::0;;;;93452:20:0;;::::1;::::0;;;::::1;::::0;;93384:96::o;90702:31::-;;;;:::o;90084:20::-;;;-1:-1:-1;;;90084:20:0;;;;;:::o;61201:202::-;59293:10;;-1:-1:-1;;;;;59293:10:0;59279;:24;;:54;;;59321:12;:10;:12::i;:::-;-1:-1:-1;;;;;59307:26:0;:10;-1:-1:-1;;;;;59307:26:0;;59279:54;59271:78;;;;-1:-1:-1;;;59271:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;61288:25:0;::::1;61280:34;;;::::0;::::1;;61325:10;:24:::0;;-1:-1:-1;;;;;;61325:24:0::1;-1:-1:-1::0;;;;;61325:24:0;::::1;;::::0;;61365:30:::1;::::0;::::1;::::0;::::1;::::0;61325:24;;61365:30:::1;:::i;91218:24::-:0;;;;;;;;;:::o;90809:44::-;;;;:::o;79571:307::-;79660:5;;-1:-1:-1;;;;;79660:5:0;79638:10;:28;;:58;;;79684:12;:10;:12::i;:::-;-1:-1:-1;;;;;79670:26:0;:10;-1:-1:-1;;;;;79670:26:0;;79638:58;79630:67;;;;;;79754:5;;79716:34;;;-1:-1:-1;;;79716:34:0;;;;-1:-1:-1;;;;;79754:5:0;;;;79716:32;;;;;:34;;;;;;;;;;;;;;:32;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;79716:43:0;;79708:52;;;;;;79771:30;79788:12;79771:16;:30::i;:::-;79812:4;;79840:29;;-1:-1:-1;;;79840:29:0;;-1:-1:-1;;;;;79812:4:0;;;;:13;;79826:12;;79812:4;;79840:14;;:29;;79863:4;;79840:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;79812:58;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;79571:307;:::o;95448:327::-;95495:7;95515:22;95540;:20;:22::i;:::-;95590:5;;:31;;-1:-1:-1;;;95590:31:0;;95515:47;;-1:-1:-1;95575:12:0;;-1:-1:-1;;;;;95590:5:0;;;;:16;;:31;;95615:4;;95590:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;95575:56;;95653:14;95646:4;:21;95642:126;;;95691:1;95684:8;;;;;;95642:126;95732:24;:14;95751:4;95732:18;:24::i;:::-;95725:31;;;;;;93854:119;119264:12;:10;:12::i;:::-;93935:13:::1;:30:::0;93854:119::o;98370:1476::-;98421:7;98442:16;98460:15;98479:20;:18;:20::i;:::-;98441:58;;;;98514:8;98526:1;98514:13;98510:122;;;98551:1;98544:8;;;;;;98510:122;98715:6;;98681:42;;-1:-1:-1;;;98681:42:0;;98644:34;;89808:42;;98681:25;;:42;;98715:6;;;;-1:-1:-1;;;;;98715:6:0;;98681:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98805:6;;98771:42;;-1:-1:-1;;;98771:42:0;;98644:79;;-1:-1:-1;98734:34:0;;89808:42;;98771:25;;:42;;98805:6;;;-1:-1:-1;;;;;98805:6:0;;98771:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98734:79;;98824:19;98846:6;;;;;;;;;-1:-1:-1;;;;;98846:6:0;-1:-1:-1;;;;;98846:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98824:43;;98959:25;98987:6;;;;;;;;;-1:-1:-1;;;;;98987:6:0;-1:-1:-1;;;;;98987:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98959:48;;99018:19;99040:60;99095:4;99040:50;99062:6;;;;;;;;;-1:-1:-1;;;;;99062:6:0;-1:-1:-1;;;;;99062:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99040:17;;:21;:50::i;:60::-;99018:82;-1:-1:-1;99113:24:0;99155:15;;99152:123;;99206:57;99251:11;99206:40;:8;99219:26;99206:12;:40::i;:57::-;99187:76;;99152:123;99287:24;99329:15;;99326:122;;99380:56;99424:11;99380:39;:7;99392:26;99380:11;:39::i;:56::-;99361:75;;99326:122;99508:18;99529:38;:16;99550;99529:20;:38::i;:::-;99637:5;;:31;;-1:-1:-1;;;99637:31:0;;99508:59;;-1:-1:-1;99616:18:0;;-1:-1:-1;;;;;99637:5:0;;;;:16;;:31;;99662:4;;99637:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;;;-1:-1:-1;99690:23:0;99715:41;99753:2;99716:31;:15;99637:42;99716:19;:31::i;99715:41::-;99690:66;-1:-1:-1;99807:31:0;99690:66;99827:10;99807:19;:31::i;:::-;99800:38;;;;;;;;;;;;;;98370:1476;:::o;90258:41::-;;;-1:-1:-1;;;;;90258:41:0;;:::o;62479:181::-;59436:10;;-1:-1:-1;;;;;59436:10:0;59422;:24;59414:48;;;;-1:-1:-1;;;59414:48:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;62560:22:0;::::1;62552:31;;;::::0;::::1;;62594:7;:18:::0;;-1:-1:-1;;;;;;62594:18:0::1;-1:-1:-1::0;;;;;62594:18:0;::::1;;::::0;;62628:24:::1;::::0;::::1;::::0;::::1;::::0;62594:18;;62628:24:::1;:::i;73809:1504::-:0;73880:4;73897:28;;:::i;:::-;73928:5;;:31;;-1:-1:-1;;;73928:31:0;;-1:-1:-1;;;;;73928:5:0;;;;:16;;:31;;73953:4;;73928:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;73897:62;;74036:6;:17;;;74057:1;74036:22;74032:40;;;74067:5;74060:12;;;;;74032:40;74191:14;;74169:17;;;;74149:38;;:15;;:19;:38::i;:::-;:56;74145:73;;74214:4;74207:11;;;;;74145:73;74648:5;;:23;;;-1:-1:-1;;;74648:23:0;;;;74626:19;;-1:-1:-1;;;;;74648:5:0;;:21;;:23;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74626:45;;74700:13;;74686:11;:27;74682:44;;;74722:4;74715:11;;;;;;74682:44;74780:13;74796:22;:20;:22::i;:::-;74780:38;;74908:6;:16;;;74881:24;74891:13;;74881:5;:9;;:24;;;;:::i;:::-;:43;74877:60;;;74933:4;74926:11;;;;;;;74877:60;74950:14;74991:6;:16;;;74983:5;:24;74979:66;;;75028:16;;;;75018:27;;:5;;:9;:27::i;:::-;75009:36;;74979:66;75215:5;;:23;;;-1:-1:-1;;;75215:23:0;;;;75198:14;;-1:-1:-1;;;;;75215:5:0;;:21;;:23;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75198:40;-1:-1:-1;75286:18:0;75198:40;75297:6;75286:10;:18::i;:::-;75257:12;;:26;;75274:8;75257:16;:26::i;:::-;:47;;73809:1504;-1:-1:-1;;;;;;;73809:1504:0:o;94613:642::-;94675:7;94696:16;94714:15;94733:20;:18;:20::i;:::-;94695:58;;;;94766:22;94791:20;:18;:20::i;:::-;94766:45;;94822:19;94844:20;89924:42;94844:14;:20::i;:::-;95029:4;;94822:42;;-1:-1:-1;94979:21:0;;95004:63;;89924:42;;-1:-1:-1;;;;;95029:4:0;95035:31;:14;94822:42;95035:18;:31::i;95004:63::-;94979:88;-1:-1:-1;95078:24:0;95105:28;95130:2;95105:20;94979:88;95123:1;95105:17;:20::i;:28::-;95078:55;;95169:78;95239:7;95169:65;95217:16;95169:43;95203:8;95169:29;95192:4;;;;;;;;;-1:-1:-1;;;;;95192:4:0;95169:14;:29::i;:::-;:33;;:43::i;:65::-;:69;;:78::i;:::-;95162:85;;;;;;;;94613:642;:::o;63177:151::-;59293:10;;-1:-1:-1;;;;;59293:10:0;59279;:24;;:54;;;59321:12;:10;:12::i;:::-;-1:-1:-1;;;;;59307:26:0;:10;-1:-1:-1;;;;;59307:26:0;;59279:54;59271:78;;;;-1:-1:-1;;;59271:78:0;;;;;;;:::i;:::-;63255:14:::1;:23:::0;;;63294:26:::1;::::0;::::1;::::0;::::1;::::0;63272:6;;63294:26:::1;:::i;57956:21::-:0;;;-1:-1:-1;;;;;57956:21:0;;:::o;80307:164::-;59293:10;;-1:-1:-1;;;;;59293:10:0;59279;:24;;:54;;;59321:12;:10;:12::i;:::-;-1:-1:-1;;;;;59307:26:0;:10;-1:-1:-1;;;;;59307:26:0;;59279:54;59271:78;;;;-1:-1:-1;;;59271:78:0;;;;;;;:::i;:::-;80370:13:::1;:20:::0;;-1:-1:-1;;80370:20:0::1;80386:4;80370:20:::0;;::::1;::::0;;;80401:5;:22:::1;::::0;;-1:-1:-1;;;80401:22:0;;;;-1:-1:-1;;;;;80401:5:0;;::::1;::::0;:20:::1;::::0;:22:::1;::::0;;::::1;::::0;80370:13:::1;::::0;80401:22;;;;;;;;80370:13;80401:5;:22;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;80441:22:0::1;::::0;::::1;::::0;-1:-1:-1;80441:22:0;;-1:-1:-1;80441:22:0::1;80307:164::o:0;45309:622::-;45679:10;;;45678:62;;-1:-1:-1;45695:39:0;;-1:-1:-1;;;45695:39:0;;-1:-1:-1;;;;;45695:15:0;;;;;:39;;45719:4;;45726:7;;45695:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;45678:62;45670:152;;;;-1:-1:-1;;;45670:152:0;;;;;;;:::i;:::-;45833:90;45853:5;45883:22;;;45907:7;45916:5;45860:62;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;45860:62:0;;;;;;;;;;;;;;-1:-1:-1;;;;;45860:62:0;-1:-1:-1;;;;;;45860:62:0;;;;;;;;;;45833:19;:90::i;22759:196::-;22862:12;22894:53;22917:6;22925:4;22931:1;22934:12;22894:22;:53::i;:::-;22887:60;22759:196;-1:-1:-1;;;;22759:196:0:o;64783:98::-;64855:5;;:18;;;-1:-1:-1;;;64855:18:0;;;;64828:7;;-1:-1:-1;;;;;64855:5:0;;:16;;:18;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;117804:85::-;117863:16;117804:85;:::o;30094:136::-;30152:7;30179:43;30183:1;30186;30179:43;;;;;;;;;;;;;;;;;:3;:43::i;:::-;30172:50;;30094:136;;;;;:::o;119112:111::-;119174:12;:10;:12::i;:::-;-1:-1:-1;;;;;119160:26:0;:10;-1:-1:-1;;;;;119160:26:0;;:54;;;-1:-1:-1;119204:10:0;;-1:-1:-1;;;;;119204:10:0;119190;:24;119160:54;119152:63;;;;;110141:1270;110308:4;;110218:20;;;;;;110285:29;;-1:-1:-1;;;;;110308:4:0;110285:14;:29::i;:::-;110266:48;;110325:14;110342:30;110363:8;110342:16;:14;:16::i;:30::-;110325:47;;110385:23;110411:5;;;;;;;;;-1:-1:-1;;;;;110411:5:0;-1:-1:-1;;;;;110411:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;110385:49;;110468:6;110450:15;:24;110447:90;;;110498:27;:15;110518:6;110498:19;:27::i;:::-;110490:35;;110447:90;110562:13;110553:6;:22;110549:855;;;110692:16;110710:15;110729:17;:15;:17::i;:::-;110691:55;;;;110869:1;110835:31;110858:6;;;;;;;;;-1:-1:-1;;;;;110858:6:0;110835:14;:31::i;:::-;:35;110832:110;;;110890:36;110904:21;:8;110917:7;110904:12;:21::i;:::-;110890:13;:36::i;:::-;;110832:110;111020:4;;110973:54;;110982:13;;110997:29;;-1:-1:-1;;;;;111020:4:0;110997:14;:29::i;:::-;110973:8;:54::i;:::-;110958:69;;110549:855;;;;;111077:13;111066:8;:24;111062:331;;;111111:42;111125:27;:13;111143:8;111125:17;:27::i;111111:42::-;-1:-1:-1;111303:4:0;;111256:54;;111265:13;;111280:29;;-1:-1:-1;;;;;111303:4:0;111280:14;:29::i;111256:54::-;111241:69;;111062:331;;;111364:13;111349:28;;111062:331;110141:1270;;;;;;:::o;29630:181::-;29688:7;29720:5;;;29744:6;;;;29736:46;;;;-1:-1:-1;;;29736:46:0;;;;;;;:::i;30984:471::-;31042:7;31287:6;31283:47;;-1:-1:-1;31317:1:0;31310:8;;31283:47;31354:5;;;31358:1;31354;:5;:1;31378:5;;;;;:10;31370:56;;;;-1:-1:-1;;;31370:56:0;;;;;;;:::i;31931:132::-;31989:7;32016:39;32020:1;32023;32016:39;;;;;;;;;;;;;;;;;:3;:39::i;103375:1867::-;103515:13;;;;103511:52;;;103545:7;;103511:52;103689:4;;103647:16;;103666:29;;-1:-1:-1;;;;;103689:4:0;103666:14;:29::i;:::-;103647:48;;103720:16;103709:8;:27;103706:375;;;103954:6;;103965:1;;103931:31;;103954:6;;;-1:-1:-1;;;;;103954:6:0;103931:14;:31::i;:::-;:35;103928:119;;;103986:45;104000:30;:16;104021:8;104000:20;:30::i;103986:45::-;;103928:119;104063:7;;;103706:375;104094:16;104112:12;104128:60;104165:16;104154:8;:27;104183:4;104128:25;:60::i;:::-;104093:95;;;;104350:7;;104339:8;:18;104335:900;;;104457:10;;;;104452:772;;104488:6;104517:232;104523:12;;104517:232;;104570:45;104583:31;104596:8;104606:7;104583:12;:31::i;:::-;104570:8;;:12;:45::i;:::-;104559:56;;104646:1;104641;:6;104638:66;;104675:5;;104638:66;104726:3;;104517:232;;;104452:772;;;;104905:4;;:42;;-1:-1:-1;;;104905:42:0;;-1:-1:-1;;;;;104905:4:0;;;;:14;;:42;;82963;;104905;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104894:8;:53;104890:158;;;104983:45;104996:31;105009:8;105019:7;104996:12;:31::i;:::-;104983:8;;:12;:45::i;:::-;104972:56;;104890:158;105124:7;;105113:8;:18;105110:99;;;105155:34;105171:7;105180:8;105155:15;:34::i;:::-;;105110:99;103375:1867;;;;:::o;101296:1934::-;101628:6;;101413:15;;;;;;101605:31;;101628:6;;;-1:-1:-1;;;;;101628:6:0;101605:14;:31::i;:::-;101601:429;;101703:4;;101658:19;;101680:29;;-1:-1:-1;;;;;101703:4:0;101680:14;:29::i;:::-;101658:51;;101927:39;101936:11;101949:16;101927:8;:39::i;:::-;101912:54;;101981:37;;;101601:429;102043:16;102061:15;102080:17;:15;:17::i;:::-;102042:55;;;;102140:12;:10;:12::i;:::-;102184:16;:14;:16::i;:::-;102258:4;;102213:19;;102235:29;;-1:-1:-1;;;;;102258:4:0;102235:14;:29::i;:::-;102213:51;-1:-1:-1;102277:23:0;102303:21;:8;102316:7;102303:12;:21::i;:::-;102277:47;-1:-1:-1;102335:15:0;102353:32;102277:47;102373:11;102353:19;:32::i;:::-;102413:5;;:31;;-1:-1:-1;;;102413:31:0;;102335:50;;-1:-1:-1;102398:12:0;;-1:-1:-1;;;;;102413:5:0;;;;:16;;:31;;102438:4;;102413:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;102398:56;;102523:4;102513:7;:14;102509:714;;;102554:17;:7;102566:4;102554:11;:17::i;:::-;102544:27;;102606:7;102592:11;:21;102588:325;;;102685:11;102675:21;;102588:325;;;102736:29;:7;102748:16;102736:11;:29::i;:::-;102722:11;:43;102718:195;;;102801:16;102786:31;;102718:195;;;102873:24;:11;102889:7;102873:15;:24::i;:::-;102858:39;;102718:195;102509:714;;;103125:17;:4;103134:7;103125:8;:17::i;:::-;103117:25;;103172:39;103181:11;103194:16;103172:8;:39::i;:::-;103157:54;;102509:714;101296:1934;;;;;;;;;;;;:::o;70035:297::-;70208:5;;:30;;-1:-1:-1;;;70208:30:0;;70190:15;;-1:-1:-1;;;;;70208:5:0;;:15;;:30;;70232:4;;70208:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70190:48;-1:-1:-1;70253:11:0;;70249:76;;70281:5;;70296:7;;70281:32;;-1:-1:-1;;;70281:32:0;;-1:-1:-1;;;;;70281:5:0;;;;:14;;:32;;70296:7;;;70305;;70281:32;;;:::i;112441:485::-;112555:22;112595:11;-1:-1:-1;;;;;112622:25:0;;90005:42;112622:25;;:55;;-1:-1:-1;;;;;;112651:26:0;;90005:42;112651:26;112622:55;112595:82;;112710:6;:14;;112723:1;112710:14;;;112719:1;112710:14;112696:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;112696:29:0;;112688:37;;112747:8;112736:5;112742:1;112736:8;;;;;;;;;;;;;:19;-1:-1:-1;;;;;112736:19:0;;;-1:-1:-1;;;;;112736:19:0;;;;;112772:6;112768:151;;;112806:9;112795:5;112801:1;112795:8;;;;;;;;;;;;;:20;-1:-1:-1;;;;;112795:20:0;;;-1:-1:-1;;;;;112795:20:0;;;;;112768:151;;;90005:42;112848:5;112854:1;112848:8;;;;;;;;;;;;;:24;-1:-1:-1;;;;;112848:24:0;;;-1:-1:-1;;;;;112848:24:0;;;;;112898:9;112887:5;112893:1;112887:8;;;;;;;;;;;;;:20;-1:-1:-1;;;;;112887:20:0;;;-1:-1:-1;;;;;112887:20:0;;;;;112768:151;112441:485;;;;;:::o;113677:579::-;113760:12;;;;;;;113756:493;;113789:16;113807:15;113826:17;:15;:17::i;:::-;113788:55;;-1:-1:-1;113788:55:0;-1:-1:-1;113858:36:0;113872:21;113788:55;;113872:12;:21::i;113858:36::-;-1:-1:-1;113943:6:0;;:40;;-1:-1:-1;;;113943:40:0;;113916:21;;113943:6;;;-1:-1:-1;;;;;113943:6:0;;:25;;:40;;113977:4;;113943:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;113911:72;;;;;114024:6;114008:13;:22;114000:31;;;;;;89924:42;114048:12;114104:30;89924:42;114104:14;:30::i;:::-;114090:44;-1:-1:-1;114152:10:0;;114149:89;;114182:40;-1:-1:-1;;;;;114182:18:0;;114201:12;114215:6;114182:18;:40::i;:::-;113756:493;;;;;113677:579;:::o;95263:135::-;95352:38;;-1:-1:-1;;;95352:38:0;;95325:7;;-1:-1:-1;;;;;95352:23:0;;;;;:38;;95384:4;;95352:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;46955:761::-;47379:23;47405:69;47433:4;47405:69;;;;;;;;;;;;;;;;;47413:5;-1:-1:-1;;;;;47405:27:0;;;:69;;;;;:::i;:::-;47489:17;;47379:95;;-1:-1:-1;47489:21:0;47485:224;;47631:10;47620:30;;;;;;;;;;;;:::i;:::-;47612:85;;;;-1:-1:-1;;;47612:85:0;;;;;;;:::i;24136:979::-;24266:12;24299:18;24310:6;24299:10;:18::i;:::-;24291:60;;;;-1:-1:-1;;;24291:60:0;;;;;;;:::i;:::-;24425:12;24439:23;24466:6;-1:-1:-1;;;;;24466:11:0;24486:8;24497:4;24466:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24424:78;;;;24517:7;24513:595;;;24548:10;-1:-1:-1;24541:17:0;;-1:-1:-1;24541:17:0;24513:595;24662:17;;:21;24658:439;;24925:10;24919:17;24986:15;24973:10;24969:2;24965:19;24958:44;24873:148;25068:12;25061:20;;-1:-1:-1;;;25061:20:0;;;;;;;;:::i;24658:439::-;24136:979;;;;;;;;:::o;30533:192::-;30619:7;30655:12;30647:6;;;;30639:29;;;;-1:-1:-1;;;30639:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;30691:5:0;;;30533:192::o;105608:2117::-;105666:11;105691:16;105709:12;105725:41;105751:7;105760:5;105725:25;:41::i;:::-;105690:76;;;;105902:7;:29;;;;;105924:7;;105913:8;:18;105902:29;105898:853;;;106100:10;;;;106096:110;;;106142:48;106155:34;106171:7;106180:8;106155:15;:34::i;106142:48::-;106131:59;;106096:110;106222:7;106420:320;106438:7;;:16;;106450:3;106438:11;:16::i;:::-;106427:8;:27;106420:320;;;106486:42;106499:28;106512:8;106522:4;106499:12;:28::i;106486:42::-;106475:53;-1:-1:-1;106547:3:0;;106638:1;106633:6;;;;106629:96;;106673:4;106664:13;;106700:5;;106629:96;106420:320;;;105898:853;;106920:22;106944:21;106969:20;:18;:20::i;:::-;107022:16;;106919:70;;-1:-1:-1;106919:70:0;-1:-1:-1;107002:17:0;107091:14;107088:99;;107133:4;107121:16;;107088:99;107216:38;107244:9;107216:23;:13;107234:4;107216:17;:23::i;:38::-;107199:55;;107288:14;107270;:32;107267:305;;107318:18;107339:34;:14;107358;107339:18;:34::i;:::-;107318:55;;107407:7;107394:10;:20;107390:171;;;107435:6;;:35;;-1:-1:-1;;;107435:35:0;;:6;;;;-1:-1:-1;;;;;107435:6:0;;:23;;:35;;107459:10;;107435:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;107390:171;;;107513:6;;:32;;-1:-1:-1;;;107513:32:0;;:6;;;;-1:-1:-1;;;;;107513:6:0;;:23;;:32;;107537:7;;107513:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;107390:171;107267:305;;107587:16;;:21;:70;;;;-1:-1:-1;107635:4:0;;107644:13;;107612:29;;-1:-1:-1;;;;;107635:4:0;107612:14;:29::i;:::-;:45;107587:70;107584:134;;;107673:6;;:33;;-1:-1:-1;;;107673:33:0;;:6;;;;-1:-1:-1;;;;;107673:6:0;;:18;;:33;;107692:13;;107673:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;107584:134;105608:2117;;;;;;;;;:::o;28302:106::-;28360:7;28391:1;28387;:5;:13;;28399:1;28387:13;;;-1:-1:-1;28395:1:0;;28302:106;-1:-1:-1;28302:106:0:o;32559:278::-;32645:7;32680:12;32673:5;32665:28;;;;-1:-1:-1;;;32665:28:0;;;;;;;;:::i;:::-;;32704:9;32720:1;32716;:5;;;;;;;32559:278;-1:-1:-1;;;;;32559:278:0:o;108223:1739::-;108303:16;108321:12;108398:16;108416:15;108435:17;:15;:17::i;:::-;108397:55;;-1:-1:-1;108397:55:0;-1:-1:-1;108547:22:0;108572:21;108397:55;;108572:12;:21::i;:::-;108547:46;;108851:21;108891:3;108887:223;;;108927:27;:14;108946:7;108927:18;:27::i;:::-;108911:43;;108887:223;;;109000:14;108990:7;:24;108987:53;;;109026:14;109016:24;;108987:53;109071:27;:14;109090:7;109071:18;:27::i;:::-;109055:43;;108887:223;109147:11;109161:35;109179:16;;109161:13;:17;;:35;;;;:::i;:::-;109147:49;;109207:11;109221:35;109239:16;;109229:4;109221:17;;:35;;;;:::i;:::-;109207:49;-1:-1:-1;109269:21:0;109293:12;:3;109207:49;109293:7;:12::i;:::-;109269:36;;109336:3;109320:13;:19;109316:140;;;109422:22;:13;109440:3;109422:17;:22::i;:::-;109406:38;;109316:140;109661:7;109645:13;:23;109641:314;;;109695:4;;-1:-1:-1;109725:26:0;:7;109737:13;109725:11;:26::i;:::-;109714:37;;109641:314;;;109886:5;;-1:-1:-1;109917:26:0;:13;109935:7;109917:17;:26::i;:::-;109906:37;;109641:314;108223:1739;;;;;;;;;;;;:::o;114452:795::-;114519:14;114659:12;114673:16;114693:20;:18;:20::i;:::-;114658:55;;;;114803:8;114815:1;114803:13;:24;;;;;114820:7;114803:24;114799:65;;;114851:1;114844:8;;;;;;114799:65;114942:6;;114917:33;;-1:-1:-1;;;114917:33:0;;114879:32;;89808:42;;114917:16;;:33;;114942:6;;;;-1:-1:-1;;;;;114942:6:0;;114917:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;114876:74;;;;114967:7;114963:217;;;115000:64;115018:3;115023:4;115029:8;115039:24;115000:17;:64::i;:::-;114991:73;;114963:217;;;115106:62;115122:3;115127:4;115133:8;115143:24;115106:15;:62::i;:::-;115097:71;;114963:217;115197:42;115206:3;115211:6;115219:7;115236:1;115197:42;;;;;;;;;:::i;:::-;;;;;;;;114452:795;;;;;;;:::o;118070:182::-;118238:4;;118177:67;;-1:-1:-1;;;118177:67:0;;118150:7;;118177:12;;:28;;:67;;118206:7;;118215:13;;-1:-1:-1;;;;;118238:4:0;;;;118177:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;111419:237::-;111464:13;;;;111461:51;;;111494:7;;111461:51;111548:16;;;111562:1;111548:16;;;;;;;;;111522:23;;111548:16;;;;;;;;;;;-1:-1:-1;111548:16:0;111522:42;;111587:6;;;;;;;;;-1:-1:-1;;;;;111587:6:0;111575;111582:1;111575:9;;;;;;;;-1:-1:-1;;;;;111575:18:0;;;:9;;;;;;;;;;;:18;111607:41;;-1:-1:-1;;;111607:41:0;;89808:42;;111607:18;;:41;;111634:4;;111641:6;;111607:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111690:743;111736:13;111752:20;89924:42;111752:14;:20::i;:::-;111736:36;;111795:13;;111787:5;:21;111783:60;;;111825:7;;;111783:60;111859:8;;-1:-1:-1;;;111859:8:0;;;;111855:569;;;111927:227;;;;;;;;;112015:4;;90644:42;;111884:24;;111927:227;;111983:38;;89924:42;;-1:-1:-1;;;;;112015:4:0;111983:17;:38::i;:::-;111927:227;;;;112052:4;-1:-1:-1;;;;;111927:227:0;;;;;112080:3;111927:227;;;;112106:5;111927:227;;;;112134:1;111927:227;;;111884:285;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;111855:569::-;112202:15;;112337:4;;-1:-1:-1;;;;;112202:15:0;;;;:40;;112261:5;;112202:15;;112305:38;;89924:42;;112337:4;112305:17;:38::i;:::-;112370:4;112394:3;112202:210;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;112202:210:0;;;;;;;;;;;;:::i;44650:177::-;44733:86;44753:5;44783:23;;;44808:2;44812:5;44760:58;;;;;;;;;:::i;19644:619::-;19704:4;20172:20;;20015:66;20212:23;;;;;;:42;;-1:-1:-1;;20239:15:0;;;20204:51;-1:-1:-1;;19644:619:0:o;115309:1284::-;115473:25;;115650:16;;115647:100;;115700:35;115723:11;115700:18;:8;115713:4;115700:12;:18::i;:35::-;115682:53;;115647:100;115777:25;:4;115786:15;115777:8;:25::i;:::-;115757:45;;115840:8;115819:17;:29;115815:90;;115885:8;115865:28;;115815:90;115940:13;115919:17;:34;115915:100;;115990:13;115970:33;;115915:100;116025:26;116054:6;;;;;;;;;-1:-1:-1;;;;;116054:6:0;-1:-1:-1;;;;;116054:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116025:56;-1:-1:-1;116025:56:0;116243:27;:17;116265:4;116243:21;:27::i;:::-;:49;;:75;;;;;116316:2;116296:17;:22;116243:75;116240:346;;;116354:34;:17;116384:2;116354:21;:34::i;:::-;116403:6;;:42;;-1:-1:-1;;;116403:42:0;;116334:54;;-1:-1:-1;116403:6:0;;;-1:-1:-1;;;;;116403:6:0;;:23;;:42;;116334:54;;116403:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;116537:6:0;;:37;;-1:-1:-1;;;116537:37:0;;:6;;;;-1:-1:-1;;;;;116537:6:0;;:18;;:37;;116556:17;;116537:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;115309:1284;;;;;;;;:::o;116657:644::-;116817:23;;116881:31;116907:4;116881:21;:4;116890:11;116881:8;:21::i;:31::-;116853:59;-1:-1:-1;116943:31:0;116853:59;116965:8;116943:21;:31::i;:::-;116925:49;;117010:11;116991:15;:30;116987:92;;117056:11;117038:29;;116987:92;117110:2;117092:15;:20;117089:203;;;117146:32;:15;117174:2;117146:19;:32::i;:::-;117193:6;;:30;;-1:-1:-1;;;117193:30:0;;117128:50;;-1:-1:-1;117193:6:0;;;-1:-1:-1;;;;;117193:6:0;;:13;;:30;;117128:50;;117193:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;117238:6:0;;117273:4;;-1:-1:-1;;;;;117238:6:0;;;;;;;:11;;117250:29;;117273:4;117250:14;:29::i;:::-;117238:42;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;117089:203::-;116657:644;;;;;;;:::o;112934:603::-;113096:4;;113048:18;;-1:-1:-1;;;;;113096:4:0;90005:42;113088:21;113084:446;;;113177:8;113205:17;;;;;;;;;;;90005:42;113134:135;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;113126:143;;113084:446;;;113381:17;;113310:208;;;;113353:8;;113381:17;-1:-1:-1;;;113381:17:0;;;;;90005:42;;-1:-1:-1;;;113449:17:0;;;;;;;113493:9;;113310:208;;;:::i;:::-;;;;;;;;;;;;;113302:216;;112934:603;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5:130::-;72:20;;97:33;72:20;97:33;:::i;3944:128::-;4010:20;;41040:8;41029:20;;44624:34;;44614:2;;44672:1;;44662:12;4357:241;;4461:2;4449:9;4440:7;4436:23;4432:32;4429:2;;;-1:-1;;4467:12;4429:2;85:6;72:20;97:33;124:5;97:33;:::i;4605:263::-;;4720:2;4708:9;4699:7;4695:23;4691:32;4688:2;;;-1:-1;;4726:12;4688:2;226:6;220:13;238:33;265:5;238:33;:::i;4875:491::-;;;;5013:2;5001:9;4992:7;4988:23;4984:32;4981:2;;;-1:-1;;5019:12;4981:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5071:63;-1:-1;5171:2;5210:22;;72:20;97:33;72:20;97:33;:::i;:::-;4975:391;;5179:63;;-1:-1;;;5279:2;5318:22;;;;4146:20;;4975:391::o;5373:636::-;;;;5528:9;5519:7;5515:23;5540:3;5515:23;5511:33;5508:2;;;-1:-1;;5547:12;5508:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5599:63;-1:-1;2056:4;-1:-1;;2035:19;;2031:30;2028:2;;;-1:-1;;2064:12;2028:2;;2092:20;2056:4;2092:20;:::i;:::-;2195:49;2240:3;5699:2;5762:9;5758:22;2195:49;:::i;:::-;2170:75;;2056:4;2362:22;;4146:20;5699:2;2323:16;;2316:75;2177:16;-1:-1;5855:2;5840:18;;5827:32;5879:18;5868:30;;5865:2;;;-1:-1;;5901:12;5865:2;5961:22;;1392:4;1380:17;;1376:27;-1:-1;1366:2;;-1:-1;;1407:12;1366:2;1454:6;1441:20;1476:64;1491:48;1532:6;1491:48;:::i;:::-;1476:64;:::i;:::-;1560:6;1553:5;1546:21;1664:3;5699:2;1655:6;1588;1646:16;;1643:25;1640:2;;;-1:-1;;1671:12;1640:2;1691:41;1725:6;5699:2;1622:5;1618:16;5699:2;1588:6;1584:17;1691:41;:::i;:::-;5921:72;;;;;;5502:507;;;;;:::o;6016:392::-;;6156:2;;6144:9;6135:7;6131:23;6127:32;6124:2;;;-1:-1;;6162:12;6124:2;6213:17;6207:24;6251:18;6243:6;6240:30;6237:2;;;-1:-1;;6273:12;6237:2;6360:22;;422:4;410:17;;406:27;-1:-1;396:2;;-1:-1;;437:12;396:2;477:6;471:13;499:80;514:64;571:6;514:64;:::i;499:80::-;607:21;;;664:14;;;;639:17;;;753;;;744:27;;;;741:36;-1:-1;738:2;;;-1:-1;;780:12;738:2;-1:-1;806:10;;800:217;825:6;822:1;819:13;800:217;;;4294:13;;893:61;;847:1;840:9;;;;;968:14;;;;996;;800:217;;;-1:-1;6293:99;6118:290;-1:-1;;;;;;;6118:290::o;6415:235::-;;6516:2;6504:9;6495:7;6491:23;6487:32;6484:2;;;-1:-1;;6522:12;6484:2;1108:6;1095:20;1120:30;1144:5;1120:30;:::i;6657:257::-;;6769:2;6757:9;6748:7;6744:23;6740:32;6737:2;;;-1:-1;;6775:12;6737:2;1243:6;1237:13;1255:30;1279:5;1255:30;:::i;6921:393::-;;;7050:2;7038:9;7029:7;7025:23;7021:32;7018:2;;;-1:-1;;7056:12;7018:2;1243:6;1237:13;1255:30;1279:5;1255:30;:::i;:::-;7216:2;7266:22;;;;4294:13;7108:71;;4294:13;;-1:-1;;;7012:302::o;7321:523::-;;;;7464:2;7452:9;7443:7;7439:23;7435:32;7432:2;;;-1:-1;;7470:12;7432:2;1243:6;1237:13;1255:30;1279:5;1255:30;:::i;:::-;7630:2;7680:22;;4294:13;7749:2;7796:22;;1237:13;7522:71;;-1:-1;4294:13;-1:-1;1255:30;1237:13;1255:30;:::i;:::-;7757:71;;;;7426:418;;;;;:::o;8155:324::-;;8300:3;;8288:9;8279:7;8275:23;8271:33;8268:2;;;-1:-1;;8307:12;8268:2;2615:22;8300:3;2615:22;:::i;:::-;2606:31;;2761:22;4294:13;2711:16;2704:86;2857:2;2926:9;2922:22;4294:13;2857:2;2876:5;2872:16;2865:86;3017:2;3086:9;3082:22;4294:13;3017:2;3036:5;3032:16;3025:86;3177:2;3246:9;3242:22;4294:13;3177:2;3196:5;3192:16;3185:86;3338:3;3408:9;3404:22;4294:13;3338:3;3358:5;3354:16;3347:86;3499:3;3569:9;3565:22;4294:13;3499:3;3519:5;3515:16;3508:86;3660:3;3730:9;3726:22;4294:13;3660:3;3680:5;3676:16;3669:86;3821:3;3891:9;3887:22;4294:13;3821:3;3841:5;3837:16;3830:86;8359:104;;;;8262:217;;;;:::o;8486:362::-;;;8605:2;8593:9;8584:7;8580:23;8576:32;8573:2;;;-1:-1;;8611:12;8573:2;8673:52;8717:7;8693:22;8673:52;:::i;:::-;8663:62;;8780:52;8824:7;8762:2;8804:9;8800:22;8780:52;:::i;:::-;8770:62;;8567:281;;;;;:::o;8855:241::-;;8959:2;8947:9;8938:7;8934:23;8930:32;8927:2;;;-1:-1;;8965:12;8927:2;-1:-1;4146:20;;8921:175;-1:-1;8921:175::o;9103:263::-;;9218:2;9206:9;9197:7;9193:23;9189:32;9186:2;;;-1:-1;;9224:12;9186:2;-1:-1;4294:13;;9180:186;-1:-1;9180:186::o;9373:672::-;;;;;9539:3;9527:9;9518:7;9514:23;9510:33;9507:2;;;-1:-1;;9546:12;9507:2;-1:-1;;4294:13;;9709:2;9759:22;;4294:13;9828:2;9878:22;;4294:13;9947:2;9997:22;;;4294:13;;;;;-1:-1;4294:13;;-1:-1;9501:544;-1:-1;9501:544::o;11145:690::-;;11338:5;39158:12;39993:6;39988:3;39981:19;40030:4;;40025:3;40021:14;11350:93;;40030:4;11514:5;38838:14;-1:-1;11553:260;11578:6;11575:1;11572:13;11553:260;;;11639:13;;-1:-1;;;;;40902:54;10658:37;;10206:14;;;;39705;;;;41040:8;11593:9;11553:260;;;-1:-1;11819:10;;11269:566;-1:-1;;;;;11269:566::o;12891:323::-;;13023:5;39158:12;39993:6;39988:3;39981:19;13106:52;13151:6;40030:4;40025:3;40021:14;40030:4;13132:5;13128:16;13106:52;:::i;:::-;2035:19;43923:14;-1:-1;;43919:28;13170:39;;;;40030:4;13170:39;;12971:243;-1:-1;;12971:243::o;21279:526::-;44138:2;44134:14;;;-1:-1;;44134:14;;;11044:58;;44031:15;;;;;-1:-1;;;;;;44031:15;21558:2;21549:12;;20853:56;44134:14;;;21658:11;;;11044:58;21768:12;;;21449:356::o;21812:799::-;-1:-1;;44138:2;44134:14;;;;;11044:58;;-1:-1;;;;;;44031:15;;;;;;22145:2;22136:12;;20853:56;44134:14;;;;;22245:11;;;11044:58;44031:15;;;;;;;22355:12;;;20853:56;44134:14;;;;;22464:11;;;11044:58;22574:12;;;22036:575::o;22618:271::-;;13381:5;39158:12;13492:52;13537:6;13532:3;13525:4;13518:5;13514:16;13492:52;:::i;:::-;13556:16;;;;;22752:137;-1:-1;;22752:137::o;22896:222::-;-1:-1;;;;;40902:54;;;;10658:37;;23023:2;23008:18;;22994:124::o;23370:529::-;-1:-1;;;;;40902:54;;;10527:58;;23599:2;23725;23710:18;;;23703:48;;;39158:12;;23584:18;;;39981:19;;;23370:529;;38838:14;;;;40913:42;;23725:2;40021:14;;;;23370:529;12339:292;12364:6;12361:1;12358:13;12339:292;;;12425:13;;40902:54;;10658:37;;39705:14;;;;10420;;;;12386:1;12379:9;12339:292;;;-1:-1;23757:132;;23570:329;-1:-1;;;;;;;;23570:329::o;23906:349::-;-1:-1;;;;;40902:54;;;;10527:58;;24241:2;24226:18;;20982:37;24069:2;24054:18;;24040:215::o;24262:333::-;-1:-1;;;;;40902:54;;;10658:37;;40902:54;;24581:2;24566:18;;10658:37;24417:2;24402:18;;24388:207::o;24942:210::-;40699:13;;40692:21;12726:34;;25063:2;25048:18;;25034:118::o;25159:464::-;40699:13;;40692:21;12726:34;;25518:2;25503:18;;20982:37;;;;-1:-1;;;;;40902:54;25609:2;25594:18;;10658:37;25344:2;25329:18;;25315:308::o;27199:310::-;;27346:2;27367:17;27360:47;27421:78;27346:2;27335:9;27331:18;27485:6;27421:78;:::i;27516:416::-;27716:2;27730:47;;;15322:2;27701:18;;;39981:19;-1:-1;;;40021:14;;;15338:34;15391:12;;;27687:245::o;27939:416::-;28139:2;28153:47;;;15642:1;28124:18;;;39981:19;-1:-1;;;40021:14;;;15657:28;15704:12;;;28110:245::o;28362:416::-;28562:2;28576:47;;;15955:2;28547:18;;;39981:19;15991:29;40021:14;;;15971:50;16040:12;;;28533:245::o;28785:416::-;28985:2;28999:47;;;16291:2;28970:18;;;39981:19;-1:-1;;;40021:14;;;16307:35;16361:12;;;28956:245::o;29208:416::-;29408:2;29422:47;;;16612:1;29393:18;;;39981:19;-1:-1;;;40021:14;;;16627:32;16678:12;;;29379:245::o;29631:416::-;29831:2;29845:47;;;16929:2;29816:18;;;39981:19;16965:34;40021:14;;;16945:55;-1:-1;;;17020:12;;;17013:25;17057:12;;;29802:245::o;30054:416::-;30254:2;30268:47;;;17308:1;30239:18;;;39981:19;-1:-1;;;40021:14;;;17323:29;17371:12;;;30225:245::o;30477:416::-;30677:2;30691:47;;;17622:1;30662:18;;;39981:19;-1:-1;;;40021:14;;;17637:30;17686:12;;;30648:245::o;30900:416::-;31100:2;31114:47;;;17937:2;31085:18;;;39981:19;17973:31;40021:14;;;17953:52;18024:12;;;31071:245::o;31323:416::-;31523:2;31537:47;;;18275:2;31508:18;;;39981:19;-1:-1;;;40021:14;;;18291:34;18344:12;;;31494:245::o;31746:416::-;31946:2;31960:47;;;18595:2;31931:18;;;39981:19;18631:34;40021:14;;;18611:55;-1:-1;;;18686:12;;;18679:34;18732:12;;;31917:245::o;32169:416::-;32369:2;32383:47;;;18983:2;32354:18;;;39981:19;-1:-1;;;40021:14;;;18999:33;19051:12;;;32340:245::o;32592:416::-;32792:2;32806:47;;;19302:2;32777:18;;;39981:19;19338:34;40021:14;;;19318:55;-1:-1;;;19393:12;;;19386:46;19451:12;;;32763:245::o;33015:406::-;;33210:2;33231:17;33224:47;19809:16;19803:23;19737:4;33210:2;33199:9;33195:18;19839:38;19892:71;19728:14;33199:9;19728:14;19944:12;19892:71;:::i;:::-;19884:79;;41040:8;;40913:42;;;33210:2;20046:5;20042:16;20036:23;40902:54;20113:14;33199:9;20113:14;10658:37;20113:14;20204:5;20200:16;20194:23;20271:14;33199:9;20271:14;20982:37;20271:14;20362:5;20358:16;20352:23;20429:14;33199:9;20429:14;20982:37;20429:14;20528:5;20524:16;20518:23;19737:4;33199:9;20595:14;20982:37;33277:134;;;;33181:240;;;;:::o;33428:218::-;41040:8;41029:20;;;;20718:36;;33553:2;33538:18;;33524:122::o;33653:222::-;20982:37;;;33780:2;33765:18;;33751:124::o;33882:481::-;;21012:5;20989:3;20982:37;34087:2;34205;34194:9;34190:18;34183:48;34245:108;34087:2;34076:9;34072:18;34339:6;34245:108;:::i;34370:848::-;;21012:5;20989:3;20982:37;42851:24;34848:2;34837:9;34833:18;14673:58;34675:3;34885:2;34874:9;34870:18;34863:48;34925:108;34675:3;34664:9;34660:19;35019:6;34925:108;:::i;:::-;-1:-1;;;;;40902:54;;;;35120:2;35105:18;;10527:58;-1:-1;35203:3;35188:19;20982:37;34917:116;34646:572;-1:-1;;;34646:572::o;35225:333::-;20982:37;;;35544:2;35529:18;;20982:37;35380:2;35365:18;;35351:207::o;35565:560::-;20982:37;;;35943:2;35928:18;;20982:37;;;;40699:13;40692:21;36020:2;36005:18;;12726:34;-1:-1;;;;;40902:54;36111:2;36096:18;;10527:58;35778:3;35763:19;;35749:376::o;36132:444::-;20982:37;;;36479:2;36464:18;;20982:37;;;;36562:2;36547:18;;20982:37;36315:2;36300:18;;36286:290::o;36583:556::-;20982:37;;;36959:2;36944:18;;20982:37;;;;37042:2;37027:18;;20982:37;37125:2;37110:18;;20982:37;36794:3;36779:19;;36765:374::o;37146:668::-;20982:37;;;37550:2;37535:18;;20982:37;;;;37633:2;37618:18;;20982:37;;;;37716:2;37701:18;;20982:37;37799:3;37784:19;;20982:37;37385:3;37370:19;;37356:458::o;37821:256::-;37883:2;37877:9;37909:17;;;37984:18;37969:34;;38005:22;;;37966:62;37963:2;;;38041:1;;38031:12;37963:2;37883;38050:22;37861:216;;-1:-1;37861:216::o;38084:304::-;;38243:18;38235:6;38232:30;38229:2;;;-1:-1;;38265:12;38229:2;-1:-1;38310:4;38298:17;;;38363:15;;38166:222::o;38395:321::-;;38538:18;38530:6;38527:30;38524:2;;;-1:-1;;38560:12;38524:2;-1:-1;2035:19;38614:17;-1:-1;;38610:33;38701:4;38691:15;;38461:255::o;43131:145::-;43212:6;43207:3;43202;43189:30;-1:-1;43268:1;43250:16;;43243:27;43182:94::o;43285:268::-;43350:1;43357:101;43371:6;43368:1;43365:13;43357:101;;;43438:11;;;43432:18;43419:11;;;43412:39;43393:2;43386:10;43357:101;;;43473:6;43470:1;43467:13;43464:2;;;-1:-1;;43350:1;43520:16;;43513:27;43334:219::o;44166:117::-;-1:-1;;;;;40902:54;;44225:35;;44215:2;;44274:1;;44264:12;44290:111;44371:5;40699:13;40692:21;44349:5;44346:32;44336:2;;44392:1;;44382:12
Swarm Source
ipfs://405a4621a0971844e754f27a47b66af0df795f8a02534d0656a1b3c6a71c33f6
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 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.