Contract 0x0795ecb44b3e30c88c3bd1af93c76a45fcba2508

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x795cb3ff82aa3dc4f35df1e2719c37b1cdacd66427c2a016d6c53b0ec48dd24aSet Strategist184106952022-08-09 8:28:388 days 23 hrs ago0x6acc0709fa64d691dd0c28f31d90abd1a486ef52 IN  0x0795ecb44b3e30c88c3bd1af93c76a45fcba25080 AVAX0.‍000734552 26
0x80645ba8b3b213c30adab49ca11da2a663af7eabc002ce0204ed51b8a15623f6Set Keeper184099172022-08-09 8:02:268 days 23 hrs ago0x6acc0709fa64d691dd0c28f31d90abd1a486ef52 IN  0x0795ecb44b3e30c88c3bd1af93c76a45fcba25080 AVAX0.‍000784862 26
0xa7068c699adec2688796b85394b6f67455074f19f2e9f57d90d90026d7074e640x60806040182482942022-08-05 13:24:2612 days 18 hrs ago0x6acc0709fa64d691dd0c28f31d90abd1a486ef52 IN  Create: WAVAXUSDCVTX0 AVAX0.‍1594635525
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
WAVAXUSDCVTX

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU AGPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at snowtrace.io on 2022-08-06
*/

pragma experimental ABIEncoderV2;

// File: Address.sol

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: DataTypes.sol

library DataTypes {
    struct ReserveData {
        //stores the reserve configuration
        ReserveConfigurationMap configuration;
        //the liquidity index. Expressed in ray
        uint128 liquidityIndex;
        //the current supply rate. Expressed in ray
        uint128 currentLiquidityRate;
        //variable borrow index. Expressed in ray
        uint128 variableBorrowIndex;
        //the current variable borrow rate. Expressed in ray
        uint128 currentVariableBorrowRate;
        //the current stable borrow rate. Expressed in ray
        uint128 currentStableBorrowRate;
        //timestamp of last update
        uint40 lastUpdateTimestamp;
        //the id of the reserve. Represents the position in the list of the active reserves
        uint16 id;
        //aToken address
        address aTokenAddress;
        //stableDebtToken address
        address stableDebtTokenAddress;
        //variableDebtToken address
        address variableDebtTokenAddress;
        //address of the interest rate strategy
        address interestRateStrategyAddress;
        //the current treasury balance, scaled
        uint128 accruedToTreasury;
        //the outstanding unbacked aTokens minted through the bridging feature
        uint128 unbacked;
        //the outstanding debt borrowed against this asset in isolation mode
        uint128 isolationModeTotalDebt;
    }

    struct ReserveConfigurationMap {
        //bit 0-15: LTV
        //bit 16-31: Liq. threshold
        //bit 32-47: Liq. bonus
        //bit 48-55: Decimals
        //bit 56: reserve is active
        //bit 57: reserve is frozen
        //bit 58: borrowing is enabled
        //bit 59: stable rate borrowing enabled
        //bit 60: asset is paused
        //bit 61: borrowing in isolation mode is enabled
        //bit 62-63: reserved
        //bit 64-79: reserve factor
        //bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap
        //bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap
        //bit 152-167 liquidation protocol fee
        //bit 168-175 eMode category
        //bit 176-211 unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled
        //bit 212-251 debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals
        //bit 252-255 unused

        uint256 data;
    }

    struct UserConfigurationMap {
        /*
         * Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset.
         * The first bit indicates if an asset is used as collateral by the user, the second whether an
         * asset is borrowed by the user.
         */
        uint256 data;
    }

    struct EModeCategory {
        // each eMode category has a custom ltv and liquidation threshold
        uint16 ltv;
        uint16 liquidationThreshold;
        uint16 liquidationBonus;
        // each eMode category may or may not have a custom oracle to override the individual assets price oracles
        address priceSource;
        string label;
    }

    enum InterestRateMode {NONE, STABLE, VARIABLE}

    struct ReserveCache {
        uint256 currScaledVariableDebt;
        uint256 nextScaledVariableDebt;
        uint256 currPrincipalStableDebt;
        uint256 currAvgStableBorrowRate;
        uint256 currTotalStableDebt;
        uint256 nextAvgStableBorrowRate;
        uint256 nextTotalStableDebt;
        uint256 currLiquidityIndex;
        uint256 nextLiquidityIndex;
        uint256 currVariableBorrowIndex;
        uint256 nextVariableBorrowIndex;
        uint256 currLiquidityRate;
        uint256 currVariableBorrowRate;
        uint256 reserveFactor;
        ReserveConfigurationMap reserveConfiguration;
        address aTokenAddress;
        address stableDebtTokenAddress;
        address variableDebtTokenAddress;
        uint40 reserveLastUpdateTimestamp;
        uint40 stableDebtLastUpdateTimestamp;
    }

    struct ExecuteLiquidationCallParams {
        uint256 reservesCount;
        uint256 debtToCover;
        address collateralAsset;
        address debtAsset;
        address user;
        bool receiveAToken;
        address priceOracle;
        uint8 userEModeCategory;
        address priceOracleSentinel;
    }

    struct ExecuteSupplyParams {
        address asset;
        uint256 amount;
        address onBehalfOf;
        uint16 referralCode;
    }

    struct ExecuteBorrowParams {
        address asset;
        address user;
        address onBehalfOf;
        uint256 amount;
        InterestRateMode interestRateMode;
        uint16 referralCode;
        bool releaseUnderlying;
        uint256 maxStableRateBorrowSizePercent;
        uint256 reservesCount;
        address oracle;
        uint8 userEModeCategory;
        address priceOracleSentinel;
    }

    struct ExecuteRepayParams {
        address asset;
        uint256 amount;
        InterestRateMode interestRateMode;
        address onBehalfOf;
        bool useATokens;
    }

    struct ExecuteWithdrawParams {
        address asset;
        uint256 amount;
        address to;
        uint256 reservesCount;
        address oracle;
        uint8 userEModeCategory;
    }

    struct ExecuteSetUserEModeParams {
        uint256 reservesCount;
        address oracle;
        uint8 categoryId;
    }

    struct FinalizeTransferParams {
        address asset;
        address from;
        address to;
        uint256 amount;
        uint256 balanceFromBefore;
        uint256 balanceToBefore;
        uint256 reservesCount;
        address oracle;
        uint8 fromEModeCategory;
    }

    struct FlashloanParams {
        address receiverAddress;
        address[] assets;
        uint256[] amounts;
        uint256[] interestRateModes;
        address onBehalfOf;
        bytes params;
        uint16 referralCode;
        uint256 flashLoanPremiumToProtocol;
        uint256 flashLoanPremiumTotal;
        uint256 maxStableRateBorrowSizePercent;
        uint256 reservesCount;
        address addressesProvider;
        uint8 userEModeCategory;
        bool isAuthorizedFlashBorrower;
    }

    struct FlashloanSimpleParams {
        address receiverAddress;
        address asset;
        uint256 amount;
        bytes params;
        uint16 referralCode;
        uint256 flashLoanPremiumToProtocol;
        uint256 flashLoanPremiumTotal;
    }

    struct FlashLoanRepaymentParams {
        uint256 amount;
        uint256 totalPremium;
        uint256 flashLoanPremiumToProtocol;
        address asset;
        address receiverAddress;
        uint16 referralCode;
    }

    struct CalculateUserAccountDataParams {
        UserConfigurationMap userConfig;
        uint256 reservesCount;
        address user;
        address oracle;
        uint8 userEModeCategory;
    }

    struct ValidateBorrowParams {
        ReserveCache reserveCache;
        UserConfigurationMap userConfig;
        address asset;
        address userAddress;
        uint256 amount;
        InterestRateMode interestRateMode;
        uint256 maxStableLoanPercent;
        uint256 reservesCount;
        address oracle;
        uint8 userEModeCategory;
        address priceOracleSentinel;
        bool isolationModeActive;
        address isolationModeCollateralAddress;
        uint256 isolationModeDebtCeiling;
    }

    struct ValidateLiquidationCallParams {
        ReserveCache debtReserveCache;
        uint256 totalDebt;
        uint256 healthFactor;
        address priceOracleSentinel;
    }

    struct CalculateInterestRatesParams {
        uint256 unbacked;
        uint256 liquidityAdded;
        uint256 liquidityTaken;
        uint256 totalStableDebt;
        uint256 totalVariableDebt;
        uint256 averageStableBorrowRate;
        uint256 reserveFactor;
        address reserve;
        address aToken;
    }

    struct InitReserveParams {
        address asset;
        address aTokenAddress;
        address stableDebtAddress;
        address variableDebtAddress;
        address interestRateStrategyAddress;
        uint16 reservesCount;
        uint16 maxNumberReserves;
    }
}

// File: IERC20.sol

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// File: IPoolAddressesProvider.sol

/**
 * @title IPoolAddressesProvider
 * @author Aave
 * @notice Defines the basic interface for a Pool Addresses Provider.
 **/
interface IPoolAddressesProvider {
    function owner() external view returns (address);

    /**
     * @dev Emitted when the market identifier is updated.
     * @param oldMarketId The old id of the market
     * @param newMarketId The new id of the market
     */
    event MarketIdSet(string indexed oldMarketId, string indexed newMarketId);

    /**
     * @dev Emitted when the pool is updated.
     * @param oldAddress The old address of the Pool
     * @param newAddress The new address of the Pool
     */
    event PoolUpdated(address indexed oldAddress, address indexed newAddress);

    /**
     * @dev Emitted when the pool configurator is updated.
     * @param oldAddress The old address of the PoolConfigurator
     * @param newAddress The new address of the PoolConfigurator
     */
    event PoolConfiguratorUpdated(
        address indexed oldAddress,
        address indexed newAddress
    );

    /**
     * @dev Emitted when the price oracle is updated.
     * @param oldAddress The old address of the PriceOracle
     * @param newAddress The new address of the PriceOracle
     */
    event PriceOracleUpdated(
        address indexed oldAddress,
        address indexed newAddress
    );

    /**
     * @dev Emitted when the ACL manager is updated.
     * @param oldAddress The old address of the ACLManager
     * @param newAddress The new address of the ACLManager
     */
    event ACLManagerUpdated(
        address indexed oldAddress,
        address indexed newAddress
    );

    /**
     * @dev Emitted when the ACL admin is updated.
     * @param oldAddress The old address of the ACLAdmin
     * @param newAddress The new address of the ACLAdmin
     */
    event ACLAdminUpdated(
        address indexed oldAddress,
        address indexed newAddress
    );

    /**
     * @dev Emitted when the price oracle sentinel is updated.
     * @param oldAddress The old address of the PriceOracleSentinel
     * @param newAddress The new address of the PriceOracleSentinel
     */
    event PriceOracleSentinelUpdated(
        address indexed oldAddress,
        address indexed newAddress
    );

    /**
     * @dev Emitted when the pool data provider is updated.
     * @param oldAddress The old address of the PoolDataProvider
     * @param newAddress The new address of the PoolDataProvider
     */
    event PoolDataProviderUpdated(
        address indexed oldAddress,
        address indexed newAddress
    );

    /**
     * @dev Emitted when a new proxy is created.
     * @param id The identifier of the proxy
     * @param proxyAddress The address of the created proxy contract
     * @param implementationAddress The address of the implementation contract
     */
    event ProxyCreated(
        bytes32 indexed id,
        address indexed proxyAddress,
        address indexed implementationAddress
    );

    /**
     * @dev Emitted when a new non-proxied contract address is registered.
     * @param id The identifier of the contract
     * @param oldAddress The address of the old contract
     * @param newAddress The address of the new contract
     */
    event AddressSet(
        bytes32 indexed id,
        address indexed oldAddress,
        address indexed newAddress
    );

    /**
     * @dev Emitted when the implementation of the proxy registered with id is updated
     * @param id The identifier of the contract
     * @param proxyAddress The address of the proxy contract
     * @param oldImplementationAddress The address of the old implementation contract
     * @param newImplementationAddress The address of the new implementation contract
     */
    event AddressSetAsProxy(
        bytes32 indexed id,
        address indexed proxyAddress,
        address oldImplementationAddress,
        address indexed newImplementationAddress
    );

    /**
     * @notice Returns the id of the Aave market to which this contract points to.
     * @return The market id
     **/
    function getMarketId() external view returns (string memory);

    /**
     * @notice Associates an id with a specific PoolAddressesProvider.
     * @dev This can be used to create an onchain registry of PoolAddressesProviders to
     * identify and validate multiple Aave markets.
     * @param newMarketId The market id
     */
    function setMarketId(string calldata newMarketId) external;

    /**
     * @notice Returns an address by its identifier.
     * @dev The returned address might be an EOA or a contract, potentially proxied
     * @dev It returns ZERO if there is no registered address with the given id
     * @param id The id
     * @return The address of the registered for the specified id
     */
    function getAddress(bytes32 id) external view returns (address);

    /**
     * @notice General function to update the implementation of a proxy registered with
     * certain `id`. If there is no proxy registered, it will instantiate one and
     * set as implementation the `newImplementationAddress`.
     * @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit
     * setter function, in order to avoid unexpected consequences
     * @param id The id
     * @param newImplementationAddress The address of the new implementation
     */
    function setAddressAsProxy(bytes32 id, address newImplementationAddress)
        external;

    /**
     * @notice Sets an address for an id replacing the address saved in the addresses map.
     * @dev IMPORTANT Use this function carefully, as it will do a hard replacement
     * @param id The id
     * @param newAddress The address to set
     */
    function setAddress(bytes32 id, address newAddress) external;

    /**
     * @notice Returns the address of the Pool proxy.
     * @return The Pool proxy address
     **/
    function getPool() external view returns (address);

    function getLendingPool() external view returns (address);

    /**
     * @notice Updates the implementation of the Pool, or creates a proxy
     * setting the new `pool` implementation when the function is called for the first time.
     * @param newPoolImpl The new Pool implementation
     **/
    function setPoolImpl(address newPoolImpl) external;

    /**
     * @notice Returns the address of the PoolConfigurator proxy.
     * @return The PoolConfigurator proxy address
     **/
    function getPoolConfigurator() external view returns (address);

    /**
     * @notice Updates the implementation of the PoolConfigurator, or creates a proxy
     * setting the new `PoolConfigurator` implementation when the function is called for the first time.
     * @param newPoolConfiguratorImpl The new PoolConfigurator implementation
     **/
    function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external;

    /**
     * @notice Returns the address of the price oracle.
     * @return The address of the PriceOracle
     */
    function getPriceOracle() external view returns (address);

    /**
     * @notice Updates the address of the price oracle.
     * @param newPriceOracle The address of the new PriceOracle
     */
    function setPriceOracle(address newPriceOracle) external;

    /**
     * @notice Returns the address of the ACL manager.
     * @return The address of the ACLManager
     */
    function getACLManager() external view returns (address);

    /**
     * @notice Updates the address of the ACL manager.
     * @param newAclManager The address of the new ACLManager
     **/
    function setACLManager(address newAclManager) external;

    /**
     * @notice Returns the address of the ACL admin.
     * @return The address of the ACL admin
     */
    function getACLAdmin() external view returns (address);

    /**
     * @notice Updates the address of the ACL admin.
     * @param newAclAdmin The address of the new ACL admin
     */
    function setACLAdmin(address newAclAdmin) external;

    /**
     * @notice Returns the address of the price oracle sentinel.
     * @return The address of the PriceOracleSentinel
     */
    function getPriceOracleSentinel() external view returns (address);

    /**
     * @notice Updates the address of the price oracle sentinel.
     * @param newPriceOracleSentinel The address of the new PriceOracleSentinel
     **/
    function setPriceOracleSentinel(address newPriceOracleSentinel) external;

    /**
     * @notice Returns the address of the data provider.
     * @return The address of the DataProvider
     */
    function getPoolDataProvider() external view returns (address);

    /**
     * @notice Updates the address of the data provider.
     * @param newDataProvider The address of the new DataProvider
     **/
    function setPoolDataProvider(address newDataProvider) external;
}

// File: IPriceOracleGetter.sol

/**
 * @title IPriceOracleGetter
 * @author Aave
 * @notice Interface for the Aave price oracle.
 **/
interface IPriceOracleGetter {
    /**
     * @notice Returns the base currency address
     * @dev Address 0x0 is reserved for USD as base currency.
     * @return Returns the base currency address.
     **/
    function BASE_CURRENCY() external view returns (address);

    /**
     * @notice Returns the base currency unit
     * @dev 1 ether for ETH, 1e8 for USD.
     * @return Returns the base currency unit.
     **/
    function BASE_CURRENCY_UNIT() external view returns (uint256);

    /**
     * @notice Returns the asset price in the base currency
     * @param asset The address of the asset
     * @return The price of the asset
     **/
    function getAssetPrice(address asset) external view returns (uint256);
}

// File: IScaledBalanceToken.sol

/**
 * @title IScaledBalanceToken
 * @author Aave
 * @notice Defines the basic interface for a scaledbalance token.
 **/
interface IScaledBalanceToken {
    /**
     * @dev Emitted after the mint action
     * @param caller The address performing the mint
     * @param onBehalfOf The address of the user that will receive the minted scaled balance tokens
     * @param value The amount being minted (user entered amount + balance increase from interest)
     * @param balanceIncrease The increase in balance since the last action of the user
     * @param index The next liquidity index of the reserve
     **/
    event Mint(
        address indexed caller,
        address indexed onBehalfOf,
        uint256 value,
        uint256 balanceIncrease,
        uint256 index
    );

    /**
     * @dev Emitted after scaled balance tokens are burned
     * @param from The address from which the scaled tokens will be burned
     * @param target The address that will receive the underlying, if any
     * @param value The amount being burned (user entered amount - balance increase from interest)
     * @param balanceIncrease The increase in balance since the last action of the user
     * @param index The next liquidity index of the reserve
     **/
    event Burn(
        address indexed from,
        address indexed target,
        uint256 value,
        uint256 balanceIncrease,
        uint256 index
    );

    /**
     * @notice Returns the scaled balance of the user.
     * @dev The scaled balance is the sum of all the updated stored balance divided by the reserve's liquidity index
     * at the moment of the update
     * @param user The user whose balance is calculated
     * @return The scaled balance of the user
     **/
    function scaledBalanceOf(address user) external view returns (uint256);

    /**
     * @notice Returns the scaled balance of the user and the scaled total supply.
     * @param user The address of the user
     * @return The scaled balance of the user
     * @return The scaled total supply
     **/
    function getScaledUserBalanceAndSupply(address user)
        external
        view
        returns (uint256, uint256);

    /**
     * @notice Returns the scaled total supply of the scaled balance token. Represents sum(debt/index)
     * @return The scaled total supply
     **/
    function scaledTotalSupply() external view returns (uint256);

    /**
     * @notice Returns last index interest was accrued to the user's balance
     * @param user The address of the user
     * @return The last index interest was accrued to the user's balance, expressed in ray
     **/
    function getPreviousIndex(address user) external view returns (uint256);
}

// File: Math.sol

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

// File: SafeMath.sol

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

// File: farm.sol

struct UserInfo {
    uint256 amount; // How many LP tokens the user has provided.
    uint256 rewardDebt; // Reward debt.
}

interface IFarmMasterChef {
    function deposit(uint256 _pid, uint256 _amount) external;

    function withdraw(uint256 _pid, uint256 _amount) external;

    function harvestFromMasterChef() external;

    function userInfo(uint256 _pid, address user)
        external
        view
        returns (UserInfo calldata);
}

// File: uniswap.sol

// Feel free to change the license, but this is what we use

