ETH Price: $2,230.03 (-5.09%)
 

Overview

Max Total Supply

0 ERC20 ***

Holders

0

Transfers

-
0

Market

Onchain Market Cap

-

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 0 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Strategy

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
/**
 *Submitted for verification at Etherscan.io on 2021-07-10
*/

pragma solidity 0.6.12;

/**
 * @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, with an overflow flag.
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @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) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @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) {
        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, reverting 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) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * 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);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * 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);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * 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;
    }
}

/**
 * @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) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @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");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.3._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.3._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        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);
            }
        }
    }
}

/**
 * @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);
}

/**
 * @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");
        }
    }
}

pragma experimental ABIEncoderV2;

struct StrategyParams {
    uint256 performanceFee;
    uint256 activation;
    uint256 debtRatio;
    uint256 minDebtPerHarvest;
    uint256 maxDebtPerHarvest;
    uint256 lastReport;
    uint256 totalDebt;
    uint256 totalGain;
    uint256 totalLoss;
}

interface VaultAPI is IERC20 {
    function name() external view returns (string calldata);

    function symbol() external view returns (string calldata);

    function decimals() external view returns (uint256);

    function apiVersion() external pure returns (string memory);

    function permit(
        address owner,
        address spender,
        uint256 amount,
        uint256 expiry,
        bytes calldata signature
    ) external returns (bool);

    // NOTE: Vyper produces multiple signatures for a given function with "default" args
    function deposit() external returns (uint256);

    function deposit(uint256 amount) external returns (uint256);

    function deposit(uint256 amount, address recipient) external returns (uint256);

    // NOTE: Vyper produces multiple signatures for a given function with "default" args
    function withdraw() external returns (uint256);

    function withdraw(uint256 maxShares) external returns (uint256);

    function withdraw(uint256 maxShares, address recipient) external returns (uint256);

    function token() external view returns (address);

    function strategies(address _strategy) external view returns (StrategyParams memory);

    function pricePerShare() external view returns (uint256);

    function totalAssets() external view returns (uint256);

    function depositLimit() external view returns (uint256);

    function maxAvailableShares() external view returns (uint256);

    /**
     * View how much the Vault would increase this Strategy's borrow limit,
     * based on its present performance (since its last report). Can be used to
     * determine expectedReturn in your Strategy.
     */
    function creditAvailable() external view returns (uint256);

    /**
     * View how much the Vault would like to pull back from the Strategy,
     * based on its present performance (since its last report). Can be used to
     * determine expectedReturn in your Strategy.
     */
    function debtOutstanding() external view returns (uint256);

    /**
     * View how much the Vault expect this Strategy to return at the current
     * block, based on its present performance (since its last report). Can be
     * used to determine expectedReturn in your Strategy.
     */
    function expectedReturn() external view returns (uint256);

    /**
     * This is the main contact point where the Strategy interacts with the
     * Vault. It is critical that this call is handled as intended by the
     * Strategy. Therefore, this function will be called by BaseStrategy to
     * make sure the integration is correct.
     */
    function report(
        uint256 _gain,
        uint256 _loss,
        uint256 _debtPayment
    ) external returns (uint256);

    /**
     * This function should only be used in the scenario where the Strategy is
     * being retired but no migration of the positions are possible, or in the
     * extreme scenario that the Strategy needs to be put into "Emergency Exit"
     * mode in order for it to exit as quickly as possible. The latter scenario
     * could be for any reason that is considered "critical" that the Strategy
     * exits its position as fast as possible, such as a sudden change in
     * market conditions leading to losses, or an imminent failure in an
     * external dependency.
     */
    function revokeStrategy() external;

    /**
     * View the governance address of the Vault to assert privileged functions
     * can only be called by governance. The Strategy serves the Vault, so it
     * is subject to governance defined by the Vault.
     */
    function governance() external view returns (address);

    /**
     * View the management address of the Vault to assert privileged functions
     * can only be called by management. The Strategy serves the Vault, so it
     * is subject to management defined by the Vault.
     */
    function management() external view returns (address);

    /**
     * View the guardian address of the Vault to assert privileged functions
     * can only be called by guardian. The Strategy serves the Vault, so it
     * is subject to guardian defined by the Vault.
     */
    function guardian() external view returns (address);
}

/**
 * This interface is here for the keeper bot to use.
 */
interface StrategyAPI {
    function name() external view returns (string memory);

    function vault() external view returns (address);

    function want() external view returns (address);

    function apiVersion() external pure returns (string memory);

    function keeper() external view returns (address);

    function isActive() external view returns (bool);

    function delegatedAssets() external view returns (uint256);

    function estimatedTotalAssets() external view returns (uint256);

    function tendTrigger(uint256 callCost) external view returns (bool);

    function tend() external;

    function harvestTrigger(uint256 callCost) external view returns (bool);

    function harvest() external;

    event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding);
}

interface HealthCheck {
    function check(
        uint256 profit,
        uint256 loss,
        uint256 debtPayment,
        uint256 debtOutstanding,
        uint256 totalDebt
    ) external view returns (bool);
}

/**
 * @title Yearn Base Strategy
 * @author yearn.finance
 * @notice
 *  BaseStrategy implements all of the required functionality to interoperate
 *  closely with the Vault contract. This contract should be inherited and the
 *  abstract methods implemented to adapt the Strategy to the particular needs
 *  it has to create a return.
 *
 *  Of special interest is the relationship between `harvest()` and
 *  `vault.report()'. `harvest()` may be called simply because enough time has
 *  elapsed since the last report, and not because any funds need to be moved
 *  or positions adjusted. This is critical so that the Vault may maintain an
 *  accurate picture of the Strategy's performance. See  `vault.report()`,
 *  `harvest()`, and `harvestTrigger()` for further details.
 */
abstract contract BaseStrategy {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    string public metadataURI;

    // health checks
    bool public doHealthCheck;
    address public healthCheck;

    /**
     * @notice
     *  Used to track which version of `StrategyAPI` this Strategy
     *  implements.
     * @dev The Strategy's version must match the Vault's `API_VERSION`.
     * @return A string which holds the current API version of this contract.
     */
    function apiVersion() public pure returns (string memory) {
        return "0.3.5";
    }

    /**
     * @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.
     *  Also note that this value is used to determine the total assets under management by this
     *  strategy, for the purposes of computing the management fee in `Vault`
     * @return
     *  The amount of assets this strategy manages that should not be included in Yearn's Total Value
     *  Locked (TVL) calculation across it's ecosystem.
     */
    function delegatedAssets() external 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 UpdatedMinReportDelay(uint256 delay);

    event UpdatedMaxReportDelay(uint256 delay);

    event UpdatedProfitFactor(uint256 profitFactor);

    event UpdatedDebtThreshold(uint256 debtThreshold);

    event EmergencyExitEnabled();

    event UpdatedMetadataURI(string metadataURI);

    // The minimum number of seconds between harvest calls. See
    // `setMinReportDelay()` for more details.
    uint256 public minReportDelay;

    // The maximum number of seconds between harvest calls. See
    // `setMaxReportDelay()` for more details.
    uint256 public maxReportDelay;

    // The minimum multiple that `callCost` must be above the credit/profit to
    // be "justifiable". See `setProfitFactor()` for more details.
    uint256 public profitFactor;

    // Use this to adjust the threshold at which running a debt causes a
    // harvest trigger. See `setDebtThreshold()` for more details.
    uint256 public debtThreshold;

    // See note on `setEmergencyExit()`.
    bool public emergencyExit;

    // modifiers
    modifier onlyAuthorized() {
        require(msg.sender == strategist || msg.sender == governance(), "!authorized");
        _;
    }

    modifier onlyStrategist() {
        require(msg.sender == strategist, "!strategist");
        _;
    }

    modifier onlyGovernance() {
        require(msg.sender == governance(), "!authorized");
        _;
    }

    modifier onlyKeepers() {
        require(
            msg.sender == keeper ||
                msg.sender == strategist ||
                msg.sender == governance() ||
                msg.sender == vault.guardian() ||
                msg.sender == vault.management(),
            "!authorized"
        );
        _;
    }

    modifier onlyVaultManagers() {
        require(
            msg.sender == vault.management() || msg.sender == governance(),
            "!authorized"
        );
        _;
    }


    constructor(address _vault) public {
        _initialize(_vault, msg.sender, msg.sender, msg.sender);
    }

    /**
     * @notice
     *  Initializes the Strategy, this is called only once, when the
     *  contract is deployed.
     * @dev `_vault` should implement `VaultAPI`.
     * @param _vault The address of the Vault responsible for this Strategy.
     */
    function _initialize(
        address _vault,
        address _strategist,
        address _rewards,
        address _keeper
    ) internal {
        require(address(want) == address(0), "Strategy already initialized");

        vault = VaultAPI(_vault);
        want = IERC20(vault.token());
        want.safeApprove(_vault, uint256(-1)); // Give Vault unlimited access (might save gas)
        strategist = _strategist;
        rewards = _rewards;
        keeper = _keeper;

        // initialize variables
        minReportDelay = 0;
        maxReportDelay = 86400;
        profitFactor = 100;
        debtThreshold = 0;

        vault.approve(rewards, uint256(-1)); // Allow rewards to be pulled
    }

    function setHealthCheck(address _healthCheck) external onlyVaultManagers {
        healthCheck = _healthCheck;
    }

    function setDoHealthCheck(bool _doHealthCheck) external onlyVaultManagers {
        doHealthCheck = _doHealthCheck;
    }

    /**
     * @notice
     *  Used to change `strategist`.
     *
     *  This may only be called by governance or the existing strategist.
     * @param _strategist The new address to assign as `strategist`.
     */
    function setStrategist(address _strategist) external onlyAuthorized {
        require(_strategist != address(0));
        strategist = _strategist;
        emit UpdatedStrategist(_strategist);
    }

    /**
     * @notice
     *  Used to change `keeper`.
     *
     *  `keeper` is the only address that may call `tend()` or `harvest()`,
     *  other than `governance()` or `strategist`. However, unlike
     *  `governance()` or `strategist`, `keeper` may *only* call `tend()`
     *  and `harvest()`, and no other authorized functions, following the
     *  principle of least privilege.
     *
     *  This may only be called by governance or the strategist.
     * @param _keeper The new address to assign as `keeper`.
     */
    function setKeeper(address _keeper) external onlyAuthorized {
        require(_keeper != address(0));
        keeper = _keeper;
        emit UpdatedKeeper(_keeper);
    }

    /**
     * @notice
     *  Used to change `rewards`. EOA or smart contract which has the permission
     *  to pull rewards from the vault.
     *
     *  This may only be called by the strategist.
     * @param _rewards The address to use for pulling rewards.
     */
    function setRewards(address _rewards) external onlyStrategist {
        require(_rewards != address(0));
        vault.approve(rewards, 0);
        rewards = _rewards;
        vault.approve(rewards, uint256(-1));
        emit UpdatedRewards(_rewards);
    }

    /**
     * @notice
     *  Used to change `minReportDelay`. `minReportDelay` is the minimum number
     *  of blocks that should pass for `harvest()` to be called.
     *
     *  For external keepers (such as the Keep3r network), this is the minimum
     *  time between jobs to wait. (see `harvestTrigger()`
     *  for more details.)
     *
     *  This may only be called by governance or the strategist.
     * @param _delay The minimum number of seconds to wait between harvests.
     */
    function setMinReportDelay(uint256 _delay) external onlyAuthorized {
        minReportDelay = _delay;
        emit UpdatedMinReportDelay(_delay);
    }

    /**
     * @notice
     *  Used to change `maxReportDelay`. `maxReportDelay` is the maximum number
     *  of blocks that should pass for `harvest()` to be called.
     *
     *  For external keepers (such as the Keep3r network), this is the maximum
     *  time between jobs to wait. (see `harvestTrigger()`
     *  for more details.)
     *
     *  This may only be called by governance or the strategist.
     * @param _delay The maximum number of seconds to wait between harvests.
     */
    function setMaxReportDelay(uint256 _delay) external onlyAuthorized {
        maxReportDelay = _delay;
        emit UpdatedMaxReportDelay(_delay);
    }

    /**
     * @notice
     *  Used to change `profitFactor`. `profitFactor` is used to determine
     *  if it's worthwhile to harvest, given gas costs. (See `harvestTrigger()`
     *  for more details.)
     *
     *  This may only be called by governance or the strategist.
     * @param _profitFactor A ratio to multiply anticipated
     * `harvest()` gas cost against.
     */
    function setProfitFactor(uint256 _profitFactor) external onlyAuthorized {
        profitFactor = _profitFactor;
        emit UpdatedProfitFactor(_profitFactor);
    }

    /**
     * @notice
     *  Sets how far the Strategy can go into loss without a harvest and report
     *  being required.
     *
     *  By default this is 0, meaning any losses would cause a harvest which
     *  will subsequently report the loss to the Vault for tracking. (See
     *  `harvestTrigger()` for more details.)
     *
     *  This may only be called by governance or the strategist.
     * @param _debtThreshold How big of a loss this Strategy may carry without
     * being required to report to the Vault.
     */
    function setDebtThreshold(uint256 _debtThreshold) external onlyAuthorized {
        debtThreshold = _debtThreshold;
        emit UpdatedDebtThreshold(_debtThreshold);
    }

    /**
     * @notice
     *  Used to change `metadataURI`. `metadataURI` is used to store the URI
     * of the file describing the strategy.
     *
     *  This may only be called by governance or the strategist.
     * @param _metadataURI The URI that describe the strategy.
     */
    function setMetadataURI(string calldata _metadataURI) external onlyAuthorized {
        metadataURI = _metadataURI;
        emit UpdatedMetadataURI(_metadataURI);
    }

    /**
     * Resolve governance address from Vault contract, used to make assertions
     * on protected functions in the Strategy.
     */
    function governance() internal view returns (address) {
        return vault.governance();
    }

    /**
     * @notice
     *  Provide an accurate 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) where the amount made available is less than what is needed.
     * 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 `_liquidatedAmount + _loss <= _amountNeeded` should always be maintained
     */
    function liquidatePosition(uint256 _amountNeeded) internal virtual returns (uint256 _liquidatedAmount, uint256 _loss);

    /**
     * @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 `min/maxReportDelay`, `profitFactor`, `debtThreshold` to adjust the
     *  strategist-controlled parameters that will influence whether this call
     *  returns `true` or not. These parameters will be used in conjunction
     *  with the parameters reported to the Vault (see `params`) to determine
     *  if calling `harvest()` is merited.
     *
     *  It is expected that an external system will check `harvestTrigger()`.
     *  This could be a script run off a desktop or cloud bot (e.g.
     *  https://github.com/iearn-finance/yearn-vaults/blob/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 not trigger if we haven't waited long enough since previous harvest
        if (block.timestamp.sub(params.lastReport) < minReportDelay) return false;

        // Should trigger if hasn't been called in a while
        if (block.timestamp.sub(params.lastReport) >= maxReportDelay) return true;

        // If some amount is owed, pay it back
        // NOTE: Since debt is based on deposits, it makes sense to guard against large
        //       changes to the value from triggering a harvest directly through user
        //       behavior. This should ensure reasonable resistance to manipulation
        //       from user-initiated withdrawals as the outstanding debt fluctuates.
        uint256 outstanding = vault.debtOutstanding();
        if (outstanding > debtThreshold) return true;

        // Check for profits and losses
        uint256 total = estimatedTotalAssets();
        // Trigger if we have a loss to report
        if (total.add(debtThreshold) < params.totalDebt) return true;

        uint256 profit = 0;
        if (total > params.totalDebt) profit = total.sub(params.totalDebt); // We've earned a profit!

        // Otherwise, only trigger if it "makes sense" economically (gas cost
        // is <N% of value moved)
        uint256 credit = vault.creditAvailable();
        return (profitFactor.mul(callCost) < credit.add(profit));
    }

    /**
     * @notice
     *  Harvests the Strategy, recognizing any profits or losses and adjusting
     *  the Strategy's position.
     *
     *  In the rare case the Strategy is in emergency shutdown, this will exit
     *  the Strategy's position.
     *
     *  This may only be called by governance, the strategist, or the keeper.
     * @dev
     *  When `harvest()` is called, the Strategy reports to the Vault (via
     *  `vault.report()`), so in some cases `harvest()` must be called in order
     *  to take in profits, to borrow newly available funds from the Vault, or
     *  otherwise adjust its position. In other cases `harvest()` must be
     *  called to report to the Vault on the Strategy's position, especially if
     *  any losses have occurred.
     */
    function harvest() external onlyKeepers {
        uint256 profit = 0;
        uint256 loss = 0;
        uint256 debtOutstanding = vault.debtOutstanding();
        uint256 debtPayment = 0;
        if (emergencyExit) {
            // Free up as much capital as possible
            uint256 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);

        // Check if free returns are left, and re-invest them
        adjustPosition(debtOutstanding);

        // call healthCheck contract
        if (doHealthCheck && healthCheck != address(0)) {
            require(
                HealthCheck(healthCheck).check(
                    profit,
                    loss,
                    debtPayment,
                    debtOutstanding,
                    totalDebt
                ),
                "!healthcheck"
            );
        } else {
            doHealthCheck = true;
        }

        emit Harvested(profit, loss, debtPayment, debtOutstanding);
    }

    /**
     * @notice
     *  Withdraws `_amountNeeded` to `vault`.
     *
     *  This may only be called by the Vault.
     * @param _amountNeeded How much `want` to withdraw.
     * @return _loss Any realized losses
     */
    function withdraw(uint256 _amountNeeded) external returns (uint256 _loss) {
        require(msg.sender == address(vault), "!vault");
        // Liquidate as much as possible to `want`, up to `_amountNeeded`
        uint256 amountFreed;
        (amountFreed, _loss) = liquidatePosition(_amountNeeded);
        // Send it directly back (NOTE: Using `msg.sender` saves some gas here)
        want.safeTransfer(msg.sender, amountFreed);
        // NOTE: Reinvest anything leftover on next `tend`/`harvest`
    }

    /**
     * Do anything necessary to prepare this Strategy for migration, such as
     * transferring any reserve or LP tokens, CDPs, or other tokens or stores of
     * value.
     */
    function prepareMigration(address _newStrategy) internal virtual;

    /**
     * @notice
     *  Transfers all `want` from this Strategy to `_newStrategy`.
     *
     *  This may only be called by 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.safeTransfer(_newStrategy, want.balanceOf(address(this)));
    }

    /**
     * @notice
     *  Activates emergency exit. Once activated, the Strategy will exit its
     *  position upon the next harvest, depositing all funds into the Vault as
     *  quickly as is reasonable given on-chain conditions.
     *
     *  This may only be called by governance or the strategist.
     * @dev
     *  See `vault.setEmergencyShutdown()` and `harvest()` for further details.
     */
    function setEmergencyExit() external 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).safeTransfer(governance(), IERC20(_token).balanceOf(address(this)));
    }
}