// Feel free to change this version of Solidity. We support >=0.6.0 <0.7.0;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);

    function WETH() external pure returns (address);

    /// added in to support with JOE integrations
    function WAVAX() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    )
        external
        returns (
            uint256 amountA,
            uint256 amountB,
            uint256 liquidity
        );

    function addLiquidityETH(
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
        external
        payable
        returns (
            uint256 amountToken,
            uint256 amountETH,
            uint256 liquidity
        );

    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETH(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountToken, uint256 amountETH);

    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETHWithPermit(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountToken, uint256 amountETH);

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

    function swapTokensForExactTokens(
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function swapTokensForExactETH(
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

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

    function swapETHForExactTokens(
        uint256 amountOut,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function quote(
        uint256 amountA,
        uint256 reserveA,
        uint256 reserveB
    ) external pure returns (uint256 amountB);

    function getAmountOut(
        uint256 amountIn,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountOut);

    function getAmountIn(
        uint256 amountOut,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountIn);

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

    function getAmountsIn(uint256 amountOut, address[] calldata path)
        external
        view
        returns (uint256[] memory amounts);
}

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountETH);

    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;

    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable;

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;
}

interface IUniswapV2Pair {
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
    event Transfer(address indexed from, address indexed to, uint256 value);

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

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

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address owner) external view returns (uint256);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

    function nonces(address owner) external view returns (uint256);

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    event Mint(address indexed sender, uint256 amount0, uint256 amount1);
    event Burn(
        address indexed sender,
        uint256 amount0,
        uint256 amount1,
        address indexed to
    );
    event Swap(
        address indexed sender,
        uint256 amount0In,
        uint256 amount1In,
        uint256 amount0Out,
        uint256 amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function factory() external view returns (address);

    function token0() external view returns (address);

    function token1() external view returns (address);

    function getReserves()
        external
        view
        returns (
            uint112 reserve0,
            uint112 reserve1,
            uint32 blockTimestampLast
        );

    function price0CumulativeLast() external view returns (uint256);

    function price1CumulativeLast() external view returns (uint256);

    function kLast() external view returns (uint256);

    function mint(address to) external returns (uint256 liquidity);

    function burn(address to)
        external
        returns (uint256 amount0, uint256 amount1);

    function swap(
        uint256 amount0Out,
        uint256 amount1Out,
        address to,
        bytes calldata data
    ) external;

    function skim(address to) external;

    function sync() external;

    function initialize(address, address) external;
}

// File: vector.sol

// Feel free to change the license, but this is what we use

// Feel free to change this version of Solidity. We support >=0.6.0 <0.7.0;

interface IVectorChef {
    function deposit(uint256 amount) external;

    function withdraw(uint256 amount) external;

    function balanceOf(address _address) external view returns (uint256);

    function getReward() external;
}

interface IBaseRewardPool {
    function earned(address _account, address _token)
        external
        view
        returns (uint256);
}

// File: IAToken.sol

/**
 * @title IAToken
 * @author Aave
 * @notice Defines the basic interface for an AToken.
 **/
interface IAToken is IERC20, IScaledBalanceToken {
    /**
     * @dev Emitted during the transfer action
     * @param from The user whose tokens are being transferred
     * @param to The recipient
     * @param value The amount being transferred
     * @param index The next liquidity index of the reserve
     **/
    event BalanceTransfer(
        address indexed from,
        address indexed to,
        uint256 value,
        uint256 index
    );

    /**
     * @notice Mints `amount` aTokens to `user`
     * @param caller The address performing the mint
     * @param onBehalfOf The address of the user that will receive the minted aTokens
     * @param amount The amount of tokens getting minted
     * @param index The next liquidity index of the reserve
     * @return `true` if the the previous balance of the user was 0
     */
    function mint(
        address caller,
        address onBehalfOf,
        uint256 amount,
        uint256 index
    ) external returns (bool);

    /**
     * @notice Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying`
     * @dev In some instances, the mint event could be emitted from a burn transaction
     * if the amount to burn is less than the interest that the user accrued
     * @param from The address from which the aTokens will be burned
     * @param receiverOfUnderlying The address that will receive the underlying
     * @param amount The amount being burned
     * @param index The next liquidity index of the reserve
     **/
    function burn(
        address from,
        address receiverOfUnderlying,
        uint256 amount,
        uint256 index
    ) external;

    /**
     * @notice Mints aTokens to the reserve treasury
     * @param amount The amount of tokens getting minted
     * @param index The next liquidity index of the reserve
     */
    function mintToTreasury(uint256 amount, uint256 index) external;

    /**
     * @notice Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken
     * @param from The address getting liquidated, current owner of the aTokens
     * @param to The recipient
     * @param value The amount of tokens getting transferred
     **/
    function transferOnLiquidation(
        address from,
        address to,
        uint256 value
    ) external;

    /**
     * @notice Transfers the underlying asset to `target`.
     * @dev Used by the Pool to transfer assets in borrow(), withdraw() and flashLoan()
     * @param user The recipient of the underlying
     * @param amount The amount getting transferred
     **/
    function transferUnderlyingTo(address user, uint256 amount) external;

    /**
     * @notice Handles the underlying received by the aToken after the transfer has been completed.
     * @dev The default implementation is empty as with standard ERC20 tokens, nothing needs to be done after the
     * transfer is concluded. However in the future there may be aTokens that allow for example to stake the underlying
     * to receive LM rewards. In that case, `handleRepayment()` would perform the staking of the underlying asset.
     * @param user The user executing the repayment
     * @param amount The amount getting repaid
     **/
    function handleRepayment(address user, uint256 amount) external;

    /**
     * @notice Allow passing a signed message to approve spending
     * @dev implements the permit function as for
     * https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
     * @param owner The owner of the funds
     * @param spender The spender
     * @param value The amount
     * @param deadline The deadline timestamp, type(uint256).max for max deadline
     * @param v Signature param
     * @param s Signature param
     * @param r Signature param
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH)
     * @return The address of the underlying asset
     **/
    function UNDERLYING_ASSET_ADDRESS() external view returns (address);

    /**
     * @notice Returns the address of the Aave treasury, receiving the fees on this aToken.
     * @return Address of the Aave treasury
     **/
    function RESERVE_TREASURY_ADDRESS() external view returns (address);

    /**
     * @notice Get the domain separator for the token
     * @dev Return cached value if chainId matches cache, otherwise recomputes separator
     * @return The domain separator of the token at current chain
     */
    function DOMAIN_SEPARATOR() external view returns (bytes32);

    /**
     * @notice Returns the nonce for owner.
     * @param owner The address of the owner
     * @return The nonce of the owner
     **/
    function nonces(address owner) external view returns (uint256);

    /**
     * @notice Rescue and transfer tokens locked in this contract
     * @param token The address of the token
     * @param to The address of the recipient
     * @param amount The amount of token to transfer
     */
    function rescueTokens(
        address token,
        address to,
        uint256 amount
    ) external;
}

// File: IAaveOracle.sol

// https://github.com/aave/aave-v3-core/blob/master/contracts/interfaces/IAaveOracle.sol
/**
 * @title IAaveOracle
 * @author Aave
 * @notice Defines the basic interface for the Aave Oracle
 */
interface IAaveOracle is IPriceOracleGetter {
    /**
     * @dev Emitted after the base currency is set
     * @param baseCurrency The base currency of used for price quotes
     * @param baseCurrencyUnit The unit of the base currency
     */
    event BaseCurrencySet(
        address indexed baseCurrency,
        uint256 baseCurrencyUnit
    );

    /**
     * @dev Emitted after the price source of an asset is updated
     * @param asset The address of the asset
     * @param source The price source of the asset
     */
    event AssetSourceUpdated(address indexed asset, address indexed source);

    /**
     * @dev Emitted after the address of fallback oracle is updated
     * @param fallbackOracle The address of the fallback oracle
     */
    event FallbackOracleUpdated(address indexed fallbackOracle);

    /**
     * @notice Returns the PoolAddressesProvider
     * @return The address of the PoolAddressesProvider contract
     */
    function ADDRESSES_PROVIDER()
        external
        view
        returns (IPoolAddressesProvider);

    /**
     * @notice Sets or replaces price sources of assets
     * @param assets The addresses of the assets
     * @param sources The addresses of the price sources
     */
    function setAssetSources(
        address[] calldata assets,
        address[] calldata sources
    ) external;

    /**
     * @notice Sets the fallback oracle
     * @param fallbackOracle The address of the fallback oracle
     */
    function setFallbackOracle(address fallbackOracle) external;

    /**
     * @notice Returns a list of prices from a list of assets addresses
     * @param assets The list of assets addresses
     * @return The prices of the given assets
     */
    function getAssetsPrices(address[] calldata assets)
        external
        view
        returns (uint256[] memory);

    /**
     * @notice Returns the address of the source for an asset address
     * @param asset The address of the asset
     * @return The address of the source
     */
    function getSourceOfAsset(address asset) external view returns (address);

    /**
     * @notice Returns the address of the fallback oracle
     * @return The address of the fallback oracle
     */
    function getFallbackOracle() external view returns (address);
}

// File: IPool.sol

/**
 * @title IPool
 * @author Aave
 * @notice Defines the basic interface for an Aave Pool.
 **/
interface IPool {
    /**
     * @dev Emitted on mintUnbacked()
     * @param reserve The address of the underlying asset of the reserve
     * @param user The address initiating the supply
     * @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens
     * @param amount The amount of supplied assets
     * @param referralCode The referral code used
     **/
    event MintUnbacked(
        address indexed reserve,
        address user,
        address indexed onBehalfOf,
        uint256 amount,
        uint16 indexed referralCode
    );

    /**
     * @dev Emitted on backUnbacked()
     * @param reserve The address of the underlying asset of the reserve
     * @param backer The address paying for the backing
     * @param amount The amount added as backing
     * @param fee The amount paid in fees
     **/
    event BackUnbacked(
        address indexed reserve,
        address indexed backer,
        uint256 amount,
        uint256 fee
    );

    /**
     * @dev Emitted on supply()
     * @param reserve The address of the underlying asset of the reserve
     * @param user The address initiating the supply
     * @param onBehalfOf The beneficiary of the supply, receiving the aTokens
     * @param amount The amount supplied
     * @param referralCode The referral code used
     **/
    event Supply(
        address indexed reserve,
        address user,
        address indexed onBehalfOf,
        uint256 amount,
        uint16 indexed referralCode
    );

    /**
     * @dev Emitted on withdraw()
     * @param reserve The address of the underlying asset being withdrawn
     * @param user The address initiating the withdrawal, owner of aTokens
     * @param to The address that will receive the underlying
     * @param amount The amount to be withdrawn
     **/
    event Withdraw(
        address indexed reserve,
        address indexed user,
        address indexed to,
        uint256 amount
    );

    /**
     * @dev Emitted on borrow() and flashLoan() when debt needs to be opened
     * @param reserve The address of the underlying asset being borrowed
     * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
     * initiator of the transaction on flashLoan()
     * @param onBehalfOf The address that will be getting the debt
     * @param amount The amount borrowed out
     * @param interestRateMode The rate mode: 1 for Stable, 2 for Variable
     * @param borrowRate The numeric rate at which the user has borrowed, expressed in ray
     * @param referralCode The referral code used
     **/
    event Borrow(
        address indexed reserve,
        address user,
        address indexed onBehalfOf,
        uint256 amount,
        DataTypes.InterestRateMode interestRateMode,
        uint256 borrowRate,
        uint16 indexed referralCode
    );

    /**
     * @dev Emitted on repay()
     * @param reserve The address of the underlying asset of the reserve
     * @param user The beneficiary of the repayment, getting his debt reduced
     * @param repayer The address of the user initiating the repay(), providing the funds
     * @param amount The amount repaid
     * @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly
     **/
    event Repay(
        address indexed reserve,
        address indexed user,
        address indexed repayer,
        uint256 amount,
        bool useATokens
    );

    /**
     * @dev Emitted on swapBorrowRateMode()
     * @param reserve The address of the underlying asset of the reserve
     * @param user The address of the user swapping his rate mode
     * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable
     **/
    event SwapBorrowRateMode(
        address indexed reserve,
        address indexed user,
        DataTypes.InterestRateMode interestRateMode
    );

    /**
     * @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets
     * @param asset The address of the underlying asset of the reserve
     * @param totalDebt The total isolation mode debt for the reserve
     */
    event IsolationModeTotalDebtUpdated(
        address indexed asset,
        uint256 totalDebt
    );

    /**
     * @dev Emitted when the user selects a certain asset category for eMode
     * @param user The address of the user
     * @param categoryId The category id
     **/
    event UserEModeSet(address indexed user, uint8 categoryId);

    /**
     * @dev Emitted on setUserUseReserveAsCollateral()
     * @param reserve The address of the underlying asset of the reserve
     * @param user The address of the user enabling the usage as collateral
     **/
    event ReserveUsedAsCollateralEnabled(
        address indexed reserve,
        address indexed user
    );

    /**
     * @dev Emitted on setUserUseReserveAsCollateral()
     * @param reserve The address of the underlying asset of the reserve
     * @param user The address of the user enabling the usage as collateral
     **/
    event ReserveUsedAsCollateralDisabled(
        address indexed reserve,
        address indexed user
    );

    /**
     * @dev Emitted on rebalanceStableBorrowRate()
     * @param reserve The address of the underlying asset of the reserve
     * @param user The address of the user for which the rebalance has been executed
     **/
    event RebalanceStableBorrowRate(
        address indexed reserve,
        address indexed user
    );

    /**
     * @dev Emitted on flashLoan()
     * @param target The address of the flash loan receiver contract
     * @param initiator The address initiating the flash loan
     * @param asset The address of the asset being flash borrowed
     * @param amount The amount flash borrowed
     * @param interestRateMode The flashloan mode: 0 for regular flashloan, 1 for Stable debt, 2 for Variable debt
     * @param premium The fee flash borrowed
     * @param referralCode The referral code used
     **/
    event FlashLoan(
        address indexed target,
        address initiator,
        address indexed asset,
        uint256 amount,
        DataTypes.InterestRateMode interestRateMode,
        uint256 premium,
        uint16 indexed referralCode
    );

    /**
     * @dev Emitted when a borrower is liquidated.
     * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
     * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
     * @param user The address of the borrower getting liquidated
     * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
     * @param liquidatedCollateralAmount The amount of collateral received by the liquidator
     * @param liquidator The address of the liquidator
     * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants
     * to receive the underlying collateral asset directly
     **/
    event LiquidationCall(
        address indexed collateralAsset,
        address indexed debtAsset,
        address indexed user,
        uint256 debtToCover,
        uint256 liquidatedCollateralAmount,
        address liquidator,
        bool receiveAToken
    );

    /**
     * @dev Emitted when the state of a reserve is updated.
     * @param reserve The address of the underlying asset of the reserve
     * @param liquidityRate The next liquidity rate
     * @param stableBorrowRate The next stable borrow rate
     * @param variableBorrowRate The next variable borrow rate
     * @param liquidityIndex The next liquidity index
     * @param variableBorrowIndex The next variable borrow index
     **/
    event ReserveDataUpdated(
        address indexed reserve,
        uint256 liquidityRate,
        uint256 stableBorrowRate,
        uint256 variableBorrowRate,
        uint256 liquidityIndex,
        uint256 variableBorrowIndex
    );

    /**
     * @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest.
     * @param reserve The address of the reserve
     * @param amountMinted The amount minted to the treasury
     **/
    event MintedToTreasury(address indexed reserve, uint256 amountMinted);

    /**
     * @dev Mints an `amount` of aTokens to the `onBehalfOf`
     * @param asset The address of the underlying asset to mint
     * @param amount The amount to mint
     * @param onBehalfOf The address that will receive the aTokens
     * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
     *   0 if the action is executed directly by the user, without any middle-man
     **/
    function mintUnbacked(
        address asset,
        uint256 amount,
        address onBehalfOf,
        uint16 referralCode
    ) external;

    /**
     * @dev Back the current unbacked underlying with `amount` and pay `fee`.
     * @param asset The address of the underlying asset to back
     * @param amount The amount to back
     * @param fee The amount paid in fees
     **/
    function backUnbacked(
        address asset,
        uint256 amount,
        uint256 fee
    ) external;

    /**
     * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
     * - E.g. User supplies 100 USDC and gets in return 100 aUSDC
     * @param asset The address of the underlying asset to supply
     * @param amount The amount to be supplied
     * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
     *   wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
     *   is a different wallet
     * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
     *   0 if the action is executed directly by the user, without any middle-man
     **/
    function supply(
        address asset,
        uint256 amount,
        address onBehalfOf,
        uint16 referralCode
    ) external;

    /**
     * @notice Supply with transfer approval of asset to be supplied done via permit function
     * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
     * @param asset The address of the underlying asset to supply
     * @param amount The amount to be supplied
     * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
     *   wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
     *   is a different wallet
     * @param deadline The deadline timestamp that the permit is valid
     * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
     *   0 if the action is executed directly by the user, without any middle-man
     * @param permitV The V parameter of ERC712 permit sig
     * @param permitR The R parameter of ERC712 permit sig
     * @param permitS The S parameter of ERC712 permit sig
     **/
    function supplyWithPermit(
        address asset,
        uint256 amount,
        address onBehalfOf,
        uint16 referralCode,
        uint256 deadline,
        uint8 permitV,
        bytes32 permitR,
        bytes32 permitS
    ) external;

    /**
     * @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
     * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
     * @param asset The address of the underlying asset to withdraw
     * @param amount The underlying amount to be withdrawn
     *   - Send the value type(uint256).max in order to withdraw the whole aToken balance
     * @param to The address that will receive the underlying, same as msg.sender if the user
     *   wants to receive it on his own wallet, or a different address if the beneficiary is a
     *   different wallet
     * @return The final amount withdrawn
     **/
    function withdraw(
        address asset,
        uint256 amount,
        address to
    ) external returns (uint256);

    /**
     * @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
     * already supplied enough collateral, or he was given enough allowance by a credit delegator on the
     * corresponding debt token (StableDebtToken or VariableDebtToken)
     * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
     *   and 100 stable/variable debt tokens, depending on the `interestRateMode`
     * @param asset The address of the underlying asset to borrow
     * @param amount The amount to be borrowed
     * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
     * @param referralCode The code used to register the integrator originating the operation, for potential rewards.
     *   0 if the action is executed directly by the user, without any middle-man
     * @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself
     * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
     * if he has been given credit delegation allowance
     **/
    function borrow(
        address asset,
        uint256 amount,
        uint256 interestRateMode,
        uint16 referralCode,
        address onBehalfOf
    ) external;

    /**
     * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
     * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
     * @param asset The address of the borrowed underlying asset previously borrowed
     * @param amount The amount to repay
     * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
     * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
     * @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the
     * user calling the function if he wants to reduce/remove his own debt, or the address of any other
     * other borrower whose debt should be removed
     * @return The final amount repaid
     **/
    function repay(
        address asset,
        uint256 amount,
        uint256 interestRateMode,
        address onBehalfOf
    ) external returns (uint256);

    /**
     * @notice Repay with transfer approval of asset to be repaid done via permit function
     * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
     * @param asset The address of the borrowed underlying asset previously borrowed
     * @param amount The amount to repay
     * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
     * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
     * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
     * user calling the function if he wants to reduce/remove his own debt, or the address of any other
     * other borrower whose debt should be removed
     * @param deadline The deadline timestamp that the permit is valid
     * @param permitV The V parameter of ERC712 permit sig
     * @param permitR The R parameter of ERC712 permit sig
     * @param permitS The S parameter of ERC712 permit sig
     * @return The final amount repaid
     **/
    function repayWithPermit(
        address asset,
        uint256 amount,
        uint256 interestRateMode,
        address onBehalfOf,
        uint256 deadline,
        uint8 permitV,
        bytes32 permitR,
        bytes32 permitS
    ) external returns (uint256);

    /**
     * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the
     * equivalent debt tokens
     * - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable/stable debt tokens
     * @dev  Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken
     * balance is not enough to cover the whole debt
     * @param asset The address of the borrowed underlying asset previously borrowed
     * @param amount The amount to repay
     * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
     * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
     * @return The final amount repaid
     **/
    function repayWithATokens(
        address asset,
        uint256 amount,
        uint256 interestRateMode
    ) external returns (uint256);

    /**
     * @notice Allows a borrower to swap his debt between stable and variable mode, or vice versa
     * @param asset The address of the underlying asset borrowed
     * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable
     **/
    function swapBorrowRateMode(address asset, uint256 interestRateMode)
        external;

    /**
     * @notice Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.
     * - Users can be rebalanced if the following conditions are satisfied:
     *     1. Usage ratio is above 95%
     *     2. the current supply APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too
     *        much has been borrowed at a stable rate and suppliers are not earning enough
     * @param asset The address of the underlying asset borrowed
     * @param user The address of the user to be rebalanced
     **/
    function rebalanceStableBorrowRate(address asset, address user) external;

    /**
     * @notice Allows suppliers to enable/disable a specific supplied asset as collateral
     * @param asset The address of the underlying asset supplied
     * @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise
     **/
    function setUserUseReserveAsCollateral(address asset, bool useAsCollateral)
        external;

    /**
     * @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
     * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
     *   a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
     * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
     * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
     * @param user The address of the borrower getting liquidated
     * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
     * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants
     * to receive the underlying collateral asset directly
     **/
    function liquidationCall(
        address collateralAsset,
        address debtAsset,
        address user,
        uint256 debtToCover,
        bool receiveAToken
    ) external;

    /**
     * @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
     * as long as the amount taken plus a fee is returned.
     * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept
     * into consideration. For further details please visit https://developers.aave.com
     * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface
     * @param assets The addresses of the assets being flash-borrowed
     * @param amounts The amounts of the assets being flash-borrowed
     * @param interestRateModes Types of the debt to open if the flash loan is not returned:
     *   0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
     *   1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
     *   2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
     * @param onBehalfOf The address  that will receive the debt in the case of using on `modes` 1 or 2
     * @param params Variadic packed params to pass to the receiver as extra information
     * @param referralCode The code used to register the integrator originating the operation, for potential rewards.
     *   0 if the action is executed directly by the user, without any middle-man
     **/
    function flashLoan(
        address receiverAddress,
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata interestRateModes,
        address onBehalfOf,
        bytes calldata params,
        uint16 referralCode
    ) external;

    /**
     * @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
     * as long as the amount taken plus a fee is returned.
     * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept
     * into consideration. For further details please visit https://developers.aave.com
     * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver interface
     * @param asset The address of the asset being flash-borrowed
     * @param amount The amount of the asset being flash-borrowed
     * @param params Variadic packed params to pass to the receiver as extra information
     * @param referralCode The code used to register the integrator originating the operation, for potential rewards.
     *   0 if the action is executed directly by the user, without any middle-man
     **/
    function flashLoanSimple(
        address receiverAddress,
        address asset,
        uint256 amount,
        bytes calldata params,
        uint16 referralCode
    ) external;

    /**
     * @notice Returns the user account data across all the reserves
     * @param user The address of the user
     * @return totalCollateralBase The total collateral of the user in the base currency used by the price feed
     * @return totalDebtBase The total debt of the user in the base currency used by the price feed
     * @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed
     * @return currentLiquidationThreshold The liquidation threshold of the user
     * @return ltv The loan to value of The user
     * @return healthFactor The current health factor of the user
     **/
    function getUserAccountData(address user)
        external
        view
        returns (
            uint256 totalCollateralBase,
            uint256 totalDebtBase,
            uint256 availableBorrowsBase,
            uint256 currentLiquidationThreshold,
            uint256 ltv,
            uint256 healthFactor
        );

    /**
     * @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an
     * interest rate strategy
     * @dev Only callable by the PoolConfigurator contract
     * @param asset The address of the underlying asset of the reserve
     * @param aTokenAddress The address of the aToken that will be assigned to the reserve
     * @param stableDebtAddress The address of the StableDebtToken that will be assigned to the reserve
     * @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve
     * @param interestRateStrategyAddress The address of the interest rate strategy contract
     **/
    function initReserve(
        address asset,
        address aTokenAddress,
        address stableDebtAddress,
        address variableDebtAddress,
        address interestRateStrategyAddress
    ) external;

    /**
     * @notice Drop a reserve
     * @dev Only callable by the PoolConfigurator contract
     * @param asset The address of the underlying asset of the reserve
     **/
    function dropReserve(address asset) external;

    /**
     * @notice Updates the address of the interest rate strategy contract
     * @dev Only callable by the PoolConfigurator contract
     * @param asset The address of the underlying asset of the reserve
     * @param rateStrategyAddress The address of the interest rate strategy contract
     **/
    function setReserveInterestRateStrategyAddress(
        address asset,
        address rateStrategyAddress
    ) external;

    /**
     * @notice Sets the configuration bitmap of the reserve as a whole
     * @dev Only callable by the PoolConfigurator contract
     * @param asset The address of the underlying asset of the reserve
     * @param configuration The new configuration bitmap
     **/
    function setConfiguration(
        address asset,
        DataTypes.ReserveConfigurationMap calldata configuration
    ) external;

    /**
     * @notice Returns the configuration of the reserve
     * @param asset The address of the underlying asset of the reserve
     * @return The configuration of the reserve
     **/
    function getConfiguration(address asset)
        external
        view
        returns (DataTypes.ReserveConfigurationMap memory);

    /**
     * @notice Returns the configuration of the user across all the reserves
     * @param user The user address
     * @return The configuration of the user
     **/
    function getUserConfiguration(address user)
        external
        view
        returns (DataTypes.UserConfigurationMap memory);

    /**
     * @notice Returns the normalized income normalized income of the reserve
     * @param asset The address of the underlying asset of the reserve
     * @return The reserve's normalized income
     */
    function getReserveNormalizedIncome(address asset)
        external
        view
        returns (uint256);

    /**
     * @notice Returns the normalized variable debt per unit of asset
     * @param asset The address of the underlying asset of the reserve
     * @return The reserve normalized variable debt
     */
    function getReserveNormalizedVariableDebt(address asset)
        external
        view
        returns (uint256);

    /**
     * @notice Returns the state and configuration of the reserve
     * @param asset The address of the underlying asset of the reserve
     * @return The state and configuration data of the reserve
     **/
    function getReserveData(address asset)
        external
        view
        returns (DataTypes.ReserveData memory);

    /**
     * @notice Validates and finalizes an aToken transfer
     * @dev Only callable by the overlying aToken of the `asset`
     * @param asset The address of the underlying asset of the aToken
     * @param from The user from which the aTokens are transferred
     * @param to The user receiving the aTokens
     * @param amount The amount being transferred/withdrawn
     * @param balanceFromBefore The aToken balance of the `from` user before the transfer
     * @param balanceToBefore The aToken balance of the `to` user before the transfer
     */
    function finalizeTransfer(
        address asset,
        address from,
        address to,
        uint256 amount,
        uint256 balanceFromBefore,
        uint256 balanceToBefore
    ) external;

    /**
     * @notice Returns the list of the underlying assets of all the initialized reserves
     * @dev It does not include dropped reserves
     * @return The addresses of the underlying assets of the initialized reserves
     **/
    function getReservesList() external view returns (address[] memory);

    /**
     * @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct
     * @param id The id of the reserve as stored in the DataTypes.ReserveData struct
     * @return The address of the reserve associated with id
     **/
    function getReserveAddressById(uint16 id) external view returns (address);

    /**
     * @notice Returns the PoolAddressesProvider connected to this contract
     * @return The address of the PoolAddressesProvider
     **/
    function ADDRESSES_PROVIDER()
        external
        view
        returns (IPoolAddressesProvider);

    /**
     * @notice Updates the protocol fee on the bridging
     * @param bridgeProtocolFee The part of the premium sent to the protocol treasury
     */
    function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external;

    /**
     * @notice Updates flash loan premiums. Flash loan premium consists of two parts:
     * - A part is sent to aToken holders as extra, one time accumulated interest
     * - A part is collected by the protocol treasury
     * @dev The total premium is calculated on the total borrowed amount
     * @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal`
     * @dev Only callable by the PoolConfigurator contract
     * @param flashLoanPremiumTotal The total premium, expressed in bps
     * @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps
     */
    function updateFlashloanPremiums(
        uint128 flashLoanPremiumTotal,
        uint128 flashLoanPremiumToProtocol
    ) external;

    /**
     * @notice Configures a new category for the eMode.
     * @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category.
     * The category 0 is reserved as it's the default for volatile assets
     * @param id The id of the category
     * @param config The configuration of the category
     */
    function configureEModeCategory(
        uint8 id,
        DataTypes.EModeCategory memory config
    ) external;

    /**
     * @notice Returns the data of an eMode category
     * @param id The id of the category
     * @return The configuration data of the category
     */
    function getEModeCategoryData(uint8 id)
        external
        view
        returns (DataTypes.EModeCategory memory);

    /**
     * @notice Allows a user to use the protocol in eMode
     * @param categoryId The id of the category
     */
    function setUserEMode(uint8 categoryId) external;

    /**
     * @notice Returns the eMode the user is using
     * @param user The address of the user
     * @return The eMode id
     */
    function getUserEMode(address user) external view returns (uint256);

    /**
     * @notice Resets the isolation mode total debt of the given asset to zero
     * @dev It requires the given asset has zero debt ceiling
     * @param asset The address of the underlying asset to reset the isolationModeTotalDebt
     */
    function resetIsolationModeTotalDebt(address asset) external;

    /**
     * @notice Returns the percentage of available liquidity that can be borrowed at once at stable rate
     * @return The percentage of available liquidity to borrow, expressed in bps
     */
    function MAX_STABLE_RATE_BORROW_SIZE_PERCENT()
        external
        view
        returns (uint256);

    /**
     * @notice Returns the total fee on flash loans
     * @return The total fee on flashloans
     */
    function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128);

    /**
     * @notice Returns the part of the bridge fees sent to protocol
     * @return The bridge fee sent to the protocol treasury
     */
    function BRIDGE_PROTOCOL_FEE() external view returns (uint256);

    /**
     * @notice Returns the part of the flashloan fees sent to protocol
     * @return The flashloan fee sent to the protocol treasury
     */
    function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128);

    /**
     * @notice Returns the maximum number of reserves supported to be listed in this Pool
     * @return The maximum number of reserves supported
     */
    function MAX_NUMBER_RESERVES() external view returns (uint16);

    /**
     * @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens
     * @param assets The list of reserves for which the minting needs to be executed
     **/
    function mintToTreasury(address[] calldata assets) external;

    /**
     * @notice Rescue and transfer tokens locked in this contract
     * @param token The address of the token
     * @param to The address of the recipient
     * @param amount The amount of token to transfer
     */
    function rescueTokens(
        address token,
        address to,
        uint256 amount
    ) external;

    /**
     * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
     * - E.g. User supplies 100 USDC and gets in return 100 aUSDC
     * @dev Deprecated: Use the `supply` function instead
     * @param asset The address of the underlying asset to supply
     * @param amount The amount to be supplied
     * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
     *   wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
     *   is a different wallet
     * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
     *   0 if the action is executed directly by the user, without any middle-man
     **/
    function deposit(
        address asset,
        uint256 amount,
        address onBehalfOf,
        uint16 referralCode
    ) external;
}

// File: IVariableDebtToken.sol

/**
 * @title IVariableDebtToken
 * @author Aave
 * @notice Defines the basic interface for a variable debt token.
 **/
interface IVariableDebtToken is IScaledBalanceToken, IERC20 {
    /**
     * @notice Mints debt token to the `onBehalfOf` address
     * @param user The address receiving the borrowed underlying, being the delegatee in case
     * of credit delegate, or same as `onBehalfOf` otherwise
     * @param onBehalfOf The address receiving the debt tokens
     * @param amount The amount of debt being minted
     * @param index The variable debt index of the reserve
     * @return True if the previous balance of the user is 0, false otherwise
     * @return The scaled total debt of the reserve
     **/
    function mint(
        address user,
        address onBehalfOf,
        uint256 amount,
        uint256 index
    ) external returns (bool, uint256);

    /**
     * @notice Burns user variable debt
     * @dev In some instances, a burn transaction will emit a mint event
     * if the amount to burn is less than the interest that the user accrued
     * @param from The address from which the debt will be burned
     * @param amount The amount getting burned
     * @param index The variable debt index of the reserve
     * @return The scaled total debt of the reserve
     **/
    function burn(
        address from,
        uint256 amount,
        uint256 index
    ) external returns (uint256);

    /**
     * @notice Returns the address of the underlying asset of this debtToken (E.g. WETH for variableDebtWETH)
     * @return The address of the underlying asset
     **/
    function UNDERLYING_ASSET_ADDRESS() external view returns (address);
}

// File: SafeERC20.sol

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

// File: BaseStrategy.sol

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

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

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

    function decimals() external view returns (uint256);

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

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

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

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

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

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

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

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

    function token() external view returns (address);

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

    function pricePerShare() external view returns (uint256);

    function totalAssets() external view returns (uint256);

    function depositLimit() external view returns (uint256);

    function maxAvailableShares() external view returns (uint256);

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

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

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

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

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

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

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

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

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

    function vault() external view returns (address);

    function want() external view returns (address);

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

    function keeper() external view returns (address);

    function isActive() external view returns (bool);

    function delegatedAssets() external view returns (uint256);

    function estimatedTotalAssets() external view returns (uint256);

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

    function tend() external;

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

    function harvest() external;

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

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

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

abstract contract BaseStrategy {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    string public metadataURI;

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

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

    /**
     * @notice This Strategy's name.
     * @dev
     *  You can use this field to manage the "version" of this Strategy, e.g.
     *  `StrategySomethingOrOtherV1`. However, "API Version" is managed by
     *  `apiVersion()` function above.
     * @return This Strategy's name.
     */
    function name() external view virtual returns (string memory);

    /**
     * @notice
     *  The amount (priced in want) of the total assets managed by this strategy should not count
     *  towards Yearn's TVL calculations.
     * @dev
     *  You can override this field to set it to a non-zero value if some of the assets of this
     *  Strategy is somehow delegated inside another part of of Yearn's ecosystem e.g. another Vault.
     *  Note that this value must be strictly less than or equal to the amount provided by
     *  `estimatedTotalAssets()` below, as the TVL calc will be total assets minus delegated assets.
     *  Also note that this value is used to determine the total assets under management by this
     *  strategy, for the purposes of computing the management fee in `Vault`
     * @return
     *  The amount of assets this strategy manages that should not be included in Yearn's Total Value
     *  Locked (TVL) calculation across it's ecosystem.
     */
    function delegatedAssets() external view virtual returns (uint256) {
        return 0;
    }

    VaultAPI public vault;
    address public strategist;
    address public rewards;
    address public keeper;

    IERC20 public want;

    // So indexers can keep track of this
    event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding);

    event UpdatedStrategist(address newStrategist);

    event UpdatedKeeper(address newKeeper);

    event UpdatedRewards(address rewards);

    event UpdatedMinReportDelay(uint256 delay);

    event UpdatedMaxReportDelay(uint256 delay);

    event UpdatedProfitFactor(uint256 profitFactor);

    event UpdatedDebtThreshold(uint256 debtThreshold);

    event EmergencyExitEnabled();

    event UpdatedMetadataURI(string metadataURI);

    event SetHealthCheck(address);
    event SetDoHealthCheck(bool);

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

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

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

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

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

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

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

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

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

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

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

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

    /**
     * @notice
     *  Initializes the Strategy, this is called only once, when the
     *  contract is deployed.
     * @dev `_vault` should implement `VaultAPI`.
     * @param _vault The address of the Vault responsible for this Strategy.
     * @param _strategist The address to assign as `strategist`.
     * The strategist is able to change the reward address
     * @param _rewards  The address to use for pulling rewards.
     * @param _keeper The adddress of the _keeper. _keeper
     * can harvest and tend a strategy.
     */
    function _initialize(
        address _vault,
        address _strategist,
        address _rewards,
        address _keeper
    ) internal {
        require(address(want) == address(0), "Strategy already initialized");

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /**
     * @notice
     *  Provide an accurate conversion from `_amtInWei` (denominated in wei)
     *  to `want` (using the native decimal characteristics of `want`).
     * @dev
     *  Care must be taken when working with decimals to assure that the conversion
     *  is compatible. As an example:
     *
     *      given 1e17 wei (0.1 ETH) as input, and want is USDC (6 decimals),
     *      with USDC/ETH = 1800, this should give back 1800000000 (180 USDC)
     *
     * @param _amtInWei The amount (in wei/1e-18 ETH) to convert to `want`
     * @return The amount in `want` of `_amtInEth` converted to `want`
     **/
    function ethToWant(uint256 _amtInWei) public view virtual returns (uint256);

    /**
     * @notice
     *  Provide an accurate estimate for the total amount of assets
     *  (principle + return) that this Strategy is currently managing,
     *  denominated in terms of `want` tokens.
     *
     *  This total should be "realizable" e.g. the total value that could
     *  *actually* be obtained from this Strategy if it were to divest its
     *  entire position based on current on-chain conditions.
     * @dev
     *  Care must be taken in using this function, since it relies on external
     *  systems, which could be manipulated by the attacker to give an inflated
     *  (or reduced) value produced by this function, based on current on-chain
     *  conditions (e.g. this function is possible to influence through
     *  flashloan attacks, oracle manipulations, or other DeFi attack
     *  mechanisms).
     *
     *  It is up to governance to use this function to correctly order this
     *  Strategy relative to its peers in the withdrawal queue to minimize
     *  losses for the Vault based on sudden withdrawals. This value should be
     *  higher than the total debt of the Strategy and higher than its expected
     *  value to be "safe".
     * @return The estimated total assets in this Strategy.
     */
    function estimatedTotalAssets() public view virtual returns (uint256);

    /*
     * @notice
     *  Provide an indication of whether this strategy is currently "active"
     *  in that it is managing an active position, or will manage a position in
     *  the future. This should correlate to `harvest()` activity, so that Harvest
     *  events can be tracked externally by indexing agents.
     * @return True if the strategy is actively managing a position.
     */
    function isActive() public view returns (bool) {
        return vault.strategies(address(this)).debtRatio > 0 || estimatedTotalAssets() > 0;
    }

    /**
     * Perform any Strategy unwinding or other calls necessary to capture the
     * "free return" this Strategy has generated since the last time its core
     * position(s) were adjusted. Examples include unwrapping extra rewards.
     * This call is only used during "normal operation" of a Strategy, and
     * should be optimized to minimize losses as much as possible.
     *
     * This method returns any realized profits and/or realized losses
     * incurred, and should return the total amounts of profits/losses/debt
     * payments (in `want` tokens) for the Vault's accounting (e.g.
     * `want.balanceOf(this) >= _debtPayment + _profit`).
     *
     * `_debtOutstanding` will be 0 if the Strategy is not past the configured
     * debt limit, otherwise its value will be how far past the debt limit
     * the Strategy is. The Strategy's debt limit is configured in the Vault.
     *
     * NOTE: `_debtPayment` should be less than or equal to `_debtOutstanding`.
     *       It is okay for it to be less than `_debtOutstanding`, as that
     *       should only used as a guide for how much is left to pay back.
     *       Payments should be made to minimize loss from slippage, debt,
     *       withdrawal fees, etc.
     *
     * See `vault.debtOutstanding()`.
     */
    function prepareReturn(uint256 _debtOutstanding)
        internal
        virtual
        returns (
            uint256 _profit,
            uint256 _loss,
            uint256 _debtPayment
        );

    /**
     * Perform any adjustments to the core position(s) of this Strategy given
     * what change the Vault made in the "investable capital" available to the
     * Strategy. Note that all "free capital" in the Strategy after the report
     * was made is available for reinvestment. Also note that this number
     * could be 0, and you should handle that scenario accordingly.
     *
     * See comments regarding `_debtOutstanding` on `prepareReturn()`.
     */
    function adjustPosition(uint256 _debtOutstanding) internal virtual;

    /**
     * Liquidate up to `_amountNeeded` of `want` of this strategy's positions,
     * irregardless of slippage. Any excess will be re-invested with `adjustPosition()`.
     * This function should return the amount of `want` tokens made available by the
     * liquidation. If there is a difference between them, `_loss` indicates whether the
     * difference is due to a realized loss, or if there is some other sitution at play
     * (e.g. locked funds) where the amount made available is less than what is needed.
     *
     * NOTE: The invariant `_liquidatedAmount + _loss <= _amountNeeded` should always be maintained
     */
    function liquidatePosition(uint256 _amountNeeded) internal virtual returns (uint256 _liquidatedAmount, uint256 _loss);

    /**
     * Liquidate everything and returns the amount that got freed.
     * This function is used during emergency exit instead of `prepareReturn()` to
     * liquidate all of the Strategy's positions back to the Vault.
     */

    function liquidateAllPositions() internal virtual returns (uint256 _amountFreed);

    /**
     * @notice
     *  Provide a signal to the keeper that `tend()` should be called. The
     *  keeper will provide the estimated gas cost that they would pay to call
     *  `tend()`, and this function should use that estimate to make a
     *  determination if calling it is "worth it" for the keeper. This is not
     *  the only consideration into issuing this trigger, for example if the
     *  position would be negatively affected if `tend()` is not called
     *  shortly, then this can return `true` even if the keeper might be
     *  "at a loss" (keepers are always reimbursed by Yearn).
     * @dev
     *  `callCostInWei` must be priced in terms of `wei` (1e-18 ETH).
     *
     *  This call and `harvestTrigger()` should never return `true` at the same
     *  time.
     * @param callCostInWei The keeper's estimated gas cost to call `tend()` (in wei).
     * @return `true` if `tend()` should be called, `false` otherwise.
     */
    function tendTrigger(uint256 callCostInWei) public view virtual returns (bool) {
        // We usually don't need tend, but if there are positions that need
        // active maintainence, overriding this function is how you would
        // signal for that.
        // If your implementation uses the cost of the call in want, you can
        // use uint256 callCost = ethToWant(callCostInWei);

        return false;
    }

    /**
     * @notice
     *  Adjust the Strategy's position. The purpose of tending isn't to
     *  realize gains, but to maximize yield by reinvesting any returns.
     *
     *  See comments on `adjustPosition()`.
     *
     *  This may only be called by governance, the strategist, or the keeper.
     */
    function tend() external onlyKeepers {
        // Don't take profits with this call, but adjust for better gains
        adjustPosition(vault.debtOutstanding());
    }

    /**
     * @notice
     *  Provide a signal to the keeper that `harvest()` should be called. The
     *  keeper will provide the estimated gas cost that they would pay to call
     *  `harvest()`, and this function should use that estimate to make a
     *  determination if calling it is "worth it" for the keeper. This is not
     *  the only consideration into issuing this trigger, for example if the
     *  position would be negatively affected if `harvest()` is not called
     *  shortly, then this can return `true` even if the keeper might be "at a
     *  loss" (keepers are always reimbursed by Yearn).
     * @dev
     *  `callCostInWei` must be priced in terms of `wei` (1e-18 ETH).
     *
     *  This call and `tendTrigger` should never return `true` at the
     *  same time.
     *
     *  See `min/maxReportDelay`, `profitFactor`, `debtThreshold` to adjust the
     *  strategist-controlled parameters that will influence whether this call
     *  returns `true` or not. These parameters will be used in conjunction
     *  with the parameters reported to the Vault (see `params`) to determine
     *  if calling `harvest()` is merited.
     *
     *  It is expected that an external system will check `harvestTrigger()`.
     *  This could be a script run off a desktop or cloud bot (e.g.
     *  https://github.com/iearn-finance/yearn-vaults/blob/main/scripts/keep.py),
     *  or via an integration with the Keep3r network (e.g.
     *  https://github.com/Macarse/GenericKeep3rV2/blob/master/contracts/keep3r/GenericKeep3rV2.sol).
     * @param callCostInWei The keeper's estimated gas cost to call `harvest()` (in wei).
     * @return `true` if `harvest()` should be called, `false` otherwise.
     */
    function harvestTrigger(uint256 callCostInWei) public view virtual returns (bool) {
        uint256 callCost = ethToWant(callCostInWei);
        StrategyParams memory params = vault.strategies(address(this));

        // Should not trigger if Strategy is not activated
        if (params.activation == 0) return false;

        // Should not trigger if we haven't waited long enough since previous harvest
        if (block.timestamp.sub(params.lastReport) < minReportDelay) return false;

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

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

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

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

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

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

        // Allow Vault to take up to the "harvested" balance of this contract,
        // which is the amount it has earned since the last time it reported to
        // the Vault.
        uint256 totalDebt = vault.strategies(address(this)).totalDebt;
        debtOutstanding = vault.report(profit, loss, debtPayment);

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

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

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

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

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

    /**
     * @notice
     *  Transfers all `want` from this Strategy to `_newStrategy`.
     *
     *  This may only be called by the Vault.
     * @dev
     * The new Strategy's Vault must be the same as this Strategy's Vault.
     *  The migration process should be carefully performed to make sure all
     * the assets are migrated to the new address, which should have never
     * interacted with the vault before.
     * @param _newStrategy The Strategy to migrate to.
     */
    function migrate(address _newStrategy) external {
        require(msg.sender == address(vault));
        require(BaseStrategy(_newStrategy).vault() == vault);
        prepareMigration(_newStrategy);
        want.safeTransfer(_newStrategy, want.balanceOf(address(this)));
    }

    /**
     * @notice
     *  Activates emergency exit. Once activated, the Strategy will exit its
     *  position upon the next harvest, depositing all funds into the Vault as
     *  quickly as is reasonable given on-chain conditions.
     *
     *  This may only be called by governance or the strategist.
     * @dev
     *  See `vault.setEmergencyShutdown()` and `harvest()` for further details.
     */
    function setEmergencyExit() external onlyEmergencyAuthorized {
        emergencyExit = true;
        vault.revokeStrategy();

        emit EmergencyExitEnabled();
    }

    /**
     * Override this to add all tokens/tokenized positions this contract
     * manages on a *persistent* basis (e.g. not just for swapping back to
     * want ephemerally).
     *
     * NOTE: Do *not* include `want`, already included in `sweep` below.
     *
     * Example:
     * ```
     *    function protectedTokens() internal override view returns (address[] memory) {
     *      address[] memory protected = new address[](3);
     *      protected[0] = tokenA;
     *      protected[1] = tokenB;
     *      protected[2] = tokenC;
     *      return protected;
     *    }
     * ```
     */
    function protectedTokens() internal view virtual returns (address[] memory);

    /**
     * @notice
     *  Removes tokens from this Strategy that are not the type of tokens
     *  managed by this Strategy. This may be used in case of accidentally
     *  sending the wrong kind of token to this Strategy.
     *
     *  Tokens will be sent to `governance()`.
     *
     *  This will fail if an attempt is made to sweep `want`, or any tokens
     *  that are protected by this Strategy.
     *
     *  This may only be called by governance.
     * @dev
     *  Implement `protectedTokens()` to specify any additional tokens that
     *  should be protected from sweeping in addition to `want`.
     * @param _token The token to transfer out of this vault.
     */
    function sweep(address _token) external onlyGovernance {
        require(_token != address(want), "!want");
        require(_token != address(vault), "!shares");

        address[] memory _protectedTokens = protectedTokens();
        for (uint256 i; i < _protectedTokens.length; i++) require(_token != _protectedTokens[i], "!protected");

        IERC20(_token).safeTransfer(governance(), IERC20(_token).balanceOf(address(this)));
    }
}

abstract contract BaseStrategyInitializable is BaseStrategy {
    bool public isOriginal = true;
    event Cloned(address indexed clone);

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

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

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

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

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

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

        emit Cloned(newStrategy);
    }
}

// File: StrategyInsurance.sol

// Feel free to change the license, but this is what we use


interface StrategyAPIExt is StrategyAPI {
    function strategist() external view returns (address);

    function insurance() external view returns (address);
}

interface IStrategyInsurance {
    function reportProfit(uint256 _totalDebt, uint256 _profit)
        external
        returns (uint256 _wantNeeded);

    function reportLoss(uint256 _totalDebt, uint256 _loss)
        external
        returns (uint256 _compensation);

    function migrateInsurance(address newInsurance) external;
}

/**
 * @title Strategy Generic Insurrance
 * @author Robovault
 * @notice
 *  StrategyInsurance provides an issurrance fund for strategy losses
 *  A portion of all profits are sent to the insurrance fund untill
 *  it reaches its target insurrance percentage. When a loss is realised
 *  by the strategy the inssurance fund will return the funds to the
 *  strategy to fully compensate or soften the loss.
 */
contract StrategyInsurance {
    using SafeERC20 for IERC20;
    using Address for address;
    using SafeMath for uint256;

    StrategyAPIExt public strategy;
    IERC20 want;
    uint256 constant BPS_MAX = 10000;
    uint256 public lossSum = 0;

    event InsurancePayment(
        uint256 indexed strategyDebt,
        uint256 indexed harvestProfit,
        uint256 indexed wantPayment
    );
    event InsurancePayout(uint256 indexed wantPayout);

    // Bips - Proportion of totalDebt the inssurance fund is targeting to grow
    uint256 public targetFundSize = 50; // 0.5% default

    // Rate of the profits that go to insurrance while it's below target
    uint256 public profitTakeRate = 1000; // 10% default

    // The maximum compensation rate the insurrance fund will return funds to the strategy
    // proportional to the TotalDebt of the strategy
    uint256 public maximumCompenstionRate = 5; // 5 bips per harvest default

    function _onlyAuthorized() internal {
        require(
            msg.sender == strategy.strategist() || msg.sender == governance()
        );
    }

    function _onlyGovernance() internal {
        require(msg.sender == governance());
    }

    function _onlyStrategy() internal {
        require(msg.sender == address(strategy));
    }

    constructor(address _strategy) public {
        strategy = StrategyAPIExt(_strategy);
        want = IERC20(strategy.want());
    }

    function setTargetFundSize(uint256 _targetFundSize) external {
        _onlyAuthorized();
        require(_targetFundSize < 500); // Must be less than 5%
        targetFundSize = _targetFundSize;
    }

    function setProfitTakeRate(uint256 _profitTakeRate) external {
        _onlyAuthorized();
        require(_profitTakeRate < 4000); // Must be less than 40%
        profitTakeRate = _profitTakeRate;
    }

    function setmaximumCompenstionRate(uint256 _maximumCompenstionRate)
        external
    {
        _onlyAuthorized();
        require(_maximumCompenstionRate < 50); // Must be less than 0.5%
        maximumCompenstionRate = _maximumCompenstionRate;
    }

    /**
     * @notice
     *  Strategy reports profits to the insurrance find and informs the strategy
     *  of how much want is requested for insurrance.
     * @param _totalDebt Debt the strategy has with the vault.
     * @param _profit The profit the strategy is reporting this harvest
     * @return want amount requested for insurrance
     */
    function reportProfit(uint256 _totalDebt, uint256 _profit)
        external
        returns (uint256)
    {
        _onlyStrategy();

        // if there has been a loss that is yet to be paid fully compensated, continue
        // to compensate
        if (lossSum > _profit) {
            lossSum = lossSum.sub(_profit);
            compensate(_totalDebt);
            return 0;
        }

        // no pending losses to pay out
        lossSum = 0;

        // Have the insurrance hit the insurrance target
        uint256 balance = want.balanceOf(address(this));
        uint256 targetBalance = _totalDebt.mul(targetFundSize).div(BPS_MAX);
        if (balance >= targetBalance) {
            return 0;
        }

        uint256 payment = _profit.mul(profitTakeRate).div(BPS_MAX);
        emit InsurancePayment(_totalDebt, _profit, payment);
        return payment;
    }

    /**
     * @notice
     *  Strategy reports loss. The insurrance fund will decide weather or not to
     *  send want back to the strategy to soften the loss
     * @param _totalDebt Debt the strategy has with the vault.
     * @param _loss The loss realised by the this harvest
     * @return _compensation amount sent back to the strategy.
     */
    function reportLoss(uint256 _totalDebt, uint256 _loss)
        external
        returns (uint256 _compensation)
    {
        _onlyStrategy();

        lossSum = lossSum.add(_loss);
        _compensation = compensate(_totalDebt);
    }

    /**
     * @notice
     *  Processes insurance payouot
     * @param _totalDebt Debt the strategy has with the vault.
     * @return _compensation amount sent back to the strategy.
     */
    function compensate(uint256 _totalDebt)
        internal
        returns (uint256 _compensation)
    {
        uint256 balance = want.balanceOf(address(this));

        // Reserves are empties, we cannot compensate
        if (balance == 0) {
            lossSum = 0;
            return 0;
        }

        // Calculat what the payout will be
        uint256 maxComp = maximumCompenstionRate.mul(_totalDebt).div(BPS_MAX);
        _compensation = Math.min(Math.min(balance, lossSum), maxComp);

        if (_compensation > 0) {
            SafeERC20.safeTransfer(want, address(strategy), _compensation);
            emit InsurancePayout(_compensation);
        }
    }

    function governance() public view returns (address) {
        return VaultAPI(strategy.vault()).governance();
    }

    /**
     * @notice
     *  Sends balance to gov for the purpose of migrating to a new strategy at the
     *  disgression of governance.
     */
    function withdraw() external {
        _onlyGovernance();
        SafeERC20.safeTransfer(
            want,
            governance(),
            want.balanceOf(address(this))
        );
    }

    /**
     * @notice
     *  Sets the lossSum. Adds some flexibility with payouts to cover edge-case
     *  scenarios
     */
    function setLossSum(uint256 newLossSum) external {
        _onlyGovernance();
        lossSum = newLossSum;
    }

    /**
     * @notice
     *  called by the strategy when updating the insurance contract
     */
    function migrateInsurance(address newInsurance) external {
        _onlyStrategy();
        SafeERC20.safeTransfer(
            want,
            newInsurance,
            want.balanceOf(address(this))
        );
    }

    /**
     * @notice
     * Called by goverannace when updating the strategy
     */
    function migrateStrategy(address newStrategy) external {
        _onlyGovernance();
        SafeERC20.safeTransfer(
            want,
            StrategyAPIExt(newStrategy).insurance(),
            want.balanceOf(address(this))
        );
    }
}

// File: CoreStrategyAave.sol

// Feel free to change the license, but this is what we use

// Feel free to change this version of Solidity. We support >=0.6.0 <0.7.0;

// These are the core Yearn libraries


struct CoreStrategyAaveConfig {
    // A portion of want token is depoisited into a lending platform to be used as
    // collateral. Short token is borrowed and compined with the remaining want token
    // and deposited into LP and farmed.
    address want;
    address short;
    /*****************************/
    /*             Farm           */
    /*****************************/
    // Liquidity pool address for base <-> short tokens
    address wantShortLP;
    // Address for farming reward token - eg Spirit/BOO
    address farmToken;
    // Liquidity pool address for farmToken <-> wFTM
    address farmTokenLP;
    // Farm address for reward farming
    address farmMasterChef;
    /*****************************/
    /*        Money Market       */
    /*****************************/
    // Base token cToken @ MM
    address aToken;
    address variableDebtToken;
    // Short token cToken @ MM
    address poolAddressesProvider;
    /*****************************/
    /*            AMM            */
    /*****************************/
    // Liquidity pool address for base <-> short tokens @ the AMM.
    // @note: the AMM router address does not need to be the same
    // AMM as the farm, in fact the most liquid AMM is prefered to
    // minimise slippage.
    address router;
    uint256 minDeploy;
}

interface IERC20Extended is IERC20 {
    function decimals() external view returns (uint8);
}