abstract contract BaseStrategyInitializable is BaseStrategy {
    event Cloned(address indexed clone);

    constructor(address _vault) public BaseStrategy(_vault) {}

    function initialize(
        address _vault,
        address _strategist,
        address _rewards,
        address _keeper
    ) external virtual {
        _initialize(_vault, _strategist, _rewards, _keeper);
    }

    function clone(address _vault) external returns (address) {
        return this.clone(_vault, msg.sender, msg.sender, msg.sender);
    }

    function clone(
        address _vault,
        address _strategist,
        address _rewards,
        address _keeper
    ) external returns (address newStrategy) {
        // Copied from https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol
        bytes20 addressBytes = bytes20(address(this));

        assembly {
            // EIP-1167 bytecode
            let clone_code := mload(0x40)
            mstore(clone_code, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(clone_code, 0x14), addressBytes)
            mstore(add(clone_code, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            newStrategy := create(0, clone_code, 0x37)
        }

        BaseStrategyInitializable(newStrategy).initialize(_vault, _strategist, _rewards, _keeper);

        emit Cloned(newStrategy);
    }
}

interface MMVault {
    function token() external view returns (address);
    function getRatio() external view returns (uint256);
    function deposit(uint256) external;
    function withdraw(uint256) external;
    function withdrawAll() external;
    function earn() external;
    function balance() external view returns (uint256);
    function totalSupply() external view returns (uint256);
    function balanceOf(address _user) external view returns (uint256);
}

interface MMStrategy {
    function harvest() external;
}

interface MMFarmingPool {
    function deposit(uint256 _pid, uint256 _amount) external;
    function withdraw(uint256 _pid, uint256 _amount) external;
    function userInfo(uint256, address) external view returns (uint256 amount, uint256 rewardDebt);
    function pendingMM(uint256 _pid, address _user) external view returns (uint256);
}

interface IUni{
    function getAmountsOut(
        uint256 amountIn, 
        address[] calldata path
    ) external view returns (uint256[] memory amounts);

    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);
}

/**
 * @title Strategy for Mushrooms WBTC vault/farming pool yield
 * @author Mushrooms 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.
 */
contract Strategy is BaseStrategy {
    
    using SafeERC20 for IERC20;
    using Address for address;
    using SafeMath for uint256;
	
    address constant public wbtc = address(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599); //wbtc
    address constant public mm = address(0xa283aA7CfBB27EF0cfBcb2493dD9F4330E0fd304); //MM
    address public constant usdc = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; //USDC
    address constant public unirouter = address(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
    address constant public sushiroute = address(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F);

    address constant public weth = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); 

    address constant public mmVault = address(0xb06661A221Ab2Ec615531f9632D6Dc5D2984179A);// Mushrooms mWBTC vault
    address constant public mmFarmingPool = address(0xf8873a6080e8dbF41ADa900498DE0951074af577); //Mushrooms mining MasterChef
    uint256 constant public mmFarmingPoolId = 11; // Mushrooms farming pool id for mWBTC

    uint256 public minMMToSwap = 1; // min $MM to swap during adjustPosition()
    uint256 public minShareToProfit = 1; // min mWBTC share to withdraw as profit during prepareReturn()
	
    /**
     * @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 override view returns (string memory){
        return "yvWBTCStratMMV1";
    }

    /**
     * @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.
     */
    constructor(address _vault) BaseStrategy(_vault) public {
        require(address(want) == wbtc, '!wrongVault');				
        want.safeApprove(mmVault, uint256(-1));		
        IERC20(mmVault).safeApprove(mmFarmingPool, uint256(-1));
        IERC20(mm).safeApprove(unirouter, uint256(-1));
        IERC20(mm).safeApprove(sushiroute, uint256(-1));
    }    

    function setMinMMToSwap(uint256 _minMMToSwap) external onlyAuthorized {
        minMMToSwap = _minMMToSwap;
    }   

    function setMinShareToProfit(uint256 _minShareToProfit) external onlyAuthorized {
        minShareToProfit = _minShareToProfit;
    }
    
	/**
     * @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 override view returns (uint256) {
        return 0;
    }
	
    /**
     * @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 override view returns (uint256){
        (uint256 _mToken, ) = MMFarmingPool(mmFarmingPool).userInfo(mmFarmingPoolId, address(this));
        uint256 _mmVault = IERC20(mmVault).balanceOf(address(this));
        return _convertMTokenToWant(_mToken.add(_mmVault)).add(want.balanceOf(address(this)));
    }

    /**
     * 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
        override
        returns (
            uint256 _profit,
            uint256 _loss,
            uint256 _debtPayment
    ){			
		
        // Pay debt if any
        if (_debtOutstanding > 0) {
            (uint256 _amountFreed, uint256 _reportLoss) = liquidatePosition(_debtOutstanding);
            _debtPayment = _amountFreed > _debtOutstanding? _debtOutstanding : _amountFreed;
            _loss = _reportLoss;
        }	
		
        // Capture some additional profit if underlying vault get appreciation
        uint256 debt = vault.strategies(address(this)).totalDebt;
        uint256 currentValue = estimatedTotalAssets();
        if (currentValue > debt){
            uint256 target = currentValue.sub(debt);
            uint256 _beforeWant = want.balanceOf(address(this));
            uint256 _withdrawMShare = _convertWantToMToken(target);
            if (_withdrawMShare > minShareToProfit){
                uint256 _mmVault = IERC20(mmVault).balanceOf(address(this));
                if (_mmVault < _withdrawMShare){
                    _withdrawFromFarming(_withdrawMShare, _mmVault);
                }
                MMVault(mmVault).withdraw(_withdrawMShare);
                uint256 _afterWant = want.balanceOf(address(this));
                if (_afterWant > _beforeWant){
                    uint256 actual = _afterWant.sub(_beforeWant);
                    _profit = _profit.add(actual);
                    _loss = _loss.add(actual < target? target.sub(actual) : 0);
                }			
            }
        }		
		
        // Claim $MM profit
        uint256 _pendingMM = MMFarmingPool(mmFarmingPool).pendingMM(mmFarmingPoolId, address(this));
        if (_pendingMM > 0){
            MMFarmingPool(mmFarmingPool).withdraw(mmFarmingPoolId, 0);		
        }
        _profit = _profit.add(_disposeOfMM());
		
        // zero-out _profit & _loss
        if (_profit > _loss){
            _profit = _profit.sub(_loss);
            _loss = 0;
        } else{
            _loss = _loss.sub(_profit);
            _profit = 0;
        }
		
        return (_profit, _loss, _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 override{
	
        //emergency exit is dealt with in prepareReturn
        if (emergencyExit) {
            return;
        }
		
        uint256 _before = IERC20(mmVault).balanceOf(address(this));
        uint256 _after = _before;	
		
        uint256 _want = want.balanceOf(address(this));
        if (_want > _debtOutstanding) {
            _want = _want.sub(_debtOutstanding);
            
            MMVault(mmVault).deposit(_want);
            _after = IERC20(mmVault).balanceOf(address(this));
            require(_after > _before, '!mismatchDepositIntoMushrooms');
        } else if(_debtOutstanding > _want){
            return;		
        }		
								
        if (_after > 0){
            MMFarmingPool(mmFarmingPool).deposit(mmFarmingPoolId, _after);
        }		            
    }

    /**
     * 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 `_liquidatedAmount + _loss <= _amountNeeded` should always be maintained
     */
    function liquidatePosition(uint256 _amountNeeded) internal override returns (uint256 _liquidatedAmount, uint256 _loss){
		
        bool liquidateAll = _amountNeeded >= estimatedTotalAssets()? true : false;
        
        if (liquidateAll){ 	
            (uint256 _mToken, ) = MMFarmingPool(mmFarmingPool).userInfo(mmFarmingPoolId, address(this));
            MMFarmingPool(mmFarmingPool).withdraw(mmFarmingPoolId, _mToken);
            MMVault(mmVault).withdraw(IERC20(mmVault).balanceOf(address(this)));
            _liquidatedAmount = IERC20(want).balanceOf(address(this));
            uint256 ttDebt = vault.strategies(address(this)).totalDebt;
            uint256 _liquidateAllLoss = 0;
            if (_liquidatedAmount < ttDebt){
               _liquidateAllLoss = ttDebt.sub(_liquidatedAmount);
            }
            return (_liquidatedAmount, _liquidateAllLoss);		  		  
        } else{ 	
            uint256 _before = IERC20(want).balanceOf(address(this));
            if (_before < _amountNeeded){            
               uint256 _gap = _amountNeeded.sub(_before);	
               uint256 _mShare = _convertWantToMToken(_gap);			
               
               uint256 _mmVault = IERC20(mmVault).balanceOf(address(this));
               if (_mmVault < _mShare){
                   _withdrawFromFarming(_mShare, _mmVault);
               }
               MMVault(mmVault).withdraw(_mShare);
               uint256 _after = IERC20(want).balanceOf(address(this));
               require(_after > _before, '!mismatchMushroomsVaultWithdraw');

               return (_after, _amountNeeded > _after? _amountNeeded.sub(_after): 0);		
            } else{
               return (_amountNeeded, _loss);
            }		
        }
    }
	
	/**
     * @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 view override returns (bool) {
        return super.harvestTrigger(ethToWant(callCost));
    }

    /**
     * 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 override{
        (uint256 _mToken, ) = MMFarmingPool(mmFarmingPool).userInfo(mmFarmingPoolId, address(this));
        MMFarmingPool(mmFarmingPool).withdraw(mmFarmingPoolId, _mToken);
		
        uint256 _mmVault = IERC20(mmVault).balanceOf(address(this));
        if (_mmVault > 0){
            IERC20(mmVault).safeTransfer(_newStrategy, _mmVault);
        }
	    
        uint256 _mm = IERC20(mm).balanceOf(address(this));
        if (_mm > 0){
            IERC20(mm).safeTransfer(_newStrategy, _mm);
        }
    }

    /**
     * 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 override view returns (address[] memory){
        address[] memory protected = new address[](1);
        protected[0] = mmVault;
        return protected;
    }
	
    function _convertMTokenToWant(uint256 _shares) internal view returns (uint256){
        uint256 _mTokenTotal = IERC20(mmVault).totalSupply();
        if (_mTokenTotal == 0){
            return 0;
        }
        uint256 _wantInVault = MMVault(mmVault).balance();
        return (_wantInVault.mul(_shares)).div(_mTokenTotal);
    }
	
    function _convertWantToMToken(uint256 _want) internal view returns (uint256){
        return _want.mul(1e18).div(MMVault(mmVault).getRatio());
    }	
	
    function _withdrawFromFarming(uint256 _target, uint256 _balance) internal {
        uint256 _mvGap = _target.sub(_balance); 			
        (uint256 _mToken, ) = MMFarmingPool(mmFarmingPool).userInfo(mmFarmingPoolId, address(this));
        require(_mToken >= _mvGap, '!insufficientMTokenInMasterChef');		
        MMFarmingPool(mmFarmingPool).withdraw(mmFarmingPoolId, _mvGap);	
    }
	
    // swap $MM for $WBTC
    function _disposeOfMM() internal returns (uint256){
        uint256 _mm = IERC20(mm).balanceOf(address(this));
        uint256 _wantProfit; 
		
        if (_mm >= minMMToSwap) {
            // intuitively in favor of sushiswap over uniswap if possible for better efficiency and cost
			
            address[] memory pathSushi = new address[](3);
            pathSushi[0] = mm;
            pathSushi[1] = weth;
            pathSushi[2] = wbtc;
            uint256 outputSushi = IUni(sushiroute).getAmountsOut(_mm, pathSushi)[pathSushi.length - 1];
						            
            address[] memory pathUni = new address[](4);
            pathUni[0] = mm;
            pathUni[1] = usdc;
            pathUni[2] = weth;
            pathUni[3] = wbtc;
            uint256 outputUni = IUni(unirouter).getAmountsOut(_mm, pathUni)[pathUni.length - 1];
			
            uint256 _want = want.balanceOf(address(this));
            if (outputSushi >= outputUni){
                IUni(sushiroute).swapExactTokensForTokens(_mm, uint256(0), pathSushi, address(this), now);			
            } else{
                IUni(unirouter).swapExactTokensForTokens(_mm, uint256(0), pathUni, address(this), now);			
            }
            _wantProfit = want.balanceOf(address(this)).sub(_want);
        }
        return _wantProfit;
    }
	
    function ethToWant(uint256 _amount) public view returns (uint256) {
        if (_amount == 0) {
            return 0;
        }

        address[] memory path = new address[](2);
        path[0] = weth;
        path[1] = wbtc;
        uint256[] memory amounts = IUni(unirouter).getAmountsOut(_amount, path);

        return amounts[amounts.length - 1];
    }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_vault","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":"debtThreshold","type":"uint256"}],"name":"UpdatedDebtThreshold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newKeeper","type":"address"}],"name":"UpdatedKeeper","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"delay","type":"uint256"}],"name":"UpdatedMaxReportDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"metadataURI","type":"string"}],"name":"UpdatedMetadataURI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"delay","type":"uint256"}],"name":"UpdatedMinReportDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profitFactor","type":"uint256"}],"name":"UpdatedProfitFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"rewards","type":"address"}],"name":"UpdatedRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newStrategist","type":"address"}],"name":"UpdatedStrategist","type":"event"},{"inputs":[],"name":"apiVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"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":"emergencyExit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"estimatedTotalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"ethToWant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"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":[],"name":"maxReportDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newStrategy","type":"address"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minMMToSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minReportDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minShareToProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mm","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mmFarmingPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mmFarmingPoolId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mmVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"profitFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debtThreshold","type":"uint256"}],"name":"setDebtThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_doHealthCheck","type":"bool"}],"name":"setDoHealthCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setEmergencyExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_healthCheck","type":"address"}],"name":"setHealthCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"setKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setMaxReportDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_metadataURI","type":"string"}],"name":"setMetadataURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minMMToSwap","type":"uint256"}],"name":"setMinMMToSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setMinReportDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minShareToProfit","type":"uint256"}],"name":"setMinShareToProfit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_profitFactor","type":"uint256"}],"name":"setProfitFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewards","type":"address"}],"name":"setRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategist","type":"address"}],"name":"setStrategist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sushiroute","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":"callCost","type":"uint256"}],"name":"tendTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unirouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdc","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"wbtc","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountNeeded","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"_loss","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

60806040526001600c556001600d553480156200001b57600080fd5b50604051620050cf380380620050cf8339810160408190526200003e9162000657565b806200004d81338080620001a3565b506006546001600160a01b0316732260fac5e5542a773aa44fbcfedf7c193bc2c59914620000985760405162461bcd60e51b81526004016200008f90620007be565b60405180910390fd5b600654620000d3906001600160a01b031673b06661a221ab2ec615531f9632d6dc5d2984179a6000196200037e602090811b62001ee917901c565b6200011673b06661a221ab2ec615531f9632d6dc5d2984179a73f8873a6080e8dbf41ada900498de0951074af5776000196200037e602090811b62001ee917901c565b6200015973a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd304737a250d5630b4cf539739df2c5dacb4c659f2488d6000196200037e602090811b62001ee917901c565b6200019c73a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd30473d9e1ce17f2641f24ae83637ab66a2cca9c378b9f6000196200037e602090811b62001ee917901c565b50620008f4565b6006546001600160a01b031615620001cf5760405162461bcd60e51b81526004016200008f9062000787565b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b1580156200022c57600080fd5b505afa15801562000241573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000267919062000657565b600680546001600160a01b0319166001600160a01b039283161790819055620002a19116856000196200037e602090811b62001ee917901c565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b39362000321939116916000199101620006f3565b602060405180830381600087803b1580156200033c57600080fd5b505af115801562000351573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000377919062000680565b5050505050565b8015806200040d5750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e90620003b79030908690600401620006d9565b60206040518083038186803b158015620003d057600080fd5b505afa158015620003e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040b9190620006a2565b155b6200042c5760405162461bcd60e51b81526004016200008f9062000864565b620004878363095ea7b360e01b84846040516024016200044e929190620006f3565b60408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b03938416179052906200048c16565b505050565b6060620004e8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200052860201b62001fe8179092919060201c565b80519091501562000487578080602001905181019062000509919062000680565b620004875760405162461bcd60e51b81526004016200008f906200081a565b606062000539848460008562000543565b90505b9392505050565b606082471015620005685760405162461bcd60e51b81526004016200008f9062000741565b620005738562000613565b620005925760405162461bcd60e51b81526004016200008f90620007e3565b60006060866001600160a01b03168587604051620005b19190620006bb565b60006040518083038185875af1925050503d8060008114620005f0576040519150601f19603f3d011682016040523d82523d6000602084013e620005f5565b606091505b5090925090506200060882828662000619565b979650505050505050565b3b151590565b606083156200062a5750816200053c565b8251156200063b5782518084602001fd5b8160405162461bcd60e51b81526004016200008f91906200070c565b60006020828403121562000669578081fd5b81516001600160a01b03811681146200053c578182fd5b60006020828403121562000692578081fd5b815180151581146200053c578182fd5b600060208284031215620006b4578081fd5b5051919050565b60008251620006cf818460208701620008c1565b9190910192915050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b60006020825282518060208401526200072d816040850160208701620008c1565b601f01601f19169190910160400192915050565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b6020808252600b908201526a085ddc9bdb99d5985d5b1d60aa1b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606082015260800190565b60005b83811015620008de578181015183820152602001620008c4565b83811115620008ee576000848401525b50505050565b6147cb80620009046000396000f3fe608060405234801561001057600080fd5b50600436106102d65760003560e01c80636718835f11610182578063b0ad9d00116100e9578063e90eaa51116100a2578063efbb5cb01161007c578063efbb5cb014610545578063f017c92f1461054d578063fbfa77cf14610560578063fcf2d0ad14610568576102d6565b8063e90eaa5114610517578063ec38a8621461051f578063ed882c2b14610532576102d6565b8063b0ad9d00146104d1578063b252720b146104d9578063bbdfac27146104e1578063c7b9d530146104e9578063ce5494bb146104fc578063e8040ba11461050f576102d6565b80638e6350e21161013b5780638e6350e21461048b57806391397ab41461049357806395e80c50146104a65780639ec5a894146104ae578063ac00ff26146104b6578063aced1661146104c9576102d6565b80636718835f1461043a578063711e905214610442578063748747e61461044a578063750521f51461045d578063780022a0146104705780638cdfe16614610483576102d6565b806325829410116102415780633e413bee116101fa5780634641257d116101d45780634641257d146104045780635641ec031461040c5780636278cdc014610414578063650d188014610427576102d6565b80633e413bee146103ec5780633fc8cef3146103f4578063440368a3146103fc576102d6565b806325829410146103a657806328b7ccf7146103ae5780632e1a7d4d146103b6578063326ab283146103c957806339a172a8146103d15780633cdc5389146103e4576102d6565b80631221d660116102935780631221d6601461034f5780631d12f28b146103645780631f1fcd51146103795780631fe4a6861461038157806322f3e2d414610389578063257ae0de1461039e576102d6565b806301681a62146102db57806303ee438c146102f057806306fdde031461030e5780630f0dc9ea146103165780630f969b871461032957806311bc82451461033c575b600080fd5b6102ee6102e9366004613f16565b610570565b005b6102f861070f565b6040516103059190614239565b60405180910390f35b6102f861079d565b6102ee610324366004614106565b6107c6565b6102ee610337366004614106565b610818565b6102ee61034a366004613f16565b6108a5565b6103576109a6565b60405161030591906141b8565b61036c6109be565b6040516103059190614608565b6103576109c4565b6103576109d3565b6103916109e2565b60405161030591906141ff565b610357610a84565b6102f8610a9c565b61036c610abb565b61036c6103c4366004614106565b610ac1565b610357610b1c565b6102ee6103df366004614106565b610b34565b610357610bb6565b610357610bce565b610357610be6565b6102ee610bfe565b6102ee610e27565b6103916112f9565b6102ee610422366004614106565b611302565b610391610435366004614106565b611354565b61039161135c565b61036c611365565b6102ee610458366004613f16565b61136b565b6102ee61046b36600461401b565b611416565b61036c61047e366004614106565b6114ad565b61036c61160b565b61036c611611565b6102ee6104a1366004614106565b611616565b61036c611698565b61035761169e565b6102ee6104c4366004613fe3565b6116ad565b610357611799565b6103576117a8565b6103576117ba565b61036c6117ce565b6102ee6104f7366004613f16565b6117d4565b6102ee61050a366004613f16565b61187f565b61036c6119f0565b6103576119f5565b6102ee61052d366004613f16565b611a0d565b610391610540366004614106565b611ba0565b61036c611bb9565b6102ee61055b366004614106565b611d75565b610357611df7565b6102ee611e06565b610578612001565b6001600160a01b0316336001600160a01b0316146105b15760405162461bcd60e51b81526004016105a8906144e8565b60405180910390fd5b6006546001600160a01b03828116911614156105df5760405162461bcd60e51b81526004016105a8906142c8565b6002546001600160a01b038281169116141561060d5760405162461bcd60e51b81526004016105a890614459565b606061061761207e565b905060005b81518110156106725781818151811061063157fe5b60200260200101516001600160a01b0316836001600160a01b0316141561066a5760405162461bcd60e51b81526004016105a890614557565b60010161061c565b5061070b61067e612001565b6040516370a0823160e01b81526001600160a01b038516906370a08231906106aa9030906004016141b8565b60206040518083038186803b1580156106c257600080fd5b505afa1580156106d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106fa919061411e565b6001600160a01b03851691906120dc565b5050565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107955780601f1061076a57610100808354040283529160200191610795565b820191906000526020600020905b81548152906001019060200180831161077857829003601f168201915b505050505081565b60408051808201909152600f81526e79765742544353747261744d4d563160881b602082015290565b6003546001600160a01b03163314806107f757506107e2612001565b6001600160a01b0316336001600160a01b0316145b6108135760405162461bcd60e51b81526004016105a8906144e8565b600c55565b6003546001600160a01b03163314806108495750610834612001565b6001600160a01b0316336001600160a01b0316145b6108655760405162461bcd60e51b81526004016105a8906144e8565b600a8190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a86009061089a908390614608565b60405180910390a150565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156108f357600080fd5b505afa158015610907573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092b9190613f32565b6001600160a01b0316336001600160a01b03161480610962575061094d612001565b6001600160a01b0316336001600160a01b0316145b61097e5760405162461bcd60e51b81526004016105a8906144e8565b600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b73d9e1ce17f2641f24ae83637ab66a2cca9c378b9f81565b600a5481565b6006546001600160a01b031681565b6003546001600160a01b031681565b6002546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610a179030906004016141b8565b6101206040518083038186803b158015610a3057600080fd5b505afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190614088565b604001511180610a7f57506000610a7d611bb9565b115b905090565b737a250d5630b4cf539739df2c5dacb4c659f2488d81565b604080518082019091526005815264302e332e3560d81b602082015290565b60085481565b6002546000906001600160a01b03163314610aee5760405162461bcd60e51b81526004016105a890614439565b6000610af9836120fb565b600654909350909150610b16906001600160a01b031633836120dc565b50919050565b73f8873a6080e8dbf41ada900498de0951074af57781565b6003546001600160a01b0316331480610b655750610b50612001565b6001600160a01b0316336001600160a01b0316145b610b815760405162461bcd60e51b81526004016105a8906144e8565b60078190556040517fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b19061089a908390614608565b732260fac5e5542a773aa44fbcfedf7c193bc2c59981565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6005546001600160a01b0316331480610c2157506003546001600160a01b031633145b80610c445750610c2f612001565b6001600160a01b0316336001600160a01b0316145b80610ce55750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b158015610c9857600080fd5b505afa158015610cac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd09190613f32565b6001600160a01b0316336001600160a01b0316145b80610d865750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610d3957600080fd5b505afa158015610d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d719190613f32565b6001600160a01b0316336001600160a01b0316145b610da25760405162461bcd60e51b81526004016105a8906144e8565b6002546040805163bf3759b560e01b81529051610e25926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b158015610de857600080fd5b505afa158015610dfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e20919061411e565b61269c565b565b6005546001600160a01b0316331480610e4a57506003546001600160a01b031633145b80610e6d5750610e58612001565b6001600160a01b0316336001600160a01b0316145b80610f0e5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b158015610ec157600080fd5b505afa158015610ed5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef99190613f32565b6001600160a01b0316336001600160a01b0316145b80610faf5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610f6257600080fd5b505afa158015610f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9a9190613f32565b6001600160a01b0316336001600160a01b0316145b610fcb5760405162461bcd60e51b81526004016105a8906144e8565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561101e57600080fd5b505afa158015611032573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611056919061411e565b600b5490915060009060ff16156110ac576000611071611bb9565b905061108a8382116110835783611085565b815b6120fb565b94509150828211156110a6576110a08284612960565b94508291505b506110bd565b6110b582612988565b919550935090505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf823906110ee9030906004016141b8565b6101206040518083038186803b15801561110757600080fd5b505afa15801561111b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113f9190614088565b60c001516002546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc906111789088908890879060040161468b565b602060405180830381600087803b15801561119257600080fd5b505af11580156111a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ca919061411e565b92506111d58361269c565b60015460ff1680156111f6575060015461010090046001600160a01b031615155b156112a85760015460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b9061123790889088908790899088906004016146bc565b60206040518083038186803b15801561124f57600080fd5b505afa158015611263573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112879190613fff565b6112a35760405162461bcd60e51b81526004016105a89061431e565b6112b5565b6001805460ff1916811790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d509858584866040516112ea94939291906146a1565b60405180910390a15050505050565b600b5460ff1681565b6003546001600160a01b0316331480611333575061131e612001565b6001600160a01b0316336001600160a01b0316145b61134f5760405162461bcd60e51b81526004016105a8906144e8565b600d55565b60005b919050565b60015460ff1681565b600c5481565b6003546001600160a01b031633148061139c5750611387612001565b6001600160a01b0316336001600160a01b0316145b6113b85760405162461bcd60e51b81526004016105a8906144e8565b6001600160a01b0381166113cb57600080fd5b600580546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe71549061089a9083906141b8565b6003546001600160a01b03163314806114475750611432612001565b6001600160a01b0316336001600160a01b0316145b6114635760405162461bcd60e51b81526004016105a8906144e8565b61146f60008383613e37565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda682826040516114a192919061420a565b60405180910390a15050565b6000816114bc57506000611357565b604080516002808252606080830184529260208301908036833701905050905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2816000815181106114fe57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050732260fac5e5542a773aa44fbcfedf7c193bc2c5998160018151811061154057fe5b6001600160a01b039092166020928302919091019091015260405163d06ca61f60e01b8152606090737a250d5630b4cf539739df2c5dacb4c659f2488d9063d06ca61f906115949087908690600401614628565b60006040518083038186803b1580156115ac57600080fd5b505afa1580156115c0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115e89190810190613f4e565b9050806001825103815181106115fa57fe5b602002602001015192505050919050565b60095481565b600090565b6003546001600160a01b03163314806116475750611632612001565b6001600160a01b0316336001600160a01b0316145b6116635760405162461bcd60e51b81526004016105a8906144e8565b60098190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec2989061089a908390614608565b60075481565b6004546001600160a01b031681565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156116fb57600080fd5b505afa15801561170f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117339190613f32565b6001600160a01b0316336001600160a01b0316148061176a5750611755612001565b6001600160a01b0316336001600160a01b0316145b6117865760405162461bcd60e51b81526004016105a8906144e8565b6001805460ff1916911515919091179055565b6005546001600160a01b031681565b60008051602061477683398151915281565b60015461010090046001600160a01b031681565b600d5481565b6003546001600160a01b031633148061180557506117f0612001565b6001600160a01b0316336001600160a01b0316145b6118215760405162461bcd60e51b81526004016105a8906144e8565b6001600160a01b03811661183457600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b49061089a9083906141b8565b6002546001600160a01b03163314806118b0575061189b612001565b6001600160a01b0316336001600160a01b0316145b6118b957600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b15801561190057600080fd5b505afa158015611914573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119389190613f32565b6001600160a01b03161461194b57600080fd5b61195481612e1d565b6006546040516370a0823160e01b81526119ed9183916001600160a01b03909116906370a082319061198a9030906004016141b8565b60206040518083038186803b1580156119a257600080fd5b505afa1580156119b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119da919061411e565b6006546001600160a01b031691906120dc565b50565b600b81565b73a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd30481565b6003546001600160a01b03163314611a375760405162461bcd60e51b81526004016105a89061426c565b6001600160a01b038116611a4a57600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b393611a819390911691600091016141e6565b602060405180830381600087803b158015611a9b57600080fd5b505af1158015611aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad39190613fff565b50600480546001600160a01b0319166001600160a01b038381169190911780835560025460405163095ea7b360e01b81529083169363095ea7b393611b1e93169160001991016141e6565b602060405180830381600087803b158015611b3857600080fd5b505af1158015611b4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b709190613fff565b507fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a0698160405161089a91906141b8565b6000611bb3611bae836114ad565b61306f565b92915050565b6040516393f1a40b60e01b8152600090819073f8873a6080e8dbf41ada900498de0951074af577906393f1a40b90611bf890600b903090600401614611565b604080518083038186803b158015611c0f57600080fd5b505afa158015611c23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c479190614136565b506040516370a0823160e01b8152909150600090600080516020614776833981519152906370a0823190611c7f9030906004016141b8565b60206040518083038186803b158015611c9757600080fd5b505afa158015611cab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ccf919061411e565b6006546040516370a0823160e01b8152919250611d6e916001600160a01b03909116906370a0823190611d069030906004016141b8565b60206040518083038186803b158015611d1e57600080fd5b505afa158015611d32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d56919061411e565b611d68611d6385856132e7565b61330c565b906132e7565b9250505090565b6003546001600160a01b0316331480611da65750611d91612001565b6001600160a01b0316336001600160a01b0316145b611dc25760405162461bcd60e51b81526004016105a8906144e8565b60088190556040517f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c59061089a908390614608565b6002546001600160a01b031681565b6003546001600160a01b0316331480611e375750611e22612001565b6001600160a01b0316336001600160a01b0316145b611e535760405162461bcd60e51b81526004016105a8906144e8565b600b805460ff191660011790556002546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b158015611ea657600080fd5b505af1158015611eba573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b801580611f715750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e90611f1f90309086906004016141cc565b60206040518083038186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f6f919061411e565b155b611f8d5760405162461bcd60e51b81526004016105a89061457b565b611fe38363095ea7b360e01b8484604051602401611fac9291906141e6565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261343e565b505050565b6060611ff784846000856134cd565b90505b9392505050565b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b15801561204657600080fd5b505afa15801561205a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7f9190613f32565b60408051600180825281830190925260609182919060208083019080368337019050509050600080516020614776833981519152816000815181106120bf57fe5b6001600160a01b0390921660209283029190910190910152905090565b611fe38363a9059cbb60e01b8484604051602401611fac9291906141e6565b6000806000612108611bb9565b841015612116576000612119565b60015b90508015612423576040516393f1a40b60e01b815260009073f8873a6080e8dbf41ada900498de0951074af577906393f1a40b9061215e90600b903090600401614611565b604080518083038186803b15801561217557600080fd5b505afa158015612189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ad9190614136565b50604051630441a3e760e41b815290915073f8873a6080e8dbf41ada900498de0951074af5779063441a3e70906121eb90600b908590600401614641565b600060405180830381600087803b15801561220557600080fd5b505af1158015612219573d6000803e3d6000fd5b50506040516370a0823160e01b81526000805160206147768339815191529250632e1a7d4d915082906370a08231906122569030906004016141b8565b60206040518083038186803b15801561226e57600080fd5b505afa158015612282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a6919061411e565b6040518263ffffffff1660e01b81526004016122c29190614608565b600060405180830381600087803b1580156122dc57600080fd5b505af11580156122f0573d6000803e3d6000fd5b50506006546040516370a0823160e01b81526001600160a01b0390911692506370a0823191506123249030906004016141b8565b60206040518083038186803b15801561233c57600080fd5b505afa158015612350573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612374919061411e565b6002546040516339ebf82360e01b81529195506000916001600160a01b03909116906339ebf823906123aa9030906004016141b8565b6101206040518083038186803b1580156123c357600080fd5b505afa1580156123d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fb9190614088565b60c001519050600081861015612418576124158287612960565b90505b935061269792505050565b6006546040516370a0823160e01b81526000916001600160a01b0316906370a08231906124549030906004016141b8565b60206040518083038186803b15801561246c57600080fd5b505afa158015612480573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a4919061411e565b9050848110156126915760006124ba8683612960565b905060006124c78261358e565b6040516370a0823160e01b8152909150600090600080516020614776833981519152906370a08231906124fe9030906004016141b8565b60206040518083038186803b15801561251657600080fd5b505afa15801561252a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254e919061411e565b905081811015612562576125628282613624565b604051632e1a7d4d60e01b815260008051602061477683398151915290632e1a7d4d90612593908590600401614608565b600060405180830381600087803b1580156125ad57600080fd5b505af11580156125c1573d6000803e3d6000fd5b50506006546040516370a0823160e01b8152600093506001600160a01b0390911691506370a08231906125f89030906004016141b8565b60206040518083038186803b15801561261057600080fd5b505afa158015612624573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612648919061411e565b90508481116126695760405162461bcd60e51b81526004016105a890614291565b80818a11612678576000612682565b6126828a83612960565b97509750505050505050612697565b84935050505b915091565b600b5460ff16156126ac576119ed565b6040516370a0823160e01b8152600090600080516020614776833981519152906370a08231906126e09030906004016141b8565b60206040518083038186803b1580156126f857600080fd5b505afa15801561270c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612730919061411e565b6006546040516370a0823160e01b815291925082916000916001600160a01b0316906370a08231906127669030906004016141b8565b60206040518083038186803b15801561277e57600080fd5b505afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b6919061411e565b9050838111156128d7576127ca8185612960565b60405163b6b55f2560e01b81529091506000805160206147768339815191529063b6b55f25906127fe908490600401614608565b600060405180830381600087803b15801561281857600080fd5b505af115801561282c573d6000803e3d6000fd5b50506040516370a0823160e01b815260008051602061477683398151915292506370a0823191506128619030906004016141b8565b60206040518083038186803b15801561287957600080fd5b505afa15801561288d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128b1919061411e565b91508282116128d25760405162461bcd60e51b81526004016105a8906145d1565b6128e7565b808411156128e7575050506119ed565b811561295a57604051631c57762b60e31b815273f8873a6080e8dbf41ada900498de0951074af5779063e2bbb1589061292790600b908690600401614641565b600060405180830381600087803b15801561294157600080fd5b505af1158015612955573d6000803e3d6000fd5b505050505b50505050565b6000828211156129825760405162461bcd60e51b81526004016105a890614344565b50900390565b6000808083156129b85760008061299e866120fb565b915091508582116129af57816129b1565b855b9093509150505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf823906129e99030906004016141b8565b6101206040518083038186803b158015612a0257600080fd5b505afa158015612a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a3a9190614088565b60c0015190506000612a4a611bb9565b905081811115612cce576000612a608284612960565b6006546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190612a969030906004016141b8565b60206040518083038186803b158015612aae57600080fd5b505afa158015612ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae6919061411e565b90506000612af38361358e565b9050600d54811115612cca576040516370a0823160e01b8152600090600080516020614776833981519152906370a0823190612b339030906004016141b8565b60206040518083038186803b158015612b4b57600080fd5b505afa158015612b5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b83919061411e565b905081811015612b9757612b978282613624565b604051632e1a7d4d60e01b815260008051602061477683398151915290632e1a7d4d90612bc8908590600401614608565b600060405180830381600087803b158015612be257600080fd5b505af1158015612bf6573d6000803e3d6000fd5b50506006546040516370a0823160e01b8152600093506001600160a01b0390911691506370a0823190612c2d9030906004016141b8565b60206040518083038186803b158015612c4557600080fd5b505afa158015612c59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7d919061411e565b905083811115612cc7576000612c938286612960565b9050612c9f8b826132e7565b9a50612cc3868210612cb2576000612cbc565b612cbc8783612960565b8b906132e7565b9950505b50505b5050505b604051637a9f959f60e01b815260009073f8873a6080e8dbf41ada900498de0951074af57790637a9f959f90612d0b90600b903090600401614611565b60206040518083038186803b158015612d2357600080fd5b505afa158015612d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5b919061411e565b90508015612dd157604051630441a3e760e41b815273f8873a6080e8dbf41ada900498de0951074af5779063441a3e7090612d9e90600b90600090600401614641565b600060405180830381600087803b158015612db857600080fd5b505af1158015612dcc573d6000803e3d6000fd5b505050505b612de3612ddc61371c565b87906132e7565b955084861115612e0257612df78686612960565b955060009450612e13565b612e0c8587612960565b9450600095505b5050509193909250565b6040516393f1a40b60e01b815260009073f8873a6080e8dbf41ada900498de0951074af577906393f1a40b90612e5a90600b903090600401614611565b604080518083038186803b158015612e7157600080fd5b505afa158015612e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea99190614136565b50604051630441a3e760e41b815290915073f8873a6080e8dbf41ada900498de0951074af5779063441a3e7090612ee790600b908590600401614641565b600060405180830381600087803b158015612f0157600080fd5b505af1158015612f15573d6000803e3d6000fd5b50506040516370a0823160e01b81526000925060008051602061477683398151915291506370a0823190612f4d9030906004016141b8565b60206040518083038186803b158015612f6557600080fd5b505afa158015612f79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9d919061411e565b90508015612fbe57612fbe60008051602061477683398151915284836120dc565b6040516370a0823160e01b815260009073a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd304906370a0823190612ff89030906004016141b8565b60206040518083038186803b15801561301057600080fd5b505afa158015613024573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613048919061411e565b9050801561295a5761295a73a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd30485836120dc565b6000613079613eb5565b6002546040516339ebf82360e01b81526001600160a01b03909116906339ebf823906130a99030906004016141b8565b6101206040518083038186803b1580156130c257600080fd5b505afa1580156130d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130fa9190614088565b9050806020015160001415613113576000915050611357565b60075460a0820151613126904290612960565b1015613136576000915050611357565b60085460a0820151613149904290612960565b10613158576001915050611357565b6002546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561319d57600080fd5b505afa1580156131b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d5919061411e565b9050600a548111156131ec57600192505050611357565b60006131f6611bb9565b90508260c00151613212600a54836132e790919063ffffffff16565b10156132245760019350505050611357565b60008360c001518211156132455760c0840151613242908390612960565b90505b6002546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b15801561328a57600080fd5b505afa15801561329e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132c2919061411e565b90506132ce81836132e7565b6009546132db9089613d8c565b10979650505050505050565b600082820183811015611ffa5760405162461bcd60e51b81526004016105a8906142e7565b6000806000805160206147768339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561335657600080fd5b505afa15801561336a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061338e919061411e565b90508061339f576000915050611357565b60006000805160206147768339815191526001600160a01b031663b69ef8a86040518163ffffffff1660e01b815260040160206040518083038186803b1580156133e857600080fd5b505afa1580156133fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613420919061411e565b9050613436826134308387613d8c565b90613dc6565b949350505050565b6060613493826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611fe89092919063ffffffff16565b805190915015611fe357808060200190518101906134b19190613fff565b611fe35760405162461bcd60e51b81526004016105a89061450d565b6060824710156134ef5760405162461bcd60e51b81526004016105a89061437b565b6134f885613df8565b6135145760405162461bcd60e51b81526004016105a8906144b1565b60006060866001600160a01b03168587604051613531919061419c565b60006040518083038185875af1925050503d806000811461356e576040519150601f19603f3d011682016040523d82523d6000602084013e613573565b606091505b5091509150613583828286613dfe565b979650505050505050565b6000611bb36000805160206147768339815191526001600160a01b031663ec1ebd7a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156135da57600080fd5b505afa1580156135ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613612919061411e565b61343084670de0b6b3a7640000613d8c565b60006136308383612960565b6040516393f1a40b60e01b815290915060009073f8873a6080e8dbf41ada900498de0951074af577906393f1a40b9061367090600b903090600401614611565b604080518083038186803b15801561368757600080fd5b505afa15801561369b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136bf9190614136565b509050818110156136e25760405162461bcd60e51b81526004016105a89061447a565b604051630441a3e760e41b815273f8873a6080e8dbf41ada900498de0951074af5779063441a3e709061292790600b908690600401614641565b6040516370a0823160e01b8152600090819073a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd304906370a08231906137589030906004016141b8565b60206040518083038186803b15801561377057600080fd5b505afa158015613784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137a8919061411e565b90506000600c548210613d86576040805160038082526080820190925260609160208201838036833701905050905073a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd304816000815181106137f957fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160018151811061383b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050732260fac5e5542a773aa44fbcfedf7c193bc2c5998160028151811061387d57fe5b6001600160a01b039092166020928302919091019091015260405163d06ca61f60e01b815260009073d9e1ce17f2641f24ae83637ab66a2cca9c378b9f9063d06ca61f906138d19087908690600401614628565b60006040518083038186803b1580156138e957600080fd5b505afa1580156138fd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139259190810190613f4e565b60018351038151811061393457fe5b602002602001015190506060600467ffffffffffffffff8111801561395857600080fd5b50604051908082528060200260200182016040528015613982578160200160208202803683370190505b50905073a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd304816000815181106139a757fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48816001815181106139e957fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600281518110613a2b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050732260fac5e5542a773aa44fbcfedf7c193bc2c59981600381518110613a6d57fe5b6001600160a01b039092166020928302919091019091015260405163d06ca61f60e01b8152600090737a250d5630b4cf539739df2c5dacb4c659f2488d9063d06ca61f90613ac19089908690600401614628565b60006040518083038186803b158015613ad957600080fd5b505afa158015613aed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613b159190810190613f4e565b600183510381518110613b2457fe5b60209081029190910101516006546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190613b659030906004016141b8565b60206040518083038186803b158015613b7d57600080fd5b505afa158015613b91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bb5919061411e565b9050818410613c5a576040516338ed173960e01b815273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f906338ed173990613bfe908a906000908a903090429060040161464f565b600060405180830381600087803b158015613c1857600080fd5b505af1158015613c2c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c549190810190613f4e565b50613cf2565b6040516338ed173960e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d906338ed173990613c9a908a9060009088903090429060040161464f565b600060405180830381600087803b158015613cb457600080fd5b505af1158015613cc8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613cf09190810190613f4e565b505b6006546040516370a0823160e01b8152613d7e9183916001600160a01b03909116906370a0823190613d289030906004016141b8565b60206040518083038186803b158015613d4057600080fd5b505afa158015613d54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d78919061411e565b90612960565b955050505050505b91505090565b600082613d9b57506000611bb3565b82820282848281613da857fe5b0414611ffa5760405162461bcd60e51b81526004016105a8906143f8565b6000808211613de75760405162461bcd60e51b81526004016105a8906143c1565b818381613df057fe5b049392505050565b3b151590565b60608315613e0d575081611ffa565b825115613e1d5782518084602001fd5b8160405162461bcd60e51b81526004016105a89190614239565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613e785782800160ff19823516178555613ea5565b82800160010185558215613ea5579182015b82811115613ea5578235825591602001919060010190613e8a565b50613eb1929150613f01565b5090565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5b80821115613eb15760008155600101613f02565b600060208284031215613f27578081fd5b8135611ffa81614752565b600060208284031215613f43578081fd5b8151611ffa81614752565b60006020808385031215613f60578182fd5b825167ffffffffffffffff811115613f76578283fd5b8301601f81018513613f86578283fd5b8051613f99613f9482614706565b6146df565b8181528381019083850185840285018601891015613fb5578687fd5b8694505b83851015613fd7578051835260019490940193918501918501613fb9565b50979650505050505050565b600060208284031215613ff4578081fd5b8135611ffa81614767565b600060208284031215614010578081fd5b8151611ffa81614767565b6000806020838503121561402d578081fd5b823567ffffffffffffffff80821115614044578283fd5b818501915085601f830112614057578283fd5b813581811115614065578384fd5b866020828501011115614076578384fd5b60209290920196919550909350505050565b600061012080838503121561409b578182fd5b6140a4816146df565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b600060208284031215614117578081fd5b5035919050565b60006020828403121561412f578081fd5b5051919050565b60008060408385031215614148578182fd5b505080516020909101519092909150565b6000815180845260208085019450808401835b838110156141915781516001600160a01b03168752958201959082019060010161416c565b509495945050505050565b600082516141ae818460208701614726565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b6000602082528251806020840152614258816040850160208701614726565b601f01601f19169190910160400192915050565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b6020808252601f908201527f216d69736d617463684d757368726f6f6d735661756c74576974686472617700604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252601f908201527f21696e73756666696369656e744d546f6b656e496e4d61737465724368656600604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b6020808252601d908201527f216d69736d617463684465706f736974496e746f4d757368726f6f6d73000000604082015260600190565b90815260200190565b9182526001600160a01b0316602082015260400190565b600083825260406020830152611ff76040830184614159565b918252602082015260400190565b600086825285602083015260a0604083015261466e60a0830186614159565b6001600160a01b0394909416606083015250608001529392505050565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff811182821017156146fe57600080fd5b604052919050565b600067ffffffffffffffff82111561471c578081fd5b5060209081020190565b60005b83811015614741578181015183820152602001614729565b8381111561295a5750506000910152565b6001600160a01b03811681146119ed57600080fd5b80151581146119ed57600080fdfe000000000000000000000000b06661a221ab2ec615531f9632d6dc5d2984179aa2646970667358221220431ab2f95957f4396a720dc72e951e5c46310dee0ada8f4691e3afeec7e9567b64736f6c634300060c0033000000000000000000000000a696a63cc78dffa1a63e9e50587c197387ff6c7e

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102d65760003560e01c80636718835f11610182578063b0ad9d00116100e9578063e90eaa51116100a2578063efbb5cb01161007c578063efbb5cb014610545578063f017c92f1461054d578063fbfa77cf14610560578063fcf2d0ad14610568576102d6565b8063e90eaa5114610517578063ec38a8621461051f578063ed882c2b14610532576102d6565b8063b0ad9d00146104d1578063b252720b146104d9578063bbdfac27146104e1578063c7b9d530146104e9578063ce5494bb146104fc578063e8040ba11461050f576102d6565b80638e6350e21161013b5780638e6350e21461048b57806391397ab41461049357806395e80c50146104a65780639ec5a894146104ae578063ac00ff26146104b6578063aced1661146104c9576102d6565b80636718835f1461043a578063711e905214610442578063748747e61461044a578063750521f51461045d578063780022a0146104705780638cdfe16614610483576102d6565b806325829410116102415780633e413bee116101fa5780634641257d116101d45780634641257d146104045780635641ec031461040c5780636278cdc014610414578063650d188014610427576102d6565b80633e413bee146103ec5780633fc8cef3146103f4578063440368a3146103fc576102d6565b806325829410146103a657806328b7ccf7146103ae5780632e1a7d4d146103b6578063326ab283146103c957806339a172a8146103d15780633cdc5389146103e4576102d6565b80631221d660116102935780631221d6601461034f5780631d12f28b146103645780631f1fcd51146103795780631fe4a6861461038157806322f3e2d414610389578063257ae0de1461039e576102d6565b806301681a62146102db57806303ee438c146102f057806306fdde031461030e5780630f0dc9ea146103165780630f969b871461032957806311bc82451461033c575b600080fd5b6102ee6102e9366004613f16565b610570565b005b6102f861070f565b6040516103059190614239565b60405180910390f35b6102f861079d565b6102ee610324366004614106565b6107c6565b6102ee610337366004614106565b610818565b6102ee61034a366004613f16565b6108a5565b6103576109a6565b60405161030591906141b8565b61036c6109be565b6040516103059190614608565b6103576109c4565b6103576109d3565b6103916109e2565b60405161030591906141ff565b610357610a84565b6102f8610a9c565b61036c610abb565b61036c6103c4366004614106565b610ac1565b610357610b1c565b6102ee6103df366004614106565b610b34565b610357610bb6565b610357610bce565b610357610be6565b6102ee610bfe565b6102ee610e27565b6103916112f9565b6102ee610422366004614106565b611302565b610391610435366004614106565b611354565b61039161135c565b61036c611365565b6102ee610458366004613f16565b61136b565b6102ee61046b36600461401b565b611416565b61036c61047e366004614106565b6114ad565b61036c61160b565b61036c611611565b6102ee6104a1366004614106565b611616565b61036c611698565b61035761169e565b6102ee6104c4366004613fe3565b6116ad565b610357611799565b6103576117a8565b6103576117ba565b61036c6117ce565b6102ee6104f7366004613f16565b6117d4565b6102ee61050a366004613f16565b61187f565b61036c6119f0565b6103576119f5565b6102ee61052d366004613f16565b611a0d565b610391610540366004614106565b611ba0565b61036c611bb9565b6102ee61055b366004614106565b611d75565b610357611df7565b6102ee611e06565b610578612001565b6001600160a01b0316336001600160a01b0316146105b15760405162461bcd60e51b81526004016105a8906144e8565b60405180910390fd5b6006546001600160a01b03828116911614156105df5760405162461bcd60e51b81526004016105a8906142c8565b6002546001600160a01b038281169116141561060d5760405162461bcd60e51b81526004016105a890614459565b606061061761207e565b905060005b81518110156106725781818151811061063157fe5b60200260200101516001600160a01b0316836001600160a01b0316141561066a5760405162461bcd60e51b81526004016105a890614557565b60010161061c565b5061070b61067e612001565b6040516370a0823160e01b81526001600160a01b038516906370a08231906106aa9030906004016141b8565b60206040518083038186803b1580156106c257600080fd5b505afa1580156106d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106fa919061411e565b6001600160a01b03851691906120dc565b5050565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107955780601f1061076a57610100808354040283529160200191610795565b820191906000526020600020905b81548152906001019060200180831161077857829003601f168201915b505050505081565b60408051808201909152600f81526e79765742544353747261744d4d563160881b602082015290565b6003546001600160a01b03163314806107f757506107e2612001565b6001600160a01b0316336001600160a01b0316145b6108135760405162461bcd60e51b81526004016105a8906144e8565b600c55565b6003546001600160a01b03163314806108495750610834612001565b6001600160a01b0316336001600160a01b0316145b6108655760405162461bcd60e51b81526004016105a8906144e8565b600a8190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a86009061089a908390614608565b60405180910390a150565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156108f357600080fd5b505afa158015610907573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092b9190613f32565b6001600160a01b0316336001600160a01b03161480610962575061094d612001565b6001600160a01b0316336001600160a01b0316145b61097e5760405162461bcd60e51b81526004016105a8906144e8565b600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b73d9e1ce17f2641f24ae83637ab66a2cca9c378b9f81565b600a5481565b6006546001600160a01b031681565b6003546001600160a01b031681565b6002546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610a179030906004016141b8565b6101206040518083038186803b158015610a3057600080fd5b505afa158015610a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a689190614088565b604001511180610a7f57506000610a7d611bb9565b115b905090565b737a250d5630b4cf539739df2c5dacb4c659f2488d81565b604080518082019091526005815264302e332e3560d81b602082015290565b60085481565b6002546000906001600160a01b03163314610aee5760405162461bcd60e51b81526004016105a890614439565b6000610af9836120fb565b600654909350909150610b16906001600160a01b031633836120dc565b50919050565b73f8873a6080e8dbf41ada900498de0951074af57781565b6003546001600160a01b0316331480610b655750610b50612001565b6001600160a01b0316336001600160a01b0316145b610b815760405162461bcd60e51b81526004016105a8906144e8565b60078190556040517fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b19061089a908390614608565b732260fac5e5542a773aa44fbcfedf7c193bc2c59981565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6005546001600160a01b0316331480610c2157506003546001600160a01b031633145b80610c445750610c2f612001565b6001600160a01b0316336001600160a01b0316145b80610ce55750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b158015610c9857600080fd5b505afa158015610cac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd09190613f32565b6001600160a01b0316336001600160a01b0316145b80610d865750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610d3957600080fd5b505afa158015610d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d719190613f32565b6001600160a01b0316336001600160a01b0316145b610da25760405162461bcd60e51b81526004016105a8906144e8565b6002546040805163bf3759b560e01b81529051610e25926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b158015610de857600080fd5b505afa158015610dfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e20919061411e565b61269c565b565b6005546001600160a01b0316331480610e4a57506003546001600160a01b031633145b80610e6d5750610e58612001565b6001600160a01b0316336001600160a01b0316145b80610f0e5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b158015610ec157600080fd5b505afa158015610ed5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef99190613f32565b6001600160a01b0316336001600160a01b0316145b80610faf5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610f6257600080fd5b505afa158015610f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9a9190613f32565b6001600160a01b0316336001600160a01b0316145b610fcb5760405162461bcd60e51b81526004016105a8906144e8565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561101e57600080fd5b505afa158015611032573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611056919061411e565b600b5490915060009060ff16156110ac576000611071611bb9565b905061108a8382116110835783611085565b815b6120fb565b94509150828211156110a6576110a08284612960565b94508291505b506110bd565b6110b582612988565b919550935090505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf823906110ee9030906004016141b8565b6101206040518083038186803b15801561110757600080fd5b505afa15801561111b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113f9190614088565b60c001516002546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc906111789088908890879060040161468b565b602060405180830381600087803b15801561119257600080fd5b505af11580156111a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ca919061411e565b92506111d58361269c565b60015460ff1680156111f6575060015461010090046001600160a01b031615155b156112a85760015460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b9061123790889088908790899088906004016146bc565b60206040518083038186803b15801561124f57600080fd5b505afa158015611263573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112879190613fff565b6112a35760405162461bcd60e51b81526004016105a89061431e565b6112b5565b6001805460ff1916811790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d509858584866040516112ea94939291906146a1565b60405180910390a15050505050565b600b5460ff1681565b6003546001600160a01b0316331480611333575061131e612001565b6001600160a01b0316336001600160a01b0316145b61134f5760405162461bcd60e51b81526004016105a8906144e8565b600d55565b60005b919050565b60015460ff1681565b600c5481565b6003546001600160a01b031633148061139c5750611387612001565b6001600160a01b0316336001600160a01b0316145b6113b85760405162461bcd60e51b81526004016105a8906144e8565b6001600160a01b0381166113cb57600080fd5b600580546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe71549061089a9083906141b8565b6003546001600160a01b03163314806114475750611432612001565b6001600160a01b0316336001600160a01b0316145b6114635760405162461bcd60e51b81526004016105a8906144e8565b61146f60008383613e37565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda682826040516114a192919061420a565b60405180910390a15050565b6000816114bc57506000611357565b604080516002808252606080830184529260208301908036833701905050905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2816000815181106114fe57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050732260fac5e5542a773aa44fbcfedf7c193bc2c5998160018151811061154057fe5b6001600160a01b039092166020928302919091019091015260405163d06ca61f60e01b8152606090737a250d5630b4cf539739df2c5dacb4c659f2488d9063d06ca61f906115949087908690600401614628565b60006040518083038186803b1580156115ac57600080fd5b505afa1580156115c0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115e89190810190613f4e565b9050806001825103815181106115fa57fe5b602002602001015192505050919050565b60095481565b600090565b6003546001600160a01b03163314806116475750611632612001565b6001600160a01b0316336001600160a01b0316145b6116635760405162461bcd60e51b81526004016105a8906144e8565b60098190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec2989061089a908390614608565b60075481565b6004546001600160a01b031681565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156116fb57600080fd5b505afa15801561170f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117339190613f32565b6001600160a01b0316336001600160a01b0316148061176a5750611755612001565b6001600160a01b0316336001600160a01b0316145b6117865760405162461bcd60e51b81526004016105a8906144e8565b6001805460ff1916911515919091179055565b6005546001600160a01b031681565b60008051602061477683398151915281565b60015461010090046001600160a01b031681565b600d5481565b6003546001600160a01b031633148061180557506117f0612001565b6001600160a01b0316336001600160a01b0316145b6118215760405162461bcd60e51b81526004016105a8906144e8565b6001600160a01b03811661183457600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b49061089a9083906141b8565b6002546001600160a01b03163314806118b0575061189b612001565b6001600160a01b0316336001600160a01b0316145b6118b957600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b15801561190057600080fd5b505afa158015611914573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119389190613f32565b6001600160a01b03161461194b57600080fd5b61195481612e1d565b6006546040516370a0823160e01b81526119ed9183916001600160a01b03909116906370a082319061198a9030906004016141b8565b60206040518083038186803b1580156119a257600080fd5b505afa1580156119b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119da919061411e565b6006546001600160a01b031691906120dc565b50565b600b81565b73a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd30481565b6003546001600160a01b03163314611a375760405162461bcd60e51b81526004016105a89061426c565b6001600160a01b038116611a4a57600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b393611a819390911691600091016141e6565b602060405180830381600087803b158015611a9b57600080fd5b505af1158015611aaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad39190613fff565b50600480546001600160a01b0319166001600160a01b038381169190911780835560025460405163095ea7b360e01b81529083169363095ea7b393611b1e93169160001991016141e6565b602060405180830381600087803b158015611b3857600080fd5b505af1158015611b4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b709190613fff565b507fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a0698160405161089a91906141b8565b6000611bb3611bae836114ad565b61306f565b92915050565b6040516393f1a40b60e01b8152600090819073f8873a6080e8dbf41ada900498de0951074af577906393f1a40b90611bf890600b903090600401614611565b604080518083038186803b158015611c0f57600080fd5b505afa158015611c23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c479190614136565b506040516370a0823160e01b8152909150600090600080516020614776833981519152906370a0823190611c7f9030906004016141b8565b60206040518083038186803b158015611c9757600080fd5b505afa158015611cab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ccf919061411e565b6006546040516370a0823160e01b8152919250611d6e916001600160a01b03909116906370a0823190611d069030906004016141b8565b60206040518083038186803b158015611d1e57600080fd5b505afa158015611d32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d56919061411e565b611d68611d6385856132e7565b61330c565b906132e7565b9250505090565b6003546001600160a01b0316331480611da65750611d91612001565b6001600160a01b0316336001600160a01b0316145b611dc25760405162461bcd60e51b81526004016105a8906144e8565b60088190556040517f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c59061089a908390614608565b6002546001600160a01b031681565b6003546001600160a01b0316331480611e375750611e22612001565b6001600160a01b0316336001600160a01b0316145b611e535760405162461bcd60e51b81526004016105a8906144e8565b600b805460ff191660011790556002546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b158015611ea657600080fd5b505af1158015611eba573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b801580611f715750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e90611f1f90309086906004016141cc565b60206040518083038186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f6f919061411e565b155b611f8d5760405162461bcd60e51b81526004016105a89061457b565b611fe38363095ea7b360e01b8484604051602401611fac9291906141e6565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261343e565b505050565b6060611ff784846000856134cd565b90505b9392505050565b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b15801561204657600080fd5b505afa15801561205a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7f9190613f32565b60408051600180825281830190925260609182919060208083019080368337019050509050600080516020614776833981519152816000815181106120bf57fe5b6001600160a01b0390921660209283029190910190910152905090565b611fe38363a9059cbb60e01b8484604051602401611fac9291906141e6565b6000806000612108611bb9565b841015612116576000612119565b60015b90508015612423576040516393f1a40b60e01b815260009073f8873a6080e8dbf41ada900498de0951074af577906393f1a40b9061215e90600b903090600401614611565b604080518083038186803b15801561217557600080fd5b505afa158015612189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ad9190614136565b50604051630441a3e760e41b815290915073f8873a6080e8dbf41ada900498de0951074af5779063441a3e70906121eb90600b908590600401614641565b600060405180830381600087803b15801561220557600080fd5b505af1158015612219573d6000803e3d6000fd5b50506040516370a0823160e01b81526000805160206147768339815191529250632e1a7d4d915082906370a08231906122569030906004016141b8565b60206040518083038186803b15801561226e57600080fd5b505afa158015612282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a6919061411e565b6040518263ffffffff1660e01b81526004016122c29190614608565b600060405180830381600087803b1580156122dc57600080fd5b505af11580156122f0573d6000803e3d6000fd5b50506006546040516370a0823160e01b81526001600160a01b0390911692506370a0823191506123249030906004016141b8565b60206040518083038186803b15801561233c57600080fd5b505afa158015612350573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612374919061411e565b6002546040516339ebf82360e01b81529195506000916001600160a01b03909116906339ebf823906123aa9030906004016141b8565b6101206040518083038186803b1580156123c357600080fd5b505afa1580156123d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fb9190614088565b60c001519050600081861015612418576124158287612960565b90505b935061269792505050565b6006546040516370a0823160e01b81526000916001600160a01b0316906370a08231906124549030906004016141b8565b60206040518083038186803b15801561246c57600080fd5b505afa158015612480573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a4919061411e565b9050848110156126915760006124ba8683612960565b905060006124c78261358e565b6040516370a0823160e01b8152909150600090600080516020614776833981519152906370a08231906124fe9030906004016141b8565b60206040518083038186803b15801561251657600080fd5b505afa15801561252a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254e919061411e565b905081811015612562576125628282613624565b604051632e1a7d4d60e01b815260008051602061477683398151915290632e1a7d4d90612593908590600401614608565b600060405180830381600087803b1580156125ad57600080fd5b505af11580156125c1573d6000803e3d6000fd5b50506006546040516370a0823160e01b8152600093506001600160a01b0390911691506370a08231906125f89030906004016141b8565b60206040518083038186803b15801561261057600080fd5b505afa158015612624573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612648919061411e565b90508481116126695760405162461bcd60e51b81526004016105a890614291565b80818a11612678576000612682565b6126828a83612960565b97509750505050505050612697565b84935050505b915091565b600b5460ff16156126ac576119ed565b6040516370a0823160e01b8152600090600080516020614776833981519152906370a08231906126e09030906004016141b8565b60206040518083038186803b1580156126f857600080fd5b505afa15801561270c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612730919061411e565b6006546040516370a0823160e01b815291925082916000916001600160a01b0316906370a08231906127669030906004016141b8565b60206040518083038186803b15801561277e57600080fd5b505afa158015612792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b6919061411e565b9050838111156128d7576127ca8185612960565b60405163b6b55f2560e01b81529091506000805160206147768339815191529063b6b55f25906127fe908490600401614608565b600060405180830381600087803b15801561281857600080fd5b505af115801561282c573d6000803e3d6000fd5b50506040516370a0823160e01b815260008051602061477683398151915292506370a0823191506128619030906004016141b8565b60206040518083038186803b15801561287957600080fd5b505afa15801561288d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128b1919061411e565b91508282116128d25760405162461bcd60e51b81526004016105a8906145d1565b6128e7565b808411156128e7575050506119ed565b811561295a57604051631c57762b60e31b815273f8873a6080e8dbf41ada900498de0951074af5779063e2bbb1589061292790600b908690600401614641565b600060405180830381600087803b15801561294157600080fd5b505af1158015612955573d6000803e3d6000fd5b505050505b50505050565b6000828211156129825760405162461bcd60e51b81526004016105a890614344565b50900390565b6000808083156129b85760008061299e866120fb565b915091508582116129af57816129b1565b855b9093509150505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf823906129e99030906004016141b8565b6101206040518083038186803b158015612a0257600080fd5b505afa158015612a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a3a9190614088565b60c0015190506000612a4a611bb9565b905081811115612cce576000612a608284612960565b6006546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190612a969030906004016141b8565b60206040518083038186803b158015612aae57600080fd5b505afa158015612ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae6919061411e565b90506000612af38361358e565b9050600d54811115612cca576040516370a0823160e01b8152600090600080516020614776833981519152906370a0823190612b339030906004016141b8565b60206040518083038186803b158015612b4b57600080fd5b505afa158015612b5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b83919061411e565b905081811015612b9757612b978282613624565b604051632e1a7d4d60e01b815260008051602061477683398151915290632e1a7d4d90612bc8908590600401614608565b600060405180830381600087803b158015612be257600080fd5b505af1158015612bf6573d6000803e3d6000fd5b50506006546040516370a0823160e01b8152600093506001600160a01b0390911691506370a0823190612c2d9030906004016141b8565b60206040518083038186803b158015612c4557600080fd5b505afa158015612c59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7d919061411e565b905083811115612cc7576000612c938286612960565b9050612c9f8b826132e7565b9a50612cc3868210612cb2576000612cbc565b612cbc8783612960565b8b906132e7565b9950505b50505b5050505b604051637a9f959f60e01b815260009073f8873a6080e8dbf41ada900498de0951074af57790637a9f959f90612d0b90600b903090600401614611565b60206040518083038186803b158015612d2357600080fd5b505afa158015612d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5b919061411e565b90508015612dd157604051630441a3e760e41b815273f8873a6080e8dbf41ada900498de0951074af5779063441a3e7090612d9e90600b90600090600401614641565b600060405180830381600087803b158015612db857600080fd5b505af1158015612dcc573d6000803e3d6000fd5b505050505b612de3612ddc61371c565b87906132e7565b955084861115612e0257612df78686612960565b955060009450612e13565b612e0c8587612960565b9450600095505b5050509193909250565b6040516393f1a40b60e01b815260009073f8873a6080e8dbf41ada900498de0951074af577906393f1a40b90612e5a90600b903090600401614611565b604080518083038186803b158015612e7157600080fd5b505afa158015612e85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea99190614136565b50604051630441a3e760e41b815290915073f8873a6080e8dbf41ada900498de0951074af5779063441a3e7090612ee790600b908590600401614641565b600060405180830381600087803b158015612f0157600080fd5b505af1158015612f15573d6000803e3d6000fd5b50506040516370a0823160e01b81526000925060008051602061477683398151915291506370a0823190612f4d9030906004016141b8565b60206040518083038186803b158015612f6557600080fd5b505afa158015612f79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9d919061411e565b90508015612fbe57612fbe60008051602061477683398151915284836120dc565b6040516370a0823160e01b815260009073a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd304906370a0823190612ff89030906004016141b8565b60206040518083038186803b15801561301057600080fd5b505afa158015613024573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613048919061411e565b9050801561295a5761295a73a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd30485836120dc565b6000613079613eb5565b6002546040516339ebf82360e01b81526001600160a01b03909116906339ebf823906130a99030906004016141b8565b6101206040518083038186803b1580156130c257600080fd5b505afa1580156130d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130fa9190614088565b9050806020015160001415613113576000915050611357565b60075460a0820151613126904290612960565b1015613136576000915050611357565b60085460a0820151613149904290612960565b10613158576001915050611357565b6002546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561319d57600080fd5b505afa1580156131b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d5919061411e565b9050600a548111156131ec57600192505050611357565b60006131f6611bb9565b90508260c00151613212600a54836132e790919063ffffffff16565b10156132245760019350505050611357565b60008360c001518211156132455760c0840151613242908390612960565b90505b6002546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b15801561328a57600080fd5b505afa15801561329e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132c2919061411e565b90506132ce81836132e7565b6009546132db9089613d8c565b10979650505050505050565b600082820183811015611ffa5760405162461bcd60e51b81526004016105a8906142e7565b6000806000805160206147768339815191526001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561335657600080fd5b505afa15801561336a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061338e919061411e565b90508061339f576000915050611357565b60006000805160206147768339815191526001600160a01b031663b69ef8a86040518163ffffffff1660e01b815260040160206040518083038186803b1580156133e857600080fd5b505afa1580156133fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613420919061411e565b9050613436826134308387613d8c565b90613dc6565b949350505050565b6060613493826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611fe89092919063ffffffff16565b805190915015611fe357808060200190518101906134b19190613fff565b611fe35760405162461bcd60e51b81526004016105a89061450d565b6060824710156134ef5760405162461bcd60e51b81526004016105a89061437b565b6134f885613df8565b6135145760405162461bcd60e51b81526004016105a8906144b1565b60006060866001600160a01b03168587604051613531919061419c565b60006040518083038185875af1925050503d806000811461356e576040519150601f19603f3d011682016040523d82523d6000602084013e613573565b606091505b5091509150613583828286613dfe565b979650505050505050565b6000611bb36000805160206147768339815191526001600160a01b031663ec1ebd7a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156135da57600080fd5b505afa1580156135ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613612919061411e565b61343084670de0b6b3a7640000613d8c565b60006136308383612960565b6040516393f1a40b60e01b815290915060009073f8873a6080e8dbf41ada900498de0951074af577906393f1a40b9061367090600b903090600401614611565b604080518083038186803b15801561368757600080fd5b505afa15801561369b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136bf9190614136565b509050818110156136e25760405162461bcd60e51b81526004016105a89061447a565b604051630441a3e760e41b815273f8873a6080e8dbf41ada900498de0951074af5779063441a3e709061292790600b908690600401614641565b6040516370a0823160e01b8152600090819073a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd304906370a08231906137589030906004016141b8565b60206040518083038186803b15801561377057600080fd5b505afa158015613784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137a8919061411e565b90506000600c548210613d86576040805160038082526080820190925260609160208201838036833701905050905073a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd304816000815181106137f957fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160018151811061383b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050732260fac5e5542a773aa44fbcfedf7c193bc2c5998160028151811061387d57fe5b6001600160a01b039092166020928302919091019091015260405163d06ca61f60e01b815260009073d9e1ce17f2641f24ae83637ab66a2cca9c378b9f9063d06ca61f906138d19087908690600401614628565b60006040518083038186803b1580156138e957600080fd5b505afa1580156138fd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139259190810190613f4e565b60018351038151811061393457fe5b602002602001015190506060600467ffffffffffffffff8111801561395857600080fd5b50604051908082528060200260200182016040528015613982578160200160208202803683370190505b50905073a283aa7cfbb27ef0cfbcb2493dd9f4330e0fd304816000815181106139a757fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48816001815181106139e957fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600281518110613a2b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050732260fac5e5542a773aa44fbcfedf7c193bc2c59981600381518110613a6d57fe5b6001600160a01b039092166020928302919091019091015260405163d06ca61f60e01b8152600090737a250d5630b4cf539739df2c5dacb4c659f2488d9063d06ca61f90613ac19089908690600401614628565b60006040518083038186803b158015613ad957600080fd5b505afa158015613aed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613b159190810190613f4e565b600183510381518110613b2457fe5b60209081029190910101516006546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190613b659030906004016141b8565b60206040518083038186803b158015613b7d57600080fd5b505afa158015613b91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bb5919061411e565b9050818410613c5a576040516338ed173960e01b815273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f906338ed173990613bfe908a906000908a903090429060040161464f565b600060405180830381600087803b158015613c1857600080fd5b505af1158015613c2c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c549190810190613f4e565b50613cf2565b6040516338ed173960e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d906338ed173990613c9a908a9060009088903090429060040161464f565b600060405180830381600087803b158015613cb457600080fd5b505af1158015613cc8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613cf09190810190613f4e565b505b6006546040516370a0823160e01b8152613d7e9183916001600160a01b03909116906370a0823190613d289030906004016141b8565b60206040518083038186803b158015613d4057600080fd5b505afa158015613d54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d78919061411e565b90612960565b955050505050505b91505090565b600082613d9b57506000611bb3565b82820282848281613da857fe5b0414611ffa5760405162461bcd60e51b81526004016105a8906143f8565b6000808211613de75760405162461bcd60e51b81526004016105a8906143c1565b818381613df057fe5b049392505050565b3b151590565b60608315613e0d575081611ffa565b825115613e1d5782518084602001fd5b8160405162461bcd60e51b81526004016105a89190614239565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613e785782800160ff19823516178555613ea5565b82800160010185558215613ea5579182015b82811115613ea5578235825591602001919060010190613e8a565b50613eb1929150613f01565b5090565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5b80821115613eb15760008155600101613f02565b600060208284031215613f27578081fd5b8135611ffa81614752565b600060208284031215613f43578081fd5b8151611ffa81614752565b60006020808385031215613f60578182fd5b825167ffffffffffffffff811115613f76578283fd5b8301601f81018513613f86578283fd5b8051613f99613f9482614706565b6146df565b8181528381019083850185840285018601891015613fb5578687fd5b8694505b83851015613fd7578051835260019490940193918501918501613fb9565b50979650505050505050565b600060208284031215613ff4578081fd5b8135611ffa81614767565b600060208284031215614010578081fd5b8151611ffa81614767565b6000806020838503121561402d578081fd5b823567ffffffffffffffff80821115614044578283fd5b818501915085601f830112614057578283fd5b813581811115614065578384fd5b866020828501011115614076578384fd5b60209290920196919550909350505050565b600061012080838503121561409b578182fd5b6140a4816146df565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b600060208284031215614117578081fd5b5035919050565b60006020828403121561412f578081fd5b5051919050565b60008060408385031215614148578182fd5b505080516020909101519092909150565b6000815180845260208085019450808401835b838110156141915781516001600160a01b03168752958201959082019060010161416c565b509495945050505050565b600082516141ae818460208701614726565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b6000602082528251806020840152614258816040850160208701614726565b601f01601f19169190910160400192915050565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b6020808252601f908201527f216d69736d617463684d757368726f6f6d735661756c74576974686472617700604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252601f908201527f21696e73756666696369656e744d546f6b656e496e4d61737465724368656600604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b6020808252601d908201527f216d69736d617463684465706f736974496e746f4d757368726f6f6d73000000604082015260600190565b90815260200190565b9182526001600160a01b0316602082015260400190565b600083825260406020830152611ff76040830184614159565b918252602082015260400190565b600086825285602083015260a0604083015261466e60a0830186614159565b6001600160a01b0394909416606083015250608001529392505050565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff811182821017156146fe57600080fd5b604052919050565b600067ffffffffffffffff82111561471c578081fd5b5060209081020190565b60005b83811015614741578181015183820152602001614729565b8381111561295a5750506000910152565b6001600160a01b03811681146119ed57600080fd5b80151581146119ed57600080fdfe000000000000000000000000b06661a221ab2ec615531f9632d6dc5d2984179aa2646970667358221220431ab2f95957f4396a720dc72e951e5c46310dee0ada8f4691e3afeec7e9567b64736f6c634300060c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000a696a63cc78dffa1a63e9e50587c197387ff6c7e

-----Decoded View---------------
Arg [0] : _vault (address): 0xA696a63cc78DfFa1a63E9E50587C197387FF6C7E

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000a696a63cc78dffa1a63e9e50587c197387ff6c7e


Deployed Bytecode Sourcemap

59467:18628:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55414:444;;;;;;:::i;:::-;;:::i;:::-;;28166:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61000:105;;;:::i;61736:115::-;;;;;;:::i;:::-;;:::i;38027:175::-;;;;;;:::i;:::-;;:::i;33595:118::-;;;;;;:::i;:::-;;:::i;59984:88::-;;;:::i;:::-;;;;;;;:::i;31445:28::-;;;:::i;:::-;;;;;;;:::i;30193:18::-;;;:::i;30102:25::-;;;:::i;40700:148::-;;;:::i;:::-;;;;;;;:::i;59890:87::-;;;:::i;28565:91::-;;;:::i;31081:29::-;;;:::i;51994:515::-;;;;;;:::i;:::-;;:::i;60289:91::-;;;:::i;36076:154::-;;;;;;:::i;:::-;;:::i;59615:82::-;;;:::i;59803:73::-;;;:::i;60081:82::-;;;:::i;45453:170::-;;;:::i;49846:1904::-;;;:::i;31524:25::-;;;:::i;61862:135::-;;;;;;:::i;:::-;;:::i;44838:286::-;;;;;;:::i;:::-;;:::i;28222:25::-;;;:::i;60509:30::-;;;:::i;34833:174::-;;;;;;:::i;:::-;;:::i;38505:171::-;;;;;;:::i;:::-;;:::i;77723:369::-;;;;;;:::i;:::-;;:::i;31267:27::-;;;:::i;62765:95::-;;;:::i;37301:169::-;;;;;;:::i;:::-;;:::i;30930:29::-;;;:::i;30134:22::-;;;:::i;33721:123::-;;;;;;:::i;:::-;;:::i;30163:21::-;;;:::i;60173:85::-;;;:::i;28254:26::-;;;:::i;60589:35::-;;;:::i;34077:202::-;;;;;;:::i;:::-;;:::i;53100:311::-;;;;;;:::i;:::-;;:::i;60417:44::-;;;:::i;59711:80::-;;;:::i;35296:263::-;;;;;;:::i;:::-;;:::i;73684:145::-;;;;;;:::i;:::-;;:::i;64147:346::-;;;:::i;36747:154::-;;;;;;:::i;:::-;;:::i;30074:21::-;;;:::i;53840:164::-;;;:::i;55414:444::-;31891:12;:10;:12::i;:::-;-1:-1:-1;;;;;31877:26:0;:10;-1:-1:-1;;;;;31877:26:0;;31869:50;;;;-1:-1:-1;;;31869:50:0;;;;;;;:::i;:::-;;;;;;;;;55506:4:::1;::::0;-1:-1:-1;;;;;55488:23:0;;::::1;55506:4:::0;::::1;55488:23;;55480:41;;;;-1:-1:-1::0;;;55480:41:0::1;;;;;;;:::i;:::-;55558:5;::::0;-1:-1:-1;;;;;55540:24:0;;::::1;55558:5:::0;::::1;55540:24;;55532:44;;;;-1:-1:-1::0;;;55532:44:0::1;;;;;;;:::i;:::-;55589:33;55625:17;:15;:17::i;:::-;55589:53;;55658:9;55653:102;55673:16;:23;55669:1;:27;55653:102;;;55721:16;55738:1;55721:19;;;;;;;;;;;;;;-1:-1:-1::0;;;;;55711:29:0::1;:6;-1:-1:-1::0;;;;;55711:29:0::1;;;55703:52;;;;-1:-1:-1::0;;;55703:52:0::1;;;;;;;:::i;:::-;55698:3;;55653:102;;;;55768:82;55796:12;:10;:12::i;:::-;55810:39;::::0;-1:-1:-1;;;55810:39:0;;-1:-1:-1;;;;;55810:24:0;::::1;::::0;::::1;::::0;:39:::1;::::0;55843:4:::1;::::0;55810:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;55768:27:0;::::1;::::0;:82;:27:::1;:82::i;:::-;31930:1;55414:444:::0;:::o;28166:25::-;;;;;;;;;;;;;;;-1:-1:-1;;28166:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;61000:105::-;61073:24;;;;;;;;;;;;-1:-1:-1;;;61073:24:0;;;;61000:105;:::o;61736:115::-;31635:10;;-1:-1:-1;;;;;31635:10:0;31621;:24;;:54;;;31663:12;:10;:12::i;:::-;-1:-1:-1;;;;;31649:26:0;:10;-1:-1:-1;;;;;31649:26:0;;31621:54;31613:78;;;;-1:-1:-1;;;31613:78:0;;;;;;;:::i;:::-;61817:11:::1;:26:::0;61736:115::o;38027:175::-;31635:10;;-1:-1:-1;;;;;31635:10:0;31621;:24;;:54;;;31663:12;:10;:12::i;:::-;-1:-1:-1;;;;;31649:26:0;:10;-1:-1:-1;;;;;31649:26:0;;31621:54;31613:78;;;;-1:-1:-1;;;31613:78:0;;;;;;;:::i;:::-;38112:13:::1;:30:::0;;;38158:36:::1;::::0;::::1;::::0;::::1;::::0;38128:14;;38158:36:::1;:::i;:::-;;;;;;;;38027:175:::0;:::o;33595:118::-;32362:5;;;;;;;;;-1:-1:-1;;;;;32362:5:0;-1:-1:-1;;;;;32362:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;32348:32:0;:10;-1:-1:-1;;;;;32348:32:0;;:62;;;;32398:12;:10;:12::i;:::-;-1:-1:-1;;;;;32384:26:0;:10;-1:-1:-1;;;;;32384:26:0;;32348:62;32326:123;;;;-1:-1:-1;;;32326:123:0;;;;;;;:::i;:::-;33679:11:::1;:26:::0;;-1:-1:-1;;;;;33679:26:0;;::::1;;;-1:-1:-1::0;;;;;;33679:26:0;;::::1;::::0;;;::::1;::::0;;33595:118::o;59984:88::-;60029:42;59984:88;:::o;31445:28::-;;;;:::o;30193:18::-;;;-1:-1:-1;;;;;30193:18:0;;:::o;30102:25::-;;;-1:-1:-1;;;;;30102:25:0;;:::o;40700:148::-;40765:5;;:31;;-1:-1:-1;;;40765:31:0;;40741:4;;;;-1:-1:-1;;;;;40765:5:0;;;;:16;;:31;;40790:4;;40765:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;:45;:75;;;;40839:1;40814:22;:20;:22::i;:::-;:26;40765:75;40758:82;;40700:148;:::o;59890:87::-;59934:42;59890:87;:::o;28565:91::-;28634:14;;;;;;;;;;;;-1:-1:-1;;;28634:14:0;;;;28565:91;:::o;31081:29::-;;;;:::o;51994:515::-;52109:5;;52053:13;;-1:-1:-1;;;;;52109:5:0;52087:10;:28;52079:47;;;;-1:-1:-1;;;52079:47:0;;;;;;;:::i;:::-;52212:19;52265:32;52283:13;52265:17;:32::i;:::-;52389:4;;52242:55;;-1:-1:-1;52242:55:0;;-1:-1:-1;52389:42:0;;-1:-1:-1;;;;;52389:4:0;52407:10;52242:55;52389:17;:42::i;:::-;51994:515;;;;:::o;60289:91::-;60337:42;60289:91;:::o;36076:154::-;31635:10;;-1:-1:-1;;;;;31635:10:0;31621;:24;;:54;;;31663:12;:10;:12::i;:::-;-1:-1:-1;;;;;31649:26:0;:10;-1:-1:-1;;;;;31649:26:0;;31621:54;31613:78;;;;-1:-1:-1;;;31613:78:0;;;;;;;:::i;:::-;36154:14:::1;:23:::0;;;36193:29:::1;::::0;::::1;::::0;::::1;::::0;36171:6;;36193:29:::1;:::i;59615:82::-:0;59654:42;59615:82;:::o;59803:73::-;59834:42;59803:73;:::o;60081:82::-;60120:42;60081:82;:::o;45453:170::-;32017:6;;-1:-1:-1;;;;;32017:6:0;32003:10;:20;;:65;;-1:-1:-1;32058:10:0;;-1:-1:-1;;;;;32058:10:0;32044;:24;32003:65;:112;;;;32103:12;:10;:12::i;:::-;-1:-1:-1;;;;;32089:26:0;:10;-1:-1:-1;;;;;32089:26:0;;32003:112;:163;;;;32150:5;;;;;;;;;-1:-1:-1;;;;;32150:5:0;-1:-1:-1;;;;;32150:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;32136:30:0;:10;-1:-1:-1;;;;;32136:30:0;;32003:163;:216;;;;32201:5;;;;;;;;;-1:-1:-1;;;;;32201:5:0;-1:-1:-1;;;;;32201:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;32187:32:0;:10;-1:-1:-1;;;;;32187:32:0;;32003:216;31981:277;;;;-1:-1:-1;;;31981:277:0;;;;;;;:::i;:::-;45591:5:::1;::::0;:23:::1;::::0;;-1:-1:-1;;;45591:23:0;;;;45576:39:::1;::::0;-1:-1:-1;;;;;45591:5:0::1;::::0;:21:::1;::::0;:23:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:5;:23;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;45576:14;:39::i;:::-;45453:170::o:0;49846:1904::-;32017:6;;-1:-1:-1;;;;;32017:6:0;32003:10;:20;;:65;;-1:-1:-1;32058:10:0;;-1:-1:-1;;;;;32058:10:0;32044;:24;32003:65;:112;;;;32103:12;:10;:12::i;:::-;-1:-1:-1;;;;;32089:26:0;:10;-1:-1:-1;;;;;32089:26:0;;32003:112;:163;;;;32150:5;;;;;;;;;-1:-1:-1;;;;;32150:5:0;-1:-1:-1;;;;;32150:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;32136:30:0;:10;-1:-1:-1;;;;;32136:30:0;;32003:163;:216;;;;32201:5;;;;;;;;;-1:-1:-1;;;;;32201:5:0;-1:-1:-1;;;;;32201:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;32187:32:0;:10;-1:-1:-1;;;;;32187:32:0;;32003:216;31981:277;;;;-1:-1:-1;;;31981:277:0;;;;;;;:::i;:::-;49897:14:::1;49926:12:::0;49953:23:::1;49979:5;;;;;;;;;-1:-1:-1::0;;;;;49979:5:0::1;-1:-1:-1::0;;;;;49979:21:0::1;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;50051:13;::::0;49953:49;;-1:-1:-1;50013:19:0::1;::::0;50051:13:::1;;50047:731;;;50133:19;50155:22;:20;:22::i;:::-;50133:44;;50311:80;50343:15;50329:11;:29;:61;;50375:15;50329:61;;;50361:11;50329:61;50311:17;:80::i;:::-;50289:102:::0;-1:-1:-1;50289:102:0;-1:-1:-1;50469:29:0;;::::1;50465:159;;;50528:32;:11:::0;50544:15;50528::::1;:32::i;:::-;50519:41;;50593:15;50579:29;;50465:159;50047:731;;;;50736:30;50750:15;50736:13;:30::i;:::-;50706:60:::0;;-1:-1:-1;50706:60:0;-1:-1:-1;50706:60:0;-1:-1:-1;50047:731:0::1;50994:5;::::0;:31:::1;::::0;-1:-1:-1;;;50994:31:0;;50974:17:::1;::::0;-1:-1:-1;;;;;50994:5:0::1;::::0;:16:::1;::::0;:31:::1;::::0;51019:4:::1;::::0;50994:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;::::0;51064:5:::1;::::0;:39:::1;::::0;-1:-1:-1;;;51064:39:0;;50994:41;;-1:-1:-1;;;;;;51064:5:0::1;::::0;:12:::1;::::0;:39:::1;::::0;51077:6;;51085:4;;51091:11;;51064:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51046:57;;51179:31;51194:15;51179:14;:31::i;:::-;51265:13;::::0;::::1;;:42:::0;::::1;;;-1:-1:-1::0;51282:11:0::1;::::0;::::1;::::0;::::1;-1:-1:-1::0;;;;;51282:11:0::1;:25:::0;::::1;51265:42;51261:411;;;51362:11;::::0;51350:209:::1;::::0;-1:-1:-1;;;51350:209:0;;51362:11:::1;::::0;;::::1;-1:-1:-1::0;;;;;51362:11:0::1;::::0;51350:30:::1;::::0;:209:::1;::::0;51403:6;;51432:4;;51459:11;;51493:15;;51531:9;;51350:209:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51324:283;;;;-1:-1:-1::0;;;51324:283:0::1;;;;;;;:::i;:::-;51261:411;;;51656:4;51640:20:::0;;-1:-1:-1;;51640:20:0::1;::::0;::::1;::::0;;51261:411:::1;51689:53;51699:6;51707:4;51713:11;51726:15;51689:53;;;;;;;;;:::i;:::-;;;;;;;;32269:1;;;;;49846:1904::o:0;31524:25::-;;;;;;:::o;61862:135::-;31635:10;;-1:-1:-1;;;;;31635:10:0;31621;:24;;:54;;;31663:12;:10;:12::i;:::-;-1:-1:-1;;;;;31649:26:0;:10;-1:-1:-1;;;;;31649:26:0;;31621:54;31613:78;;;;-1:-1:-1;;;31613:78:0;;;;;;;:::i;:::-;61953:16:::1;:36:::0;61862:135::o;44838:286::-;44906:4;44838:286;;;;:::o;28222:25::-;;;;;;:::o;60509:30::-;;;;:::o;34833:174::-;31635:10;;-1:-1:-1;;;;;31635:10:0;31621;:24;;:54;;;31663:12;:10;:12::i;:::-;-1:-1:-1;;;;;31649:26:0;:10;-1:-1:-1;;;;;31649:26:0;;31621:54;31613:78;;;;-1:-1:-1;;;31613:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;34912:21:0;::::1;34904:30;;;::::0;::::1;;34945:6;:16:::0;;-1:-1:-1;;;;;;34945:16:0::1;-1:-1:-1::0;;;;;34945:16:0;::::1;;::::0;;34977:22:::1;::::0;::::1;::::0;::::1;::::0;34945:16;;34977:22:::1;:::i;38505:171::-:0;31635:10;;-1:-1:-1;;;;;31635:10:0;31621;:24;;:54;;;31663:12;:10;:12::i;:::-;-1:-1:-1;;;;;31649:26:0;:10;-1:-1:-1;;;;;31649:26:0;;31621:54;31613:78;;;;-1:-1:-1;;;31613:78:0;;;;;;;:::i;:::-;38594:26:::1;:11;38608:12:::0;;38594:26:::1;:::i;:::-;;38636:32;38655:12;;38636:32;;;;;;;:::i;:::-;;;;;;;;38505:171:::0;;:::o;77723:369::-;77780:7;77804:12;77800:53;;-1:-1:-1;77840:1:0;77833:8;;77800:53;77889:16;;;77903:1;77889:16;;;77865:21;77889:16;;;;;77865:21;77889:16;;;;;;;;;;-1:-1:-1;77889:16:0;77865:40;;60120:42;77916:4;77921:1;77916:7;;;;;;;;;;;;;:14;-1:-1:-1;;;;;77916:14:0;;;-1:-1:-1;;;;;77916:14:0;;;;;59654:42;77941:4;77946:1;77941:7;;;;;;;;-1:-1:-1;;;;;77941:14:0;;;:7;;;;;;;;;;;:14;77993:44;;-1:-1:-1;;;77993:44:0;;77966:24;;59934:42;;77993:29;;:44;;78023:7;;78032:4;;77993:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;77993:44:0;;;;;;;;;;;;:::i;:::-;77966:71;;78057:7;78082:1;78065:7;:14;:18;78057:27;;;;;;;;;;;;;;78050:34;;;;77723:369;;;:::o;31267:27::-;;;;:::o;62765:95::-;62824:7;62765:95;:::o;37301:169::-;31635:10;;-1:-1:-1;;;;;31635:10:0;31621;:24;;:54;;;31663:12;:10;:12::i;:::-;-1:-1:-1;;;;;31649:26:0;:10;-1:-1:-1;;;;;31649:26:0;;31621:54;31613:78;;;;-1:-1:-1;;;31613:78:0;;;;;;;:::i;:::-;37384:12:::1;:28:::0;;;37428:34:::1;::::0;::::1;::::0;::::1;::::0;37399:13;;37428:34:::1;:::i;30930:29::-:0;;;;:::o;30134:22::-;;;-1:-1:-1;;;;;30134:22:0;;:::o;33721:123::-;32362:5;;;;;;;;;-1:-1:-1;;;;;32362:5:0;-1:-1:-1;;;;;32362:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;32348:32:0;:10;-1:-1:-1;;;;;32348:32:0;;:62;;;;32398:12;:10;:12::i;:::-;-1:-1:-1;;;;;32384:26:0;:10;-1:-1:-1;;;;;32384:26:0;;32348:62;32326:123;;;;-1:-1:-1;;;32326:123:0;;;;;;;:::i;:::-;33806:13:::1;:30:::0;;-1:-1:-1;;33806:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;33721:123::o;30163:21::-;;;-1:-1:-1;;;;;30163:21:0;;:::o;60173:85::-;-1:-1:-1;;;;;;;;;;;60173:85:0;:::o;28254:26::-;;;;;;-1:-1:-1;;;;;28254:26:0;;:::o;60589:35::-;;;;:::o;34077:202::-;31635:10;;-1:-1:-1;;;;;31635:10:0;31621;:24;;:54;;;31663:12;:10;:12::i;:::-;-1:-1:-1;;;;;31649:26:0;:10;-1:-1:-1;;;;;31649:26:0;;31621:54;31613:78;;;;-1:-1:-1;;;31613:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;34164:25:0;::::1;34156:34;;;::::0;::::1;;34201:10;:24:::0;;-1:-1:-1;;;;;;34201:24:0::1;-1:-1:-1::0;;;;;34201:24:0;::::1;;::::0;;34241:30:::1;::::0;::::1;::::0;::::1;::::0;34201:24;;34241:30:::1;:::i;53100:311::-:0;53189:5;;-1:-1:-1;;;;;53189:5:0;53167:10;:28;;:58;;;53213:12;:10;:12::i;:::-;-1:-1:-1;;;;;53199:26:0;:10;-1:-1:-1;;;;;53199:26:0;;53167:58;53159:67;;;;;;53283:5;;53245:34;;;-1:-1:-1;;;53245:34:0;;;;-1:-1:-1;;;;;53283:5:0;;;;53245:32;;;;;:34;;;;;;;;;;;;;;:32;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;53245:43:0;;53237:52;;;;;;53300:30;53317:12;53300:16;:30::i;:::-;53373:4;;:29;;-1:-1:-1;;;53373:29:0;;53341:62;;53359:12;;-1:-1:-1;;;;;53373:4:0;;;;:14;;:29;;53396:4;;53373:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53341:4;;-1:-1:-1;;;;;53341:4:0;;:62;:17;:62::i;:::-;53100:311;:::o;60417:44::-;60459:2;60417:44;:::o;59711:80::-;59748:42;59711:80;:::o;35296:263::-;31778:10;;-1:-1:-1;;;;;31778:10:0;31764;:24;31756:48;;;;-1:-1:-1;;;31756:48:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;35377:22:0;::::1;35369:31;;;::::0;::::1;;35411:5;::::0;35425:7:::1;::::0;;35411:25:::1;::::0;-1:-1:-1;;;35411:25:0;;-1:-1:-1;;;;;35411:5:0;;::::1;::::0;:13:::1;::::0;:25:::1;::::0;35425:7;;::::1;::::0;35411:5:::1;::::0;:25:::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;35447:7:0::1;:18:::0;;-1:-1:-1;;;;;;35447:18:0::1;-1:-1:-1::0;;;;;35447:18:0;;::::1;::::0;;;::::1;::::0;;;35476:5:::1;::::0;:35:::1;::::0;-1:-1:-1;;;35476:35:0;;:5;;::::1;::::0;:13:::1;::::0;:35:::1;::::0;35490:7:::1;::::0;-1:-1:-1;;35507:2:0;35476:35:::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;35527:24;35542:8;35527:24;;;;;;:::i;73684:145::-:0;73756:4;73780:41;73801:19;73811:8;73801:9;:19::i;:::-;73780:20;:41::i;:::-;73773:48;73684:145;-1:-1:-1;;73684:145:0:o;64147:346::-;64250:69;;-1:-1:-1;;;64250:69:0;;64209:7;;;;60337:42;;64250:37;;:69;;60459:2;;64313:4;;64250:69;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;64349:40:0;;-1:-1:-1;;;64349:40:0;;64228:91;;-1:-1:-1;64330:16:0;;-1:-1:-1;;;;;;;;;;;60215:42:0;64349:25;;:40;;64383:4;;64349:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64455:4;;:29;;-1:-1:-1;;;64455:29:0;;64330:59;;-1:-1:-1;64407:78:0;;-1:-1:-1;;;;;64455:4:0;;;;:14;;:29;;64478:4;;64455:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64407:43;64428:21;:7;64440:8;64428:11;:21::i;:::-;64407:20;:43::i;:::-;:47;;:78::i;:::-;64400:85;;;;64147:346;:::o;36747:154::-;31635:10;;-1:-1:-1;;;;;31635:10:0;31621;:24;;:54;;;31663:12;:10;:12::i;:::-;-1:-1:-1;;;;;31649:26:0;:10;-1:-1:-1;;;;;31649:26:0;;31621:54;31613:78;;;;-1:-1:-1;;;31613:78:0;;;;;;;:::i;:::-;36825:14:::1;:23:::0;;;36864:29:::1;::::0;::::1;::::0;::::1;::::0;36842:6;;36864:29:::1;:::i;30074:21::-:0;;;-1:-1:-1;;;;;30074:21:0;;:::o;53840:164::-;31635:10;;-1:-1:-1;;;;;31635:10:0;31621;:24;;:54;;;31663:12;:10;:12::i;:::-;-1:-1:-1;;;;;31649:26:0;:10;-1:-1:-1;;;;;31649:26:0;;31621:54;31613:78;;;;-1:-1:-1;;;31613:78:0;;;;;;;:::i;:::-;53903:13:::1;:20:::0;;-1:-1:-1;;53903:20:0::1;53919:4;53903:20;::::0;;53934:5:::1;::::0;:22:::1;::::0;;-1:-1:-1;;;53934:22:0;;;;-1:-1:-1;;;;;53934:5:0;;::::1;::::0;:20:::1;::::0;:22:::1;::::0;;::::1;::::0;53903:13:::1;::::0;53934:22;;;;;;;;53903:13;53934:5;:22;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;53974:22:0::1;::::0;::::1;::::0;-1:-1:-1;53974:22:0;;-1:-1:-1;53974:22:0::1;53840:164::o:0;19069:622::-;19439:10;;;19438:62;;-1:-1:-1;19455:39:0;;-1:-1:-1;;;19455:39:0;;-1:-1:-1;;;;;19455:15:0;;;;;:39;;19479:4;;19486:7;;19455:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;19438:62;19430:152;;;;-1:-1:-1;;;19430:152:0;;;;;;;:::i;:::-;19593:90;19613:5;19643:22;;;19667:7;19676:5;19620:62;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;19620:62:0;;;;;;;;;;;;;;-1:-1:-1;;;;;19620:62:0;-1:-1:-1;;;;;;19620:62:0;;;;;;;;;;19593:19;:90::i;:::-;19069:622;;;:::o;10797:195::-;10900:12;10932:52;10954:6;10962:4;10968:1;10971:12;10932:21;:52::i;:::-;10925:59;;10797:195;;;;;;:::o;38830:98::-;38902:5;;:18;;;-1:-1:-1;;;38902:18:0;;;;38875:7;;-1:-1:-1;;;;;38902:5:0;;:16;;:18;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;75237:200::-;75353:16;;;75367:1;75353:16;;;;;;;;;75296;;;;75353;;;;;;;;;;;;-1:-1:-1;75353:16:0;75324:45;;-1:-1:-1;;;;;;;;;;;75380:9:0;75390:1;75380:12;;;;;;;;-1:-1:-1;;;;;75380:22:0;;;:12;;;;;;;;;;;:22;75420:9;-1:-1:-1;75237:200:0;:::o;18410:177::-;18493:86;18513:5;18543:23;;;18568:2;18572:5;18520:58;;;;;;;;;:::i;70173:1777::-;70250:25;70277:13;70306:17;70343:22;:20;:22::i;:::-;70326:13;:39;;:53;;70374:5;70326:53;;;70367:4;70326:53;70306:73;;70404:12;70400:1543;;;70456:69;;-1:-1:-1;;;70456:69:0;;70435:15;;60337:42;;70456:37;;:69;;60459:2;;70519:4;;70456:69;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;70540:63:0;;-1:-1:-1;;;70540:63:0;;70434:91;;-1:-1:-1;60337:42:0;;70540:37;;:63;;60459:2;;70434:91;;70540:63;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;70644:40:0;;-1:-1:-1;;;70644:40:0;;-1:-1:-1;;;;;;;;;;;60215:42:0;-1:-1:-1;70618:25:0;;-1:-1:-1;60215:42:0;;70644:25;;:40;;70678:4;;70644:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70618:67;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;70727:4:0;;70720:37;;-1:-1:-1;;;70720:37:0;;-1:-1:-1;;;;;70727:4:0;;;;-1:-1:-1;70720:22:0;;-1:-1:-1;70720:37:0;;70751:4;;70720:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70789:5;;:31;;-1:-1:-1;;;70789:31:0;;70700:57;;-1:-1:-1;70772:14:0;;-1:-1:-1;;;;;70789:5:0;;;;:16;;:31;;70814:4;;70789:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;70772:58;;70845:25;70913:6;70893:17;:26;70889:114;;;70958:29;:6;70969:17;70958:10;:29::i;:::-;70938:49;;70889:114;71044:17;-1:-1:-1;71017:45:0;;-1:-1:-1;;;71017:45:0;70400:1543;71129:4;;71122:37;;-1:-1:-1;;;71122:37:0;;71104:15;;-1:-1:-1;;;;;71129:4:0;;71122:22;;:37;;71153:4;;71122:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71104:55;;71188:13;71178:7;:23;71174:756;;;71232:12;71247:26;:13;71265:7;71247:17;:26::i;:::-;71232:41;;71292:15;71310:26;71331:4;71310:20;:26::i;:::-;71393:40;;-1:-1:-1;;;71393:40:0;;71292:44;;-1:-1:-1;71374:16:0;;-1:-1:-1;;;;;;;;;;;60215:42:0;71393:25;;:40;;71427:4;;71393:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71374:59;;71466:7;71455:8;:18;71451:103;;;71496:39;71517:7;71526:8;71496:20;:39::i;:::-;71571:34;;-1:-1:-1;;;71571:34:0;;-1:-1:-1;;;;;;;;;;;60215:42:0;71571:25;;:34;;71597:7;;71571:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;71647:4:0;;71640:37;;-1:-1:-1;;;71640:37:0;;71623:14;;-1:-1:-1;;;;;;71647:4:0;;;;-1:-1:-1;71640:22:0;;:37;;71671:4;;71640:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71623:54;;71712:7;71703:6;:16;71695:60;;;;-1:-1:-1;;;71695:60:0;;;;;;;:::i;:::-;71783:6;71807;71791:13;:22;:52;;71842:1;71791:52;;;71815:25;:13;71833:6;71815:17;:25::i;:::-;71775:69;;;;;;;;;;;;71174:756;71893:13;71885:29;;;;70173:1777;;;;:::o;68556:873::-;68698:13;;;;68694:52;;;68728:7;;68694:52;68778:40;;-1:-1:-1;;;68778:40:0;;68760:15;;-1:-1:-1;;;;;;;;;;;60215:42:0;68778:25;;:40;;68812:4;;68778:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68885:4;;:29;;-1:-1:-1;;;68885:29:0;;68760:58;;-1:-1:-1;68760:58:0;;68829:14;;-1:-1:-1;;;;;68885:4:0;;:14;;:29;;68908:4;;68885:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68869:45;;68937:16;68929:5;:24;68925:358;;;68978:27;:5;68988:16;68978:9;:27::i;:::-;69034:31;;-1:-1:-1;;;69034:31:0;;68970:35;;-1:-1:-1;;;;;;;;;;;;60215:42:0;69034:24;;:31;;68970:35;;69034:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69089:40:0;;-1:-1:-1;;;69089:40:0;;-1:-1:-1;;;;;;;;;;;60215:42:0;-1:-1:-1;69089:25:0;;-1:-1:-1;69089:40:0;;69123:4;;69089:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69080:49;;69161:7;69152:6;:16;69144:58;;;;-1:-1:-1;;;69144:58:0;;;;;;;:::i;:::-;68925:358;;;69242:5;69223:16;:24;69220:63;;;69263:7;;;;;69220:63;69309:10;;69305:103;;69335:61;;-1:-1:-1;;;69335:61:0;;60337:42;;69335:36;;:61;;60459:2;;69389:6;;69335:61;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69305:103;68556:873;;;;:::o;2993:158::-;3051:7;3084:1;3079;:6;;3071:49;;;;-1:-1:-1;;;3071:49:0;;;;;;;:::i;:::-;-1:-1:-1;3138:5:0;;;2993:158::o;65835:2232::-;65952:15;;;66087:20;;66083:262;;66125:20;66147:19;66170:35;66188:16;66170:17;:35::i;:::-;66124:81;;;;66250:16;66235:12;:31;:64;;66287:12;66235:64;;;66268:16;66235:64;66322:11;;-1:-1:-1;66220:79:0;-1:-1:-1;;66083:262:0;66455:5;;:31;;-1:-1:-1;;;66455:31:0;;66440:12;;-1:-1:-1;;;;;66455:5:0;;:16;;:31;;66480:4;;66455:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;66440:56;;66507:20;66530:22;:20;:22::i;:::-;66507:45;;66582:4;66567:12;:19;66563:911;;;66602:14;66619:22;:12;66636:4;66619:16;:22::i;:::-;66678:4;;:29;;-1:-1:-1;;;66678:29:0;;66602:39;;-1:-1:-1;66656:19:0;;-1:-1:-1;;;;;66678:4:0;;;;:14;;:29;;66701:4;;66678:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66656:51;;66722:23;66748:28;66769:6;66748:20;:28::i;:::-;66722:54;;66813:16;;66795:15;:34;66791:672;;;66868:40;;-1:-1:-1;;;66868:40:0;;66849:16;;-1:-1:-1;;;;;;;;;;;60215:42:0;66868:25;;:40;;66902:4;;66868:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66849:59;;66942:15;66931:8;:26;66927:121;;;66981:47;67002:15;67019:8;66981:20;:47::i;:::-;67066:42;;-1:-1:-1;;;67066:42:0;;-1:-1:-1;;;;;;;;;;;60215:42:0;67066:25;;:42;;67092:15;;67066:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;67148:4:0;;:29;;-1:-1:-1;;;67148:29:0;;67127:18;;-1:-1:-1;;;;;;67148:4:0;;;;-1:-1:-1;67148:14:0;;:29;;67171:4;;67148:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67127:50;;67213:11;67200:10;:24;67196:249;;;67248:14;67265:27;:10;67280:11;67265:14;:27::i;:::-;67248:44;-1:-1:-1;67325:19:0;:7;67248:44;67325:11;:19::i;:::-;67315:29;;67375:50;67394:6;67385;:15;:39;;67423:1;67385:39;;;67402:18;:6;67413;67402:10;:18::i;:::-;67375:5;;:9;:50::i;:::-;67367:58;;67196:249;;66791:672;;;66563:911;;;;67540:70;;-1:-1:-1;;;67540:70:0;;67519:18;;60337:42;;67540:38;;:70;;60459:2;;67604:4;;67540:70;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67519:91;-1:-1:-1;67625:14:0;;67621:105;;67655:57;;-1:-1:-1;;;67655:57:0;;60337:42;;67655:37;;:57;;60459:2;;67710:1;;67655:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67621:105;67746:27;67758:14;:12;:14::i;:::-;67746:7;;:11;:27::i;:::-;67736:37;;67839:5;67829:7;:15;67825:183;;;67870:18;:7;67882:5;67870:11;:18::i;:::-;67860:28;;67911:1;67903:9;;67825:183;;;67952:18;:5;67962:7;67952:9;:18::i;:::-;67944:26;;67995:1;67985:11;;67825:183;68022:37;;;65835:2232;;;;;:::o;74030:587::-;74128:69;;-1:-1:-1;;;74128:69:0;;74107:15;;60337:42;;74128:37;;:69;;60459:2;;74191:4;;74128:69;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;74208:63:0;;-1:-1:-1;;;74208:63:0;;74106:91;;-1:-1:-1;60337:42:0;;74208:37;;:63;;60459:2;;74106:91;;74208:63;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;74305:40:0;;-1:-1:-1;;;74305:40:0;;74286:16;;-1:-1:-1;;;;;;;;;;;;60215:42:0;-1:-1:-1;74305:25:0;;:40;;74339:4;;74305:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74286:59;-1:-1:-1;74360:12:0;;74356:96;;74388:52;-1:-1:-1;;;;;;;;;;;74417:12:0;74431:8;74388:28;:52::i;:::-;74483:35;;-1:-1:-1;;;74483:35:0;;74469:11;;59748:42;;74483:20;;:35;;74512:4;;74483:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74469:49;-1:-1:-1;74533:7:0;;74529:81;;74556:42;59748;74580:12;74594:3;74556:23;:42::i;47363:1677::-;47434:4;47451:28;;:::i;:::-;47482:5;;:31;;-1:-1:-1;;;47482:31:0;;-1:-1:-1;;;;;47482:5:0;;;;:16;;:31;;47507:4;;47482:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;47451:62;;47590:6;:17;;;47611:1;47590:22;47586:40;;;47621:5;47614:12;;;;;47586:40;47771:14;;47750:17;;;;47730:38;;:15;;:19;:38::i;:::-;:55;47726:73;;;47794:5;47787:12;;;;;47726:73;47918:14;;47896:17;;;;47876:38;;:15;;:19;:38::i;:::-;:56;47872:73;;47941:4;47934:11;;;;;47872:73;48375:5;;:23;;;-1:-1:-1;;;48375:23:0;;;;48353:19;;-1:-1:-1;;;;;48375:5:0;;:21;;:23;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48353:45;;48427:13;;48413:11;:27;48409:44;;;48449:4;48442:11;;;;;;48409:44;48507:13;48523:22;:20;:22::i;:::-;48507:38;;48635:6;:16;;;48608:24;48618:13;;48608:5;:9;;:24;;;;:::i;:::-;:43;48604:60;;;48660:4;48653:11;;;;;;;48604:60;48677:14;48718:6;:16;;;48710:5;:24;48706:66;;;48755:16;;;;48745:27;;:5;;:9;:27::i;:::-;48736:36;;48706:66;48942:5;;:23;;;-1:-1:-1;;;48942:23:0;;;;48925:14;;-1:-1:-1;;;;;48942:5:0;;:21;;:23;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48925:40;-1:-1:-1;49013:18:0;48925:40;49024:6;49013:10;:18::i;:::-;48984:12;;:26;;49001:8;48984:16;:26::i;:::-;:47;;47363:1677;-1:-1:-1;;;;;;;47363:1677:0:o;2531:179::-;2589:7;2621:5;;;2645:6;;;;2637:46;;;;-1:-1:-1;;;2637:46:0;;;;;;;:::i;75446:339::-;75516:7;75535:20;-1:-1:-1;;;;;;;;;;;;;;;;75558:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75535:52;-1:-1:-1;75602:17:0;75598:57;;75642:1;75635:8;;;;;75598:57;75665:20;-1:-1:-1;;;;;;;;;;;;;;;;75688:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75665:49;-1:-1:-1;75732:45:0;75764:12;75733:25;75665:49;75750:7;75733:16;:25::i;:::-;75732:31;;:45::i;:::-;75725:52;75446:339;-1:-1:-1;;;;75446:339:0:o;20715:761::-;21139:23;21165:69;21193:4;21165:69;;;;;;;;;;;;;;;;;21173:5;-1:-1:-1;;;;;21165:27:0;;;:69;;;;;:::i;:::-;21249:17;;21139:95;;-1:-1:-1;21249:21:0;21245:224;;21391:10;21380:30;;;;;;;;;;;;:::i;:::-;21372:85;;;;-1:-1:-1;;;21372:85:0;;;;;;;:::i;11849:530::-;11976:12;12034:5;12009:21;:30;;12001:81;;;;-1:-1:-1;;;12001:81:0;;;;;;;:::i;:::-;12101:18;12112:6;12101:10;:18::i;:::-;12093:60;;;;-1:-1:-1;;;12093:60:0;;;;;;;:::i;:::-;12227:12;12241:23;12268:6;-1:-1:-1;;;;;12268:11:0;12288:5;12296:4;12268:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12226:75;;;;12319:52;12337:7;12346:10;12358:12;12319:17;:52::i;:::-;12312:59;11849:530;-1:-1:-1;;;;;;;11849:530:0:o;75794:150::-;75862:7;75888:48;-1:-1:-1;;;;;;;;;;;;;;;;75908:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75888:15;:5;75898:4;75888:9;:15::i;75954:385::-;76039:14;76056:21;:7;76068:8;76056:11;:21::i;:::-;76114:69;;-1:-1:-1;;;76114:69:0;;76039:38;;-1:-1:-1;76093:15:0;;60337:42;;76114:37;;:69;;60459:2;;76177:4;;76114:69;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;76092:91;;;76213:6;76202:7;:17;;76194:61;;;;-1:-1:-1;;;76194:61:0;;;;;;;:::i;:::-;76268:62;;-1:-1:-1;;;76268:62:0;;60337:42;;76268:37;;:62;;60459:2;;76323:6;;76268:62;;;:::i;76375:1339::-;76450:35;;-1:-1:-1;;;76450:35:0;;76417:7;;;;59748:42;;76450:20;;:35;;76479:4;;76450:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;76436:49;;76496:19;76542:11;;76535:3;:18;76531:1147;;76710:16;;;76724:1;76710:16;;;;;;;;;76681:26;;76710:16;;;76681:26;;76710:16;;;;;-1:-1:-1;76710:16:0;76681:45;;59748:42;76741:9;76751:1;76741:12;;;;;;;;;;;;;:17;-1:-1:-1;;;;;76741:17:0;;;-1:-1:-1;;;;;76741:17:0;;;;;60120:42;76773:9;76783:1;76773:12;;;;;;;;;;;;;:19;-1:-1:-1;;;;;76773:19:0;;;-1:-1:-1;;;;;76773:19:0;;;;;59654:42;76807:9;76817:1;76807:12;;;;;;;;-1:-1:-1;;;;;76807:19:0;;;:12;;;;;;;;;;;:19;76863:46;;-1:-1:-1;;;76863:46:0;;76841:19;;60029:42;;76863:30;;:46;;76894:3;;76899:9;;76863:46;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;76863:46:0;;;;;;;;;;;;:::i;:::-;76929:1;76910:9;:16;:20;76863:68;;;;;;;;;;;;;;76841:90;;76966:24;77007:1;76993:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;76993:16:0;;76966:43;;59748:42;77024:7;77032:1;77024:10;;;;;;;;;;;;;:15;-1:-1:-1;;;;;77024:15:0;;;-1:-1:-1;;;;;77024:15:0;;;;;59834:42;77054:7;77062:1;77054:10;;;;;;;;;;;;;:17;-1:-1:-1;;;;;77054:17:0;;;-1:-1:-1;;;;;77054:17:0;;;;;60120:42;77086:7;77094:1;77086:10;;;;;;;;;;;;;:17;-1:-1:-1;;;;;77086:17:0;;;-1:-1:-1;;;;;77086:17:0;;;;;59654:42;77118:7;77126:1;77118:10;;;;;;;;-1:-1:-1;;;;;77118:17:0;;;:10;;;;;;;;;;;:17;77170:43;;-1:-1:-1;;;77170:43:0;;77150:17;;59934:42;;77170:29;;:43;;77200:3;;77205:7;;77170:43;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;77170:43:0;;;;;;;;;;;;:::i;:::-;77231:1;77214:7;:14;:18;77170:63;;;;;;;;;;;;;;;;;;77269:4;;:29;;-1:-1:-1;;;77269:29:0;;77170:63;;-1:-1:-1;77253:13:0;;-1:-1:-1;;;;;77269:4:0;;;;:14;;:29;;77292:4;;77269:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77253:45;;77332:9;77317:11;:24;77313:285;;77361:89;;-1:-1:-1;;;77361:89:0;;60029:42;;77361:41;;:89;;77403:3;;77416:1;;77420:9;;77439:4;;77446:3;;77361:89;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;77361:89:0;;;;;;;;;;;;:::i;:::-;;77313:285;;;77493:86;;-1:-1:-1;;;77493:86:0;;59934:42;;77493:40;;:86;;77534:3;;77547:1;;77551:7;;77568:4;;77575:3;;77493:86;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;77493:86:0;;;;;;;;;;;;:::i;:::-;;77313:285;77626:4;;:29;;-1:-1:-1;;;77626:29:0;;:40;;77660:5;;-1:-1:-1;;;;;77626:4:0;;;;:14;;:29;;77649:4;;77626:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:33;;:40::i;:::-;77612:54;;76531:1147;;;;;;77695:11;-1:-1:-1;;76375:1339:0;:::o;3410:220::-;3468:7;3492:6;3488:20;;-1:-1:-1;3507:1:0;3500:8;;3488:20;3531:5;;;3535:1;3531;:5;:1;3555:5;;;;;:10;3547:56;;;;-1:-1:-1;;;3547:56:0;;;;;;;:::i;4108:153::-;4166:7;4198:1;4194;:5;4186:44;;;;-1:-1:-1;;;4186:44:0;;;;;;;:::i;:::-;4252:1;4248;:5;;;;;;;4108:153;-1:-1:-1;;;4108:153:0:o;7879:422::-;8246:20;8285:8;;;7879:422::o;14389:742::-;14504:12;14533:7;14529:595;;;-1:-1:-1;14564:10:0;14557:17;;14529:595;14678:17;;:21;14674:439;;14941:10;14935:17;15002:15;14989:10;14985:2;14981:19;14974:44;14889:148;15084:12;15077:20;;-1:-1:-1;;;15077:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;3815:241;;3919:2;3907:9;3898:7;3894:23;3890:32;3887:2;;;-1:-1;;3925:12;3887:2;85:6;72:20;97:33;124:5;97:33;:::i;4063:263::-;;4178:2;4166:9;4157:7;4153:23;4149:32;4146:2;;;-1:-1;;4184:12;4146:2;226:6;220:13;238:33;265:5;238:33;:::i;4333:392::-;;4473:2;;4461:9;4452:7;4448:23;4444:32;4441:2;;;-1:-1;;4479:12;4441:2;4530:17;4524:24;4568:18;4560:6;4557:30;4554:2;;;-1:-1;;4590:12;4554:2;4677:22;;422:4;410:17;;406:27;-1:-1;396:2;;-1:-1;;437:12;396:2;477:6;471:13;499:80;514:64;571:6;514:64;:::i;:::-;499:80;:::i;:::-;607:21;;;664:14;;;;639:17;;;753;;;744:27;;;;741:36;-1:-1;738:2;;;-1:-1;;780:12;738:2;-1:-1;806:10;;800:217;825:6;822:1;819:13;800:217;;;3752:13;;893:61;;847:1;840:9;;;;;968:14;;;;996;;800:217;;;-1:-1;4610:99;4435:290;-1:-1;;;;;;;4435:290::o;4732:235::-;;4833:2;4821:9;4812:7;4808:23;4804:32;4801:2;;;-1:-1;;4839:12;4801:2;1108:6;1095:20;1120:30;1144:5;1120:30;:::i;4974:257::-;;5086:2;5074:9;5065:7;5061:23;5057:32;5054:2;;;-1:-1;;5092:12;5054:2;1243:6;1237:13;1255:30;1279:5;1255:30;:::i;5542:367::-;;;5666:2;5654:9;5645:7;5641:23;5637:32;5634:2;;;-1:-1;;5672:12;5634:2;5730:17;5717:31;5768:18;;5760:6;5757:30;5754:2;;;-1:-1;;5790:12;5754:2;5876:6;5865:9;5861:22;;;1602:3;1595:4;1587:6;1583:17;1579:27;1569:2;;-1:-1;;1610:12;1569:2;1653:6;1640:20;5768:18;1672:6;1669:30;1666:2;;;-1:-1;;1702:12;1666:2;1797:3;5666:2;1777:17;1738:6;1763:32;;1760:41;1757:2;;;-1:-1;;1804:12;1757:2;5666;1734:17;;;;;5810:83;;-1:-1;5628:281;;-1:-1;;;;5628:281::o;5916:326::-;;6062:3;;6050:9;6041:7;6037:23;6033:33;6030:2;;;-1:-1;;6069:12;6030:2;2029:22;6062:3;2029:22;:::i;:::-;2020:31;;2175:22;3752:13;2125:16;2118:86;2271:2;2340:9;2336:22;3752:13;2271:2;2290:5;2286:16;2279:86;2431:2;2500:9;2496:22;3752:13;2431:2;2450:5;2446:16;2439:86;2599:2;2668:9;2664:22;3752:13;2599:2;2618:5;2614:16;2607:86;2767:3;2837:9;2833:22;3752:13;2767:3;2787:5;2783:16;2776:86;2929:3;2999:9;2995:22;3752:13;2929:3;2949:5;2945:16;2938:86;3090:3;3160:9;3156:22;3752:13;3090:3;3110:5;3106:16;3099:86;3251:3;3321:9;3317:22;3752:13;3251:3;3271:5;3267:16;3260:86;3412:3;;3484:9;3480:22;3752:13;3412:3;3432:5;3428:18;3421:88;;6121:105;;;;6024:218;;;;:::o;6249:241::-;;6353:2;6341:9;6332:7;6328:23;6324:32;6321:2;;;-1:-1;;6359:12;6321:2;-1:-1;3604:20;;6315:175;-1:-1;6315:175::o;6497:263::-;;6612:2;6600:9;6591:7;6587:23;6583:32;6580:2;;;-1:-1;;6618:12;6580:2;-1:-1;3752:13;;6574:186;-1:-1;6574:186::o;6767:399::-;;;6899:2;6887:9;6878:7;6874:23;6870:32;6867:2;;;-1:-1;;6905:12;6867:2;-1:-1;;3752:13;;7068:2;7118:22;;;3752:13;;;;;-1:-1;6861:305::o;7616:690::-;;7809:5;31859:12;32403:6;32398:3;32391:19;32440:4;;32435:3;32431:14;7821:93;;32440:4;7985:5;31713:14;-1:-1;8024:260;8049:6;8046:1;8043:13;8024:260;;;8110:13;;-1:-1;;;;;33151:54;7416:37;;7327:14;;;;32246;;;;4568:18;8064:9;8024:260;;;-1:-1;8290:10;;7740:566;-1:-1;;;;;7740:566::o;16211:271::-;;8585:5;31859:12;8696:52;8741:6;8736:3;8729:4;8722:5;8718:16;8696:52;:::i;:::-;8760:16;;;;;16345:137;-1:-1;;16345:137::o;16489:222::-;-1:-1;;;;;33151:54;;;;7416:37;;16616:2;16601:18;;16587:124::o;16718:333::-;-1:-1;;;;;33151:54;;;7416:37;;33151:54;;17037:2;17022:18;;7416:37;16873:2;16858:18;;16844:207::o;17058:349::-;-1:-1;;;;;33151:54;;;;7416:37;;17393:2;17378:18;;9195:58;17221:2;17206:18;;17192:215::o;17754:210::-;32948:13;;32941:21;8379:34;;17875:2;17860:18;;17846:118::o;18491:330::-;;18648:2;18669:17;18662:47;32403:6;18648:2;18637:9;18633:18;32391:19;34080:6;34075:3;32431:14;18637:9;32431:14;34057:30;34118:16;;;32431:14;34118:16;;;34111:27;;;;34513:7;34497:14;;;-1:-1;;34493:28;9545:39;;;18619:202;-1:-1;18619:202::o;18828:310::-;;18975:2;18996:17;18989:47;9743:5;31859:12;32403:6;18975:2;18964:9;18960:18;32391:19;9837:52;9882:6;32431:14;18964:9;32431:14;18975:2;9863:5;9859:16;9837:52;:::i;:::-;34513:7;34497:14;-1:-1;;34493:28;9901:39;;;;32431:14;9901:39;;18946:192;-1:-1;;18946:192::o;19145:416::-;19345:2;19359:47;;;10177:2;19330:18;;;32391:19;-1:-1;;;32431:14;;;10193:34;10246:12;;;19316:245::o;19568:416::-;19768:2;19782:47;;;10497:2;19753:18;;;32391:19;10533:33;32431:14;;;10513:54;10586:12;;;19739:245::o;19991:416::-;20191:2;20205:47;;;10837:1;20176:18;;;32391:19;-1:-1;;;32431:14;;;10852:28;10899:12;;;20162:245::o;20414:416::-;20614:2;20628:47;;;11150:2;20599:18;;;32391:19;11186:29;32431:14;;;11166:50;11235:12;;;20585:245::o;20837:416::-;21037:2;21051:47;;;11486:2;21022:18;;;32391:19;-1:-1;;;32431:14;;;11502:35;11556:12;;;21008:245::o;21260:416::-;21460:2;21474:47;;;11807:2;21445:18;;;32391:19;11843:32;32431:14;;;11823:53;11895:12;;;21431:245::o;21683:416::-;21883:2;21897:47;;;12146:2;21868:18;;;32391:19;12182:34;32431:14;;;12162:55;-1:-1;;;12237:12;;;12230:30;12279:12;;;21854:245::o;22106:416::-;22306:2;22320:47;;;12530:2;22291:18;;;32391:19;12566:28;32431:14;;;12546:49;12614:12;;;22277:245::o;22529:416::-;22729:2;22743:47;;;12865:2;22714:18;;;32391:19;12901:34;32431:14;;;12881:55;-1:-1;;;12956:12;;;12949:25;12993:12;;;22700:245::o;22952:416::-;23152:2;23166:47;;;13244:1;23137:18;;;32391:19;-1:-1;;;32431:14;;;13259:29;13307:12;;;23123:245::o;23375:416::-;23575:2;23589:47;;;13558:1;23560:18;;;32391:19;-1:-1;;;32431:14;;;13573:30;13622:12;;;23546:245::o;23798:416::-;23998:2;24012:47;;;13873:2;23983:18;;;32391:19;13909:33;32431:14;;;13889:54;13962:12;;;23969:245::o;24221:416::-;24421:2;24435:47;;;14213:2;24406:18;;;32391:19;14249:31;32431:14;;;14229:52;14300:12;;;24392:245::o;24644:416::-;24844:2;24858:47;;;14551:2;24829:18;;;32391:19;-1:-1;;;32431:14;;;14567:34;14620:12;;;24815:245::o;25067:416::-;25267:2;25281:47;;;14871:2;25252:18;;;32391:19;14907:34;32431:14;;;14887:55;-1:-1;;;14962:12;;;14955:34;15008:12;;;25238:245::o;25490:416::-;25690:2;25704:47;;;15259:2;25675:18;;;32391:19;-1:-1;;;32431:14;;;15275:33;15327:12;;;25661:245::o;25913:416::-;26113:2;26127:47;;;15578:2;26098:18;;;32391:19;15614:34;32431:14;;;15594:55;-1:-1;;;15669:12;;;15662:46;15727:12;;;26084:245::o;26336:416::-;26536:2;26550:47;;;15978:2;26521:18;;;32391:19;16014:31;32431:14;;;15994:52;16065:12;;;26507:245::o;26759:222::-;16162:37;;;26886:2;26871:18;;26857:124::o;26988:333::-;16162:37;;;-1:-1;;;;;33151:54;27307:2;27292:18;;7416:37;27143:2;27128:18;;27114:207::o;27328:481::-;;16192:5;16169:3;16162:37;27533:2;27651;27640:9;27636:18;27629:48;27691:108;27533:2;27522:9;27518:18;27785:6;27691:108;:::i;27816:349::-;16162:37;;;28151:2;28136:18;;9195:58;27979:2;27964:18;;27950:215::o;28512:816::-;;16192:5;16169:3;16162:37;16192:5;28966:2;28955:9;28951:18;16162:37;28801:3;29003:2;28992:9;28988:18;28981:48;29043:108;28801:3;28790:9;28786:19;29137:6;29043:108;:::i;:::-;-1:-1;;;;;33151:54;;;;29230:2;29215:18;;7416:37;-1:-1;29313:3;29298:19;16162:37;29035:116;28772:556;-1:-1;;;28772:556::o;29335:444::-;16162:37;;;29682:2;29667:18;;16162:37;;;;29765:2;29750:18;;16162:37;29518:2;29503:18;;29489:290::o;29786:556::-;16162:37;;;30162:2;30147:18;;16162:37;;;;30245:2;30230:18;;16162:37;30328:2;30313:18;;16162:37;29997:3;29982:19;;29968:374::o;30349:668::-;16162:37;;;30753:2;30738:18;;16162:37;;;;30836:2;30821:18;;16162:37;;;;30919:2;30904:18;;16162:37;31002:3;30987:19;;16162:37;30588:3;30573:19;;30559:458::o;31024:256::-;31086:2;31080:9;31112:17;;;31187:18;31172:34;;31208:22;;;31169:62;31166:2;;;31244:1;;31234:12;31166:2;31086;31253:22;31064:216;;-1:-1;31064:216::o;31287:304::-;;31446:18;31438:6;31435:30;31432:2;;;-1:-1;;31468:12;31432:2;-1:-1;31513:4;31501:17;;;31566:15;;31369:222::o;34153:268::-;34218:1;34225:101;34239:6;34236:1;34233:13;34225:101;;;34306:11;;;34300:18;34287:11;;;34280:39;34261:2;34254:10;34225:101;;;34341:6;34338:1;34335:13;34332:2;;;-1:-1;;34218:1;34388:16;;34381:27;34202:219::o;34534:117::-;-1:-1;;;;;33151:54;;34593:35;;34583:2;;34642:1;;34632:12;34658:111;34739:5;32948:13;32941:21;34717:5;34714:32;34704:2;;34760:1;;34750:12

Swarm Source

ipfs://431ab2f95957f4396a720dc72e951e5c46310dee0ada8f4691e3afeec7e9567b
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.