abstract contract CoreStrategyAave is BaseStrategy {
    using SafeERC20 for IERC20;
    using Address for address;
    using SafeMath for uint256;
    using SafeMath for uint8;

    event DebtRebalance(
        uint256 indexed debtRatio,
        uint256 indexed swapAmount,
        uint256 indexed slippage
    );
    event CollatRebalance(
        uint256 indexed collatRatio,
        uint256 indexed adjAmount
    );

    uint256 public collatUpper = 6700;
    uint256 public collatTarget = 6000;
    uint256 public collatLower = 5300;
    uint256 public debtUpper = 10190;
    uint256 public debtLower = 9810;
    uint256 public rebalancePercent = 10000; // 100% (how far does rebalance of debt move towards 100% from threshold)

    // protocal limits & upper, target and lower thresholds for ratio of debt to collateral
    uint256 public collatLimit = 7500;

    bool public doPriceCheck = true;

    // ERC20 Tokens;
    IERC20 public short;
    uint8 wantDecimals;
    uint8 shortDecimals;
    IUniswapV2Pair wantShortLP; // This is public because it helps with unit testing
    IERC20 farmTokenLP;
    IERC20 farmToken;
    // Contract Interfaces
    address farmMasterChef; //Since it is usually custom, will leave it as an address
    IUniswapV2Router01 router;
    IStrategyInsurance public insurance;
    IPool pool;
    IAToken aToken;
    IVariableDebtToken debtToken;
    IAaveOracle public oracle;

    uint256 public slippageAdj = 9900; // 99%

    uint256 constant BASIS_PRECISION = 10000;
    uint256 public priceSourceDiffKeeper = 500; // 5% Default
    uint256 public priceSourceDiffUser = 200; // 2% Default

    bool public isPaused = false;

    uint256 constant STD_PRECISION = 1e18;
    address weth;
    uint256 public minDeploy;

    constructor(address _vault, CoreStrategyAaveConfig memory _config)
        public
        BaseStrategy(_vault)
    {
        // initialise token interfaces
        short = IERC20(_config.short);
        wantShortLP = IUniswapV2Pair(_config.wantShortLP);
        farmTokenLP = IERC20(_config.farmTokenLP);
        farmToken = IERC20(_config.farmToken);
        wantDecimals = IERC20Extended(_config.want).decimals();
        shortDecimals = IERC20Extended(_config.short).decimals();

        // initialise other interfaces
        farmMasterChef = _config.farmMasterChef;
        router = IUniswapV2Router01(_config.router);

        IPoolAddressesProvider provider =
            IPoolAddressesProvider(_config.poolAddressesProvider);
        pool = IPool(provider.getPool());
        oracle = IAaveOracle(provider.getPriceOracle());

        aToken = IAToken(_config.aToken);
        debtToken = IVariableDebtToken(_config.variableDebtToken);

        maxReportDelay = 21600;
        minReportDelay = 14400;
        profitFactor = 1500;
        minDeploy = _config.minDeploy;
        _setup();
        approveContracts();
    }

    function _setup() internal virtual {}

    function name() external view override returns (string memory) {
        return "StrategyHedgedFarmingAaveV2.2";
    }

    function prepareReturn(uint256 _debtOutstanding)
        internal
        override
        returns (
            uint256 _profit,
            uint256 _loss,
            uint256 _debtPayment
        )
    {
        uint256 totalAssets = estimatedTotalAssets();
        uint256 totalDebt = _getTotalDebt();
        if (totalAssets > totalDebt) {
            _profit = totalAssets.sub(totalDebt);
            (uint256 amountFreed, ) = _withdraw(_debtOutstanding.add(_profit));
            if (_debtOutstanding > amountFreed) {
                _debtPayment = amountFreed;
                _profit = 0;
            } else {
                _debtPayment = _debtOutstanding;
                _profit = amountFreed.sub(_debtOutstanding);
            }
        } else {
            _withdraw(_debtOutstanding);
            _debtPayment = balanceOfWant();
            _loss = totalDebt.sub(totalAssets);
        }

        _profit += _harvestInternal();

        // Check if we're net loss or net profit
        if (_loss >= _profit) {
            _profit = 0;
            _loss = _loss.sub(_profit);
            insurance.reportLoss(totalDebt, _loss);
        } else {
            _profit = _profit.sub(_loss);
            _loss = 0;
            uint256 insurancePayment =
                insurance.reportProfit(totalDebt, _profit);
            _profit = _profit.sub(insurancePayment);

            // double check insurance isn't asking for too much or zero
            if (insurancePayment > 0 && insurancePayment < _profit) {
                SafeERC20.safeTransfer(
                    want,
                    address(insurance),
                    insurancePayment
                );
            }
        }
    }

    function adjustPosition(uint256 _debtOutstanding) internal override {
        uint256 _wantAvailable = balanceOfWant();
        if (_debtOutstanding >= _wantAvailable) {
            return;
        }
        uint256 toInvest = _wantAvailable.sub(_debtOutstanding);

        if (toInvest > 0) {
            _deploy(toInvest);
        }
    }

    function prepareMigration(address _newStrategy) internal override {
        liquidateAllPositionsInternal();
    }

    function ethToWant(uint256 _amtInWei)
        public
        view
        virtual
        override
        returns (uint256)
    {
        // This is not currently used by the strategies and is
        // being removed to reduce the size of the contract
        return 0;
    }

    function getTokenOutPath(address _token_in, address _token_out)
        internal
        view
        returns (address[] memory _path)
    {
        bool is_weth =
            _token_in == address(weth) || _token_out == address(weth);
        _path = new address[](is_weth ? 2 : 3);
        _path[0] = _token_in;
        if (is_weth) {
            _path[1] = _token_out;
        } else {
            _path[1] = address(weth);
            _path[2] = _token_out;
        }
    }

    function approveContracts() internal {
        want.safeApprove(address(pool), uint256(-1));
        short.safeApprove(address(pool), uint256(-1));
        want.safeApprove(address(router), uint256(-1));
        short.safeApprove(address(router), uint256(-1));
        farmToken.safeApprove(address(router), uint256(-1));
        IERC20(address(wantShortLP)).safeApprove(address(router), uint256(-1));
        IERC20(address(wantShortLP)).safeApprove(farmMasterChef, uint256(-1));
    }

    function setSlippageConfig(
        uint256 _slippageAdj,
        uint256 _priceSourceDiffUser,
        uint256 _priceSourceDiffKeeper,
        bool _doPriceCheck
    ) external onlyAuthorized {
        slippageAdj = _slippageAdj;
        priceSourceDiffKeeper = _priceSourceDiffKeeper;
        priceSourceDiffUser = _priceSourceDiffUser;
        doPriceCheck = _doPriceCheck;
    }

    function setInsurance(address _insurance) external onlyAuthorized {
        require(address(insurance) == address(0));
        insurance = IStrategyInsurance(_insurance);
    }

    function migrateInsurance(address _newInsurance) external onlyGovernance {
        require(address(_newInsurance) == address(0));
        insurance.migrateInsurance(_newInsurance);
        insurance = IStrategyInsurance(_newInsurance);
    }

    function setDebtThresholds(
        uint256 _lower,
        uint256 _upper,
        uint256 _rebalancePercent
    ) external onlyAuthorized {
        require(_lower <= BASIS_PRECISION);
        require(_rebalancePercent <= BASIS_PRECISION);
        require(_upper >= BASIS_PRECISION);
        rebalancePercent = _rebalancePercent;
        debtUpper = _upper;
        debtLower = _lower;
    }

    function setCollateralThresholds(
        uint256 _lower,
        uint256 _target,
        uint256 _upper,
        uint256 _limit
    ) external onlyAuthorized {
        require(_limit <= BASIS_PRECISION);
        collatLimit = _limit;
        require(collatLimit > _upper);
        require(_upper >= _target);
        require(_target >= _lower);
        collatUpper = _upper;
        collatTarget = _target;
        collatLower = _lower;
    }

    function pauseStrat() external onlyKeepers {
        require(!isPaused);
        liquidateAllPositionsInternal();
        _lendWant(balanceOfWant());
        isPaused = true;
    }

    function unpauseStrat() external onlyKeepers {
        require(isPaused);
        isPaused = false;
        _redeemWant(balanceLend());
        _deploy(balanceOfWant());
    }

    function liquidatePositionAuth(uint256 _amount) external onlyAuthorized {
        liquidatePosition(_amount);
    }

    function liquidateAllToLend() internal {
        _withdrawAllPooled();
        _removeAllLp();
        _lendWant(balanceOfWant());
    }

    function liquidateAllPositions()
        internal
        override
        returns (uint256 _amountFreed)
    {
        (_amountFreed, ) = liquidateAllPositionsInternal();
    }

    function liquidateAllPositionsInternal()
        internal
        returns (uint256 _amountFreed, uint256 _loss)
    {
        _withdrawAllPooled();
        _removeAllLp();

        uint256 debtInShort = balanceDebtInShortCurrent();
        uint256 balShort = balanceShort();
        if (balShort >= debtInShort) {
            _repayDebt();
            if (balanceShortWantEq() > 0) {
                (, _loss) = _swapExactShortWant(short.balanceOf(address(this)));
            }
        } else {
            uint256 debtDifference = debtInShort.sub(balShort);
            if (convertShortToWantLP(debtDifference) > 0) {
                (_loss) = _swapWantShortExact(debtDifference);
            } else {
                _swapExactWantShort(uint256(1));
            }
            _repayDebt();
        }

        _redeemWant(balanceLend());
        _amountFreed = balanceOfWant();
    }

    // rebalances RoboVault strat position to within target collateral range
    function rebalanceCollateral() external onlyKeepers {
        // ratio of amount borrowed to collateral
        require(!isPaused);
        uint256 collatRatio = calcCollateral();
        require(collatRatio <= collatLower || collatRatio >= collatUpper);
        _rebalanceCollateralInternal();
    }

    /// rebalances RoboVault holding of short token vs LP to within target collateral range
    function rebalanceDebt() external onlyKeepers {
        require(!isPaused);
        uint256 debtRatio = calcDebtRatio();
        require(debtRatio < debtLower || debtRatio > debtUpper);
        require(_testPriceSource(priceSourceDiffKeeper));
        _rebalanceDebtInternal();
    }

    function claimHarvest() internal virtual;

    /// called by keeper to harvest rewards and either repay debt
    function _harvestInternal() internal returns (uint256 _wantHarvested) {
        uint256 wantBefore = balanceOfWant();
        /// harvest from farm & wantd on amt borrowed vs LP value either -> repay some debt or add to collateral
        claimHarvest();
        _sellHarvestWant();
        _wantHarvested = balanceOfWant().sub(wantBefore);
    }

    /**
     * Checks if collateral cap is reached or if deploying `_amount` will make it reach the cap
     * returns true if the cap is reached
     */
    function collateralCapReached(uint256 _amount)
        public
        view
        virtual
        returns (bool)
    {
        // TODO check that _amount + AMOUNT_OF_TOKENS_LENT < AMOUNT_OF_TOKENS_TO_LEND_MAX
        // There is no limit to how much we can supply
        return false;
    }

    function _rebalanceCollateralInternal() internal {
        uint256 collatRatio = calcCollateral();
        uint256 shortPos = balanceDebt();
        uint256 lendPos = balanceLend();

        if (collatRatio > collatTarget) {
            uint256 adjAmount =
                (shortPos.sub(lendPos.mul(collatTarget).div(BASIS_PRECISION)))
                    .mul(BASIS_PRECISION)
                    .div(BASIS_PRECISION.add(collatTarget));
            /// remove some LP use 50% of withdrawn LP to repay debt and half to add to collateral
            _withdrawLpRebalanceCollateral(adjAmount.mul(2));
            emit CollatRebalance(collatRatio, adjAmount);
        } else if (collatRatio < collatTarget) {
            uint256 adjAmount =
                ((lendPos.mul(collatTarget).div(BASIS_PRECISION)).sub(shortPos))
                    .mul(BASIS_PRECISION)
                    .div(BASIS_PRECISION.add(collatTarget));
            uint256 borrowAmt = _borrowWantEq(adjAmount);
            _redeemWant(adjAmount);
            _addToLP(borrowAmt);
            _depositLp();
            emit CollatRebalance(collatRatio, adjAmount);
        }
    }

    // deploy assets according to vault strategy
    function _deploy(uint256 _amount) internal {
        if (isPaused) {
            _lendWant(balanceOfWant());
            return;
        }

        if (_amount < minDeploy || collateralCapReached(_amount)) {
            return;
        }
        uint256 oPrice = getOraclePrice();
        uint256 lpPrice = getLpPrice();
        uint256 borrow =
            collatTarget.mul(_amount).mul(1e18).div(
                BASIS_PRECISION.mul(
                    (collatTarget.mul(lpPrice).div(BASIS_PRECISION).add(oPrice))
                )
            );

        uint256 debtAllocation = borrow.mul(lpPrice).div(1e18);
        uint256 lendNeeded = _amount.sub(debtAllocation);
        _lendWant(lendNeeded);
        _borrow(borrow);
        _addToLP(borrow);
        _depositLp();
    }

    /**
     * @notice
     *  Returns pending rewards in the reward token. Does NOT convert to want.
     */
    function _pendingRewards() internal view virtual returns (uint256);

    function getLpPrice() public view returns (uint256) {
        (uint256 wantInLp, uint256 shortInLp) = getLpReserves();
        return wantInLp.mul(1e18).div(shortInLp);
    }

    function getOraclePrice() public view returns (uint256) {
        uint256 shortOPrice = oracle.getAssetPrice(address(short));
        uint256 wantOPrice = oracle.getAssetPrice(address(want));
        return
            shortOPrice.mul(10**(wantDecimals.add(18).sub(shortDecimals))).div(
                wantOPrice
            );
    }

    /**
     * @notice
     *  Reverts if the difference in the price sources are >  priceDiff
     */
    function _testPriceSource(uint256 priceDiff) internal returns (bool) {
        if (doPriceCheck) {
            uint256 oPrice = getOraclePrice();
            uint256 lpPrice = getLpPrice();
            uint256 priceSourceRatio = oPrice.mul(BASIS_PRECISION).div(lpPrice);
            return (priceSourceRatio > BASIS_PRECISION.sub(priceDiff) &&
                priceSourceRatio < BASIS_PRECISION.add(priceDiff));
        }
        return true;
    }

    /**
     * @notice
     *  Assumes all balance is in Lend outside of a small amount of debt and short. Deploys
     *  capital maintaining the collatRatioTarget
     *
     * @dev
     *  Some crafty maths here:
     *  B: borrow amount in short (Not total debt!)
     *  L: Lend in want
     *  Cr: Collateral Target
     *  Po: Oracle price (short * Po = want)
     *  Plp: LP Price
     *  Di: Initial Debt in short
     *  Si: Initial short balance
     *
     *  We want:
     *  Cr = BPo / L
     *  T = L + Plp(B + 2Si - Di)
     *
     *  Solving this for L finds:
     *  B = (TCr - Cr*Plp(2Si-Di)) / (Po + Cr*Plp)
     */
    function _calcDeployment(uint256 _amount)
        internal
        returns (uint256 _lendNeeded, uint256 _borrow)
    {
        uint256 oPrice = getOraclePrice();
        uint256 lpPrice = getLpPrice();
        uint256 Si2 = balanceShort().mul(2);
        uint256 Di = balanceDebtInShort();
        uint256 CrPlp = collatTarget.mul(lpPrice);
        uint256 numerator;

        // NOTE: may throw if _amount * CrPlp > 1e70
        if (Di > Si2) {
            numerator = (
                collatTarget.mul(_amount).mul(1e18).add(CrPlp.mul(Di.sub(Si2)))
            )
                .sub(oPrice.mul(BASIS_PRECISION).mul(Di));
        } else {
            numerator = (
                collatTarget.mul(_amount).mul(1e18).sub(CrPlp.mul(Si2.sub(Di)))
            )
                .sub(oPrice.mul(BASIS_PRECISION).mul(Di));
        }

        _borrow = numerator.div(
            BASIS_PRECISION.mul(oPrice.add(CrPlp.div(BASIS_PRECISION)))
        );
        _lendNeeded = _amount.sub(
            (_borrow.add(Si2).sub(Di)).mul(lpPrice).div(1e18)
        );
    }

    function _deployFromLend(uint256 _amount) internal {
        if (isPaused) {
            return;
        }

        (uint256 _lendNeeded, uint256 _borrowAmt) = _calcDeployment(_amount);
        _redeemWant(balanceLend().sub(_lendNeeded));
        _borrow(_borrowAmt);
        _addToLP(balanceShort());
        _depositLp();
    }

    function _rebalanceDebtInternal() internal {
        uint256 swapAmountWant;
        uint256 slippage;
        uint256 debtRatio = calcDebtRatio();

        // Liquidate all the lend, leaving some in debt or as short
        liquidateAllToLend();

        uint256 debtInShort = balanceDebtInShort();
        uint256 balShort = balanceShort();

        if (debtInShort > balShort) {
            uint256 debt = convertShortToWantLP(debtInShort.sub(balShort));
            // If there's excess debt, we swap some want to repay a portion of the debt
            swapAmountWant = debt.mul(rebalancePercent).div(BASIS_PRECISION);
            _redeemWant(swapAmountWant);
            slippage = _swapExactWantShort(swapAmountWant);
        } else {
            uint256 excessShort = balShort - debtInShort;
            // If there's excess short, we swap some to want which will be used
            // to create lp in _deployFromLend()
            (swapAmountWant, slippage) = _swapExactShortWant(
                excessShort.mul(rebalancePercent).div(BASIS_PRECISION)
            );
        }
        _repayDebt();
        _deployFromLend(estimatedTotalAssets());
        emit DebtRebalance(debtRatio, swapAmountWant, slippage);
    }

    /**
     * Withdraws and removes `_deployedPercent` percentage if LP from farming and pool respectively
     *
     * @param _deployedPercent percentage multiplied by BASIS_PRECISION of LP to remove.
     */
    function _removeLpPercent(uint256 _deployedPercent) internal {
        uint256 lpPooled = countLpPooled();
        uint256 lpUnpooled = wantShortLP.balanceOf(address(this));
        uint256 lpCount = lpUnpooled.add(lpPooled);
        uint256 lpReq = lpCount.mul(_deployedPercent).div(BASIS_PRECISION);
        uint256 lpWithdraw;
        if (lpReq - lpUnpooled < lpPooled) {
            lpWithdraw = lpReq.sub(lpUnpooled);
        } else {
            lpWithdraw = lpPooled;
        }

        // Finnally withdraw the LP from farms and remove from pool
        _withdrawSomeLp(lpWithdraw);
        _removeAllLp();
    }

    function _getTotalDebt() internal view returns (uint256) {
        return vault.strategies(address(this)).totalDebt;
    }

    function liquidatePosition(uint256 _amountNeeded)
        internal
        override
        returns (uint256 _liquidatedAmount, uint256 _loss)
    {
        uint256 balanceWant = balanceOfWant();
        uint256 totalAssets = estimatedTotalAssets();

        // if estimatedTotalAssets is less than params.debtRatio it means there's
        // been a loss (ignores pending harvests). This type of loss is calculated
        // proportionally
        // This stops a run-on-the-bank if there's IL between harvests.
        uint256 newAmount = _amountNeeded;
        uint256 totalDebt = _getTotalDebt();
        if (totalDebt > totalAssets) {
            uint256 ratio = totalAssets.mul(STD_PRECISION).div(totalDebt);
            newAmount = _amountNeeded.mul(ratio).div(STD_PRECISION);
            _loss = _amountNeeded.sub(newAmount);
        }

        // Liquidate the amount needed
        (, uint256 _slippage) = _withdraw(newAmount);
        _loss = _loss.add(_slippage);

        // NOTE: Maintain invariant `want.balanceOf(this) >= _liquidatedAmount`
        // NOTE: Maintain invariant `_liquidatedAmount + _loss <= _amountNeeded`
        _liquidatedAmount = balanceOfWant();
        if (_liquidatedAmount.add(_loss) > _amountNeeded) {
            _liquidatedAmount = _amountNeeded.sub(_loss);
        } else {
            _loss = _amountNeeded.sub(_liquidatedAmount);
        }
    }

    /**
     * function to remove funds from strategy when users withdraws funds in excess of reserves
     *
     * withdraw takes the following steps:
     * 1. Removes _amountNeeded worth of LP from the farms and pool
     * 2. Uses the short removed to repay debt (Swaps short or base for large withdrawals)
     * 3. Redeems the
     * @param _amountNeeded `want` amount to liquidate
     */
    function _withdraw(uint256 _amountNeeded)
        internal
        returns (uint256 _liquidatedAmount, uint256 _loss)
    {
        uint256 balanceWant = balanceOfWant();

        if (isPaused) {
            if (_amountNeeded > balanceWant) {
                _redeemWant(_amountNeeded.sub(balanceWant));
            }
            return (_amountNeeded, 0);
        }

        require(_testPriceSource(priceSourceDiffUser));
        if (_amountNeeded <= balanceWant) {
            return (_amountNeeded, 0);
        }

        uint256 balanceDeployed = balanceDeployed();

        // stratPercent: Percentage of the deployed capital we want to liquidate.
        uint256 stratPercent =
            _amountNeeded.sub(balanceWant).mul(BASIS_PRECISION).div(
                balanceDeployed
            );

        if (stratPercent > 9500) {
            // If this happened, we just undeploy the lot
            // and it'll be redeployed during the next harvest.
            (, _loss) = liquidateAllPositionsInternal();
            _liquidatedAmount = balanceOfWant().sub(balanceWant);
        } else {
            // liquidate all to lend
            liquidateAllToLend();
            // Only rebalance if more than 5% is being liquidated
            // to save on gas
            uint256 slippage = 0;
            if (stratPercent > 500) {
                // swap to ensure the debt ratio isn't negatively affected
                uint256 shortInShort = balanceShort();
                uint256 debtInShort = balanceDebtInShort();
                if (debtInShort > shortInShort) {
                    uint256 debt =
                        convertShortToWantLP(debtInShort.sub(shortInShort));
                    uint256 swapAmountWant =
                        debt.mul(stratPercent).div(BASIS_PRECISION);
                    _redeemWant(swapAmountWant);
                    slippage = _swapExactWantShort(swapAmountWant);
                } else {
                    (, slippage) = _swapExactShortWant(
                        (shortInShort.sub(debtInShort)).mul(stratPercent).div(
                            BASIS_PRECISION
                        )
                    );
                }
            }
            _repayDebt();

            // Redeploy the strat
            _deployFromLend(balanceDeployed.sub(_amountNeeded).add(slippage));
            _liquidatedAmount = balanceOfWant().sub(balanceWant);
            _loss = slippage;
        }
    }

    function enterMarket() internal {
        return;
    }

    // calculate total value of vault assets
    function estimatedTotalAssets() public view override returns (uint256) {
        return balanceOfWant().add(balanceDeployed());
    }

    // calculate total value of vault assets
    function balanceDeployed() public view returns (uint256) {
        return
            balanceLend().add(balanceLp()).add(balanceShortWantEq()).sub(
                balanceDebt()
            );
    }

    // debt ratio - used to trigger rebalancing of debt
    function calcDebtRatio() public view returns (uint256) {
        return (balanceDebt().mul(BASIS_PRECISION).mul(2).div(balanceLp()));
    }

    // calculate debt / collateral - used to trigger rebalancing of debt & collateral
    function calcCollateral() public view returns (uint256) {
        return balanceDebtOracle().mul(BASIS_PRECISION).div(balanceLend());
    }

    function getLpReserves()
        public
        view
        returns (uint256 _wantInLp, uint256 _shortInLp)
    {
        (uint112 reserves0, uint112 reserves1, ) = wantShortLP.getReserves();
        if (wantShortLP.token0() == address(want)) {
            _wantInLp = uint256(reserves0);
            _shortInLp = uint256(reserves1);
        } else {
            _wantInLp = uint256(reserves1);
            _shortInLp = uint256(reserves0);
        }
    }

    function convertShortToWantLP(uint256 _amountShort)
        internal
        view
        returns (uint256)
    {
        (uint256 wantInLp, uint256 shortInLp) = getLpReserves();
        return (_amountShort.mul(wantInLp).div(shortInLp));
    }

    function convertShortToWantOracle(uint256 _amountShort)
        internal
        view
        returns (uint256)
    {
        return _amountShort.mul(getOraclePrice()).div(1e18);
    }

    function convertWantToShortLP(uint256 _amountWant)
        internal
        view
        returns (uint256)
    {
        (uint256 wantInLp, uint256 shortInLp) = getLpReserves();
        return _amountWant.mul(shortInLp).div(wantInLp);
    }

    function balanceLpInShort() public view returns (uint256) {
        return countLpPooled().add(wantShortLP.balanceOf(address(this)));
    }

    /// get value of all LP in want currency
    function balanceLp() public view returns (uint256) {
        (uint256 wantInLp, ) = getLpReserves();
        return
            balanceLpInShort().mul(wantInLp).mul(2).div(
                wantShortLP.totalSupply()
            );
    }

    // value of borrowed tokens in value of want tokens
    function balanceDebtInShort() public view returns (uint256) {
        // Each debtToken is pegged 1:1 with the short token
        return debtToken.balanceOf(address(this));
    }

    // value of borrowed tokens in value of want tokens
    // Uses current exchange price, not stored
    function balanceDebtInShortCurrent() internal returns (uint256) {
        return debtToken.balanceOf(address(this));
    }

    // value of borrowed tokens in value of want tokens
    function balanceDebt() public view returns (uint256) {
        return convertShortToWantLP(balanceDebtInShort());
    }

    /**
     * Debt balance using price oracle
     */
    function balanceDebtOracle() public view returns (uint256) {
        return convertShortToWantOracle(balanceDebtInShort());
    }

    //Farm can be very different -> implement in the strategy directly
    function balancePendingHarvest() public view virtual returns (uint256);

    // reserves
    function balanceOfWant() public view returns (uint256) {
        return (want.balanceOf(address(this)));
    }

    function balanceShort() public view returns (uint256) {
        return (short.balanceOf(address(this)));
    }

    function balanceShortWantEq() public view returns (uint256) {
        return (convertShortToWantLP(short.balanceOf(address(this))));
    }

    function balanceLend() public view returns (uint256) {
        return aToken.balanceOf(address(this));
    }

    // Strategy specific
    function countLpPooled() internal view virtual returns (uint256);

    // lend want tokens to lending platform
    function _lendWant(uint256 amount) internal {
        pool.supply(address(want), amount, address(this), 0);
    }

    // borrow tokens woth _amount of want tokens
    function _borrowWantEq(uint256 _amount)
        internal
        returns (uint256 _borrowamount)
    {
        _borrowamount = convertWantToShortLP(_amount);
        _borrow(_borrowamount);
    }

    function _borrow(uint256 borrowAmount) internal {
        pool.borrow(address(short), borrowAmount, 2, 0, address(this));
    }

    // automatically repays debt using any short tokens held in wallet up to total debt value
    function _repayDebt() internal {
        uint256 _bal = short.balanceOf(address(this));
        if (_bal == 0) return;

        uint256 _debt = balanceDebtInShort();
        if (_bal < _debt) {
            pool.repay(address(short), _bal, 2, address(this));
        } else {
            pool.repay(address(short), _debt, 2, address(this));
        }
    }

    function _getHarvestInHarvestLp() internal view returns (uint256) {
        uint256 harvest_lp = farmToken.balanceOf(address(farmTokenLP));
        return harvest_lp;
    }

    function _getShortInHarvestLp() internal view returns (uint256) {
        uint256 shortToken_lp = short.balanceOf(address(farmTokenLP));
        return shortToken_lp;
    }

    function _redeemWant(uint256 _redeem_amount) internal {
        pool.withdraw(address(want), _redeem_amount, address(this));
    }

    // withdraws some LP worth _amount, converts all withdrawn LP to short token to repay debt
    function _withdrawLpRebalance(uint256 _amount)
        internal
        returns (uint256 swapAmountWant, uint256 slippageWant)
    {
        uint256 lpUnpooled = wantShortLP.balanceOf(address(this));
        uint256 lpPooled = countLpPooled();
        uint256 lpCount = lpUnpooled.add(lpPooled);
        uint256 lpReq = _amount.mul(lpCount).div(balanceLp());
        uint256 lpWithdraw;
        if (lpReq - lpUnpooled < lpPooled) {
            lpWithdraw = lpReq - lpUnpooled;
        } else {
            lpWithdraw = lpPooled;
        }
        _withdrawSomeLp(lpWithdraw);
        _removeAllLp();
        swapAmountWant = Math.min(
            _amount.div(2),
            want.balanceOf(address(this))
        );
        slippageWant = _swapExactWantShort(swapAmountWant);

        _repayDebt();
    }

    //  withdraws some LP worth _amount, uses withdrawn LP to add to collateral & repay debt
    function _withdrawLpRebalanceCollateral(uint256 _amount) internal {
        uint256 lpUnpooled = wantShortLP.balanceOf(address(this));
        uint256 lpPooled = countLpPooled();
        uint256 lpCount = lpUnpooled.add(lpPooled);
        uint256 lpReq = _amount.mul(lpCount).div(balanceLp());
        uint256 lpWithdraw;
        if (lpReq - lpUnpooled < lpPooled) {
            lpWithdraw = lpReq - lpUnpooled;
        } else {
            lpWithdraw = lpPooled;
        }
        _withdrawSomeLp(lpWithdraw);
        _removeAllLp();
        uint256 wantBal = balanceOfWant();
        if (_amount.div(2) <= wantBal) {
            _lendWant(_amount.div(2));
        } else {
            _lendWant(wantBal);
        }
        _repayDebt();
    }

    function _addToLP(uint256 _amountShort) internal {
        uint256 _amountWant = convertShortToWantLP(_amountShort);

        uint256 balWant = want.balanceOf(address(this));
        if (balWant < _amountWant) {
            _amountWant = balWant;
        }

        router.addLiquidity(
            address(short),
            address(want),
            _amountShort,
            _amountWant,
            _amountShort.mul(slippageAdj).div(BASIS_PRECISION),
            _amountWant.mul(slippageAdj).div(BASIS_PRECISION),
            address(this),
            now
        );
    }

    // Farm-specific methods
    function _depositLp() internal virtual;

    function _withdrawFarm(uint256 _amount) internal virtual;

    function _withdrawSomeLp(uint256 _amount) internal {
        require(_amount <= countLpPooled());
        _withdrawFarm(_amount);
    }

    function _withdrawAllPooled() internal {
        uint256 lpPooled = countLpPooled();
        _withdrawFarm(lpPooled);
    }

    // all LP currently not in Farm is removed.
    function _removeAllLp() internal {
        uint256 _amount = wantShortLP.balanceOf(address(this));
        if (_amount > 0) {
            (uint256 wantLP, uint256 shortLP) = getLpReserves();

            uint256 lpIssued = wantShortLP.totalSupply();

            uint256 amountAMin =
                _amount.mul(shortLP).mul(slippageAdj).div(BASIS_PRECISION).div(
                    lpIssued
                );
            uint256 amountBMin =
                _amount.mul(wantLP).mul(slippageAdj).div(BASIS_PRECISION).div(
                    lpIssued
                );
            router.removeLiquidity(
                address(short),
                address(want),
                _amount,
                amountAMin,
                amountBMin,
                address(this),
                now
            );
        }
    }

    function _sellHarvestWant() internal virtual {
        uint256 harvestBalance = farmToken.balanceOf(address(this));
        if (harvestBalance == 0) return;
        router.swapExactTokensForTokens(
            harvestBalance,
            0,
            getTokenOutPath(address(farmToken), address(want)),
            address(this),
            now
        );
    }

    /**
     * @notice
     *  Swaps _amount of want for short
     *
     * @param _amount The amount of want to swap
     *
     * @return slippageWant Returns the cost of fees + slippage in want
     */
    function _swapExactWantShort(uint256 _amount)
        internal
        returns (uint256 slippageWant)
    {
        uint256 amountOutMin = convertWantToShortLP(_amount);
        uint256[] memory amounts =
            router.swapExactTokensForTokens(
                _amount,
                amountOutMin.mul(slippageAdj).div(BASIS_PRECISION),
                getTokenOutPath(address(want), address(short)), // _pathWantToShort(),
                address(this),
                now
            );
        slippageWant = convertShortToWantLP(
            amountOutMin.sub(amounts[amounts.length - 1])
        );
    }

    /**
     * @notice
     *  Swaps _amount of short for want
     *
     * @param _amountShort The amount of short to swap
     *
     * @return _amountWant Returns the want amount minus fees
     * @return _slippageWant Returns the cost of fees + slippage in want
     */
    function _swapExactShortWant(uint256 _amountShort)
        internal
        returns (uint256 _amountWant, uint256 _slippageWant)
    {
        _amountWant = convertShortToWantLP(_amountShort);
        uint256[] memory amounts =
            router.swapExactTokensForTokens(
                _amountShort,
                _amountWant.mul(slippageAdj).div(BASIS_PRECISION),
                getTokenOutPath(address(short), address(want)),
                address(this),
                now
            );
        _slippageWant = _amountWant.sub(amounts[amounts.length - 1]);
    }

    function _swapWantShortExact(uint256 _amountOut)
        internal
        returns (uint256 _slippageWant)
    {
        uint256 amountInWant = convertShortToWantLP(_amountOut);
        uint256 amountInMax =
            (amountInWant.mul(BASIS_PRECISION).div(slippageAdj)).add(10); // add 1 to make up for rounding down
        uint256[] memory amounts =
            router.swapTokensForExactTokens(
                _amountOut,
                amountInMax,
                getTokenOutPath(address(want), address(short)),
                address(this),
                now
            );
        _slippageWant = amounts[0].sub(amountInWant);
    }

    /**
     * @notice
     *  Intentionally not implmenting this. The justification being:
     *   1. It doesn't actually add any additional security because gov
     *      has the powers to do the same thing with addStrategy already
     *   2. Being able to sweep tokens from a strategy could be helpful
     *      incase of an unexpected catastropic failure.
     */
    function protectedTokens()
        internal
        view
        override
        returns (address[] memory)
    {}
}

// File: WAVAXUSDCVTX.sol


// Pool address -> 0x794a61358d6845594f94dc1db02a252b5b4814ad
// AAVE addresses: https://docs.aave.com/developers/deployed-contracts/v3-mainnet/polygon
contract WAVAXUSDCVTX is CoreStrategyAave {
    using SafeERC20 for IERC20;

    // Find rewarder farmMasterChef -> masterVtx.addressToPoolInfo(farmMasterChef.stakingToken).rewarder
    address constant rewarder = 0xb81941bd8E538167885a9C3e18fa2B799Df2e625;

    constructor(address _vault)
        public
        CoreStrategyAave(
            _vault,
            CoreStrategyAaveConfig(
                0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7, // want -> WAVAX
                0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E, // short -> USDC
                0xf4003F4efBE8691B60249E6afbD307aBE7758adb, // wantShortLP -> USDC/AVAX
                0x6e84a6216eA6dACC71eE8E6b0a5B7322EEbC0fDd, // farmToken -> JOE
                0x454E67025631C065d3cFAD6d71E6892f74487a15, // farmTokenLp -> JOE/WAVAX
                0x9eF319429c4d32bc98957881723070DBca036B39, // farmMasterChef
                0x6d80113e533a2C0fe82EaBD35f1875DcEA89Ea97, // aToken
                0xFCCf3cAbbe80101232d343252614b6A3eE81C989, // variableDebtTOken
                0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb, // PoolAddressesProvider
                0x60aE616a2155Ee3d9A68541Ba4544862310933d4, // router
                1e4 //mindeploy
            )
        )
    {}

    function balancePendingHarvest() public view override returns (uint256) {
        uint256 pending = _pendingRewards();

        if (pending == 0) return 0;

        uint256[] memory amounts =
            router.getAmountsOut(
                pending,
                getTokenOutPath(address(farmToken), address(want))
            );
        return amounts[amounts.length - 1];
    }

    function _pendingRewards() internal view override returns (uint256) {
        return
            IBaseRewardPool(rewarder)
                .earned(address(this), address(farmToken))
                .add(farmToken.balanceOf(address(this)));
    }

    function _setup() internal override {
        weth = router.WAVAX();
    }

    function _depositLp() internal override {
        uint256 lpBalance = wantShortLP.balanceOf(address(this));
        IVectorChef(farmMasterChef).deposit(lpBalance);
    }

    function _withdrawFarm(uint256 _amount) internal override {
        if (_amount > 0) IVectorChef(farmMasterChef).withdraw(_amount);
    }

    function claimHarvest() internal override {
        IVectorChef(farmMasterChef).getReward();
    }

    function countLpPooled() internal view override returns (uint256) {
        return IVectorChef(farmMasterChef).balanceOf(address(this));
    }
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"collatRatio","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"adjAmount","type":"uint256"}],"name":"CollatRebalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"debtRatio","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"swapAmount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"DebtRebalance","type":"event"},{"anonymous":false,"inputs":[],"name":"EmergencyExitEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loss","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtPayment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtOutstanding","type":"uint256"}],"name":"Harvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"","type":"bool"}],"name":"SetDoHealthCheck","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"","type":"address"}],"name":"SetHealthCheck","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":"balanceDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceDebtInShort","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceDebtOracle","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceDeployed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceLend","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceLp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceLpInShort","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOfWant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balancePendingHarvest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceShort","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceShortWantEq","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calcCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calcDebtRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatLower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatTarget","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatUpper","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"collateralCapReached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtLower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtUpper","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":"doPriceCheck","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyExit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"estimatedTotalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amtInWei","type":"uint256"}],"name":"ethToWant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLpPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLpReserves","outputs":[{"internalType":"uint256","name":"_wantInLp","type":"uint256"},{"internalType":"uint256","name":"_shortInLp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOraclePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"callCostInWei","type":"uint256"}],"name":"harvestTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"healthCheck","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"insurance","outputs":[{"internalType":"contract IStrategyInsurance","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"liquidatePositionAuth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxReportDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newStrategy","type":"address"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newInsurance","type":"address"}],"name":"migrateInsurance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minDeploy","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":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IAaveOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseStrat","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"priceSourceDiffKeeper","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceSourceDiffUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"profitFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalanceCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rebalanceDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rebalancePercent","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":"_lower","type":"uint256"},{"internalType":"uint256","name":"_target","type":"uint256"},{"internalType":"uint256","name":"_upper","type":"uint256"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setCollateralThresholds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debtThreshold","type":"uint256"}],"name":"setDebtThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lower","type":"uint256"},{"internalType":"uint256","name":"_upper","type":"uint256"},{"internalType":"uint256","name":"_rebalancePercent","type":"uint256"}],"name":"setDebtThresholds","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":"_insurance","type":"address"}],"name":"setInsurance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"setKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setMaxReportDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_metadataURI","type":"string"}],"name":"setMetadataURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setMinReportDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"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":"uint256","name":"_slippageAdj","type":"uint256"},{"internalType":"uint256","name":"_priceSourceDiffUser","type":"uint256"},{"internalType":"uint256","name":"_priceSourceDiffKeeper","type":"uint256"},{"internalType":"bool","name":"_doPriceCheck","type":"bool"}],"name":"setSlippageConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategist","type":"address"}],"name":"setStrategist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"short","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"slippageAdj","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"callCostInWei","type":"uint256"}],"name":"tendTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpauseStrat","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract VaultAPI","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"want","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountNeeded","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"_loss","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

6080604052611a2c600c55611770600d556114b4600e556127ce600f55612652601055612710601155611d4c6012556013805460ff199081166001179091556126ac601e556101f4601f5560c86020556021805490911690553480156200006557600080fd5b5060405162006e1238038062006e12833981016040819052620000889162000bbb565b604080516101608101825273b31f66aa3c1e785363f0875a1b74e27b85fd66c7815273b97ef9ef8734c71904d8002f8b6bc66dd9c48a6e602082015273f4003f4efbe8691b60249e6afbd307abe7758adb91810191909152736e84a6216ea6dacc71ee8e6b0a5b7322eebc0fdd606082015273454e67025631c065d3cfad6d71e6892f74487a156080820152739ef319429c4d32bc98957881723070dbca036b3960a0820152736d80113e533a2c0fe82eabd35f1875dcea89ea9760c082015273fccf3cabbe80101232d343252614b6a3ee81c98960e082015273a97684ead0e402dc232d5a977953df7ecbab3cdb6101008201527360ae616a2155ee3d9a68541ba4544862310933d4610120820152612710610140820152819081620001b2813380806200050f565b5060208181015160138054610100600160a81b0319166101006001600160a01b0393841602179055604080840151601480546001600160a01b031990811692851692909217905560808501516015805483169185169190911790556060850151601680549092169084161790558351815163313ce56760e01b8152915192169263313ce56792600480840193829003018186803b1580156200025357600080fd5b505afa15801562000268573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200028e919062000c26565b601360156101000a81548160ff021916908360ff16021790555080602001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015620002e657600080fd5b505afa158015620002fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000321919062000c26565b6013805460ff92909216600160b01b0260ff60b01b1990921691909117905560a0810151601780546001600160a01b039283166001600160a01b03199182161790915561012083015160188054918416919092161790556101008201516040805163026b1d5f60e01b81529051919283169163026b1d5f91600480820192602092909190829003018186803b158015620003ba57600080fd5b505afa158015620003cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003f5919062000bbb565b601a60006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b031663fca513a86040518163ffffffff1660e01b815260040160206040518083038186803b1580156200045557600080fd5b505afa1580156200046a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000490919062000bbb565b601d80546001600160a01b039283166001600160a01b03199182161790915560c0840151601b805491841691831691909117905560e0840151601c80549190931691161790556154606008556138406007556105dc600955610140820151602255620004fb620006f3565b62000505620007a5565b5050505062000e17565b6006546001600160a01b031615620005445760405162461bcd60e51b81526004016200053b9062000ccf565b60405180910390fd5b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b158015620005a157600080fd5b505afa158015620005b6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005dc919062000bbb565b600680546001600160a01b0319166001600160a01b03928316179081905562000616911685600019620008ec602090811b6200341917901c565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b3936200069693911691600019910162000c81565b602060405180830381600087803b158015620006b157600080fd5b505af1158015620006c6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006ec919062000beb565b5050505050565b601860009054906101000a90046001600160a01b03166001600160a01b03166373b295c26040518163ffffffff1660e01b815260040160206040518083038186803b1580156200074257600080fd5b505afa15801562000757573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200077d919062000bbb565b602160016101000a8154816001600160a01b0302191690836001600160a01b03160217905550565b601a54600654620007d2916001600160a01b039182169116600019620008ec602090811b6200341917901c565b601a5460135462000804916001600160a01b0361010090920482169116600019620008ec602090811b6200341917901c565b60185460065462000831916001600160a01b039182169116600019620008ec602090811b6200341917901c565b60185460135462000863916001600160a01b0361010090920482169116600019620008ec602090811b6200341917901c565b60185460165462000890916001600160a01b039182169116600019620008ec602090811b6200341917901c565b601854601454620008bd916001600160a01b039182169116600019620008ec602090811b6200341917901c565b601754601454620008ea916001600160a01b039182169116600019620008ec602090811b6200341917901c565b565b8015806200097b5750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e9062000925903090869060040162000c67565b60206040518083038186803b1580156200093e57600080fd5b505afa15801562000953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000979919062000c0d565b155b6200099a5760405162461bcd60e51b81526004016200053b9062000d87565b620009f58363095ea7b360e01b8484604051602401620009bc92919062000c81565b60408051808303601f190181529190526020810180516001600160e01b0319939093166001600160e01b0393841617905290620009fa16565b505050565b606062000a56826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662000a9660201b62003513179092919060201c565b805190915015620009f5578080602001905181019062000a77919062000beb565b620009f55760405162461bcd60e51b81526004016200053b9062000d3d565b606062000aa7848460008562000aaf565b949350505050565b606062000abc8562000b81565b62000adb5760405162461bcd60e51b81526004016200053b9062000d06565b60006060866001600160a01b0316858760405162000afa919062000c49565b60006040518083038185875af1925050503d806000811462000b39576040519150601f19603f3d011682016040523d82523d6000602084013e62000b3e565b606091505b5091509150811562000b5457915062000aa79050565b80511562000b655780518082602001fd5b8360405162461bcd60e51b81526004016200053b919062000c9a565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159062000aa7575050151592915050565b60006020828403121562000bcd578081fd5b81516001600160a01b038116811462000be4578182fd5b9392505050565b60006020828403121562000bfd578081fd5b8151801515811462000be4578182fd5b60006020828403121562000c1f578081fd5b5051919050565b60006020828403121562000c38578081fd5b815160ff8116811462000be4578182fd5b6000825162000c5d81846020870162000de4565b9190910192915050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b600060208252825180602084015262000cbb81604085016020870162000de4565b601f01601f19169190910160400192915050565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606082015260800190565b60005b8381101562000e0157818101518382015260200162000de7565b8381111562000e11576000848401525b50505050565b615feb8062000e276000396000f3fe608060405234801561001057600080fd5b50600436106104805760003560e01c806385889c5411610257578063cad20a2911610146578063efbb5cb0116100c3578063f91d7b2e11610087578063f91d7b2e14610817578063fbfa77cf1461081f578063fcf2d0ad14610827578063feb6848a1461082f578063ff7fae1d146105f157610480565b8063efbb5cb0146107e4578063f017c92f146107ec578063f38c5ccc146107ff578063f40feaed14610807578063f8c1e75e1461080f57610480565b8063ec079f381161010a578063ec079f38146107a6578063ec38a862146107ae578063ecda3cd6146107c1578063ed882c2b146107c9578063edf9d152146107dc57610480565b8063cad20a2914610773578063ce5494bb1461077b578063cf15e73c1461078e578063d2b49a9214610796578063e6e7114b1461079e57610480565b8063ac00ff26116101d4578063b252720b11610198578063b252720b14610732578063b282e0f91461073a578063be48a8f114610750578063c1a3d44c14610758578063c7b9d5301461076057610480565b8063ac00ff26146106f4578063aced166114610707578063ad46355f1461070f578063ae7c961914610722578063b187bd261461072a57610480565b806391397ab41161021b57806391397ab4146106c157806395e80c50146106d45780639ec5a894146106dc578063a9b0ca38146106e4578063a9c19c66146106ec57610480565b806385889c541461068e57806389cf3204146106965780638cdfe1661461069e5780638e6350e2146106a65780639011ccdc146106ae57610480565b8063440368a3116103735780636cd7751f116102f05780637acd7922116102b45780637acd79221461065b5780637b4747dd146106635780637dc0d1d01461067657806381117ff21461067e5780638555e2e51461068657610480565b80636cd7751f1461060c578063748747e61461061f578063750521f514610632578063780022a014610645578063796da7af1461065357610480565b80635641ec03116103375780635641ec03146105ce578063572f1e78146105d65780635fc7a201146105de578063650d1880146105f15780636718835f1461060457610480565b8063440368a3146105a6578063460ab840146105ae5780634641257d146105b65780634c7198f4146105be5780634d46544d146105c657610480565b8063258294101161040157806338bea4cb116103c557806338bea4cb1461057357806339a172a81461057b57806339bb9c241461058e5780633e44de51146105965780633e4db0471461059e57610480565b8063258294101461053557806328b7ccf71461053d57806329b909ea146105455780632e1a7d4d1461054d578063315c41f21461056057610480565b80631d12f28b116104485780631d12f28b146104e65780631e0cd0a7146104fb5780631f1fcd51146105035780631fe4a6861461051857806322f3e2d41461052057610480565b806301681a621461048557806303ee438c1461049a57806306fdde03146104b85780630f969b87146104c057806311bc8245146104d3575b600080fd5b61049861049336600461565c565b610837565b005b6104a26109d6565b6040516104af9190615bd4565b60405180910390f35b6104a2610a64565b6104986104ce3660046158a0565b610a9c565b6104986104e136600461565c565b610b29565b6104ee610c61565b6040516104af9190615e4a565b6104ee610c67565b61050b610c6d565b6040516104af9190615a1b565b61050b610c7c565b610528610c8b565b6040516104af9190615b9a565b6104a2610d2d565b6104ee610d4c565b6104ee610d52565b6104ee61055b3660046158a0565b610de7565b61049861056e36600461598b565b610e42565b61050b610ed5565b6104986105893660046158a0565b610ee9565b6104ee610f6b565b6104ee610f71565b6104ee610f77565b610498611052565b61049861127b565b610498611458565b6104ee611969565b61049861199e565b610528611b7b565b6104ee611b84565b6104986105ec3660046158f3565b611c14565b6105286105ff3660046158a0565b611c99565b610528611ca1565b61049861061a36600461565c565b611caa565b61049861062d36600461565c565b611d2f565b610498610640366004615761565b611dda565b6104ee6105ff3660046158a0565b6104ee611e71565b6104ee611fcc565b61049861067136600461594b565b611fd2565b61050b61203e565b61049861204d565b6104ee612234565b6104ee61225a565b61050b612260565b6104ee61226f565b6104ee612275565b6104986106bc36600461565c565b61227a565b6104986106cf3660046158a0565b61234b565b6104ee6123cd565b61050b6123d3565b6104ee6123e2565b6104ee6123e8565b610498610702366004615729565b612469565b61050b61258c565b61049861071d3660046158a0565b61259b565b6104ee6125f6565b6105286125fc565b61050b612605565b610742612619565b6040516104af929190615ea8565b6104ee612779565b6104ee61277f565b61049861076e36600461565c565b6127b0565b6104ee61285b565b61049861078936600461565c565b612868565b6104ee6129b3565b6104986129b9565b6104ee612baf565b6104ee612bca565b6104986107bc36600461565c565b612c78565b6104ee612e0b565b6105286107d73660046158a0565b612e3c565b6104ee6130c6565b6104ee6130f1565b6104986107fa3660046158a0565b613106565b6104ee613188565b6104ee61318e565b6104ee6131a0565b6105286131a6565b61050b6131af565b6104986131be565b6104ee6133e3565b61083f61352a565b6001600160a01b0316336001600160a01b0316146108785760405162461bcd60e51b815260040161086f90615d61565b60405180910390fd5b6006546001600160a01b03828116911614156108a65760405162461bcd60e51b815260040161086f90615c2c565b6002546001600160a01b03828116911614156108d45760405162461bcd60e51b815260040161086f90615d09565b60606108de6135a7565b905060005b8151811015610939578181815181106108f857fe5b60200260200101516001600160a01b0316836001600160a01b031614156109315760405162461bcd60e51b815260040161086f90615dd0565b6001016108e3565b506109d261094561352a565b6040516370a0823160e01b81526001600160a01b038516906370a0823190610971903090600401615a1b565b60206040518083038186803b15801561098957600080fd5b505afa15801561099d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c191906158b8565b6001600160a01b03851691906135ac565b5050565b6000805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610a5c5780601f10610a3157610100808354040283529160200191610a5c565b820191906000526020600020905b815481529060010190602001808311610a3f57829003601f168201915b505050505081565b60408051808201909152601d81527f53747261746567794865646765644661726d696e674161766556322e3200000060208201525b90565b6003546001600160a01b0316331480610acd5750610ab861352a565b6001600160a01b0316336001600160a01b0316145b610ae95760405162461bcd60e51b815260040161086f90615d61565b600a8190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a860090610b1e908390615e4a565b60405180910390a150565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610b7757600080fd5b505afa158015610b8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610baf9190615678565b6001600160a01b0316336001600160a01b03161480610be65750610bd161352a565b6001600160a01b0316336001600160a01b0316145b610c025760405162461bcd60e51b815260040161086f90615d61565b7fc8db9c35f716b87af1fbb83f03c78646061931269301fd7ba6dcf189b4cdc2fc81604051610c319190615a1b565b60405180910390a1600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600a5481565b60225481565b6006546001600160a01b031681565b6003546001600160a01b031681565b6002546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610cc0903090600401615a1b565b6101206040518083038186803b158015610cd957600080fd5b505afa158015610ced573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1191906157ce565b604001511180610d2857506000610d266130f1565b115b905090565b604080518082019091526005815264302e342e3360d81b602082015290565b60085481565b6014546040516370a0823160e01b8152600091610d28916001600160a01b03909116906370a0823190610d89903090600401615a1b565b60206040518083038186803b158015610da157600080fd5b505afa158015610db5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd991906158b8565b610de16135cb565b906135fc565b6002546000906001600160a01b03163314610e145760405162461bcd60e51b815260040161086f90615ce9565b6000610e1f8361362a565b600654909350909150610e3c906001600160a01b031633836135ac565b50919050565b6003546001600160a01b0316331480610e735750610e5e61352a565b6001600160a01b0316336001600160a01b0316145b610e8f5760405162461bcd60e51b815260040161086f90615d61565b612710811115610e9e57600080fd5b6012819055818111610eaf57600080fd5b82821015610ebc57600080fd5b83831015610ec957600080fd5b50600c55600d55600e55565b60135461010090046001600160a01b031681565b6003546001600160a01b0316331480610f1a5750610f0561352a565b6001600160a01b0316336001600160a01b0316145b610f365760405162461bcd60e51b815260040161086f90615d61565b60078190556040517fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190610b1e908390615e4a565b601e5481565b60105481565b600080610f826136f8565b905080610f93576000915050610a99565b6018546016546006546060926001600160a01b039081169263d06ca61f928692610fc09281169116613815565b6040518363ffffffff1660e01b8152600401610fdd929190615e53565b60006040518083038186803b158015610ff557600080fd5b505afa158015611009573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110319190810190615694565b90508060018251038151811061104357fe5b60200260200101519250505090565b6005546001600160a01b031633148061107557506003546001600160a01b031633145b80611098575061108361352a565b6001600160a01b0316336001600160a01b0316145b806111395750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156110ec57600080fd5b505afa158015611100573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111249190615678565b6001600160a01b0316336001600160a01b0316145b806111da5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561118d57600080fd5b505afa1580156111a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c59190615678565b6001600160a01b0316336001600160a01b0316145b6111f65760405162461bcd60e51b815260040161086f90615d61565b6002546040805163bf3759b560e01b81529051611279926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561123c57600080fd5b505afa158015611250573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127491906158b8565b613985565b565b6005546001600160a01b031633148061129e57506003546001600160a01b031633145b806112c157506112ac61352a565b6001600160a01b0316336001600160a01b0316145b806113625750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561131557600080fd5b505afa158015611329573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134d9190615678565b6001600160a01b0316336001600160a01b0316145b806114035750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156113b657600080fd5b505afa1580156113ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ee9190615678565b6001600160a01b0316336001600160a01b0316145b61141f5760405162461bcd60e51b815260040161086f90615d61565b60215460ff1661142e57600080fd5b6021805460ff191690556114486114436123e8565b6139bb565b61127961145361277f565b613a45565b6005546001600160a01b031633148061147b57506003546001600160a01b031633145b8061149e575061148961352a565b6001600160a01b0316336001600160a01b0316145b8061153f5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156114f257600080fd5b505afa158015611506573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152a9190615678565b6001600160a01b0316336001600160a01b0316145b806115e05750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561159357600080fd5b505afa1580156115a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115cb9190615678565b6001600160a01b0316336001600160a01b0316145b6115fc5760405162461bcd60e51b815260040161086f90615d61565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561164f57600080fd5b505afa158015611663573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168791906158b8565b600b5490915060009060ff16156116e45760006116a2613b3c565b9050828110156116bd576116b68382613b46565b93506116d2565b828111156116d2576116cf8184613b46565b94505b6116dc8385613b46565b9150506116f5565b6116ed82613b88565b919550935090505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf82390611726903090600401615a1b565b6101206040518083038186803b15801561173f57600080fd5b505afa158015611753573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177791906157ce565b60c001516002546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc906117b090889088908790600401615eb6565b602060405180830381600087803b1580156117ca57600080fd5b505af11580156117de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180291906158b8565b925061180d83613985565b60015460ff16801561182e575060015461010090046001600160a01b031615155b156118e05760015460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b9061186f9088908890879089908890600401615ee7565b60206040518083038186803b15801561188757600080fd5b505afa15801561189b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bf9190615745565b6118db5760405162461bcd60e51b815260040161086f90615c82565b611925565b7ff769f6bf659bbbdabf212d830720ce893eedc57f25ebb8e44edf5b300618a35b60016040516119109190615b9a565b60405180910390a16001805460ff1916811790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d5098585848660405161195a9493929190615ecc565b60405180910390a15050505050565b6000806000611976612619565b90925090506119978161199184670de0b6b3a7640000613da8565b90613de2565b9250505090565b6005546001600160a01b03163314806119c157506003546001600160a01b031633145b806119e457506119cf61352a565b6001600160a01b0316336001600160a01b0316145b80611a855750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b158015611a3857600080fd5b505afa158015611a4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a709190615678565b6001600160a01b0316336001600160a01b0316145b80611b265750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015611ad957600080fd5b505afa158015611aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b119190615678565b6001600160a01b0316336001600160a01b0316145b611b425760405162461bcd60e51b815260040161086f90615d61565b60215460ff1615611b5257600080fd5b611b5a613e24565b5050611b6c611b6761277f565b613f63565b6021805460ff19166001179055565b600b5460ff1681565b6013546040516370a0823160e01b8152600091610d28916101009091046001600160a01b0316906370a0823190611bbf903090600401615a1b565b60206040518083038186803b158015611bd757600080fd5b505afa158015611beb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c0f91906158b8565b613fd3565b6003546001600160a01b0316331480611c455750611c3061352a565b6001600160a01b0316336001600160a01b0316145b611c615760405162461bcd60e51b815260040161086f90615d61565b612710831115611c7057600080fd5b612710811115611c7f57600080fd5b612710821015611c8e57600080fd5b601155600f55601055565b60005b919050565b60015460ff1681565b6003546001600160a01b0316331480611cdb5750611cc661352a565b6001600160a01b0316336001600160a01b0316145b611cf75760405162461bcd60e51b815260040161086f90615d61565b6019546001600160a01b031615611d0d57600080fd5b601980546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b0316331480611d605750611d4b61352a565b6001600160a01b0316336001600160a01b0316145b611d7c5760405162461bcd60e51b815260040161086f90615d61565b6001600160a01b038116611d8f57600080fd5b600580546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490610b1e908390615a1b565b6003546001600160a01b0316331480611e0b5750611df661352a565b6001600160a01b0316336001600160a01b0316145b611e275760405162461bcd60e51b815260040161086f90615d61565b611e336000838361557d565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda68282604051611e65929190615ba5565b60405180910390a15050565b601d5460135460405163b3596f0760e01b815260009283926001600160a01b039182169263b3596f0792611eae9261010090041690600401615a1b565b60206040518083038186803b158015611ec657600080fd5b505afa158015611eda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611efe91906158b8565b601d5460065460405163b3596f0760e01b81529293506000926001600160a01b039283169263b3596f0792611f3892911690600401615a1b565b60206040518083038186803b158015611f5057600080fd5b505afa158015611f64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8891906158b8565b60135490915061199790829061199190611fc29060ff600160b01b8204811691611fbc91600160a81b9091041660126135fc565b90613b46565b8590600a0a613da8565b600d5481565b6003546001600160a01b03163314806120035750611fee61352a565b6001600160a01b0316336001600160a01b0316145b61201f5760405162461bcd60e51b815260040161086f90615d61565b601e93909355601f556020556013805460ff1916911515919091179055565b601d546001600160a01b031681565b6005546001600160a01b031633148061207057506003546001600160a01b031633145b80612093575061207e61352a565b6001600160a01b0316336001600160a01b0316145b806121345750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156120e757600080fd5b505afa1580156120fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211f9190615678565b6001600160a01b0316336001600160a01b0316145b806121d55750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561218857600080fd5b505afa15801561219c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c09190615678565b6001600160a01b0316336001600160a01b0316145b6121f15760405162461bcd60e51b815260040161086f90615d61565b60215460ff161561220157600080fd5b600061220b612baf565b9050600e54811115806122205750600c548110155b61222957600080fd5b612231613ff3565b50565b6000610d28612241612bca565b611991600261225461271061225461285b565b90613da8565b60125481565b6019546001600160a01b031681565b60095481565b600090565b61228261352a565b6001600160a01b0316336001600160a01b0316146122b25760405162461bcd60e51b815260040161086f90615d61565b6001600160a01b038116156122c657600080fd5b601954604051632404733760e21b81526001600160a01b0390911690639011ccdc906122f6908490600401615a1b565b600060405180830381600087803b15801561231057600080fd5b505af1158015612324573d6000803e3d6000fd5b5050601980546001600160a01b0319166001600160a01b0394909416939093179092555050565b6003546001600160a01b031633148061237c575061236761352a565b6001600160a01b0316336001600160a01b0316145b6123985760405162461bcd60e51b815260040161086f90615d61565b60098190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec29890610b1e908390615e4a565b60075481565b6004546001600160a01b031681565b600e5481565b601b546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612419903090600401615a1b565b60206040518083038186803b15801561243157600080fd5b505afa158015612445573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2891906158b8565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156124b757600080fd5b505afa1580156124cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ef9190615678565b6001600160a01b0316336001600160a01b03161480612526575061251161352a565b6001600160a01b0316336001600160a01b0316145b6125425760405162461bcd60e51b815260040161086f90615d61565b7ff769f6bf659bbbdabf212d830720ce893eedc57f25ebb8e44edf5b300618a35b816040516125719190615b9a565b60405180910390a16001805460ff1916911515919091179055565b6005546001600160a01b031681565b6003546001600160a01b03163314806125cc57506125b761352a565b6001600160a01b0316336001600160a01b0316145b6125e85760405162461bcd60e51b815260040161086f90615d61565b6125f18161362a565b505050565b601f5481565b60215460ff1681565b60015461010090046001600160a01b031681565b600080600080601460009054906101000a90046001600160a01b03166001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561266d57600080fd5b505afa158015612681573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126a5919061584c565b5060065460145460408051630dfe168160e01b815290519496509294506001600160a01b0391821693911691630dfe1681916004808301926020929190829003018186803b1580156126f657600080fd5b505afa15801561270a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272e9190615678565b6001600160a01b0316141561275a57816001600160701b03169350806001600160701b03169250612773565b806001600160701b03169350816001600160701b031692505b50509091565b600f5481565b6006546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612419903090600401615a1b565b6003546001600160a01b03163314806127e157506127cc61352a565b6001600160a01b0316336001600160a01b0316145b6127fd5760405162461bcd60e51b815260040161086f90615d61565b6001600160a01b03811661281057600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490610b1e908390615a1b565b6000610d28611c0f612e0b565b6002546001600160a01b0316331461287f57600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b1580156128c657600080fd5b505afa1580156128da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128fe9190615678565b6001600160a01b03161461291157600080fd5b61291a81614158565b6006546040516370a0823160e01b81526122319183916001600160a01b03909116906370a0823190612950903090600401615a1b565b60206040518083038186803b15801561296857600080fd5b505afa15801561297c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a091906158b8565b6006546001600160a01b031691906135ac565b60205481565b6005546001600160a01b03163314806129dc57506003546001600160a01b031633145b806129ff57506129ea61352a565b6001600160a01b0316336001600160a01b0316145b80612aa05750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b158015612a5357600080fd5b505afa158015612a67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8b9190615678565b6001600160a01b0316336001600160a01b0316145b80612b415750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015612af457600080fd5b505afa158015612b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2c9190615678565b6001600160a01b0316336001600160a01b0316145b612b5d5760405162461bcd60e51b815260040161086f90615d61565b60215460ff1615612b6d57600080fd5b6000612b77612234565b9050601054811080612b8a5750600f5481115b612b9357600080fd5b612b9e601f54614160565b612ba757600080fd5b6122316141d0565b6000610d28612bbc6123e8565b61199161271061225461318e565b600080612bd5612619565b509050612c72601460009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c2957600080fd5b505afa158015612c3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6191906158b8565b611991600261225485612254610d52565b91505090565b6003546001600160a01b03163314612ca25760405162461bcd60e51b815260040161086f90615c07565b6001600160a01b038116612cb557600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b393612cec939091169160009101615ad2565b602060405180830381600087803b158015612d0657600080fd5b505af1158015612d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3e9190615745565b50600480546001600160a01b0319166001600160a01b038381169190911780835560025460405163095ea7b360e01b81529083169363095ea7b393612d899316916000199101615ad2565b602060405180830381600087803b158015612da357600080fd5b505af1158015612db7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ddb9190615745565b507fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06981604051610b1e9190615a1b565b601c546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612419903090600401615a1b565b600080612e4883611c99565b9050612e526155fb565b6002546040516339ebf82360e01b81526001600160a01b03909116906339ebf82390612e82903090600401615a1b565b6101206040518083038186803b158015612e9b57600080fd5b505afa158015612eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed391906157ce565b9050806020015160001415612eed57600092505050611c9c565b60075460a0820151612f00904290613b46565b1015612f1157600092505050611c9c565b60085460a0820151612f24904290613b46565b10612f3457600192505050611c9c565b6002546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b158015612f7957600080fd5b505afa158015612f8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fb191906158b8565b9050600a54811115612fc95760019350505050611c9c565b6000612fd36130f1565b90508260c00151612fef600a54836135fc90919063ffffffff16565b1015613002576001945050505050611c9c565b60008360c001518211156130235760c0840151613020908390613b46565b90505b6002546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b15801561306857600080fd5b505afa15801561307c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a091906158b8565b90506130ac81836135fc565b6009546130b99088613da8565b1098975050505050505050565b6000610d286130d361285b565b611fbc6130de611b84565b610de16130e9612bca565b610de16123e8565b6000610d286130fe6130c6565b610de161277f565b6003546001600160a01b0316331480613137575061312261352a565b6001600160a01b0316336001600160a01b0316145b6131535760405162461bcd60e51b815260040161086f90615d61565b60088190556040517f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590610b1e908390615e4a565b60115481565b6000610d2861319b612e0b565b6142c9565b600c5481565b60135460ff1681565b6002546001600160a01b031681565b6003546001600160a01b03163314806131ef57506131da61352a565b6001600160a01b0316336001600160a01b0316145b806132905750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561324357600080fd5b505afa158015613257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327b9190615678565b6001600160a01b0316336001600160a01b0316145b806133315750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156132e457600080fd5b505afa1580156132f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061331c9190615678565b6001600160a01b0316336001600160a01b0316145b61334d5760405162461bcd60e51b815260040161086f90615d61565b600b805460ff191660011790556002546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b1580156133a057600080fd5b505af11580156133b4573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b6013546040516370a0823160e01b815260009161010090046001600160a01b0316906370a0823190612419903090600401615a1b565b8015806134a15750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e9061344f9030908690600401615a2f565b60206040518083038186803b15801561346757600080fd5b505afa15801561347b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061349f91906158b8565b155b6134bd5760405162461bcd60e51b815260040161086f90615df4565b6125f18363095ea7b360e01b84846040516024016134dc929190615ad2565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526142e9565b60606135228484600085614378565b949350505050565b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b15801561356f57600080fd5b505afa158015613583573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d289190615678565b606090565b6125f18363a9059cbb60e01b84846040516024016134dc929190615ad2565b6017546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612419903090600401615a1b565b6000828201838110156136215760405162461bcd60e51b815260040161086f90615c4b565b90505b92915050565b600080600061363761277f565b905060006136436130f1565b905084600061365061443c565b90508281111561369a5760006136728261199186670de0b6b3a7640000613da8565b905061368a670de0b6b3a76400006119918a84613da8565b92506136968884613b46565b9550505b60006136a5836144c7565b91506136b3905086826135fc565b95506136bd61277f565b9650876136ca88886135fc565b11156136e1576136da8887613b46565b96506136ee565b6136eb8888613b46565b95505b5050505050915091565b6016546040516370a0823160e01b8152600091610d28916001600160a01b03909116906370a082319061372f903090600401615a1b565b60206040518083038186803b15801561374757600080fd5b505afa15801561375b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377f91906158b8565b60165460405163211dc32d60e01b815273b81941bd8e538167885a9c3e18fa2b799df2e6259163211dc32d916137c59130916001600160a01b0390911690600401615a2f565b60206040518083038186803b1580156137dd57600080fd5b505afa1580156137f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de191906158b8565b6021546060906000906001600160a01b0385811661010090920416148061384e57506021546001600160a01b0384811661010090920416145b90508061385c57600361385f565b60025b60ff1667ffffffffffffffff8111801561387857600080fd5b506040519080825280602002602001820160405280156138a2578160200160208202803683370190505b50915083826000815181106138b357fe5b60200260200101906001600160a01b031690816001600160a01b031681525050801561390c5782826001815181106138e757fe5b60200260200101906001600160a01b031690816001600160a01b03168152505061397e565b602160019054906101000a90046001600160a01b03168260018151811061392f57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050828260028151811061395d57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b5092915050565b600061398f61277f565b905080821061399e5750612231565b60006139aa8284613b46565b905080156125f1576125f181613a45565b601a54600654604051631a4ca37b60e21b81526001600160a01b03928316926369328dec926139f39291169085903090600401615aeb565b602060405180830381600087803b158015613a0d57600080fd5b505af1158015613a21573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d291906158b8565b60215460ff1615613a6057613a5b611b6761277f565b612231565b602254811080613a745750613a7481611c99565b15613a7e57612231565b6000613a88611e71565b90506000613a94611969565b90506000613ae7613ac6613abd85610de161271061199188600d54613da890919063ffffffff16565b61271090613da8565b611991670de0b6b3a764000061225488600d54613da890919063ffffffff16565b90506000613b01670de0b6b3a76400006119918486613da8565b90506000613b0f8683613b46565b9050613b1a81613f63565b613b238361463e565b613b2c83614683565b613b346147f3565b505050505050565b6000610e3c613e24565b600061362183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506148a5565b600080600080613b966130f1565b90506000613ba261443c565b905080821115613bf957613bb68282613b46565b94506000613bcc613bc788886135fc565b6144c7565b50905080871115613be35780935060009550613bf3565b869350613bf08185613b46565b95505b50613c1b565b613c02866144c7565b5050613c0c61277f565b9250613c188183613b46565b93505b613c236148d1565b85019450848410613cc75760009450613c3c8486613b46565b60195460405163746c8fd560e01b81529195506001600160a01b03169063746c8fd590613c6f9084908890600401615ea8565b602060405180830381600087803b158015613c8957600080fd5b505af1158015613c9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc191906158b8565b50613d9f565b613cd18585613b46565b60195460405163351fc74560e21b81529196506000955085916001600160a01b039091169063d47f1d1490613d0c9085908a90600401615ea8565b602060405180830381600087803b158015613d2657600080fd5b505af1158015613d3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d5e91906158b8565b9050613d6a8682613b46565b9550600081118015613d7b57508581105b15613d9d57600654601954613d9d916001600160a01b039081169116836135ac565b505b50509193909250565b600082613db757506000613624565b82820282848281613dc457fe5b04146136215760405162461bcd60e51b815260040161086f90615ca8565b600061362183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506148fa565b600080613e2f614931565b613e37614946565b6000613e41612e0b565b90506000613e4d6133e3565b9050818110613f0357613e5e614b5a565b6000613e68611b84565b1115613efe576013546040516370a0823160e01b8152613efa9161010090046001600160a01b0316906370a0823190613ea5903090600401615a1b565b60206040518083038186803b158015613ebd57600080fd5b505afa158015613ed1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ef591906158b8565b614d2f565b9350505b613f48565b6000613f0f8383613b46565b90506000613f1c82613fd3565b1115613f3257613f2b81614e3b565b9350613f3e565b613f3c6001614f4c565b505b613f46614b5a565b505b613f536114436123e8565b613f5b61277f565b935050509091565b601a5460065460405163617ba03760e01b81526001600160a01b039283169263617ba03792613f9e9291169085903090600090600401615b0e565b600060405180830381600087803b158015613fb857600080fd5b505af1158015613fcc573d6000803e3d6000fd5b5050505050565b6000806000613fe0612619565b9092509050613522816119918685613da8565b6000613ffd612baf565b9050600061400961285b565b905060006140156123e8565b9050600d548311156140b057600061406861403d600d546127106135fc90919063ffffffff16565b611991612710612254614061612710611991600d548a613da890919063ffffffff16565b8890613b46565b905061407d614078826002613da8565b61503c565b604051819085907f111845ab410c0730b6955bdc402995329bc8177eda2924040e731bce85d1736d90600090a3506125f1565b600d548310156125f15760006140fb6140d6600d546127106135fc90919063ffffffff16565b61199161271061225487611fbc612710611991600d548b613da890919063ffffffff16565b9050600061410882615165565b9050614113826139bb565b61411c81614683565b6141246147f3565b604051829086907f111845ab410c0730b6955bdc402995329bc8177eda2924040e731bce85d1736d90600090a35050505050565b6125f1613e24565b60135460009060ff16156141c8576000614178611e71565b90506000614184611969565b905060006141988261199185612710613da8565b90506141a661271086613b46565b811180156141be57506141bb612710866135fc565b81105b9350505050611c9c565b506001919050565b60008060006141dd612234565b90506141e761517b565b60006141f1612e0b565b905060006141fd6133e3565b90508082111561424f576000614216611c0f8484613b46565b905061423361271061199160115484613da890919063ffffffff16565b955061423e866139bb565b61424786614f4c565b94505061427b565b60008282039050614274613ef561271061199160115485613da890919063ffffffff16565b9096509450505b614283614b5a565b61429361428e6130f1565b615196565b8385847ff13e8bcc24e66386a72a550acb7de1120ca0305ed25e72054d804f23355b449360405160405180910390a45050505050565b6000613624670de0b6b3a76400006119916142e2611e71565b8590613da8565b606061433e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166135139092919063ffffffff16565b8051909150156125f1578080602001905181019061435c9190615745565b6125f15760405162461bcd60e51b815260040161086f90615d86565b6060614383856151e6565b61439f5760405162461bcd60e51b815260040161086f90615d2a565b60006060866001600160a01b031685876040516143bc91906159ff565b60006040518083038185875af1925050503d80600081146143f9576040519150601f19603f3d011682016040523d82523d6000602084013e6143fe565b606091505b509150915081156144125791506135229050565b8051156144225780518082602001fd5b8360405162461bcd60e51b815260040161086f9190615bd4565b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf8239061446d903090600401615a1b565b6101206040518083038186803b15801561448657600080fd5b505afa15801561449a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144be91906157ce565b60c00151905090565b60008060006144d461277f565b60215490915060ff161561450457808411156144f7576144f76114438583613b46565b8360009250925050614639565b61450f602054614160565b61451857600080fd5b80841161452c578360009250925050614639565b60006145366130c6565b9050600061454e826119916127106122548a88613b46565b905061251c81111561457957614562613e24565b9450614572905083611fbc61277f565b9450614635565b61458161517b565b60006101f482111561460b5760006145976133e3565b905060006145a3612e0b565b9050818111156145ed5760006145bc611c0f8385613b46565b905060006145d06127106119918489613da8565b90506145db816139bb565b6145e481614f4c565b94505050614608565b614604613ef5612710611991876122548787613b46565b9350505b50505b614613614b5a565b61462461428e82610de1868b613b46565b61463084611fbc61277f565b955093505b5050505b915091565b601a5460135460405163a415bcad60e01b81526001600160a01b039283169263a415bcad92613f9e926101009091049091169085906002906000903090600401615b66565b600061468e82613fd3565b6006546040516370a0823160e01b81529192506000916001600160a01b03909116906370a08231906146c4903090600401615a1b565b60206040518083038186803b1580156146dc57600080fd5b505afa1580156146f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061471491906158b8565b905081811015614722578091505b601854601354600654601e546001600160a01b039384169363e8e337009361010090048116921690879087906147619061271090611991908590613da8565b61477c612710611991601e548c613da890919063ffffffff16565b30426040518963ffffffff1660e01b81526004016147a1989796959493929190615a89565b606060405180830381600087803b1580156147bb57600080fd5b505af11580156147cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b34919061591e565b6014546040516370a0823160e01b81526000916001600160a01b0316906370a0823190614824903090600401615a1b565b60206040518083038186803b15801561483c57600080fd5b505afa158015614850573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061487491906158b8565b60175460405163b6b55f2560e01b81529192506001600160a01b03169063b6b55f2590613f9e908490600401615e4a565b600081848411156148c95760405162461bcd60e51b815260040161086f9190615bd4565b505050900390565b6000806148dc61277f565b90506148e661521f565b6148ee615289565b612c7281611fbc61277f565b6000818361491b5760405162461bcd60e51b815260040161086f9190615bd4565b50600083858161492757fe5b0495945050505050565b600061493b6135cb565b9050612231816153bc565b6014546040516370a0823160e01b81526000916001600160a01b0316906370a0823190614977903090600401615a1b565b60206040518083038186803b15801561498f57600080fd5b505afa1580156149a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149c791906158b8565b90508015612231576000806149da612619565b915091506000601460009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015614a2e57600080fd5b505afa158015614a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a6691906158b8565b90506000614a8d82611991612710611991601e54612254898c613da890919063ffffffff16565b90506000614ab483611991612710611991601e546122548b8d613da890919063ffffffff16565b601854601354600654604051635d5155ef60e11b81529394506001600160a01b039283169363baa2abde93614aff93610100900481169216908b908890889030904290600401615a49565b6040805180830381600087803b158015614b1857600080fd5b505af1158015614b2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b5091906158d0565b5050505050505050565b6013546040516370a0823160e01b815260009161010090046001600160a01b0316906370a0823190614b90903090600401615a1b565b60206040518083038186803b158015614ba857600080fd5b505afa158015614bbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614be091906158b8565b905080614bed5750611279565b6000614bf7612e0b565b905080821015614c9b57601a5460135460405163573ade8160e01b81526001600160a01b039283169263573ade8192614c43926101009091049091169086906002903090600401615b3b565b602060405180830381600087803b158015614c5d57600080fd5b505af1158015614c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c9591906158b8565b506109d2565b601a5460135460405163573ade8160e01b81526001600160a01b039283169263573ade8192614cdd926101009091049091169085906002903090600401615b3b565b602060405180830381600087803b158015614cf757600080fd5b505af1158015614d0b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f191906158b8565b600080614d3b83613fd3565b601854601e549193506060916001600160a01b03909116906338ed1739908690614d6e9061271090611991908990613da8565b601354600654614d8f916001600160a01b0361010090910481169116613815565b30426040518663ffffffff1660e01b8152600401614db1959493929190615e6c565b600060405180830381600087803b158015614dcb57600080fd5b505af1158015614ddf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614e079190810190615694565b9050614e3381600183510381518110614e1c57fe5b602002602001015184613b4690919063ffffffff16565b915050915091565b600080614e4783613fd3565b90506000614e6b600a610de1601e5461199161271087613da890919063ffffffff16565b6018546006546013549293506060926001600160a01b0392831692638803dbee9289928792614ea292811691610100900416613815565b30426040518663ffffffff1660e01b8152600401614ec4959493929190615e6c565b600060405180830381600087803b158015614ede57600080fd5b505af1158015614ef2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614f1a9190810190615694565b9050614f438382600081518110614f2d57fe5b6020026020010151613b4690919063ffffffff16565b95945050505050565b600080614f58836153f2565b601854601e549192506060916001600160a01b03909116906338ed1739908690614f8b9061271090611991908890613da8565b600654601354614fac916001600160a01b0390811691610100900416613815565b30426040518663ffffffff1660e01b8152600401614fce959493929190615e6c565b600060405180830381600087803b158015614fe857600080fd5b505af1158015614ffc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526150249190810190615694565b9050613522611c0f82600184510381518110614e1c57fe5b6014546040516370a0823160e01b81526000916001600160a01b0316906370a082319061506d903090600401615a1b565b60206040518083038186803b15801561508557600080fd5b505afa158015615099573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150bd91906158b8565b905060006150c96135cb565b905060006150d783836135fc565b905060006150f06150e6612bca565b6119918785613da8565b90506000838583031015615107575083810361510a565b50825b61511381615412565b61511b614946565b600061512561277f565b905080615133886002613de2565b1161514b57615146611b67886002613de2565b615154565b61515481613f63565b61515c614b5a565b50505050505050565b6000615170826153f2565b9050611c9c8161463e565b615183614931565b61518b614946565b611279611b6761277f565b60215460ff16156151a657612231565b6000806151b28361542f565b915091506151c561144383611fbc6123e8565b6151ce8161463e565b6151de6151d96133e3565b614683565b6125f16147f3565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590613522575050151592915050565b601760009054906101000a90046001600160a01b03166001600160a01b0316633d18b9126040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561526f57600080fd5b505af1158015615283573d6000803e3d6000fd5b50505050565b6016546040516370a0823160e01b81526000916001600160a01b0316906370a08231906152ba903090600401615a1b565b60206040518083038186803b1580156152d257600080fd5b505afa1580156152e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061530a91906158b8565b9050806153175750611279565b6018546016546006546001600160a01b03928316926338ed17399285926000926153449281169116613815565b30426040518663ffffffff1660e01b8152600401615366959493929190615e6c565b600060405180830381600087803b15801561538057600080fd5b505af1158015615394573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109d29190810190615694565b801561223157601754604051632e1a7d4d60e01b81526001600160a01b0390911690632e1a7d4d90613f9e908490600401615e4a565b60008060006153ff612619565b9092509050613522826119918684613da8565b61541a6135cb565b81111561542657600080fd5b612231816153bc565b600080600061543c611e71565b90506000615448611969565b9050600061545960026122546133e3565b90506000615465612e0b565b9050600061547e84600d54613da890919063ffffffff16565b90506000838311156154dc576154d561549d8461225489612710613da8565b611fbc6154b46154ad8789613b46565b8690613da8565b610de1670de0b6b3a76400006122548f600d54613da890919063ffffffff16565b9050615523565b6155206154ef8461225489612710613da8565b611fbc6154ff6154ad8888613b46565b611fbc670de0b6b3a76400006122548f600d54613da890919063ffffffff16565b90505b61554661553f613abd61553885612710613de2565b89906135fc565b8290613de2565b9650615570615569670de0b6b3a76400006119918861225488611fbc8e8c6135fc565b8a90613b46565b9750505050505050915091565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106155be5782800160ff198235161785556155eb565b828001600101855582156155eb579182015b828111156155eb5782358255916020019190600101906155d0565b506155f7929150615647565b5090565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5b808211156155f75760008155600101615648565b60006020828403121561566d578081fd5b813561362181615f7d565b600060208284031215615689578081fd5b815161362181615f7d565b600060208083850312156156a6578182fd5b825167ffffffffffffffff8111156156bc578283fd5b8301601f810185136156cc578283fd5b80516156df6156da82615f31565b615f0a565b81815283810190838501858402850186018910156156fb578687fd5b8694505b8385101561571d5780518352600194909401939185019185016156ff565b50979650505050505050565b60006020828403121561573a578081fd5b813561362181615f92565b600060208284031215615756578081fd5b815161362181615f92565b60008060208385031215615773578081fd5b823567ffffffffffffffff8082111561578a578283fd5b818501915085601f83011261579d578283fd5b8135818111156157ab578384fd5b8660208285010111156157bc578384fd5b60209290920196919550909350505050565b60006101208083850312156157e1578182fd5b6157ea81615f0a565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b600080600060608486031215615860578081fd5b835161586b81615fa0565b602085015190935061587c81615fa0565b604085015190925063ffffffff81168114615895578182fd5b809150509250925092565b6000602082840312156158b1578081fd5b5035919050565b6000602082840312156158c9578081fd5b5051919050565b600080604083850312156158e2578182fd5b505080516020909101519092909150565b600080600060608486031215615907578283fd5b505081359360208301359350604090920135919050565b600080600060608486031215615932578081fd5b8351925060208401519150604084015190509250925092565b60008060008060808587031215615960578182fd5b843593506020850135925060408501359150606085013561598081615f92565b939692955090935050565b600080600080608085870312156159a0578182fd5b5050823594602084013594506040840135936060013592509050565b6000815180845260208085019450808401835b838110156159f45781516001600160a01b0316875295820195908201906001016159cf565b509495945050505050565b60008251615a11818460208701615f51565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039788168152958716602087015260408601949094526060850192909252608084015290921660a082015260c081019190915260e00190565b6001600160a01b039889168152968816602088015260408701959095526060860193909352608085019190915260a084015290921660c082015260e08101919091526101000190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b03948516815260208101939093529216604082015261ffff909116606082015260800190565b6001600160a01b03948516815260208101939093526040830191909152909116606082015260800190565b6001600160a01b0395861681526020810194909452604084019290925261ffff166060830152909116608082015260a00190565b901515815260200190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b6000602082528251806020840152615bf3816040850160208701615f51565b601f01601f19169190910160400192915050565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b90815260200190565b60008382526040602083015261352260408301846159bc565b600086825285602083015260a06040830152615e8b60a08301866159bc565b6001600160a01b0394909416606083015250608001529392505050565b918252602082015260400190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff81118282101715615f2957600080fd5b604052919050565b600067ffffffffffffffff821115615f47578081fd5b5060209081020190565b60005b83811015615f6c578181015183820152602001615f54565b838111156152835750506000910152565b6001600160a01b038116811461223157600080fd5b801515811461223157600080fd5b6001600160701b038116811461223157600080fdfea2646970667358221220d096963a5bf31fca9d70dcde4162518f8f6cb6b060878ea64df0cc7122a65ca764736f6c634300060c00330000000000000000000000007a6fc041274ff996e2761e02f4b3b4b0f16e955a

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

0000000000000000000000007a6fc041274ff996e2761e02f4b3b4b0f16e955a

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

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000007a6fc041274ff996e2761e02f4b3b4b0f16e955a


Deployed ByteCode Sourcemap

178370:2601:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130313:444;;;;;;:::i;:::-;;:::i;:::-;;101335:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;144442:120;;;:::i;111873:175::-;;;;;;:::i;:::-;;:::i;107349:162::-;;;;;;:::i;:::-;;:::i;104687:28::-;;;:::i;:::-;;;;;;;:::i;143199:24::-;;;:::i;103362:18::-;;;:::i;:::-;;;;;;;:::i;103271:25::-;;;:::i;115275:148::-;;;:::i;:::-;;;;;;;:::i;101734:91::-;;;:::i;104323:29::-;;;:::i;167530:141::-;;;:::i;126717:515::-;;;;;;:::i;:::-;;:::i;149366:458::-;;;;;;:::i;:::-;;:::i;142370:19::-;;;:::i;109922:154::-;;;;;;:::i;:::-;;:::i;142877:33::-;;;:::i;142013:31::-;;;:::i;179646:393::-;;;:::i;120372:170::-;;;:::i;150025:180::-;;;:::i;124851:1622::-;;;:::i;155555:177::-;;;:::i;149832:185::-;;;:::i;104766:25::-;;;:::i;169249:140::-;;;:::i;148955:403::-;;;;;;:::i;:::-;;:::i;119611:432::-;;;;;;:::i;:::-;;:::i;101391:25::-;;;:::i;148515:179::-;;;;;;:::i;:::-;;:::i;108679:174::-;;;;;;:::i;:::-;;:::i;112351:171::-;;;;;;:::i;:::-;;:::i;146819:287::-;;;;;;:::i;155740:341::-;;;:::i;141893:34::-;;;:::i;148115:392::-;;;;;;:::i;:::-;;:::i;142843:25::-;;;:::i;151674:306::-;;;:::i;165956:141::-;;;:::i;142266:33::-;;;:::i;142728:35::-;;;:::i;104509:27::-;;;:::i;103141:94::-;;;:::i;148702:245::-;;;;;;:::i;:::-;;:::i;111147:169::-;;;;;;:::i;:::-;;:::i;104172:29::-;;;:::i;103303:22::-;;;:::i;141934:33::-;;;:::i;169397:110::-;;;:::i;107519:171::-;;;;;;:::i;:::-;;:::i;103332:21::-;;;:::i;150213:117::-;;;;;;:::i;:::-;;:::i;142973:42::-;;;:::i;143099:28::-;;;:::i;101423:26::-;;;:::i;166341:469::-;;;:::i;:::-;;;;;;;;:::i;141974:32::-;;;:::i;169009:112::-;;;:::i;107923:202::-;;;;;;:::i;:::-;;:::i;168515:121::-;;;:::i;128004:281::-;;;;;;:::i;:::-;;:::i;143036:40::-;;;:::i;152081:289::-;;;:::i;166192:141::-;;;:::i;167725:241::-;;;:::i;109142:263::-;;;;;;:::i;:::-;;:::i;168031:182::-;;;:::i;122309:1736::-;;;;;;:::i;:::-;;:::i;165688:203::-;;;:::i;165499:135::-;;;:::i;110593:154::-;;;;;;:::i;:::-;;:::i;142051:39::-;;;:::i;168702:131::-;;;:::i;141853:33::-;;;:::i;142308:31::-;;;:::i;103243:21::-;;;:::i;128714:173::-;;;:::i;169129:112::-;;;:::i;130313:444::-;105392:12;:10;:12::i;:::-;-1:-1:-1;;;;;105378:26:0;:10;-1:-1:-1;;;;;105378:26:0;;105370:50;;;;-1:-1:-1;;;105370:50:0;;;;;;;:::i;:::-;;;;;;;;;130405:4:::1;::::0;-1:-1:-1;;;;;130387:23:0;;::::1;130405:4:::0;::::1;130387:23;;130379:41;;;;-1:-1:-1::0;;;130379:41:0::1;;;;;;;:::i;:::-;130457:5;::::0;-1:-1:-1;;;;;130439:24:0;;::::1;130457:5:::0;::::1;130439:24;;130431:44;;;;-1:-1:-1::0;;;130431:44:0::1;;;;;;;:::i;:::-;130488:33;130524:17;:15;:17::i;:::-;130488:53;;130557:9;130552:102;130572:16;:23;130568:1;:27;130552:102;;;130620:16;130637:1;130620:19;;;;;;;;;;;;;;-1:-1:-1::0;;;;;130610:29:0::1;:6;-1:-1:-1::0;;;;;130610:29:0::1;;;130602:52;;;;-1:-1:-1::0;;;130602:52:0::1;;;;;;;:::i;:::-;130597:3;;130552:102;;;;130667:82;130695:12;:10;:12::i;:::-;130709:39;::::0;-1:-1:-1;;;130709:39:0;;-1:-1:-1;;;;;130709:24:0;::::1;::::0;::::1;::::0;:39:::1;::::0;130742:4:::1;::::0;130709:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;130667:27:0;::::1;::::0;:82;:27:::1;:82::i;:::-;105431:1;130313:444:::0;:::o;101335:25::-;;;;;;;;;;;;;;;-1:-1:-1;;101335:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;144442:120::-;144516:38;;;;;;;;;;;;;;;;;144442:120;;:::o;111873:175::-;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;111958:13:::1;:30:::0;;;112004:36:::1;::::0;::::1;::::0;::::1;::::0;111974:14;;112004:36:::1;:::i;:::-;;;;;;;;111873:175:::0;:::o;107349:162::-;105849:5;;;;;;;;;-1:-1:-1;;;;;105849:5:0;-1:-1:-1;;;;;105849:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105835:32:0;:10;-1:-1:-1;;;;;105835:32:0;;:62;;;;105885:12;:10;:12::i;:::-;-1:-1:-1;;;;;105871:26:0;:10;-1:-1:-1;;;;;105871:26:0;;105835:62;105827:86;;;;-1:-1:-1;;;105827:86:0;;;;;;;:::i;:::-;107438:28:::1;107453:12;107438:28;;;;;;:::i;:::-;;;;;;;;107477:11;:26:::0;;-1:-1:-1;;;;;107477:26:0;;::::1;;;-1:-1:-1::0;;;;;;107477:26:0;;::::1;::::0;;;::::1;::::0;;107349:162::o;104687:28::-;;;;:::o;143199:24::-;;;;:::o;103362:18::-;;;-1:-1:-1;;;;;103362:18:0;;:::o;103271:25::-;;;-1:-1:-1;;;;;103271:25:0;;:::o;115275:148::-;115340:5;;:31;;-1:-1:-1;;;115340:31:0;;115316:4;;;;-1:-1:-1;;;;;115340:5:0;;;;:16;;:31;;115365:4;;115340:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;:45;:75;;;;115414:1;115389:22;:20;:22::i;:::-;:26;115340:75;115333:82;;115275:148;:::o;101734:91::-;101803:14;;;;;;;;;;;;-1:-1:-1;;;101803:14:0;;;;101734:91;:::o;104323:29::-;;;;:::o;167530:141::-;167626:11;;:36;;-1:-1:-1;;;167626:36:0;;167579:7;;167606:57;;-1:-1:-1;;;;;167626:11:0;;;;:21;;:36;;167656:4;;167626:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;167606:15;:13;:15::i;:::-;:19;;:57::i;126717:515::-;126832:5;;126776:13;;-1:-1:-1;;;;;126832:5:0;126810:10;:28;126802:47;;;;-1:-1:-1;;;126802:47:0;;;;;;;:::i;:::-;126935:19;126988:32;127006:13;126988:17;:32::i;:::-;127112:4;;126965:55;;-1:-1:-1;126965:55:0;;-1:-1:-1;127112:42:0;;-1:-1:-1;;;;;127112:4:0;127130:10;126965:55;127112:17;:42::i;:::-;126717:515;;;;:::o;149366:458::-;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;142961:5:::1;149550:6;:25;;149542:34;;;::::0;::::1;;149587:11;:20:::0;;;149626;;::::1;149618:29;;;::::0;::::1;;149676:7;149666:6;:17;;149658:26;;;::::0;::::1;;149714:6;149703:7;:17;;149695:26;;;::::0;::::1;;-1:-1:-1::0;149732:11:0::1;:20:::0;149763:12:::1;:22:::0;149796:11:::1;:20:::0;149366:458::o;142370:19::-;;;;;;-1:-1:-1;;;;;142370:19:0;;:::o;109922:154::-;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;110000:14:::1;:23:::0;;;110039:29:::1;::::0;::::1;::::0;::::1;::::0;110017:6;;110039:29:::1;:::i;142877:33::-:0;;;;:::o;142013:31::-;;;;:::o;179646:393::-;179709:7;179729:15;179747:17;:15;:17::i;:::-;179729:35;-1:-1:-1;179781:12:0;179777:26;;179802:1;179795:8;;;;;179777:26;179856:6;;179945:9;;179965:4;;179816:24;;-1:-1:-1;;;;;179856:6:0;;;;:20;;179895:7;;179921:50;;179945:9;;;179965:4;179921:15;:50::i;:::-;179856:130;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;179856:130:0;;;;;;;;;;;;:::i;:::-;179816:170;;180004:7;180029:1;180012:7;:14;:18;180004:27;;;;;;;;;;;;;;179997:34;;;;179646:393;:::o;120372:170::-;105518:6;;-1:-1:-1;;;;;105518:6:0;105504:10;:20;;:65;;-1:-1:-1;105559:10:0;;-1:-1:-1;;;;;105559:10:0;105545;:24;105504:65;:112;;;;105604:12;:10;:12::i;:::-;-1:-1:-1;;;;;105590:26:0;:10;-1:-1:-1;;;;;105590:26:0;;105504:112;:163;;;;105651:5;;;;;;;;;-1:-1:-1;;;;;105651:5:0;-1:-1:-1;;;;;105651:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105637:30:0;:10;-1:-1:-1;;;;;105637:30:0;;105504:163;:216;;;;105702:5;;;;;;;;;-1:-1:-1;;;;;105702:5:0;-1:-1:-1;;;;;105702:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105688:32:0;:10;-1:-1:-1;;;;;105688:32:0;;105504:216;105482:277;;;;-1:-1:-1;;;105482:277:0;;;;;;;:::i;:::-;120510:5:::1;::::0;:23:::1;::::0;;-1:-1:-1;;;120510:23:0;;;;120495:39:::1;::::0;-1:-1:-1;;;;;120510:5:0::1;::::0;:21:::1;::::0;:23:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:5;:23;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;120495:14;:39::i;:::-;120372:170::o:0;150025:180::-;105518:6;;-1:-1:-1;;;;;105518:6:0;105504:10;:20;;:65;;-1:-1:-1;105559:10:0;;-1:-1:-1;;;;;105559:10:0;105545;:24;105504:65;:112;;;;105604:12;:10;:12::i;:::-;-1:-1:-1;;;;;105590:26:0;:10;-1:-1:-1;;;;;105590:26:0;;105504:112;:163;;;;105651:5;;;;;;;;;-1:-1:-1;;;;;105651:5:0;-1:-1:-1;;;;;105651:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105637:30:0;:10;-1:-1:-1;;;;;105637:30:0;;105504:163;:216;;;;105702:5;;;;;;;;;-1:-1:-1;;;;;105702:5:0;-1:-1:-1;;;;;105702:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105688:32:0;:10;-1:-1:-1;;;;;105688:32:0;;105504:216;105482:277;;;;-1:-1:-1;;;105482:277:0;;;;;;;:::i;:::-;150089:8:::1;::::0;::::1;;150081:17;;;::::0;::::1;;150109:8;:16:::0;;-1:-1:-1;;150109:16:0::1;::::0;;150136:26:::1;150148:13;:11;:13::i;:::-;150136:11;:26::i;:::-;150173:24;150181:15;:13;:15::i;:::-;150173:7;:24::i;124851:1622::-:0;105518:6;;-1:-1:-1;;;;;105518:6:0;105504:10;:20;;:65;;-1:-1:-1;105559:10:0;;-1:-1:-1;;;;;105559:10:0;105545;:24;105504:65;:112;;;;105604:12;:10;:12::i;:::-;-1:-1:-1;;;;;105590:26:0;:10;-1:-1:-1;;;;;105590:26:0;;105504:112;:163;;;;105651:5;;;;;;;;;-1:-1:-1;;;;;105651:5:0;-1:-1:-1;;;;;105651:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105637:30:0;:10;-1:-1:-1;;;;;105637:30:0;;105504:163;:216;;;;105702:5;;;;;;;;;-1:-1:-1;;;;;105702:5:0;-1:-1:-1;;;;;105702:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105688:32:0;:10;-1:-1:-1;;;;;105688:32:0;;105504:216;105482:277;;;;-1:-1:-1;;;105482:277:0;;;;;;;:::i;:::-;124902:14:::1;124931:12:::0;124958:23:::1;124984:5;;;;;;;;;-1:-1:-1::0;;;;;124984:5:0::1;-1:-1:-1::0;;;;;124984:21:0::1;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;125056:13;::::0;124958:49;;-1:-1:-1;125018:19:0::1;::::0;125056:13:::1;;125052:580;;;125138:19;125160:23;:21;:23::i;:::-;125138:45;;125216:15;125202:11;:29;125198:226;;;125259:32;:15:::0;125279:11;125259:19:::1;:32::i;:::-;125252:39;;125198:226;;;125331:15;125317:11;:29;125313:111;;;125376:32;:11:::0;125392:15;125376::::1;:32::i;:::-;125367:41;;125313:111;125452:25;:15:::0;125472:4;125452:19:::1;:25::i;:::-;125438:39;;125052:580;;;;125590:30;125604:15;125590:13;:30::i;:::-;125560:60:::0;;-1:-1:-1;125560:60:0;-1:-1:-1;125560:60:0;-1:-1:-1;125052:580:0::1;125848:5;::::0;:31:::1;::::0;-1:-1:-1;;;125848:31:0;;125828:17:::1;::::0;-1:-1:-1;;;;;125848:5:0::1;::::0;:16:::1;::::0;:31:::1;::::0;125873:4:::1;::::0;125848:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;::::0;125918:5:::1;::::0;:39:::1;::::0;-1:-1:-1;;;125918:39:0;;125848:41;;-1:-1:-1;;;;;;125918:5:0::1;::::0;:12:::1;::::0;:39:::1;::::0;125931:6;;125939:4;;125945:11;;125918:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;125900:57;;126033:31;126048:15;126033:14;:31::i;:::-;126119:13;::::0;::::1;;:42:::0;::::1;;;-1:-1:-1::0;126136:11:0::1;::::0;::::1;::::0;::::1;-1:-1:-1::0;;;;;126136:11:0::1;:25:::0;::::1;126119:42;126115:280;;;126198:11;::::0;126186:85:::1;::::0;-1:-1:-1;;;126186:85:0;;126198:11:::1;::::0;;::::1;-1:-1:-1::0;;;;;126198:11:0::1;::::0;126186:30:::1;::::0;:85:::1;::::0;126217:6;;126225:4;;126231:11;;126244:15;;126261:9;;126186:85:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;126178:110;;;;-1:-1:-1::0;;;126178:110:0::1;;;;;;;:::i;:::-;126115:280;;;126326:22;126343:4;126326:22;;;;;;:::i;:::-;;;;;;;;126379:4;126363:20:::0;;-1:-1:-1;;126363:20:0::1;::::0;::::1;::::0;;126115:280:::1;126412:53;126422:6;126430:4;126436:11;126449:15;126412:53;;;;;;;;;:::i;:::-;;;;;;;;105770:1;;;;;124851:1622::o:0;155555:177::-;155598:7;155619:16;155637:17;155658:15;:13;:15::i;:::-;155618:55;;-1:-1:-1;155618:55:0;-1:-1:-1;155691:33:0;155618:55;155691:18;155618:55;155704:4;155691:12;:18::i;:::-;:22;;:33::i;:::-;155684:40;;;;155555:177;:::o;149832:185::-;105518:6;;-1:-1:-1;;;;;105518:6:0;105504:10;:20;;:65;;-1:-1:-1;105559:10:0;;-1:-1:-1;;;;;105559:10:0;105545;:24;105504:65;:112;;;;105604:12;:10;:12::i;:::-;-1:-1:-1;;;;;105590:26:0;:10;-1:-1:-1;;;;;105590:26:0;;105504:112;:163;;;;105651:5;;;;;;;;;-1:-1:-1;;;;;105651:5:0;-1:-1:-1;;;;;105651:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105637:30:0;:10;-1:-1:-1;;;;;105637:30:0;;105504:163;:216;;;;105702:5;;;;;;;;;-1:-1:-1;;;;;105702:5:0;-1:-1:-1;;;;;105702:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105688:32:0;:10;-1:-1:-1;;;;;105688:32:0;;105504:216;105482:277;;;;-1:-1:-1;;;105482:277:0;;;;;;;:::i;:::-;149895:8:::1;::::0;::::1;;149894:9;149886:18;;;::::0;::::1;;149915:31;:29;:31::i;:::-;;;149957:26;149967:15;:13;:15::i;:::-;149957:9;:26::i;:::-;149994:8;:15:::0;;-1:-1:-1;;149994:15:0::1;150005:4;149994:15;::::0;;149832:185::o;104766:25::-;;;;;;:::o;169249:140::-;169349:5;;:30;;-1:-1:-1;;;169349:30:0;;169300:7;;169328:52;;169349:5;;;;-1:-1:-1;;;;;169349:5:0;;:15;;:30;;169373:4;;169349:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;169328:20;:52::i;148955:403::-;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;142961:5:::1;149118:6;:25;;149110:34;;;::::0;::::1;;142961:5;149163:17;:36;;149155:45;;;::::0;::::1;;142961:5;149219:6;:25;;149211:34;;;::::0;::::1;;149256:16;:36:::0;149303:9:::1;:18:::0;149332:9:::1;:18:::0;148955:403::o;119611:432::-;119684:4;119611:432;;;;:::o;101391:25::-;;;;;;:::o;148515:179::-;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;148608:9:::1;::::0;-1:-1:-1;;;;;148608:9:0::1;148600:32:::0;148592:41:::1;;;::::0;::::1;;148644:9;:42:::0;;-1:-1:-1;;;;;;148644:42:0::1;-1:-1:-1::0;;;;;148644:42:0;;;::::1;::::0;;;::::1;::::0;;148515:179::o;108679:174::-;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;108758:21:0;::::1;108750:30;;;::::0;::::1;;108791:6;:16:::0;;-1:-1:-1;;;;;;108791:16:0::1;-1:-1:-1::0;;;;;108791:16:0;::::1;;::::0;;108823:22:::1;::::0;::::1;::::0;::::1;::::0;108791:16;;108823:22:::1;:::i;112351:171::-:0;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;112440:26:::1;:11;112454:12:::0;;112440:26:::1;:::i;:::-;;112482:32;112501:12;;112482:32;;;;;;;:::i;:::-;;;;;;;;112351:171:::0;;:::o;155740:341::-;155829:6;;155858:5;;155829:36;;-1:-1:-1;;;155829:36:0;;155787:7;;;;-1:-1:-1;;;;;155829:6:0;;;;:20;;:36;;:6;155858:5;;;;155829:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;155897:6;;155926:4;;155897:35;;-1:-1:-1;;;155897:35:0;;155807:58;;-1:-1:-1;155876:18:0;;-1:-1:-1;;;;;155897:6:0;;;;:20;;:35;;155926:4;;;155897:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;156009:13;;155876:56;;-1:-1:-1;155963:110:0;;155876:56;;155963:62;;155984:39;;156009:13;-1:-1:-1;;;156009:13:0;;;;;155984:20;;-1:-1:-1;;;155984:12:0;;;;156001:2;155984:16;:20::i;:::-;:24;;:39::i;:::-;155963:11;;155979:2;:45;155963:15;:62::i;141893:34::-;;;;:::o;148115:392::-;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;148324:11:::1;:26:::0;;;;148361:21:::1;:46:::0;148418:19:::1;:42:::0;148471:12:::1;:28:::0;;-1:-1:-1;;148471:28:0::1;::::0;::::1;;::::0;;;::::1;::::0;;148115:392::o;142843:25::-;;;-1:-1:-1;;;;;142843:25:0;;:::o;151674:306::-;105518:6;;-1:-1:-1;;;;;105518:6:0;105504:10;:20;;:65;;-1:-1:-1;105559:10:0;;-1:-1:-1;;;;;105559:10:0;105545;:24;105504:65;:112;;;;105604:12;:10;:12::i;:::-;-1:-1:-1;;;;;105590:26:0;:10;-1:-1:-1;;;;;105590:26:0;;105504:112;:163;;;;105651:5;;;;;;;;;-1:-1:-1;;;;;105651:5:0;-1:-1:-1;;;;;105651:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105637:30:0;:10;-1:-1:-1;;;;;105637:30:0;;105504:163;:216;;;;105702:5;;;;;;;;;-1:-1:-1;;;;;105702:5:0;-1:-1:-1;;;;;105702:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105688:32:0;:10;-1:-1:-1;;;;;105688:32:0;;105504:216;105482:277;;;;-1:-1:-1;;;105482:277:0;;;;;;;:::i;:::-;151797:8:::1;::::0;::::1;;151796:9;151788:18;;;::::0;::::1;;151817:19;151839:16;:14;:16::i;:::-;151817:38;;151889:11;;151874;:26;;:56;;;;151919:11;;151904;:26;;151874:56;151866:65;;;::::0;::::1;;151942:30;:28;:30::i;:::-;105770:1;151674:306::o:0;165956:141::-;166002:7;166030:58;166076:11;:9;:11::i;:::-;166030:41;166069:1;166030:34;142961:5;166030:13;:11;:13::i;:::-;:17;;:34::i;142266:33::-;;;;:::o;142728:35::-;;;-1:-1:-1;;;;;142728:35:0;;:::o;104509:27::-;;;;:::o;103141:94::-;103199:7;103141:94;:::o;148702:245::-;105392:12;:10;:12::i;:::-;-1:-1:-1;;;;;105378:26:0;:10;-1:-1:-1;;;;;105378:26:0;;105370:50;;;;-1:-1:-1;;;105370:50:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;148794:36:0;::::1;::::0;148786:45:::1;;;::::0;::::1;;148842:9;::::0;:41:::1;::::0;-1:-1:-1;;;148842:41:0;;-1:-1:-1;;;;;148842:9:0;;::::1;::::0;:26:::1;::::0;:41:::1;::::0;148869:13;;148842:41:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;148894:9:0::1;:45:::0;;-1:-1:-1;;;;;;148894:45:0::1;-1:-1:-1::0;;;;;148894:45:0;;;::::1;::::0;;;::::1;::::0;;;-1:-1:-1;;148702:245:0:o;111147:169::-;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;111230:12:::1;:28:::0;;;111274:34:::1;::::0;::::1;::::0;::::1;::::0;111245:13;;111274:34:::1;:::i;104172:29::-:0;;;;:::o;103303:22::-;;;-1:-1:-1;;;;;103303:22:0;;:::o;141934:33::-;;;;:::o;169397:110::-;169468:6;;:31;;-1:-1:-1;;;169468:31:0;;169441:7;;-1:-1:-1;;;;;169468:6:0;;:16;;:31;;169493:4;;169468:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;107519:171::-;105849:5;;;;;;;;;-1:-1:-1;;;;;105849:5:0;-1:-1:-1;;;;;105849:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105835:32:0;:10;-1:-1:-1;;;;;105835:32:0;;:62;;;;105885:12;:10;:12::i;:::-;-1:-1:-1;;;;;105871:26:0;:10;-1:-1:-1;;;;;105871:26:0;;105835:62;105827:86;;;;-1:-1:-1;;;105827:86:0;;;;;;;:::i;:::-;107609:32:::1;107626:14;107609:32;;;;;;:::i;:::-;;;;;;;;107652:13;:30:::0;;-1:-1:-1;;107652:30:0::1;::::0;::::1;;::::0;;;::::1;::::0;;107519:171::o;103332:21::-;;;-1:-1:-1;;;;;103332:21:0;;:::o;150213:117::-;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;150296:26:::1;150314:7;150296:17;:26::i;:::-;;;150213:117:::0;:::o;142973:42::-;;;;:::o;143099:28::-;;;;;;:::o;101423:26::-;;;;;;-1:-1:-1;;;;;101423:26:0;;:::o;166341:469::-;166414:17;166433:18;166470:17;166489;166512:11;;;;;;;;;-1:-1:-1;;;;;166512:11:0;-1:-1:-1;;;;;166512:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;166584:4:0;;166552:11;;:20;;;-1:-1:-1;;;166552:20:0;;;;166469:68;;-1:-1:-1;166469:68:0;;-1:-1:-1;;;;;;166584:4:0;;;;166552:11;;;:18;;:20;;;;;;;;;;;;;;:11;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;166552:37:0;;166548:255;;;166626:9;-1:-1:-1;;;;;166618:18:0;166606:30;;166672:9;-1:-1:-1;;;;;166664:18:0;166651:31;;166548:255;;;166735:9;-1:-1:-1;;;;;166727:18:0;166715:30;;166781:9;-1:-1:-1;;;;;166773:18:0;166760:31;;166548:255;166341:469;;;;:::o;141974:32::-;;;;:::o;169009:112::-;169083:4;;:29;;-1:-1:-1;;;169083:29:0;;169055:7;;-1:-1:-1;;;;;169083:4:0;;:14;;:29;;169106:4;;169083:29;;;:::i;107923:202::-;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;108010:25:0;::::1;108002:34;;;::::0;::::1;;108047:10;:24:::0;;-1:-1:-1;;;;;;108047:24:0::1;-1:-1:-1::0;;;;;108047:24:0;::::1;;::::0;;108087:30:::1;::::0;::::1;::::0;::::1;::::0;108047:24;;108087:30:::1;:::i;168515:121::-:0;168559:7;168586:42;168607:20;:18;:20::i;128004:281::-;128093:5;;-1:-1:-1;;;;;128093:5:0;128071:10;:28;128063:37;;;;;;128157:5;;128119:34;;;-1:-1:-1;;;128119:34:0;;;;-1:-1:-1;;;;;128157:5:0;;;;128119:32;;;;;:34;;;;;;;;;;;;;;:32;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;128119:43:0;;128111:52;;;;;;128174:30;128191:12;128174:16;:30::i;:::-;128247:4;;:29;;-1:-1:-1;;;128247:29:0;;128215:62;;128233:12;;-1:-1:-1;;;;;128247:4:0;;;;:14;;:29;;128270:4;;128247:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;128215:4;;-1:-1:-1;;;;;128215:4:0;;:62;:17;:62::i;143036:40::-;;;;:::o;152081:289::-;105518:6;;-1:-1:-1;;;;;105518:6:0;105504:10;:20;;:65;;-1:-1:-1;105559:10:0;;-1:-1:-1;;;;;105559:10:0;105545;:24;105504:65;:112;;;;105604:12;:10;:12::i;:::-;-1:-1:-1;;;;;105590:26:0;:10;-1:-1:-1;;;;;105590:26:0;;105504:112;:163;;;;105651:5;;;;;;;;;-1:-1:-1;;;;;105651:5:0;-1:-1:-1;;;;;105651:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105637:30:0;:10;-1:-1:-1;;;;;105637:30:0;;105504:163;:216;;;;105702:5;;;;;;;;;-1:-1:-1;;;;;105702:5:0;-1:-1:-1;;;;;105702:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105688:32:0;:10;-1:-1:-1;;;;;105688:32:0;;105504:216;105482:277;;;;-1:-1:-1;;;105482:277:0;;;;;;;:::i;:::-;152147:8:::1;::::0;::::1;;152146:9;152138:18;;;::::0;::::1;;152167:17;152187:15;:13;:15::i;:::-;152167:35;;152233:9;;152221;:21;:46;;;;152258:9;;152246;:21;152221:46;152213:55;;;::::0;::::1;;152287:39;152304:21;;152287:16;:39::i;:::-;152279:48;;;::::0;::::1;;152338:24;:22;:24::i;166192:141::-:0;166239:7;166266:59;166311:13;:11;:13::i;:::-;166266:40;142961:5;166266:19;:17;:19::i;167725:241::-;167767:7;167788:16;167810:15;:13;:15::i;:::-;167787:38;;;167856:102;167918:11;;;;;;;;;-1:-1:-1;;;;;167918:11:0;-1:-1:-1;;;;;167918:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;167856:39;167893:1;167856:32;167879:8;167856:18;:16;:18::i;:102::-;167836:122;;;167725:241;:::o;109142:263::-;105279:10;;-1:-1:-1;;;;;105279:10:0;105265;:24;105257:48;;;;-1:-1:-1;;;105257:48:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;109223:22:0;::::1;109215:31;;;::::0;::::1;;109257:5;::::0;109271:7:::1;::::0;;109257:25:::1;::::0;-1:-1:-1;;;109257:25:0;;-1:-1:-1;;;;;109257:5:0;;::::1;::::0;:13:::1;::::0;:25:::1;::::0;109271:7;;::::1;::::0;109257:5:::1;::::0;:25:::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;109293:7:0::1;:18:::0;;-1:-1:-1;;;;;;109293:18:0::1;-1:-1:-1::0;;;;;109293:18:0;;::::1;::::0;;;::::1;::::0;;;109322:5:::1;::::0;:35:::1;::::0;-1:-1:-1;;;109322:35:0;;:5;;::::1;::::0;:13:::1;::::0;:35:::1;::::0;109336:7:::1;::::0;-1:-1:-1;;109353:2:0;109322:35:::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;109373:24;109388:8;109373:24;;;;;;:::i;168031:182::-:0;168171:9;;:34;;-1:-1:-1;;;168171:34:0;;168082:7;;-1:-1:-1;;;;;168171:9:0;;:19;;:34;;168199:4;;168171:34;;;:::i;122309:1736::-;122385:4;122402:16;122421:24;122431:13;122421:9;:24::i;:::-;122402:43;;122456:28;;:::i;:::-;122487:5;;:31;;-1:-1:-1;;;122487:31:0;;-1:-1:-1;;;;;122487:5:0;;;;:16;;:31;;122512:4;;122487:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;122456:62;;122595:6;:17;;;122616:1;122595:22;122591:40;;;122626:5;122619:12;;;;;;122591:40;122776:14;;122755:17;;;;122735:38;;:15;;:19;:38::i;:::-;:55;122731:73;;;122799:5;122792:12;;;;;;122731:73;122923:14;;122901:17;;;;122881:38;;:15;;:19;:38::i;:::-;:56;122877:73;;122946:4;122939:11;;;;;;122877:73;123380:5;;:23;;;-1:-1:-1;;;123380:23:0;;;;123358:19;;-1:-1:-1;;;;;123380:5:0;;:21;;:23;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123358:45;;123432:13;;123418:11;:27;123414:44;;;123454:4;123447:11;;;;;;;123414:44;123512:13;123528:22;:20;:22::i;:::-;123512:38;;123640:6;:16;;;123613:24;123623:13;;123613:5;:9;;:24;;;;:::i;:::-;:43;123609:60;;;123665:4;123658:11;;;;;;;;123609:60;123682:14;123723:6;:16;;;123715:5;:24;123711:66;;;123760:16;;;;123750:27;;:5;;:9;:27::i;:::-;123741:36;;123711:66;123947:5;;:23;;;-1:-1:-1;;;123947:23:0;;;;123930:14;;-1:-1:-1;;;;;123947:5:0;;:21;;:23;;;;;;;;;;;;;;:5;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123930:40;-1:-1:-1;124018:18:0;123930:40;124029:6;124018:10;:18::i;:::-;123989:12;;:26;;124006:8;123989:16;:26::i;:::-;:47;;122309:1736;-1:-1:-1;;;;;;;;122309:1736:0:o;165688:203::-;165736:7;165776:107;165855:13;:11;:13::i;:::-;165776:56;165811:20;:18;:20::i;:::-;165776:30;165794:11;:9;:11::i;:::-;165776:13;:11;:13::i;165499:135::-;165561:7;165588:38;165608:17;:15;:17::i;:::-;165588:15;:13;:15::i;110593:154::-;104877:10;;-1:-1:-1;;;;;104877:10:0;104863;:24;;:54;;;104905:12;:10;:12::i;:::-;-1:-1:-1;;;;;104891:26:0;:10;-1:-1:-1;;;;;104891:26:0;;104863:54;104855:78;;;;-1:-1:-1;;;104855:78:0;;;;;;;:::i;:::-;110671:14:::1;:23:::0;;;110710:29:::1;::::0;::::1;::::0;::::1;::::0;110688:6;;110710:29:::1;:::i;142051:39::-:0;;;;:::o;168702:131::-;168752:7;168779:46;168804:20;:18;:20::i;:::-;168779:24;:46::i;141853:33::-;;;;:::o;142308:31::-;;;;;;:::o;103243:21::-;;;-1:-1:-1;;;;;103243:21:0;;:::o;128714:173::-;105043:10;;-1:-1:-1;;;;;105043:10:0;105029;:24;;:54;;;105071:12;:10;:12::i;:::-;-1:-1:-1;;;;;105057:26:0;:10;-1:-1:-1;;;;;105057:26:0;;105029:54;:88;;;;105101:5;;;;;;;;;-1:-1:-1;;;;;105101:5:0;-1:-1:-1;;;;;105101:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105087:30:0;:10;-1:-1:-1;;;;;105087:30:0;;105029:88;:124;;;;105135:5;;;;;;;;;-1:-1:-1;;;;;105135:5:0;-1:-1:-1;;;;;105135:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;105121:32:0;:10;-1:-1:-1;;;;;105121:32:0;;105029:124;105007:185;;;;-1:-1:-1;;;105007:185:0;;;;;;;:::i;:::-;128786:13:::1;:20:::0;;-1:-1:-1;;128786:20:0::1;128802:4;128786:20;::::0;;128817:5:::1;::::0;:22:::1;::::0;;-1:-1:-1;;;128817:22:0;;;;-1:-1:-1;;;;;128817:5:0;;::::1;::::0;:20:::1;::::0;:22:::1;::::0;;::::1;::::0;128786:13:::1;::::0;128817:22;;;;;;;;128786:13;128817:5;:22;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;128857:22:0::1;::::0;::::1;::::0;-1:-1:-1;128857:22:0;;-1:-1:-1;128857:22:0::1;128714:173::o:0;169129:112::-;169202:5;;:30;;-1:-1:-1;;;169202:30:0;;169174:7;;169202:5;;;-1:-1:-1;;;;;169202:5:0;;:15;;:30;;169226:4;;169202:30;;;:::i;92244:622::-;92614:10;;;92613:62;;-1:-1:-1;92630:39:0;;-1:-1:-1;;;92630:39:0;;-1:-1:-1;;;;;92630:15:0;;;;;:39;;92654:4;;92661:7;;92630:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;92613:62;92605:152;;;;-1:-1:-1;;;92605:152:0;;;;;;;:::i;:::-;92768:90;92788:5;92818:22;;;92842:7;92851:5;92795:62;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;92795:62:0;;;;;;;;;;;;;;-1:-1:-1;;;;;92795:62:0;-1:-1:-1;;;;;;92795:62:0;;;;;;;;;;92768:19;:90::i;3857:196::-;3960:12;3992:53;4015:6;4023:4;4029:1;4032:12;3992:22;:53::i;:::-;3985:60;3857:196;-1:-1:-1;;;;3857:196:0:o;112676:98::-;112748:5;;:18;;;-1:-1:-1;;;112748:18:0;;;;112721:7;;-1:-1:-1;;;;;112748:5:0;;:16;;:18;;;;;;;;;;;;;;:5;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;178058:120::-;178153:16;178058:120;:::o;91585:177::-;91668:86;91688:5;91718:23;;;91743:2;91747:5;91695:58;;;;;;;;;:::i;180824:144::-;180920:14;;180908:52;;-1:-1:-1;;;180908:52:0;;180881:7;;-1:-1:-1;;;;;180920:14:0;;180908:37;;:52;;180954:4;;180908:52;;;:::i;31869:181::-;31927:7;31959:5;;;31983:6;;;;31975:46;;;;-1:-1:-1;;;31975:46:0;;;;;;;:::i;:::-;32041:1;-1:-1:-1;31869:181:0;;;;;:::o;161022:1424::-;161126:25;161153:13;161184:19;161206:15;:13;:15::i;:::-;161184:37;;161232:19;161254:22;:20;:22::i;:::-;161232:44;-1:-1:-1;161576:13:0;161556:17;161620:15;:13;:15::i;:::-;161600:35;;161662:11;161650:9;:23;161646:238;;;161690:13;161706:45;161741:9;161706:30;:11;143169:4;161706:15;:30::i;:45::-;161690:61;-1:-1:-1;161778:43:0;143169:4;161778:24;:13;161690:61;161778:17;:24::i;:43::-;161766:55;-1:-1:-1;161844:28:0;:13;161766:55;161844:17;:28::i;:::-;161836:36;;161646:238;;161939:17;161960:20;161970:9;161960;:20::i;:::-;161936:44;-1:-1:-1;161999:20:0;;-1:-1:-1;161999:5:0;161936:44;161999:9;:20::i;:::-;161991:28;;162215:15;:13;:15::i;:::-;162195:35;-1:-1:-1;162276:13:0;162245:28;162195:35;162267:5;162245:21;:28::i;:::-;:44;162241:198;;;162326:24;:13;162344:5;162326:17;:24::i;:::-;162306:44;;162241:198;;;162391:36;:13;162409:17;162391;:36::i;:::-;162383:44;;162241:198;161022:1424;;;;;;;;:::o;180047:250::-;180254:9;;:34;;-1:-1:-1;;;180254:34:0;;180106:7;;180146:143;;-1:-1:-1;;;;;180254:9:0;;;;:19;;:34;;180282:4;;180254:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;180220:9;;180146:85;;-1:-1:-1;;;180146:85:0;;178588:42;;180146:50;;:85;;180205:4;;-1:-1:-1;;;;;180220:9:0;;;;180146:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;147114:491::-;147317:4;;147228:22;;147268:12;;-1:-1:-1;;;;;147296:26:0;;;147317:4;;;;;147296:26;;:57;;-1:-1:-1;147348:4:0;;-1:-1:-1;;;;;147326:27:0;;;147348:4;;;;;147326:27;147296:57;147268:85;;147386:7;:15;;147400:1;147386:15;;;147396:1;147386:15;147372:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;147372:30:0;;147364:38;;147424:9;147413:5;147419:1;147413:8;;;;;;;;;;;;;:20;-1:-1:-1;;;;;147413:20:0;;;-1:-1:-1;;;;;147413:20:0;;;;;147448:7;147444:154;;;147483:10;147472:5;147478:1;147472:8;;;;;;;;;;;;;:21;-1:-1:-1;;;;;147472:21:0;;;-1:-1:-1;;;;;147472:21:0;;;;;147444:154;;;147545:4;;;;;;;;;-1:-1:-1;;;;;147545:4:0;147526:5;147532:1;147526:8;;;;;;;;;;;;;:24;-1:-1:-1;;;;;147526:24:0;;;-1:-1:-1;;;;;147526:24:0;;;;;147576:10;147565:5;147571:1;147565:8;;;;;;;;;;;;;:21;-1:-1:-1;;;;;147565:21:0;;;-1:-1:-1;;;;;147565:21:0;;;;;147444:154;147114:491;;;;;:::o;146337:350::-;146416:22;146441:15;:13;:15::i;:::-;146416:40;;146491:14;146471:16;:34;146467:73;;146522:7;;;146467:73;146550:16;146569:36;:14;146588:16;146569:18;:36::i;:::-;146550:55;-1:-1:-1;146622:12:0;;146618:62;;146651:17;146659:8;146651:7;:17::i;171012:132::-;171077:4;;171099;;171077:59;;-1:-1:-1;;;171077:59:0;;-1:-1:-1;;;;;171077:4:0;;;;:13;;:59;;171099:4;;;171106:14;;171130:4;;171077:59;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;154552:806::-;154610:8;;;;154606:88;;;154635:26;154645:15;:13;:15::i;154635:26::-;154676:7;;154606:88;154720:9;;154710:7;:19;:52;;;;154733:29;154754:7;154733:20;:29::i;:::-;154706:91;;;154779:7;;154706:91;154807:14;154824:16;:14;:16::i;:::-;154807:33;;154851:15;154869:12;:10;:12::i;:::-;154851:30;;154892:14;154922:194;154980:121;155023:58;155074:6;155023:46;142961:5;155023:25;155040:7;155023:12;;:16;;:25;;;;:::i;:58::-;142961:5;;154980:19;:121::i;:::-;154922:35;154952:4;154922:25;154939:7;154922:12;;:16;;:25;;;;:::i;:194::-;154892:224;-1:-1:-1;155129:22:0;155154:29;155178:4;155154:19;154892:224;155165:7;155154:10;:19::i;:29::-;155129:54;-1:-1:-1;155194:18:0;155215:27;:7;155129:54;155215:11;:27::i;:::-;155194:48;;155253:21;155263:10;155253:9;:21::i;:::-;155285:15;155293:6;155285:7;:15::i;:::-;155311:16;155320:6;155311:8;:16::i;:::-;155338:12;:10;:12::i;:::-;154552:806;;;;;;:::o;150486:183::-;150573:20;150630:31;:29;:31::i;32333:136::-;32391:7;32418:43;32422:1;32425;32418:43;;;;;;;;;;;;;;;;;:3;:43::i;144570:1759::-;144687:15;144717:13;144745:20;144793:19;144815:22;:20;:22::i;:::-;144793:44;;144848:17;144868:15;:13;:15::i;:::-;144848:35;;144912:9;144898:11;:23;144894:602;;;144948:26;:11;144964:9;144948:15;:26::i;:::-;144938:36;-1:-1:-1;144990:19:0;145015:40;145025:29;:16;144938:36;145025:20;:29::i;:::-;145015:9;:40::i;:::-;144989:66;;;145093:11;145074:16;:30;145070:261;;;145140:11;145125:26;;145180:1;145170:11;;145070:261;;;145237:16;;-1:-1:-1;145282:33:0;:11;145237:16;145282:15;:33::i;:::-;145272:43;;145070:261;144894:602;;;;145363:27;145373:16;145363:9;:27::i;:::-;;;145420:15;:13;:15::i;:::-;145405:30;-1:-1:-1;145458:26:0;:9;145472:11;145458:13;:26::i;:::-;145450:34;;144894:602;145519:18;:16;:18::i;:::-;145508:29;;;;145613:7;145604:5;:16;145600:722;;145647:1;;-1:-1:-1;145671:18:0;:5;145647:1;145671:9;:18::i;:::-;145704:9;;:38;;-1:-1:-1;;;145704:38:0;;145663:26;;-1:-1:-1;;;;;;145704:9:0;;:20;;:38;;145725:9;;145663:26;;145704:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;145600:722;;;145785:18;:7;145797:5;145785:11;:18::i;:::-;145886:9;;:42;;-1:-1:-1;;;145886:42:0;;145775:28;;-1:-1:-1;145826:1:0;;-1:-1:-1;145826:1:0;;-1:-1:-1;;;;;145886:9:0;;;;:22;;:42;;145909:9;;145775:28;;145886:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;145842:86;-1:-1:-1;145953:29:0;:7;145842:86;145953:11;:29::i;:::-;145943:39;;146095:1;146076:16;:20;:50;;;;;146119:7;146100:16;:26;146076:50;146072:239;;;146192:4;;146227:9;;146147:148;;-1:-1:-1;;;;;146192:4:0;;;;146227:9;146260:16;146147:22;:148::i;:::-;145600:722;;144570:1759;;;;;;;:::o;33223:471::-;33281:7;33526:6;33522:47;;-1:-1:-1;33556:1:0;33549:8;;33522:47;33593:5;;;33597:1;33593;:5;:1;33617:5;;;;;:10;33609:56;;;;-1:-1:-1;;;33609:56:0;;;;;;;:::i;34170:132::-;34228:7;34255:39;34259:1;34262;34255:39;;;;;;;;;;;;;;;;;:3;:39::i;150677:911::-;150754:20;150776:13;150807:20;:18;:20::i;:::-;150838:14;:12;:14::i;:::-;150865:19;150887:27;:25;:27::i;:::-;150865:49;;150925:16;150944:14;:12;:14::i;:::-;150925:33;;150985:11;150973:8;:23;150969:532;;151013:12;:10;:12::i;:::-;151067:1;151044:20;:18;:20::i;:::-;:24;151040:128;;;151121:5;;:30;;-1:-1:-1;;;151121:30:0;;151101:51;;151121:5;;;-1:-1:-1;;;;;151121:5:0;;:15;;:30;;151145:4;;151121:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;151101:19;:51::i;:::-;151089:63;-1:-1:-1;;151040:128:0;150969:532;;;151200:22;151225:25;:11;151241:8;151225:15;:25::i;:::-;151200:50;;151308:1;151269:36;151290:14;151269:20;:36::i;:::-;:40;151265:198;;;151340:35;151360:14;151340:19;:35::i;:::-;151330:45;;151265:198;;;151416:31;151444:1;151416:19;:31::i;:::-;;151265:198;151477:12;:10;:12::i;:::-;150969:532;;151513:26;151525:13;:11;:13::i;151513:26::-;151565:15;:13;:15::i;:::-;151550:30;;150677:911;;;;:::o;169659:115::-;169714:4;;169734;;169714:52;;-1:-1:-1;;;169714:52:0;;-1:-1:-1;;;;;169714:4:0;;;;:11;;:52;;169734:4;;;169741:6;;169757:4;;169714;;:52;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;169659:115;:::o;166818:251::-;166920:7;166946:16;166964:17;166985:15;:13;:15::i;:::-;166945:55;;-1:-1:-1;166945:55:0;-1:-1:-1;167019:41:0;166945:55;167019:26;:12;166945:55;167019:16;:26::i;153321:1173::-;153381:19;153403:16;:14;:16::i;:::-;153381:38;;153430:16;153449:13;:11;:13::i;:::-;153430:32;;153473:15;153491:13;:11;:13::i;:::-;153473:31;;153535:12;;153521:11;:26;153517:970;;;153564:17;153601:166;153733:33;153753:12;;142961:5;153733:19;;:33;;;;:::i;:::-;153601:105;142961:5;153602:60;153615:46;142961:5;153615:25;153627:12;;153615:7;:11;;:25;;;;:::i;:46::-;153602:8;;:12;:60::i;153601:166::-;153564:203;-1:-1:-1;153882:48:0;153913:16;153564:203;153927:1;153913:13;:16::i;:::-;153882:30;:48::i;:::-;153950:39;;153979:9;;153966:11;;153950:39;;;;;153517:970;;;;154025:12;;154011:11;:26;154007:480;;;154054:17;154091:168;154225:33;154245:12;;142961:5;154225:19;;:33;;;;:::i;:::-;154091:107;142961:5;154092:62;154145:8;154093:46;142961:5;154093:25;154105:12;;154093:7;:11;;:25;;;;:::i;154091:168::-;154054:205;;154274:17;154294:24;154308:9;154294:13;:24::i;:::-;154274:44;;154333:22;154345:9;154333:11;:22::i;:::-;154370:19;154379:9;154370:8;:19::i;:::-;154404:12;:10;:12::i;:::-;154436:39;;154465:9;;154452:11;;154436:39;;;;;154007:480;;153321:1173;;;:::o;146695:116::-;146772:31;:29;:31::i;156196:457::-;156280:12;;156259:4;;156280:12;;156276:348;;;156309:14;156326:16;:14;:16::i;:::-;156309:33;;156357:15;156375:12;:10;:12::i;:::-;156357:30;-1:-1:-1;156402:24:0;156429:40;156357:30;156429:27;:6;142961:5;156429:10;:27::i;:40::-;156402:67;-1:-1:-1;156511:30:0;142961:5;156531:9;156511:19;:30::i;:::-;156492:16;:49;:119;;;;-1:-1:-1;156581:30:0;142961:5;156601:9;156581:19;:30::i;:::-;156562:16;:49;156492:119;156484:128;;;;;;;156276:348;-1:-1:-1;156641:4:0;156196:457;;;:::o;158766:1256::-;158820:22;158853:16;158880:17;158900:15;:13;:15::i;:::-;158880:35;;158997:20;:18;:20::i;:::-;159030:19;159052:20;:18;:20::i;:::-;159030:42;;159083:16;159102:14;:12;:14::i;:::-;159083:33;;159147:8;159133:11;:22;159129:747;;;159172:12;159187:47;159208:25;:11;159224:8;159208:15;:25::i;159187:47::-;159172:62;;159355:47;142961:5;159355:26;159364:16;;159355:4;:8;;:26;;;;:::i;:47::-;159338:64;;159417:27;159429:14;159417:11;:27::i;:::-;159470:35;159490:14;159470:19;:35::i;:::-;159459:46;;159129:747;;;;159538:19;159571:11;159560:8;:22;159538:44;;159757:107;159795:54;142961:5;159795:33;159811:16;;159795:11;:15;;:33;;;;:::i;159757:107::-;159728:136;;-1:-1:-1;159728:136:0;-1:-1:-1;;159129:747:0;159886:12;:10;:12::i;:::-;159909:39;159925:22;:20;:22::i;:::-;159909:15;:39::i;:::-;160005:8;159989:14;159978:9;159964:50;;;;;;;;;;158766:1256;;;;;:::o;167077:190::-;167183:7;167215:44;167254:4;167215:34;167232:16;:14;:16::i;:::-;167215:12;;:16;:34::i;93890:761::-;94314:23;94340:69;94368:4;94340:69;;;;;;;;;;;;;;;;;94348:5;-1:-1:-1;;;;;94340:27:0;;;:69;;;;;:::i;:::-;94424:17;;94314:95;;-1:-1:-1;94424:21:0;94420:224;;94566:10;94555:30;;;;;;;;;;;;:::i;:::-;94547:85;;;;-1:-1:-1;;;94547:85:0;;;;;;;:::i;5234:979::-;5364:12;5397:18;5408:6;5397:10;:18::i;:::-;5389:60;;;;-1:-1:-1;;;5389:60:0;;;;;;;:::i;:::-;5523:12;5537:23;5564:6;-1:-1:-1;;;;;5564:11:0;5584:8;5595:4;5564:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5522:78;;;;5615:7;5611:595;;;5646:10;-1:-1:-1;5639:17:0;;-1:-1:-1;5639:17:0;5611:595;5760:17;;:21;5756:439;;6023:10;6017:17;6084:15;6071:10;6067:2;6063:19;6056:44;5971:148;6166:12;6159:20;;-1:-1:-1;;;6159:20:0;;;;;;;;:::i;160890:124::-;160965:5;;:31;;-1:-1:-1;;;160965:31:0;;160938:7;;-1:-1:-1;;;;;160965:5:0;;:16;;:31;;160990:4;;160965:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;160958:48;;160890:124;:::o;162860:2520::-;162938:25;162965:13;162996:19;163018:15;:13;:15::i;:::-;163050:8;;162996:37;;-1:-1:-1;163050:8:0;;163046:191;;;163095:11;163079:13;:27;163075:111;;;163127:43;163139:30;:13;163157:11;163139:17;:30::i;163127:43::-;163208:13;163223:1;163200:25;;;;;;;163046:191;163257:37;163274:19;;163257:16;:37::i;:::-;163249:46;;;;;;163327:11;163310:13;:28;163306:86;;163363:13;163378:1;163355:25;;;;;;;163306:86;163404:23;163430:17;:15;:17::i;:::-;163404:43;-1:-1:-1;163543:20:0;163579:104;163404:43;163579:51;142961:5;163579:30;:13;163597:11;163579:17;:30::i;:104::-;163543:140;;163715:4;163700:12;:19;163696:1677;;;163872:31;:29;:31::i;:::-;163860:43;-1:-1:-1;163938:32:0;;-1:-1:-1;163958:11:0;163938:15;:13;:15::i;:32::-;163918:52;;163696:1677;;;164041:20;:18;:20::i;:::-;164174:16;164228:3;164213:12;:18;164209:911;;;164328:20;164351:14;:12;:14::i;:::-;164328:37;;164384:19;164406:20;:18;:20::i;:::-;164384:42;;164463:12;164449:11;:26;164445:660;;;164500:12;164540:51;164561:29;:11;164577:12;164561:15;:29::i;164540:51::-;164500:91;-1:-1:-1;164614:22:0;164664:43;142961:5;164664:22;164500:91;164673:12;164664:8;:22::i;:43::-;164614:93;;164730:27;164742:14;164730:11;:27::i;:::-;164791:35;164811:14;164791:19;:35::i;:::-;164780:46;;164445:660;;;;;164890:195;164936:126;142961:5;164936:49;164972:12;164937:29;:12;164954:11;164937:16;:29::i;164890:195::-;164875:210;-1:-1:-1;;164445:660:0;164209:911;;;165134:12;:10;:12::i;:::-;165198:65;165214:48;165253:8;165214:34;:15;165234:13;165214:19;:34::i;165198:65::-;165298:32;165318:11;165298:15;:13;:15::i;:32::-;165278:52;-1:-1:-1;165353:8:0;-1:-1:-1;163696:1677:0;162860:2520;;;;;;;:::o;170041:129::-;170100:4;;170120:5;;170100:62;;-1:-1:-1;;;170100:62:0;;-1:-1:-1;;;;;170100:4:0;;;;:11;;:62;;:4;170120:5;;;;;;;170128:12;;170142:1;;170100:4;;170156;;170100:62;;;:::i;172949:597::-;173009:19;173031:34;173052:12;173031:20;:34::i;:::-;173096:4;;:29;;-1:-1:-1;;;173096:29:0;;173009:56;;-1:-1:-1;173078:15:0;;-1:-1:-1;;;;;173096:4:0;;;;:14;;:29;;173119:4;;173096:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;173078:47;;173150:11;173140:7;:21;173136:75;;;173192:7;173178:21;;173136:75;173223:6;;173265:5;;173294:4;;173384:11;;-1:-1:-1;;;;;173223:6:0;;;;:19;;:6;173265:5;;;;;173294:4;;173314:12;;173341:11;;173367:50;;142961:5;;173367:29;;173314:12;;173367:16;:29::i;:50::-;173432:49;142961:5;173432:28;173448:11;;173432;:15;;:28;;;;:::i;:49::-;173504:4;173524:3;173223:315;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;180389:172::-;180460:11;;:36;;-1:-1:-1;;;180460:36:0;;180440:17;;-1:-1:-1;;;;;180460:11:0;;:21;;:36;;180490:4;;180460:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;180519:14;;180507:46;;-1:-1:-1;;;180507:46:0;;180440:56;;-1:-1:-1;;;;;;180519:14:0;;180507:35;;:46;;180440:56;;180507:46;;;:::i;32772:192::-;32858:7;32894:12;32886:6;;;;32878:29;;;;-1:-1:-1;;;32878:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;32930:5:0;;;32772:192::o;152494:352::-;152540:22;152575:18;152596:15;:13;:15::i;:::-;152575:36;;152736:14;:12;:14::i;:::-;152761:18;:16;:18::i;:::-;152807:31;152827:10;152807:15;:13;:15::i;34798:278::-;34884:7;34919:12;34912:5;34904:28;;;;-1:-1:-1;;;34904:28:0;;;;;;;;:::i;:::-;;34943:9;34959:1;34955;:5;;;;;;;34798:278;-1:-1:-1;;;;;34798:278:0:o;173842:126::-;173892:16;173911:15;:13;:15::i;:::-;173892:34;;173937:23;173951:8;173937:13;:23::i;174025:858::-;174087:11;;:36;;-1:-1:-1;;;174087:36:0;;174069:15;;-1:-1:-1;;;;;174087:11:0;;:21;;:36;;174117:4;;174087:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;174069:54;-1:-1:-1;174138:11:0;;174134:742;;174167:14;174183:15;174202;:13;:15::i;:::-;174166:51;;;;174234:16;174253:11;;;;;;;;;-1:-1:-1;;;;;174253:11:0;-1:-1:-1;;;;;174253:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;174234:44;;174295:18;174333:112;174418:8;174333:58;142961:5;174333:37;174358:11;;174333:20;174345:7;174333;:11;;:20;;;;:::i;:112::-;174295:150;;174460:18;174498:111;174582:8;174498:57;142961:5;174498:36;174522:11;;174498:19;174510:6;174498:7;:11;;:19;;;;:::i;:111::-;174624:6;;174673:5;;174706:4;;174624:240;;-1:-1:-1;;;174624:240:0;;174460:149;;-1:-1:-1;;;;;;174624:6:0;;;;:22;;:240;;:6;174673:5;;;;;174706:4;;174730:7;;174756:10;;174460:149;;174822:4;;174846:3;;174624:240;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;174134:742;;;;;174025:858;:::o;170273:365::-;170330:5;;:30;;-1:-1:-1;;;170330:30:0;;170315:12;;170330:5;;;-1:-1:-1;;;;;170330:5:0;;:15;;:30;;170354:4;;170330:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;170315:45;-1:-1:-1;170375:9:0;170371:22;;170386:7;;;170371:22;170405:13;170421:20;:18;:20::i;:::-;170405:36;;170463:5;170456:4;:12;170452:179;;;170485:4;;170504:5;;170485:50;;-1:-1:-1;;;170485:50:0;;-1:-1:-1;;;;;170485:4:0;;;;:10;;:50;;:4;170504:5;;;;;;;170512:4;;170518:1;;170529:4;;170485:50;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;170452:179;;;170568:4;;170587:5;;170568:51;;-1:-1:-1;;;170568:51:0;;-1:-1:-1;;;;;170568:4:0;;;;:10;;:51;;:4;170587:5;;;;;;;170595;;170602:1;;170613:4;;170568:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;176410:589::-;176497:19;176518:21;176571:34;176592:12;176571:20;:34::i;:::-;176656:6;;176753:11;;176557:48;;-1:-1:-1;176616:24:0;;-1:-1:-1;;;;;176656:6:0;;;;:31;;176706:12;;176737:49;;142961:5;;176737:28;;176557:48;;176737:15;:28::i;:49::-;176829:5;;176845:4;;176805:46;;-1:-1:-1;;;;;176829:5:0;;;;;;;176845:4;176805:15;:46::i;:::-;176878:4;176902:3;176656:264;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;176656:264:0;;;;;;;;;;;;:::i;:::-;176616:304;;176947:44;176963:7;176988:1;176971:7;:14;:18;176963:27;;;;;;;;;;;;;;176947:11;:15;;:44;;;;:::i;:::-;176931:60;;176410:589;;;;:::o;177007:661::-;177092:21;177131:20;177154:32;177175:10;177154:20;:32::i;:::-;177131:55;;177197:19;177232:60;177289:2;177233:50;177271:11;;177233:33;142961:5;177233:12;:16;;:33;;;;:::i;177232:60::-;177381:6;;177514:4;;177529:5;;177197:95;;-1:-1:-1;177341:24:0;;-1:-1:-1;;;;;177381:6:0;;;;:31;;177431:10;;177197:95;;177490:46;;177514:4;;;177381:6;177529:5;;;177490:15;:46::i;:::-;177563:4;177587:3;177381:224;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;177381:224:0;;;;;;;;;;;;:::i;:::-;177341:264;;177632:28;177647:12;177632:7;177640:1;177632:10;;;;;;;;;;;;;;:14;;:28;;;;:::i;:::-;177616:44;177007:661;-1:-1:-1;;;;;177007:661:0:o;175487:631::-;175569:20;175607;175630:29;175651:7;175630:20;:29::i;:::-;175710:6;;175803:11;;175607:52;;-1:-1:-1;175670:24:0;;-1:-1:-1;;;;;175710:6:0;;;;:31;;175760:7;;175786:50;;142961:5;;175786:29;;175607:52;;175786:16;:29::i;:50::-;175879:4;;175894:5;;175855:46;;-1:-1:-1;;;;;175879:4:0;;;;;175894:5;;;175855:15;:46::i;:::-;175951:4;175975:3;175710:283;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;175710:283:0;;;;;;;;;;;;:::i;:::-;175670:323;;176019:91;176054:45;176071:7;176096:1;176079:7;:14;:18;176071:27;;;;;;;172177:764;172275:11;;:36;;-1:-1:-1;;;172275:36:0;;172254:18;;-1:-1:-1;;;;;172275:11:0;;:21;;:36;;172305:4;;172275:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;172254:57;;172322:16;172341:15;:13;:15::i;:::-;172322:34;-1:-1:-1;172367:15:0;172385:24;:10;172322:34;172385:14;:24::i;:::-;172367:42;;172420:13;172436:37;172461:11;:9;:11::i;:::-;172436:20;:7;172448;172436:11;:20::i;:37::-;172420:53;;172484:18;172538:8;172525:10;172517:5;:18;:29;172513:147;;;-1:-1:-1;172576:18:0;;;172513:147;;;-1:-1:-1;172640:8:0;172513:147;172670:27;172686:10;172670:15;:27::i;:::-;172708:14;:12;:14::i;:::-;172733:15;172751;:13;:15::i;:::-;172733:33;-1:-1:-1;172733:33:0;172781:14;:7;172793:1;172781:11;:14::i;:::-;:25;172777:134;;172823:25;172833:14;:7;172845:1;172833:11;:14::i;172823:25::-;172777:134;;;172881:18;172891:7;172881:9;:18::i;:::-;172921:12;:10;:12::i;:::-;172177:764;;;;;;;:::o;169832:201::-;169908:21;169963:29;169984:7;169963:20;:29::i;:::-;169947:45;;170003:22;170011:13;170003:7;:22::i;150338:140::-;150388:20;:18;:20::i;:::-;150419:14;:12;:14::i;:::-;150444:26;150454:15;:13;:15::i;158419:339::-;158485:8;;;;158481:47;;;158510:7;;158481:47;158541:19;158562:18;158584:24;158600:7;158584:15;:24::i;:::-;158540:68;;;;158619:43;158631:30;158649:11;158631:13;:11;:13::i;158619:43::-;158673:19;158681:10;158673:7;:19::i;:::-;158703:24;158712:14;:12;:14::i;:::-;158703:8;:24::i;:::-;158738:12;:10;:12::i;742:619::-;802:4;1270:20;;1113:66;1310:23;;;;;;:42;;-1:-1:-1;;1337:15:0;;;742:619;-1:-1:-1;;742:619:0:o;180716:100::-;180781:14;;;;;;;;;-1:-1:-1;;;;;180781:14:0;-1:-1:-1;;;;;180769:37:0;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;180716:100::o;174891:374::-;174972:9;;:34;;-1:-1:-1;;;174972:34:0;;174947:22;;-1:-1:-1;;;;;174972:9:0;;:19;;:34;;175000:4;;174972:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;174947:59;-1:-1:-1;175021:19:0;175017:32;;175042:7;;;175017:32;175059:6;;175174:9;;175194:4;;-1:-1:-1;;;;;175059:6:0;;;;:31;;175105:14;;175059:6;;175150:50;;175174:9;;;175194:4;175150:15;:50::i;:::-;175223:4;175243:3;175059:198;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;175059:198:0;;;;;;;;;;;;:::i;180569:139::-;180642:11;;180638:62;;180667:14;;180655:45;;-1:-1:-1;;;180655:45:0;;-1:-1:-1;;;;;180667:14:0;;;;180655:36;;:45;;180692:7;;180655:45;;;:::i;167275:247::-;167376:7;167402:16;167420:17;167441:15;:13;:15::i;:::-;167401:55;;-1:-1:-1;167401:55:0;-1:-1:-1;167474:40:0;167401:55;167474:26;:11;167401:55;167474:15;:26::i;173696:138::-;173777:15;:13;:15::i;:::-;173766:7;:26;;173758:35;;;;;;173804:22;173818:7;173804:13;:22::i;157319:1092::-;157397:19;157418:15;157451:14;157468:16;:14;:16::i;:::-;157451:33;;157495:15;157513:12;:10;:12::i;:::-;157495:30;;157536:11;157550:21;157569:1;157550:14;:12;:14::i;:21::-;157536:35;;157582:10;157595:20;:18;:20::i;:::-;157582:33;;157626:13;157642:25;157659:7;157642:12;;:16;;:25;;;;:::i;:::-;157626:41;;157678:17;157771:3;157766:2;:8;157762:410;;;157803:156;157923:35;157955:2;157923:27;:6;142961:5;157923:10;:27::i;:35::-;157822:63;157862:22;157872:11;:2;157879:3;157872:6;:11::i;:::-;157862:5;;:9;:22::i;:::-;157822:35;157852:4;157822:25;157839:7;157822:12;;:16;;:25;;;;:::i;157803:156::-;157791:168;;157762:410;;;158004:156;158124:35;158156:2;158124:27;:6;142961:5;158124:10;:27::i;:35::-;158023:63;158063:22;158073:11;:3;158081:2;158073:7;:11::i;158063:22::-;158023:35;158053:4;158023:25;158040:7;158023:12;;:16;;:25;;;;:::i;158004:156::-;157992:168;;157762:410;158194:98;158222:59;158242:38;158253:26;:5;142961;158253:9;:26::i;:::-;158242:6;;:10;:38::i;158222:59::-;158194:9;;:13;:98::i;:::-;158184:108;-1:-1:-1;158317:86:0;158343:49;158387:4;158343:39;158374:7;158344:24;158365:2;158344:16;158184:108;158356:3;158344:11;:16::i;158343:49::-;158317:7;;:11;:86::i;:::-;158303:100;;157319:1092;;;;;;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;4096:241;;4200:2;4188:9;4179:7;4175:23;4171:32;4168:2;;;-1:-1;;4206:12;4168:2;85:6;72:20;97:33;124:5;97:33;:::i;4344:263::-;;4459:2;4447:9;4438:7;4434:23;4430:32;4427:2;;;-1:-1;;4465:12;4427:2;226:6;220:13;238:33;265:5;238:33;:::i;4614:392::-;;4754:2;;4742:9;4733:7;4729:23;4725:32;4722:2;;;-1:-1;;4760:12;4722:2;4811:17;4805:24;4849:18;4841:6;4838:30;4835:2;;;-1:-1;;4871:12;4835:2;4958: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;;;3894:13;;893:61;;847:1;840:9;;;;;968:14;;;;996;;800:217;;;-1:-1;4891:99;4716:290;-1:-1;;;;;;;4716:290::o;5013:235::-;;5114:2;5102:9;5093:7;5089:23;5085:32;5082:2;;;-1:-1;;5120:12;5082:2;1108:6;1095:20;1120:30;1144:5;1120:30;:::i;5255:257::-;;5367:2;5355:9;5346:7;5342:23;5338:32;5335:2;;;-1:-1;;5373:12;5335:2;1243:6;1237:13;1255:30;1279:5;1255:30;:::i;5823:367::-;;;5947:2;5935:9;5926:7;5922:23;5918:32;5915:2;;;-1:-1;;5953:12;5915:2;6011:17;5998:31;6049:18;;6041:6;6038:30;6035:2;;;-1:-1;;6071:12;6035:2;6157:6;6146:9;6142:22;;;1602:3;1595:4;1587:6;1583:17;1579:27;1569:2;;-1:-1;;1610:12;1569:2;1653:6;1640:20;6049:18;1672:6;1669:30;1666:2;;;-1:-1;;1702:12;1666:2;1797:3;5947:2;1777:17;1738:6;1763:32;;1760:41;1757:2;;;-1:-1;;1804:12;1757:2;5947;1734:17;;;;;6091:83;;-1:-1;5909:281;;-1:-1;;;;5909:281::o;6197:328::-;;6344:3;;6332:9;6323:7;6319:23;6315:33;6312:2;;;-1:-1;;6351:12;6312:2;2030:22;6344:3;2030:22;:::i;:::-;2021:31;;2176:22;3894:13;2126:16;2119:86;2272:2;2341:9;2337:22;3894:13;2272:2;2291:5;2287:16;2280:86;2432:2;2501:9;2497:22;3894:13;2432:2;2451:5;2447:16;2440:86;2600:2;2669:9;2665:22;3894:13;2600:2;2619:5;2615:16;2608:86;2768:3;2838:9;2834:22;3894:13;2768:3;2788:5;2784:16;2777:86;2930:3;3000:9;2996:22;3894:13;2930:3;2950:5;2946:16;2939:86;3091:3;3161:9;3157:22;3894:13;3091:3;3111:5;3107:16;3100:86;3252:3;3322:9;3318:22;3894:13;3252:3;3272:5;3268:16;3261:86;3413:3;;3485:9;3481:22;3894:13;3413:3;3433:5;3429:18;3422:88;;6403:106;;;;6306:219;;;;:::o;6532:533::-;;;;6680:2;6668:9;6659:7;6655:23;6651:32;6648:2;;;-1:-1;;6686:12;6648:2;3622:6;3616:13;3634:33;3661:5;3634:33;:::i;:::-;6849:2;6899:22;;3616:13;6738:74;;-1:-1;3634:33;3616:13;3634:33;:::i;:::-;6968:2;7017:22;;4034:13;6857:74;;-1:-1;37639:10;37628:22;;40477:34;;40467:2;;-1:-1;;40515:12;40467:2;6976:73;;;;6642:423;;;;;:::o;7072:241::-;;7176:2;7164:9;7155:7;7151:23;7147:32;7144:2;;;-1:-1;;7182:12;7144:2;-1:-1;3746:20;;7138:175;-1:-1;7138:175::o;7320:263::-;;7435:2;7423:9;7414:7;7410:23;7406:32;7403:2;;;-1:-1;;7441:12;7403:2;-1:-1;3894:13;;7397:186;-1:-1;7397:186::o;7590:399::-;;;7722:2;7710:9;7701:7;7697:23;7693:32;7690:2;;;-1:-1;;7728:12;7690:2;-1:-1;;3894:13;;7891:2;7941:22;;;3894:13;;;;;-1:-1;7684:305::o;7996:491::-;;;;8134:2;8122:9;8113:7;8109:23;8105:32;8102:2;;;-1:-1;;8140:12;8102:2;-1:-1;;3746:20;;;8292:2;8331:22;;3746:20;;-1:-1;8400:2;8439:22;;;3746:20;;8096:391;-1:-1;8096:391::o;8494:535::-;;;;8643:2;8631:9;8622:7;8618:23;8614:32;8611:2;;;-1:-1;;8649:12;8611:2;3900:6;3894:13;8701:74;;8812:2;8866:9;8862:22;3894:13;8820:74;;8931:2;8985:9;8981:22;3894:13;8939:74;;8605:424;;;;;:::o;9036:611::-;;;;;9188:3;9176:9;9167:7;9163:23;9159:33;9156:2;;;-1:-1;;9195:12;9156:2;3759:6;3746:20;9247:63;;9347:2;9390:9;9386:22;3746:20;9355:63;;9455:2;9498:9;9494:22;3746:20;9463:63;;9563:2;9603:9;9599:22;1095:20;1120:30;1144:5;1120:30;:::i;:::-;9150:497;;;;-1:-1;9150:497;;-1:-1;;9150:497::o;9654:617::-;;;;;9809:3;9797:9;9788:7;9784:23;9780:33;9777:2;;;-1:-1;;9816:12;9777:2;-1:-1;;3746:20;;;9968:2;10007:22;;3746:20;;-1:-1;10076:2;10115:22;;3746:20;;10184:2;10223:22;3746:20;;-1:-1;9771:500;-1:-1;9771:500::o;10721:690::-;;10914:5;35923:12;36467:6;36462:3;36455:19;36504:4;;36499:3;36495:14;10926:93;;36504:4;11090:5;35777:14;-1:-1;11129:260;11154:6;11151:1;11148:13;11129:260;;;11215:13;;-1:-1;;;;;37422:54;10521:37;;10432:14;;;;36310;;;;4849:18;11169:9;11129:260;;;-1:-1;11395:10;;10845:566;-1:-1;;;;;10845:566::o;17896:271::-;;11690:5;35923:12;11801:52;11846:6;11841:3;11834:4;11827:5;11823:16;11801:52;:::i;:::-;11865:16;;;;;18030:137;-1:-1;;18030:137::o;18174:222::-;-1:-1;;;;;37422:54;;;;10521:37;;18301:2;18286:18;;18272:124::o;18403:333::-;-1:-1;;;;;37422:54;;;10521:37;;37422:54;;18722:2;18707:18;;10521:37;18558:2;18543:18;;18529:207::o;18743:892::-;-1:-1;;;;;37422:54;;;10521:37;;37422:54;;;19203:2;19188:18;;10521:37;19286:2;19271:18;;17847:37;;;;19369:2;19354:18;;17847:37;;;;19452:3;19437:19;;17847:37;37422:54;;;37433:42;19521:19;;10521:37;19620:3;19605:19;;17847:37;;;;19038:3;19023:19;;19009:626::o;19642:1004::-;-1:-1;;;;;37422:54;;;10521:37;;37422:54;;;20130:2;20115:18;;10521:37;20213:2;20198:18;;17847:37;;;;20296:2;20281:18;;17847:37;;;;20379:3;20364:19;;17847:37;;;;37433:42;20448:19;;17847:37;37422:54;;;20547:3;20532:19;;10521:37;20631:3;20616:19;;17847:37;;;;19965:3;19950:19;;19936:710::o;20653:349::-;-1:-1;;;;;37422:54;;;;10521:37;;20988:2;20973:18;;12807:58;20816:2;20801:18;;20787:215::o;21349:444::-;-1:-1;;;;;37422:54;;;10521:37;;21696:2;21681:18;;17847:37;;;;37422:54;;;21779:2;21764:18;;10521:37;21532:2;21517:18;;21503:290::o;21800:570::-;-1:-1;;;;;37422:54;;;10521:37;;22183:2;22168:18;;17847:37;;;;37422:54;;22266:2;22251:18;;10521:37;37341:6;37330:18;;;22356:2;22341:18;;12659:57;22018:3;22003:19;;21989:381::o;22377:572::-;-1:-1;;;;;37422:54;;;10521:37;;22761:2;22746:18;;17847:37;;;;22852:2;22837:18;;12807:58;;;;37422:54;;;22935:2;22920:18;;10521:37;22596:3;22581:19;;22567:382::o;22956:698::-;-1:-1;;;;;37422:54;;;10521:37;;23375:2;23360:18;;17847:37;;;;23466:2;23451:18;;12807:58;;;;37341:6;37330:18;23556:2;23541:18;;12659:57;37422:54;;;23639:3;23624:19;;10521:37;23210:3;23195:19;;23181:473::o;23661:210::-;37012:13;;37005:21;11484:34;;23782:2;23767:18;;23753:118::o;24950:330::-;;25107:2;25128:17;25121:47;36467:6;25107:2;25096:9;25092:18;36455:19;39317:6;39312:3;36495:14;25096:9;36495:14;39294:30;39355:16;;;36495:14;39355:16;;;39348:27;;;;39750:7;39734:14;;;-1:-1;;39730:28;13306:39;;;25078:202;-1:-1;25078:202::o;25287:310::-;;25434:2;25455:17;25448:47;13504:5;35923:12;36467:6;25434:2;25423:9;25419:18;36455:19;13598:52;13643:6;36495:14;25423:9;36495:14;25434:2;13624:5;13620:16;13598:52;:::i;:::-;39750:7;39734:14;-1:-1;;39730:28;13662:39;;;;36495:14;13662:39;;25405:192;-1:-1;;25405:192::o;25604:416::-;25804:2;25818:47;;;13938:2;25789:18;;;36455:19;-1:-1;;;36495:14;;;13954:34;14007:12;;;25775:245::o;26027:416::-;26227:2;26241:47;;;14258:1;26212:18;;;36455:19;-1:-1;;;36495:14;;;14273:28;14320:12;;;26198:245::o;26450:416::-;26650:2;26664:47;;;14571:2;26635:18;;;36455:19;14607:29;36495:14;;;14587:50;14656:12;;;26621:245::o;26873:416::-;27073:2;27087:47;;;14907:2;27058:18;;;36455:19;-1:-1;;;36495:14;;;14923:35;14977:12;;;27044:245::o;27296:416::-;27496:2;27510:47;;;15228:2;27481:18;;;36455:19;15264:34;36495:14;;;15244:55;-1:-1;;;15319:12;;;15312:25;15356:12;;;27467:245::o;27719:416::-;27919:2;27933:47;;;15607:1;27904:18;;;36455:19;-1:-1;;;36495:14;;;15622:29;15670:12;;;27890:245::o;28142:416::-;28342:2;28356:47;;;15921:1;28327:18;;;36455:19;-1:-1;;;36495:14;;;15936:30;15985:12;;;28313:245::o;28565:416::-;28765:2;28779:47;;;16236:2;28750:18;;;36455:19;16272:31;36495:14;;;16252:52;16323:12;;;28736:245::o;28988:416::-;29188:2;29202:47;;;16574:2;29173:18;;;36455:19;-1:-1;;;36495:14;;;16590:34;16643:12;;;29159:245::o;29411:416::-;29611:2;29625:47;;;16894:2;29596:18;;;36455:19;16930:34;36495:14;;;16910:55;-1:-1;;;16985:12;;;16978:34;17031:12;;;29582:245::o;29834:416::-;30034:2;30048:47;;;17282:2;30019:18;;;36455:19;-1:-1;;;36495:14;;;17298:33;17350:12;;;30005:245::o;30257:416::-;30457:2;30471:47;;;17601:2;30442:18;;;36455:19;17637:34;36495:14;;;17617:55;-1:-1;;;17692:12;;;17685:46;17750:12;;;30428:245::o;30680:222::-;17847:37;;;30807:2;30792:18;;30778:124::o;30909:481::-;;17877:5;17854:3;17847:37;31114:2;31232;31221:9;31217:18;31210:48;31272:108;31114:2;31103:9;31099:18;31366:6;31272:108;:::i;31397:832::-;;17877:5;17854:3;17847:37;39076:24;31867:2;31856:9;31852:18;12807:58;31694:3;31904:2;31893:9;31889:18;31882:48;31944:108;31694:3;31683:9;31679:19;32038:6;31944:108;:::i;:::-;-1:-1;;;;;37422:54;;;;32131:2;32116:18;;10521:37;-1:-1;32214:3;32199:19;17847:37;31936:116;31665:564;-1:-1;;;31665:564::o;32236:333::-;17847:37;;;32555:2;32540:18;;17847:37;32391:2;32376:18;;32362:207::o;33399:444::-;17847:37;;;33746:2;33731:18;;17847:37;;;;33829:2;33814:18;;17847:37;33582:2;33567:18;;33553:290::o;33850:556::-;17847:37;;;34226:2;34211:18;;17847:37;;;;34309:2;34294:18;;17847:37;34392:2;34377:18;;17847:37;34061:3;34046:19;;34032:374::o;34413:668::-;17847:37;;;34817:2;34802:18;;17847:37;;;;34900:2;34885:18;;17847:37;;;;34983:2;34968:18;;17847:37;35066:3;35051:19;;17847:37;34652:3;34637:19;;34623:458::o;35088:256::-;35150:2;35144:9;35176:17;;;35251:18;35236:34;;35272:22;;;35233:62;35230:2;;;35308:1;;35298:12;35230:2;35150;35317:22;35128:216;;-1:-1;35128:216::o;35351:304::-;;35510:18;35502:6;35499:30;35496:2;;;-1:-1;;35532:12;35496:2;-1:-1;35577:4;35565:17;;;35630:15;;35433:222::o;39390:268::-;39455:1;39462:101;39476:6;39473:1;39470:13;39462:101;;;39543:11;;;39537:18;39524:11;;;39517:39;39498:2;39491:10;39462:101;;;39578:6;39575:1;39572:13;39569:2;;;-1:-1;;39455:1;39625:16;;39618:27;39439:219::o;39771:117::-;-1:-1;;;;;37422:54;;39830:35;;39820:2;;39879:1;;39869:12;39895:111;39976:5;37012:13;37005:21;39954:5;39951:32;39941:2;;39997:1;;39987:12;40171:117;-1:-1;;;;;40258:5;37215:42;40233:5;40230:35;40220:2;;40279:1;;40269:12

Swarm Source

ipfs://d096963a5bf31fca9d70dcde4162518f8f6cb6b060878ea64df0cc7122a65ca7
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.