Contract 0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a72 1

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xd4ff9866a1a4766725a23a2886f4b17d5edf9e95bcc077598b0d8f8ef7eb53caHarvest451686692022-08-18 13:07:2134 secs ago0xe4a7d73bccbae0e7398f8d437ff16b4623a5ac3a IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002039697904
0xed9fd7b80ade5da8896ae034a4443412e050ebaa330b1570cf2566f0c5024936Harvest451686402022-08-18 13:06:501 min ago0x657439ed989b0ec28a09b592fda8c61ebd434b6a IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002052952956
0x5014408453042e65ceea4f2bd44af97103cec0af8c29124bf8391aaf75e85ca4Harvest451686122022-08-18 13:06:211 min ago0x0290009c77908568f53223efdeee3506cf27c6c4 IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002096578846
0x81e3ba3ca662f8620e2074b9a9650bc3029c844a09e6b47534f9fcf3fe3c686cHarvest451685832022-08-18 13:05:472 mins ago0x9d7593003c0d48014a38be07ca8c312e6d32f17d IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.001885816409
0xc315863c0cd8d8462cbb107a618632b4715434197c1581c6710aa1ed2e0dd2faHarvest451685562022-08-18 13:05:182 mins ago0x0290009c77908568f53223efdeee3506cf27c6c4 IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002016479618
0x2d5366b928460dd29890fc2bf587a46868eff469f21da570f487ee2b696f59c1Harvest451685282022-08-18 13:04:463 mins ago0xd968665350a0bb7d487aadba94d920d8890ee06f IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002161012352
0x211a150465610fa0b9356433f78cba343d506b331b4c5cca75884dd95dee8423Harvest451684982022-08-18 13:04:043 mins ago0x9d512b82e5f0fb0c049707812ebdad35cf25786d IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002932646095
0x29bade5cffaebaf21b8d3e112c692d1cf249f3a2c9d9fa50a2303704ca21eb91Harvest451684942022-08-18 13:04:003 mins ago0x0290009c77908568f53223efdeee3506cf27c6c4 IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.003904390573
0x4ce8f0b577eae7c18083bb19ac91f0785788648f242afc55977d77be6b28ee12Harvest451684452022-08-18 13:02:265 mins ago0xe4a7d73bccbae0e7398f8d437ff16b4623a5ac3a IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002053084629
0x64d461e683e3f03893ef61358eb3159a366514b609b7f27e32bf00da0fc64b5dHarvest451684152022-08-18 13:01:546 mins ago0xe4a7d73bccbae0e7398f8d437ff16b4623a5ac3a IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.001878040868
0x2401276c7fa22f5cc8e1ddabde77410e6fd8fcf7b77abc1151a269a8326c22beHarvest451683882022-08-18 13:01:246 mins ago0x9d512b82e5f0fb0c049707812ebdad35cf25786d IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002880033771
0xfba7579237ec8e1640d83d1ced07d8dea72a080dfec7e70827d17518951821e1Harvest451683812022-08-18 13:01:176 mins ago0x0290009c77908568f53223efdeee3506cf27c6c4 IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.001918646802
0xac6fed3fe7f36c57944071bc80d4105754bfbc004c8cffb36c6d09d155664a3bHarvest451683512022-08-18 13:00:317 mins ago0xd968665350a0bb7d487aadba94d920d8890ee06f IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002133843885
0x7bf2af974fd39924e1b3eb9b3444ef5ca0e26a96cefe9ae9e198db4fa4de17ccHarvest451683222022-08-18 12:59:597 mins ago0x9d7593003c0d48014a38be07ca8c312e6d32f17d IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002038425068
0x8b66a1d720cba295031ef2fc37f4753761f3a5879c4feb5fd0943524becdb4acHarvest451682942022-08-18 12:59:298 mins ago0x40c5cf51be4b6e0ad376d598e1615c156d6fc8fc IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.001991330133
0xf5922a2e339a44668370f34d49e1119f02a54c814090a1860631772de959a131Harvest451682932022-08-18 12:59:288 mins ago0x9d512b82e5f0fb0c049707812ebdad35cf25786d IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.00300733622
0x1ad112416d4b6da6ddd94d574d987964ec6e14a44ce1a31e282db5b3260ea14aHarvest451682472022-08-18 12:58:379 mins ago0x9d512b82e5f0fb0c049707812ebdad35cf25786d IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.003014581492
0x71175c54da6f66c5d12586104356848c3f633218c1519c188e01d03f2d0a5cfeHarvest451682012022-08-18 12:57:4710 mins ago0xf0ab1a62b3ca931619d3108159f0c4010873702b IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002194545
0x6cee5fc6571aa46d26fc27d8c454f2b44f687f129b201be326ea41c812b1c744Harvest451681232022-08-18 12:56:2411 mins ago0x9d7593003c0d48014a38be07ca8c312e6d32f17d IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002104436982
0x0e025abc1901f2d351ff4ec54f9dd9a184681233b3856bf6c155f6576db4864cHarvest451680462022-08-18 12:55:0112 mins ago0x9d512b82e5f0fb0c049707812ebdad35cf25786d IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.003171618335
0x641503044bdf08c4c4bcbd6006406d9c58f78ef7120822ce324142bd5010afe4Harvest451679712022-08-18 12:53:2714 mins ago0x9d512b82e5f0fb0c049707812ebdad35cf25786d IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.003180860354
0xc2d9a6e4195269dd6d36abbd13d79c29c0a6d19a84e0dc725384bd642c104cb6Harvest451679672022-08-18 12:53:2314 mins ago0x657439ed989b0ec28a09b592fda8c61ebd434b6a IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002194545
0x395722106755fcf1182506a8c5557154fcf83de2b158d2d89d918011156143f5Harvest451678892022-08-18 12:52:0015 mins ago0x9029ed3f753125a0ac46b0a1ff78fef67213e57e IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002194545
0xd46723f4d33bc0dc24997a218d8a32e4de09690c16748f0405ecad67c9570ab6Harvest451678412022-08-18 12:51:0416 mins ago0x657439ed989b0ec28a09b592fda8c61ebd434b6a IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002194545
0x7d20863710806e5d98f94e5ad0921e8208ed8a9452645a8781d22f7ab7ade3ecHarvest451677922022-08-18 12:50:1317 mins ago0x657439ed989b0ec28a09b592fda8c61ebd434b6a IN  0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a720 FTM0.002218555
[ Download CSV Export 
Latest 4 internal transactions
Parent Txn Hash Block From To Value
0xaa5d1514d0b03bd27da2a0a295bba3532e182f965f27a6b637191553d88050bf364156432022-04-19 1:53:02121 days 11 hrs ago 0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a72 Fantom Finance: Wrapped Fantom Token10,586.28 FTM
0x7ef4ef71ca3d56935b3110d3ed167d850ce883e49277e1421dda214f26ccf5cb364124872022-04-19 0:59:28121 days 12 hrs ago 0xd9db270c1b5e3bd161e8c8503c55ceabee709552 0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a7210,586.28 FTM
0x075a04e59f58e4f614ced6a30927dbc5131e0a6a2493cc64796fc82de89ac866363412072022-04-18 2:30:10122 days 10 hrs ago 0x7947aadff0f3a3b9862bfd3ba3c3e98ec9c50a72 Fantom Finance: Wrapped Fantom Token15,740.1315 FTM
0x084a772fc52e77685085df0877c0f746cd62164aa1c32006772ca84d738bfc42339626082022-03-20 21:32:15150 days 15 hrs ago 0x3b410908e71ee04e7de2a87f8f9003afe6c1c7ce  Contract Creation0 FTM
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ReaperAutoCompoundBeethoven_fBEETS

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 1 : ReaperAutoCompoundBeethoven_fBEETS.sol
/**
 *Submitted for verification at FtmScan.com on 2021-11-26
*/

/**
 *Submitted for verification at FtmScan.com on 2021-09-10
*/
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
// File: @openzeppelin/contracts/access/Ownable.sol


pragma solidity ^0.8.0;


/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


pragma solidity ^0.8.0;

/**
 * @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: @openzeppelin/contracts/math/SafeMath.sol




pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

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

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

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

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

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

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

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

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

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * 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) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

// File: @openzeppelin/contracts/utils/Address.sol


pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

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

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

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

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

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

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

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

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

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

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

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


pragma solidity ^0.8.0;
/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}



// File: @openzeppelin/contracts/token/ERC20/ERC20.sol


/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}







// File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol


pragma solidity ^0.8.0;


/**
 * @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 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'
        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) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _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
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}



// File: @openzeppelin/contracts/utils/Pausable.sol


pragma solidity ^0.8.0;


/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}



interface IAuthorizer {
    /**
     * @dev Returns true if `account` can perform the action described by `actionId` in the contract `where`.
     */
    function canPerform(
        bytes32 actionId,
        address account,
        address where
    ) external view returns (bool);
}

interface IPoolToken {
    function getPoolTokens(bytes32 poolId)
        external
        returns (
            IERC20[] memory,
            uint256[] memory,
            uint256
        );
}



interface IPoolSwapStructs {
    // This is not really an interface - it just defines common structs used by other interfaces: IGeneralPool and
    // IMinimalSwapInfoPool.
    //
    // This data structure represents a request for a token swap, where `kind` indicates the swap type ('given in' or
    // 'given out') which indicates whether or not the amount sent by the pool is known.
    //
    // The pool receives `tokenIn` and sends `tokenOut`. `amount` is the number of `tokenIn` tokens the pool will take
    // in, or the number of `tokenOut` tokens the Pool will send out, depending on the given swap `kind`.
    //
    // All other fields are not strictly necessary for most swaps, but are provided to support advanced scenarios in
    // some Pools.
    //
    // `poolId` is the ID of the Pool involved in the swap - this is useful for Pool contracts that implement more than
    // one Pool.
    //
    // The meaning of `lastChangeBlock` depends on the Pool specialization:
    //  - Two Token or Minimal Swap Info: the last block in which either `tokenIn` or `tokenOut` changed its total
    //    balance.
    //  - General: the last block in which *any* of the Pool's registered tokens changed its total balance.
    //
    // `from` is the origin address for the funds the Pool receives, and `to` is the destination address
    // where the Pool sends the outgoing tokens.
    //
    // `userData` is extra data provided by the caller - typically a signature from a trusted party.
    struct SwapRequest {
        IVault.SwapKind kind;
        IERC20 tokenIn;
        IERC20 tokenOut;
        uint256 amount;
        // Misc data
        bytes32 poolId;
        uint256 lastChangeBlock;
        address from;
        address to;
        bytes userData;
    }
}

interface IBasePool is IPoolSwapStructs {
    /**
     * @dev Called by the Vault when a user calls `IVault.joinPool` to add liquidity to this Pool. Returns how many of
     * each registered token the user should provide, as well as the amount of protocol fees the Pool owes to the Vault.
     * The Vault will then take tokens from `sender` and add them to the Pool's balances, as well as collect
     * the reported amount in protocol fees, which the pool should calculate based on `protocolSwapFeePercentage`.
     *
     * Protocol fees are reported and charged on join events so that the Pool is free of debt whenever new users join.
     *
     * `sender` is the account performing the join (from which tokens will be withdrawn), and `recipient` is the account
     * designated to receive any benefits (typically pool shares). `balances` contains the total balances
     * for each token the Pool registered in the Vault, in the same order that `IVault.getPoolTokens` would return.
     *
     * `lastChangeBlock` is the last block in which *any* of the Pool's registered tokens last changed its total
     * balance.
     *
     * `userData` contains any pool-specific instructions needed to perform the calculations, such as the type of
     * join (e.g., proportional given an amount of pool shares, single-asset, multi-asset, etc.)
     *
     * Contracts implementing this function should check that the caller is indeed the Vault before performing any
     * state-changing operations, such as minting pool shares.
     */
    function onJoinPool(
        bytes32 poolId,
        address sender,
        address recipient,
        uint256[] memory balances,
        uint256 lastChangeBlock,
        uint256 protocolSwapFeePercentage,
        bytes memory userData
    ) external returns (uint256[] memory amountsIn, uint256[] memory dueProtocolFeeAmounts);

    /**
     * @dev Called by the Vault when a user calls `IVault.exitPool` to remove liquidity from this Pool. Returns how many
     * tokens the Vault should deduct from the Pool's balances, as well as the amount of protocol fees the Pool owes
     * to the Vault. The Vault will then take tokens from the Pool's balances and send them to `recipient`,
     * as well as collect the reported amount in protocol fees, which the Pool should calculate based on
     * `protocolSwapFeePercentage`.
     *
     * Protocol fees are charged on exit events to guarantee that users exiting the Pool have paid their share.
     *
     * `sender` is the account performing the exit (typically the pool shareholder), and `recipient` is the account
     * to which the Vault will send the proceeds. `balances` contains the total token balances for each token
     * the Pool registered in the Vault, in the same order that `IVault.getPoolTokens` would return.
     *
     * `lastChangeBlock` is the last block in which *any* of the Pool's registered tokens last changed its total
     * balance.
     *
     * `userData` contains any pool-specific instructions needed to perform the calculations, such as the type of
     * exit (e.g., proportional given an amount of pool shares, single-asset, multi-asset, etc.)
     *
     * Contracts implementing this function should check that the caller is indeed the Vault before performing any
     * state-changing operations, such as burning pool shares.
     */
    function onExitPool(
        bytes32 poolId,
        address sender,
        address recipient,
        uint256[] memory balances,
        uint256 lastChangeBlock,
        uint256 protocolSwapFeePercentage,
        bytes memory userData
    ) external returns (uint256[] memory amountsOut, uint256[] memory dueProtocolFeeAmounts);

    function getPoolId() external view returns (bytes32);
}

/**
 * @dev Pool contracts with the MinimalSwapInfo or TwoToken specialization settings should implement this interface.
 *
 * This is called by the Vault when a user calls `IVault.swap` or `IVault.batchSwap` to swap with this Pool.
 * Returns the number of tokens the Pool will grant to the user in a 'given in' swap, or that the user will grant
 * to the pool in a 'given out' swap.
 *
 * This can often be implemented by a `view` function, since many pricing algorithms don't need to track state
 * changes in swaps. However, contracts implementing this in non-view functions should check that the caller is
 * indeed the Vault.
 */
interface IMinimalSwapInfoPool is IBasePool {
    function onSwap(
        SwapRequest memory swapRequest,
        uint256 currentBalanceTokenIn,
        uint256 currentBalanceTokenOut
    ) external returns (uint256 amount);
}

interface IGeneralPool is IBasePool {
    function onSwap(
        SwapRequest memory swapRequest,
        uint256[] memory balances,
        uint256 indexIn,
        uint256 indexOut
    ) external returns (uint256 amount);
}

pragma solidity ^0.8.0;

interface IMasterChef {
    function poolLength() external view returns (uint256);
    function getMultiplier(uint256 _from, uint256 _to) external view returns (uint256);
    function pendingSpirit(uint256 _pid, address _user) external view returns (uint256);
    function massUpdatePools() external;
    function updatePool(uint256 _pid) external;
    function deposit(uint256 _pid, uint256 _amount) external;
    function withdraw(uint256 _pid, uint256 _amount) external;
    function userInfo(uint256 _pid, address _user) external view returns (uint256, uint256);
    function emergencyWithdraw(uint256 _pid, address _to) external;
}

interface IMasterChefv2 {
    function harvest(uint256 pid, address to) external;
    function withdrawAndHarvest(uint256 pid, uint256 amount, address to) external;
    function deposit(uint256 pid, uint256 amount, address to) external;
    function beets() external view returns (uint256);
}

/**
 * @dev This is an empty interface used to represent either ERC20-conforming token contracts or ETH (using the zero
 * address sentinel value). We're just relying on the fact that `interface` can be used to declare new address-like
 * types.
 *
 * This concept is unrelated to a Pool's Asset Managers.
 */
interface IAsset {
    // solhint-disable-previous-line no-empty-blocks
}


/**
 * @dev Interface for the SignatureValidator helper, used to support meta-transactions.
 */
interface ISignaturesValidator {
    /**
     * @dev Returns the EIP712 domain separator.
     */
    function getDomainSeparator() external view returns (bytes32);

    /**
     * @dev Returns the next nonce used by an address to sign messages.
     */
    function getNextNonce(address user) external view returns (uint256);
}

interface ITemporarilyPausable {
    /**
     * @dev Emitted every time the pause state changes by `_setPaused`.
     */
    event PausedStateChanged(bool paused);

    /**
     * @dev Returns the current paused state.
     */
    function getPausedState()
        external
        view
        returns (
            bool paused,
            uint256 pauseWindowEndTime,
            uint256 bufferPeriodEndTime
        );
}

pragma solidity ^0.8.0;


interface IVault is ISignaturesValidator, ITemporarilyPausable {
    // Generalities about the Vault:
    //
    // - Whenever documentation refers to 'tokens', it strictly refers to ERC20-compliant token contracts. Tokens are
    // transferred out of the Vault by calling the `IERC20.transfer` function, and transferred in by calling
    // `IERC20.transferFrom`. In these cases, the sender must have previously allowed the Vault to use their tokens by
    // calling `IERC20.approve`. The only deviation from the ERC20 standard that is supported is functions not returning
    // a boolean value: in these scenarios, a non-reverting call is assumed to be successful.
    //
    // - All non-view functions in the Vault are non-reentrant: calling them while another one is mid-execution (e.g.
    // while execution control is transferred to a token contract during a swap) will result in a revert. View
    // functions can be called in a re-reentrant way, but doing so might cause them to return inconsistent results.
    // Contracts calling view functions in the Vault must make sure the Vault has not already been entered.
    //
    // - View functions revert if referring to either unregistered Pools, or unregistered tokens for registered Pools.

    // Authorizer
    //
    // Some system actions are permissioned, like setting and collecting protocol fees. This permissioning system exists
    // outside of the Vault in the Authorizer contract: the Vault simply calls the Authorizer to check if the caller
    // can perform a given action.

    /**
     * @dev Returns the Vault's Authorizer.
     */
    function getAuthorizer() external view returns (IAuthorizer);

    /**
     * @dev Sets a new Authorizer for the Vault. The caller must be allowed by the current Authorizer to do this.
     *
     * Emits an `AuthorizerChanged` event.
     */
    function setAuthorizer(IAuthorizer newAuthorizer) external;

    /**
     * @dev Emitted when a new authorizer is set by `setAuthorizer`.
     */
    event AuthorizerChanged(IAuthorizer indexed newAuthorizer);

    // Relayers
    //
    // Additionally, it is possible for an account to perform certain actions on behalf of another one, using their
    // Vault ERC20 allowance and Internal Balance. These accounts are said to be 'relayers' for these Vault functions,
    // and are expected to be smart contracts with sound authentication mechanisms. For an account to be able to wield
    // this power, two things must occur:
    //  - The Authorizer must grant the account the permission to be a relayer for the relevant Vault function. This
    //    means that Balancer governance must approve each individual contract to act as a relayer for the intended
    //    functions.
    //  - Each user must approve the relayer to act on their behalf.
    // This double protection means users cannot be tricked into approving malicious relayers (because they will not
    // have been allowed by the Authorizer via governance), nor can malicious relayers approved by a compromised
    // Authorizer or governance drain user funds, since they would also need to be approved by each individual user.

    /**
     * @dev Returns true if `user` has approved `relayer` to act as a relayer for them.
     */
    function hasApprovedRelayer(address user, address relayer) external view returns (bool);

    /**
     * @dev Allows `relayer` to act as a relayer for `sender` if `approved` is true, and disallows it otherwise.
     *
     * Emits a `RelayerApprovalChanged` event.
     */
    function setRelayerApproval(
        address sender,
        address relayer,
        bool approved
    ) external;

    /**
     * @dev Emitted every time a relayer is approved or disapproved by `setRelayerApproval`.
     */
    event RelayerApprovalChanged(address indexed relayer, address indexed sender, bool approved);

    // Internal Balance
    //
    // Users can deposit tokens into the Vault, where they are allocated to their Internal Balance, and later
    // transferred or withdrawn. It can also be used as a source of tokens when joining Pools, as a destination
    // when exiting them, and as either when performing swaps. This usage of Internal Balance results in greatly reduced
    // gas costs when compared to relying on plain ERC20 transfers, leading to large savings for frequent users.
    //
    // Internal Balance management features batching, which means a single contract call can be used to perform multiple
    // operations of different kinds, with different senders and recipients, at once.

    /**
     * @dev Returns `user`'s Internal Balance for a set of tokens.
     */
    function getInternalBalance(address user, IERC20[] memory tokens) external view returns (uint256[] memory);

    /**
     * @dev Performs a set of user balance operations, which involve Internal Balance (deposit, withdraw or transfer)
     * and plain ERC20 transfers using the Vault's allowance. This last feature is particularly useful for relayers, as
     * it lets integrators reuse a user's Vault allowance.
     *
     * For each operation, if the caller is not `sender`, it must be an authorized relayer for them.
     */
    function manageUserBalance(UserBalanceOp[] memory ops) external payable;

    /**
     * @dev Data for `manageUserBalance` operations, which include the possibility for ETH to be sent and received
     without manual WETH wrapping or unwrapping.
     */
    struct UserBalanceOp {
        UserBalanceOpKind kind;
        IAsset asset;
        uint256 amount;
        address sender;
        address payable recipient;
    }

    // There are four possible operations in `manageUserBalance`:
    //
    // - DEPOSIT_INTERNAL
    // Increases the Internal Balance of the `recipient` account by transferring tokens from the corresponding
    // `sender`. The sender must have allowed the Vault to use their tokens via `IERC20.approve()`.
    //
    // ETH can be used by passing the ETH sentinel value as the asset and forwarding ETH in the call: it will be wrapped
    // and deposited as WETH. Any ETH amount remaining will be sent back to the caller (not the sender, which is
    // relevant for relayers).
    //
    // Emits an `InternalBalanceChanged` event.
    //
    //
    // - WITHDRAW_INTERNAL
    // Decreases the Internal Balance of the `sender` account by transferring tokens to the `recipient`.
    //
    // ETH can be used by passing the ETH sentinel value as the asset. This will deduct WETH instead, unwrap it and send
    // it to the recipient as ETH.
    //
    // Emits an `InternalBalanceChanged` event.
    //
    //
    // - TRANSFER_INTERNAL
    // Transfers tokens from the Internal Balance of the `sender` account to the Internal Balance of `recipient`.
    //
    // Reverts if the ETH sentinel value is passed.
    //
    // Emits an `InternalBalanceChanged` event.
    //
    //
    // - TRANSFER_EXTERNAL
    // Transfers tokens from `sender` to `recipient`, using the Vault's ERC20 allowance. This is typically used by
    // relayers, as it lets them reuse a user's Vault allowance.
    //
    // Reverts if the ETH sentinel value is passed.
    //
    // Emits an `ExternalBalanceTransfer` event.

    enum UserBalanceOpKind { DEPOSIT_INTERNAL, WITHDRAW_INTERNAL, TRANSFER_INTERNAL, TRANSFER_EXTERNAL }

    /**
     * @dev Emitted when a user's Internal Balance changes, either from calls to `manageUserBalance`, or through
     * interacting with Pools using Internal Balance.
     *
     * Because Internal Balance works exclusively with ERC20 tokens, ETH deposits and withdrawals will use the WETH
     * address.
     */
    event InternalBalanceChanged(address indexed user, IERC20 indexed token, int256 delta);

    /**
     * @dev Emitted when a user's Vault ERC20 allowance is used by the Vault to transfer tokens to an external account.
     */
    event ExternalBalanceTransfer(IERC20 indexed token, address indexed sender, address recipient, uint256 amount);

    // Pools
    //
    // There are three specialization settings for Pools, which allow for cheaper swaps at the cost of reduced
    // functionality:
    //
    //  - General: no specialization, suited for all Pools. IGeneralPool is used for swap request callbacks, passing the
    // balance of all tokens in the Pool. These Pools have the largest swap costs (because of the extra storage reads),
    // which increase with the number of registered tokens.
    //
    //  - Minimal Swap Info: IMinimalSwapInfoPool is used instead of IGeneralPool, which saves gas by only passing the
    // balance of the two tokens involved in the swap. This is suitable for some pricing algorithms, like the weighted
    // constant product one popularized by Balancer V1. Swap costs are smaller compared to general Pools, and are
    // independent of the number of registered tokens.
    //
    //  - Two Token: only allows two tokens to be registered. This achieves the lowest possible swap gas cost. Like
    // minimal swap info Pools, these are called via IMinimalSwapInfoPool.

    enum PoolSpecialization { GENERAL, MINIMAL_SWAP_INFO, TWO_TOKEN }

    /**
     * @dev Registers the caller account as a Pool with a given specialization setting. Returns the Pool's ID, which
     * is used in all Pool-related functions. Pools cannot be deregistered, nor can the Pool's specialization be
     * changed.
     *
     * The caller is expected to be a smart contract that implements either `IGeneralPool` or `IMinimalSwapInfoPool`,
     * depending on the chosen specialization setting. This contract is known as the Pool's contract.
     *
     * Note that the same contract may register itself as multiple Pools with unique Pool IDs, or in other words,
     * multiple Pools may share the same contract.
     *
     * Emits a `PoolRegistered` event.
     */
    function registerPool(PoolSpecialization specialization) external returns (bytes32);

    /**
     * @dev Emitted when a Pool is registered by calling `registerPool`.
     */
    event PoolRegistered(bytes32 indexed poolId, address indexed poolAddress, PoolSpecialization specialization);

    /**
     * @dev Returns a Pool's contract address and specialization setting.
     */
    function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);

    /**
     * @dev Registers `tokens` for the `poolId` Pool. Must be called by the Pool's contract.
     *
     * Pools can only interact with tokens they have registered. Users join a Pool by transferring registered tokens,
     * exit by receiving registered tokens, and can only swap registered tokens.
     *
     * Each token can only be registered once. For Pools with the Two Token specialization, `tokens` must have a length
     * of two, that is, both tokens must be registered in the same `registerTokens` call, and they must be sorted in
     * ascending order.
     *
     * The `tokens` and `assetManagers` arrays must have the same length, and each entry in these indicates the Asset
     * Manager for the corresponding token. Asset Managers can manage a Pool's tokens via `managePoolBalance`,
     * depositing and withdrawing them directly, and can even set their balance to arbitrary amounts. They are therefore
     * expected to be highly secured smart contracts with sound design principles, and the decision to register an
     * Asset Manager should not be made lightly.
     *
     * Pools can choose not to assign an Asset Manager to a given token by passing in the zero address. Once an Asset
     * Manager is set, it cannot be changed except by deregistering the associated token and registering again with a
     * different Asset Manager.
     *
     * Emits a `TokensRegistered` event.
     */
    function registerTokens(
        bytes32 poolId,
        IERC20[] memory tokens,
        address[] memory assetManagers
    ) external;

    /**
     * @dev Emitted when a Pool registers tokens by calling `registerTokens`.
     */
    event TokensRegistered(bytes32 indexed poolId, IERC20[] tokens, address[] assetManagers);

    /**
     * @dev Deregisters `tokens` for the `poolId` Pool. Must be called by the Pool's contract.
     *
     * Only registered tokens (via `registerTokens`) can be deregistered. Additionally, they must have zero total
     * balance. For Pools with the Two Token specialization, `tokens` must have a length of two, that is, both tokens
     * must be deregistered in the same `deregisterTokens` call.
     *
     * A deregistered token can be re-registered later on, possibly with a different Asset Manager.
     *
     * Emits a `TokensDeregistered` event.
     */
    function deregisterTokens(bytes32 poolId, IERC20[] memory tokens) external;

    /**
     * @dev Emitted when a Pool deregisters tokens by calling `deregisterTokens`.
     */
    event TokensDeregistered(bytes32 indexed poolId, IERC20[] tokens);

    /**
     * @dev Returns detailed information for a Pool's registered token.
     *
     * `cash` is the number of tokens the Vault currently holds for the Pool. `managed` is the number of tokens
     * withdrawn and held outside the Vault by the Pool's token Asset Manager. The Pool's total balance for `token`
     * equals the sum of `cash` and `managed`.
     *
     * Internally, `cash` and `managed` are stored using 112 bits. No action can ever cause a Pool's token `cash`,
     * `managed` or `total` balance to be greater than 2^112 - 1.
     *
     * `lastChangeBlock` is the number of the block in which `token`'s total balance was last modified (via either a
     * join, exit, swap, or Asset Manager update). This value is useful to avoid so-called 'sandwich attacks', for
     * example when developing price oracles. A change of zero (e.g. caused by a swap with amount zero) is considered a
     * change for this purpose, and will update `lastChangeBlock`.
     *
     * `assetManager` is the Pool's token Asset Manager.
     */
    function getPoolTokenInfo(bytes32 poolId, IERC20 token)
        external
        view
        returns (
            uint256 cash,
            uint256 managed,
            uint256 lastChangeBlock,
            address assetManager
        );

    /**
     * @dev Returns a Pool's registered tokens, the total balance for each, and the latest block when *any* of
     * the tokens' `balances` changed.
     *
     * The order of the `tokens` array is the same order that will be used in `joinPool`, `exitPool`, as well as in all
     * Pool hooks (where applicable). Calls to `registerTokens` and `deregisterTokens` may change this order.
     *
     * If a Pool only registers tokens once, and these are sorted in ascending order, they will be stored in the same
     * order as passed to `registerTokens`.
     *
     * Total balances include both tokens held by the Vault and those withdrawn by the Pool's Asset Managers. These are
     * the amounts used by joins, exits and swaps. For a detailed breakdown of token balances, use `getPoolTokenInfo`
     * instead.
     */
    function getPoolTokens(bytes32 poolId)
        external
        view
        returns (
            IERC20[] memory tokens,
            uint256[] memory balances,
            uint256 lastChangeBlock
        );

    /**
     * @dev Called by users to join a Pool, which transfers tokens from `sender` into the Pool's balance. This will
     * trigger custom Pool behavior, which will typically grant something in return to `recipient` - often tokenized
     * Pool shares.
     *
     * If the caller is not `sender`, it must be an authorized relayer for them.
     *
     * The `assets` and `maxAmountsIn` arrays must have the same length, and each entry indicates the maximum amount
     * to send for each asset. The amounts to send are decided by the Pool and not the Vault: it just enforces
     * these maximums.
     *
     * If joining a Pool that holds WETH, it is possible to send ETH directly: the Vault will do the wrapping. To enable
     * this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead of the
     * WETH address. Note that it is not possible to combine ETH and WETH in the same join. Any excess ETH will be sent
     * back to the caller (not the sender, which is important for relayers).
     *
     * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when
     * interacting with Pools that register and deregister tokens frequently. If sending ETH however, the array must be
     * sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the final
     * `assets` array might not be sorted. Pools with no registered tokens cannot be joined.
     *
     * If `fromInternalBalance` is true, the caller's Internal Balance will be preferred: ERC20 transfers will only
     * be made for the difference between the requested amount and Internal Balance (if any). Note that ETH cannot be
     * withdrawn from Internal Balance: attempting to do so will trigger a revert.
     *
     * This causes the Vault to call the `IBasePool.onJoinPool` hook on the Pool's contract, where Pools implement
     * their own custom logic. This typically requires additional information from the user (such as the expected number
     * of Pool shares). This can be encoded in the `userData` argument, which is ignored by the Vault and passed
     * directly to the Pool's contract, as is `recipient`.
     *
     * Emits a `PoolBalanceChanged` event.
     */
    function joinPool(
        bytes32 poolId,
        address sender,
        address recipient,
        JoinPoolRequest memory request
    ) external payable;

    struct JoinPoolRequest {
        IAsset[] assets;
        uint256[] maxAmountsIn;
        bytes userData;
        bool fromInternalBalance;
    }

    /**
     * @dev Called by users to exit a Pool, which transfers tokens from the Pool's balance to `recipient`. This will
     * trigger custom Pool behavior, which will typically ask for something in return from `sender` - often tokenized
     * Pool shares. The amount of tokens that can be withdrawn is limited by the Pool's `cash` balance (see
     * `getPoolTokenInfo`).
     *
     * If the caller is not `sender`, it must be an authorized relayer for them.
     *
     * The `tokens` and `minAmountsOut` arrays must have the same length, and each entry in these indicates the minimum
     * token amount to receive for each token contract. The amounts to send are decided by the Pool and not the Vault:
     * it just enforces these minimums.
     *
     * If exiting a Pool that holds WETH, it is possible to receive ETH directly: the Vault will do the unwrapping. To
     * enable this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead
     * of the WETH address. Note that it is not possible to combine ETH and WETH in the same exit.
     *
     * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when
     * interacting with Pools that register and deregister tokens frequently. If receiving ETH however, the array must
     * be sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the
     * final `assets` array might not be sorted. Pools with no registered tokens cannot be exited.
     *
     * If `toInternalBalance` is true, the tokens will be deposited to `recipient`'s Internal Balance. Otherwise,
     * an ERC20 transfer will be performed. Note that ETH cannot be deposited to Internal Balance: attempting to
     * do so will trigger a revert.
     *
     * `minAmountsOut` is the minimum amount of tokens the user expects to get out of the Pool, for each token in the
     * `tokens` array. This array must match the Pool's registered tokens.
     *
     * This causes the Vault to call the `IBasePool.onExitPool` hook on the Pool's contract, where Pools implement
     * their own custom logic. This typically requires additional information from the user (such as the expected number
     * of Pool shares to return). This can be encoded in the `userData` argument, which is ignored by the Vault and
     * passed directly to the Pool's contract.
     *
     * Emits a `PoolBalanceChanged` event.
     */
    function exitPool(
        bytes32 poolId,
        address sender,
        address payable recipient,
        ExitPoolRequest memory request
    ) external;

    struct ExitPoolRequest {
        IAsset[] assets;
        uint256[] minAmountsOut;
        bytes userData;
        bool toInternalBalance;
    }

    /**
     * @dev Emitted when a user joins or exits a Pool by calling `joinPool` or `exitPool`, respectively.
     */
    event PoolBalanceChanged(
        bytes32 indexed poolId,
        address indexed liquidityProvider,
        IERC20[] tokens,
        int256[] deltas,
        uint256[] protocolFeeAmounts
    );

    enum PoolBalanceChangeKind { JOIN, EXIT }

    // Swaps
    //
    // Users can swap tokens with Pools by calling the `swap` and `batchSwap` functions. To do this,
    // they need not trust Pool contracts in any way: all security checks are made by the Vault. They must however be
    // aware of the Pools' pricing algorithms in order to estimate the prices Pools will quote.
    //
    // The `swap` function executes a single swap, while `batchSwap` can perform multiple swaps in sequence.
    // In each individual swap, tokens of one kind are sent from the sender to the Pool (this is the 'token in'),
    // and tokens of another kind are sent from the Pool to the recipient in exchange (this is the 'token out').
    // More complex swaps, such as one token in to multiple tokens out can be achieved by batching together
    // individual swaps.
    //
    // There are two swap kinds:
    //  - 'given in' swaps, where the amount of tokens in (sent to the Pool) is known, and the Pool determines (via the
    // `onSwap` hook) the amount of tokens out (to send to the recipient).
    //  - 'given out' swaps, where the amount of tokens out (received from the Pool) is known, and the Pool determines
    // (via the `onSwap` hook) the amount of tokens in (to receive from the sender).
    //
    // Additionally, it is possible to chain swaps using a placeholder input amount, which the Vault replaces with
    // the calculated output of the previous swap. If the previous swap was 'given in', this will be the calculated
    // tokenOut amount. If the previous swap was 'given out', it will use the calculated tokenIn amount. These extended
    // swaps are known as 'multihop' swaps, since they 'hop' through a number of intermediate tokens before arriving at
    // the final intended token.
    //
    // In all cases, tokens are only transferred in and out of the Vault (or withdrawn from and deposited into Internal
    // Balance) after all individual swaps have been completed, and the net token balance change computed. This makes
    // certain swap patterns, such as multihops, or swaps that interact with the same token pair in multiple Pools, cost
    // much less gas than they would otherwise.
    //
    // It also means that under certain conditions it is possible to perform arbitrage by swapping with multiple
    // Pools in a way that results in net token movement out of the Vault (profit), with no tokens being sent in (only
    // updating the Pool's internal accounting).
    //
    // To protect users from front-running or the market changing rapidly, they supply a list of 'limits' for each token
    // involved in the swap, where either the maximum number of tokens to send (by passing a positive value) or the
    // minimum amount of tokens to receive (by passing a negative value) is specified.
    //
    // Additionally, a 'deadline' timestamp can also be provided, forcing the swap to fail if it occurs after
    // this point in time (e.g. if the transaction failed to be included in a block promptly).
    //
    // If interacting with Pools that hold WETH, it is possible to both send and receive ETH directly: the Vault will do
    // the wrapping and unwrapping. To enable this mechanism, the IAsset sentinel value (the zero address) must be
    // passed in the `assets` array instead of the WETH address. Note that it is possible to combine ETH and WETH in the
    // same swap. Any excess ETH will be sent back to the caller (not the sender, which is relevant for relayers).
    //
    // Finally, Internal Balance can be used when either sending or receiving tokens.

    enum SwapKind { GIVEN_IN, GIVEN_OUT }

    /**
     * @dev Performs a swap with a single Pool.
     *
     * If the swap is 'given in' (the number of tokens to send to the Pool is known), it returns the amount of tokens
     * taken from the Pool, which must be greater than or equal to `limit`.
     *
     * If the swap is 'given out' (the number of tokens to take from the Pool is known), it returns the amount of tokens
     * sent to the Pool, which must be less than or equal to `limit`.
     *
     * Internal Balance usage and the recipient are determined by the `funds` struct.
     *
     * Emits a `Swap` event.
     */
    function swap(
        SingleSwap memory singleSwap,
        FundManagement memory funds,
        uint256 limit,
        uint256 deadline
    ) external payable returns (uint256);

    /**
     * @dev Data for a single swap executed by `swap`. `amount` is either `amountIn` or `amountOut` depending on
     * the `kind` value.
     *
     * `assetIn` and `assetOut` are either token addresses, or the IAsset sentinel value for ETH (the zero address).
     * Note that Pools never interact with ETH directly: it will be wrapped to or unwrapped from WETH by the Vault.
     *
     * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be
     * used to extend swap behavior.
     */
    struct SingleSwap {
        bytes32 poolId;
        SwapKind kind;
        IAsset assetIn;
        IAsset assetOut;
        uint256 amount;
        bytes userData;
    }

    /**
     * @dev Performs a series of swaps with one or multiple Pools. In each individual swap, the caller determines either
     * the amount of tokens sent to or received from the Pool, depending on the `kind` value.
     *
     * Returns an array with the net Vault asset balance deltas. Positive amounts represent tokens (or ETH) sent to the
     * Vault, and negative amounts represent tokens (or ETH) sent by the Vault. Each delta corresponds to the asset at
     * the same index in the `assets` array.
     *
     * Swaps are executed sequentially, in the order specified by the `swaps` array. Each array element describes a
     * Pool, the token to be sent to this Pool, the token to receive from it, and an amount that is either `amountIn` or
     * `amountOut` depending on the swap kind.
     *
     * Multihop swaps can be executed by passing an `amount` value of zero for a swap. This will cause the amount in/out
     * of the previous swap to be used as the amount in for the current one. In a 'given in' swap, 'tokenIn' must equal
     * the previous swap's `tokenOut`. For a 'given out' swap, `tokenOut` must equal the previous swap's `tokenIn`.
     *
     * The `assets` array contains the addresses of all assets involved in the swaps. These are either token addresses,
     * or the IAsset sentinel value for ETH (the zero address). Each entry in the `swaps` array specifies tokens in and
     * out by referencing an index in `assets`. Note that Pools never interact with ETH directly: it will be wrapped to
     * or unwrapped from WETH by the Vault.
     *
     * Internal Balance usage, sender, and recipient are determined by the `funds` struct. The `limits` array specifies
     * the minimum or maximum amount of each token the vault is allowed to transfer.
     *
     * `batchSwap` can be used to make a single swap, like `swap` does, but doing so requires more gas than the
     * equivalent `swap` call.
     *
     * Emits `Swap` events.
     */
    function batchSwap(
        SwapKind kind,
        BatchSwapStep[] memory swaps,
        IAsset[] memory assets,
        FundManagement memory funds,
        int256[] memory limits,
        uint256 deadline
    ) external payable returns (int256[] memory);

    /**
     * @dev Data for each individual swap executed by `batchSwap`. The asset in and out fields are indexes into the
     * `assets` array passed to that function, and ETH assets are converted to WETH.
     *
     * If `amount` is zero, the multihop mechanism is used to determine the actual amount based on the amount in/out
     * from the previous swap, depending on the swap kind.
     *
     * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be
     * used to extend swap behavior.
     */
    struct BatchSwapStep {
        bytes32 poolId;
        uint256 assetInIndex;
        uint256 assetOutIndex;
        uint256 amount;
        bytes userData;
    }

    /**
     * @dev Emitted for each individual swap performed by `swap` or `batchSwap`.
     */
    event Swap(
        bytes32 indexed poolId,
        IERC20 indexed tokenIn,
        IERC20 indexed tokenOut,
        uint256 amountIn,
        uint256 amountOut
    );

    /**
     * @dev All tokens in a swap are either sent from the `sender` account to the Vault, or from the Vault to the
     * `recipient` account.
     *
     * If the caller is not `sender`, it must be an authorized relayer for them.
     *
     * If `fromInternalBalance` is true, the `sender`'s Internal Balance will be preferred, performing an ERC20
     * transfer for the difference between the requested amount and the User's Internal Balance (if any). The `sender`
     * must have allowed the Vault to use their tokens via `IERC20.approve()`. This matches the behavior of
     * `joinPool`.
     *
     * If `toInternalBalance` is true, tokens will be deposited to `recipient`'s internal balance instead of
     * transferred. This matches the behavior of `exitPool`.
     *
     * Note that ETH cannot be deposited to or withdrawn from Internal Balance: attempting to do so will trigger a
     * revert.
     */
    struct FundManagement {
        address sender;
        bool fromInternalBalance;
        address payable recipient;
        bool toInternalBalance;
    }

    /**
     * @dev Simulates a call to `batchSwap`, returning an array of Vault asset deltas. Calls to `swap` cannot be
     * simulated directly, but an equivalent `batchSwap` call can and will yield the exact same result.
     *
     * Each element in the array corresponds to the asset at the same index, and indicates the number of tokens (or ETH)
     * the Vault would take from the sender (if positive) or send to the recipient (if negative). The arguments it
     * receives are the same that an equivalent `batchSwap` call would receive.
     *
     * Unlike `batchSwap`, this function performs no checks on the sender or recipient field in the `funds` struct.
     * This makes it suitable to be called by off-chain applications via eth_call without needing to hold tokens,
     * approve them for the Vault, or even know a user's address.
     *
     * Note that this function is not 'view' (due to implementation details): the client code must explicitly execute
     * eth_call instead of eth_sendTransaction.
     */
    function queryBatchSwap(
        SwapKind kind,
        BatchSwapStep[] memory swaps,
        IAsset[] memory assets,
        FundManagement memory funds
    ) external returns (int256[] memory assetDeltas);



    // Asset Management
    //
    // Each token registered for a Pool can be assigned an Asset Manager, which is able to freely withdraw the Pool's
    // tokens from the Vault, deposit them, or assign arbitrary values to its `managed` balance (see
    // `getPoolTokenInfo`). This makes them extremely powerful and dangerous. Even if an Asset Manager only directly
    // controls one of the tokens in a Pool, a malicious manager could set that token's balance to manipulate the
    // prices of the other tokens, and then drain the Pool with swaps. The risk of using Asset Managers is therefore
    // not constrained to the tokens they are managing, but extends to the entire Pool's holdings.
    //
    // However, a properly designed Asset Manager smart contract can be safely used for the Pool's benefit,
    // for example by lending unused tokens out for interest, or using them to participate in voting protocols.
    //
    // This concept is unrelated to the IAsset interface.

    /**
     * @dev Performs a set of Pool balance operations, which may be either withdrawals, deposits or updates.
     *
     * Pool Balance management features batching, which means a single contract call can be used to perform multiple
     * operations of different kinds, with different Pools and tokens, at once.
     *
     * For each operation, the caller must be registered as the Asset Manager for `token` in `poolId`.
     */
    function managePoolBalance(PoolBalanceOp[] memory ops) external;

    struct PoolBalanceOp {
        PoolBalanceOpKind kind;
        bytes32 poolId;
        IERC20 token;
        uint256 amount;
    }

    /**
     * Withdrawals decrease the Pool's cash, but increase its managed balance, leaving the total balance unchanged.
     *
     * Deposits increase the Pool's cash, but decrease its managed balance, leaving the total balance unchanged.
     *
     * Updates don't affect the Pool's cash balance, but because the managed balance changes, it does alter the total.
     * The external amount can be either increased or decreased by this call (i.e., reporting a gain or a loss).
     */
    enum PoolBalanceOpKind { WITHDRAW, DEPOSIT, UPDATE }

    /**
     * @dev Emitted when a Pool's token Asset Manager alters its balance via `managePoolBalance`.
     */
    event PoolBalanceManaged(
        bytes32 indexed poolId,
        address indexed assetManager,
        IERC20 indexed token,
        int256 cashDelta,
        int256 managedDelta
    );

    // Protocol Fees
    //
    // Some operations cause the Vault to collect tokens in the form of protocol fees, which can then be withdrawn by
    // permissioned accounts.
    //
    // There are two kinds of protocol fees:
    //
    //  - flash loan fees: charged on all flash loans, as a percentage of the amounts lent.
    //
    //  - swap fees: a percentage of the fees charged by Pools when performing swaps. For a number of reasons, including
    // swap gas costs and interface simplicity, protocol swap fees are not charged on each individual swap. Rather,
    // Pools are expected to keep track of how much they have charged in swap fees, and pay any outstanding debts to the
    // Vault when they are joined or exited. This prevents users from joining a Pool with unpaid debt, as well as
    // exiting a Pool in debt without first paying their share.

    /**
     * @dev Safety mechanism to pause most Vault operations in the event of an emergency - typically detection of an
     * error in some part of the system.
     *
     * The Vault can only be paused during an initial time period, after which pausing is forever disabled.
     *
     * While the contract is paused, the following features are disabled:
     * - depositing and transferring internal balance
     * - transferring external balance (using the Vault's allowance)
     * - swaps
     * - joining Pools
     * - Asset Manager interactions
     *
     * Internal Balance can still be withdrawn, and Pools exited.
     */
    function setPaused(bool paused) external;

    /**
     * @dev Returns the Vault's WETH instance.
     */
}

interface IBaseWeightedPool {

    enum JoinKind { INIT, EXACT_TOKENS_IN_FOR_BPT_OUT, TOKEN_IN_FOR_EXACT_BPT_OUT, ALL_TOKENS_IN_FOR_EXACT_BPT_OUT }
    enum ExitKind {
        EXACT_BPT_IN_FOR_ONE_TOKEN_OUT,
        EXACT_BPT_IN_FOR_TOKENS_OUT,
        BPT_IN_FOR_EXACT_TOKENS_OUT,
        MANAGEMENT_FEE_TOKENS_OUT // for InvestmentPool
    }

    function getNormalizedWeights() external view returns (uint256[] memory);


}

interface IBeetsBar{
    function enter(uint256 amount) external;
    function leave(uint256 amount) external;
}

interface IDelegateRegistry {
  function clearDelegate(bytes32 id) external;
  function delegation(address, bytes32) external view returns (address);
  function setDelegate(bytes32 id, address delegate) external;
}

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

interface IWrappedNative is IERC20 {
    function ERR_INVALID_ZERO_VALUE() external view returns (uint256);

    function ERR_NO_ERROR() external view returns (uint256);

    function deposit() external payable returns (uint256);

    function withdraw(uint256 amount) external returns (uint256);
}

interface IRFVault {
    function getPricePerFullShare() external view returns (uint256);
}

pragma solidity ^0.8.0;
/**
 * @dev Implementation of a strategy to get yields from farming LP Pools in SpookySwap.
 * SpookySwap is an automated market maker (“AMM”) that allows two tokens to be exchanged on Fantom's Opera Network.
 *
 * This strategy deposits whatever funds it receives from the vault into the selected masterChef pool.
 * rewards from providing liquidity are farmed every few minutes, sold and split 50/50.
 * The corresponding pair of assets are bought and more liquidity is added to the masterChef pool.
 *
 * Expect the amount of LP tokens you have to grow over time while you have assets deposit
 */
contract ReaperAutoCompoundBeethoven_fBEETS is Ownable, Pausable {
    using SafeERC20 for IERC20;
    using Address for address;
    using SafeMath for uint256;

    /**
     * @dev Tokens Used:
     * {wftm} - Required for liquidity routing when doing swaps.
     * {rewardToken} - Token generated by staking our funds.
     * {lpToken} - LP Token that the strategy maximizes.
     * {lpToken0, lpToken1} - Tokens that the strategy maximizes. IUniswapV2Pair tokens.
     */
    address public constant wftm = address(0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83);
    address public constant underlyingLP = address(0xcdE5a11a4ACB4eE4c805352Cec57E236bdBC3837);
    address public constant fBEETS = address(0xfcef8a994209d6916EB2C86cDD2AFD60Aa6F54b1);
    address public constant rewardToken = address(0xF24Bcf4d1e507740041C9cFd2DddB29585aDCe1e);// beets token
    address public constant BeetVault = address(0x20dd72Ed959b6147912C2e529F0a0C651c33c9ce);
    address public lpToken;

    uint8 public totalUnderlyingTokens;

    mapping(uint8 => bool) public isEmitting;
    bool public harvestOn = false;
    bool public depositsPaused = false;
    /**
     * @dev Third Party Contracts:
     * {router} - the router for target DEX
     * {masterChef} - masterChef contract
     * {poolId} - masterChef pool id
     */

    address public masterChef = address(0x8166994d9ebBe5829EC86Bd81258149B87faCfd3);
    uint public poolId;
    bytes32 public poolID_bytes;

    uint8 public beetsPosition = 0;
    uint8 public wftmPosition = 0;
    bool public beetsUnderlying = false;
    bool public wftmUnderlying = false;
    bytes32 public route_ID;
    bytes32 public constant wftmRoute_ID = 0xcde5a11a4acb4ee4c805352cec57e236bdbc3837000200000000000000000019;
    bool public secondReward = false;
    address public secondRewardToken;
    bytes32 public secondRewardRoute;


    struct Harvest {
        uint256 timestamp;
        uint256 vaultSharePrice;
    }

    Harvest[] public harvestLog;
    uint256 public harvestLogCadence = 1 hours;
    uint256 public constant ONE_YEAR = 365 days;

    /**
     * @dev Reaper Contracts:
     * {treasury} - Address of the Reaper treasury
     * {vault} - Address of the vault that controls the strategy's funds.
     */
    address public treasury;
    address public vault;
    address public strategistRemitter;

     /**
     * @dev Distribution of fees earned. This allocations relative to the % implemented on
     * Current implementation separates 5% for fees. Can be changed through the constructor
     * Inputs in constructor should be ratios between the Fee and Max Fee, divisble into percents by 10000
     *
     * {callFee} - Percent of the totalFee reserved for the harvester (1000 = 10% of total fee: 0.5% by default)
     * {treasuryFee} - Percent of the totalFee taken by maintainers of the software (9000 = 90% of total fee: 4.5% by default)
     * {securityFee} - Fee taxed when a user withdraws funds. Taken to prevent flash deposit/harvest attacks.
     * These funds are redistributed to stakers in the pool.
     *
     * {totalFee} - divided by 10,000 to determine the % fee. Set to 5% by default and
     * lowered as necessary to provide users with the most competitive APY.
     *
     * {MAX_FEE} - Maximum fee allowed by the strategy. Hard-capped at 5%.
     * {PERCENT_DIVISOR} - Constant used to safely calculate the correct percentages.
     */

    uint public callFee = 1000;
    uint public treasuryFee = 9000;
    uint256 public strategistFee = 2500;
    uint public securityFee = 10;
    uint public totalFee = 450;
    uint constant public MAX_FEE = 500;
    uint256 public constant STRATEGIST_MAX_FEE = 5000;
    uint constant  public PERCENT_DIVISOR = 10000;

    /**
     * @dev Routes we take to swap tokens using PanrewardTokenSwap.
     * {rewardTokenToWftmRoute} - Route we take to get from {rewardToken} into {wftm}.
     * {rewardTokenToLp0Route} - Route we take to get from {rewardToken} into {lpToken0}.
     * {rewardTokenToLp1Route} - Route we take to get from {rewardToken} into {lpToken1}.
     */

    mapping (uint8 => address) public LPs;

    /**
     * {StratHarvest} Event that is fired each time someone harvests the strat.
     * {TotalFeeUpdated} Event that is fired each time the total fee is updated.
     * {CallFeeUpdated} Event that is fired each time the call fee is updated.
     */
    event StratHarvest(address indexed harvester);
    event TotalFeeUpdated(uint newFee);
    event CallFeeUpdated(uint newCallFee, uint newTreasuryFee);

    /**
     * @dev Initializes the strategy. Sets parameters, saves routes, and gives allowances.
     * @notice see documentation for each variable above its respective declaration.
     */
    constructor (
      address _lpToken,
      uint _poolId,
      address _vault,
      address _treasury,
      address _strategistRemitter
    ) public {
        lpToken = _lpToken;
        poolId = _poolId;
        poolID_bytes = wftmRoute_ID;
        vault = _vault;
        treasury = _treasury;
        strategistRemitter = _strategistRemitter;

        //gather underlying tokens
        //we're assuming we are dealing with the PoolTokens.sol for the interface
        IERC20[] memory _lps;

        (_lps,,) = IVault(BeetVault).getPoolTokens(poolID_bytes);
        totalUnderlyingTokens = uint8(_lps.length);

        for(uint8 i; i < _lps.length; i++){
            LPs[i] = address(_lps[i]);
            if(LPs[i] == wftm){
                wftmPosition = i;
                wftmUnderlying = true;
            }

            if(LPs[i] == rewardToken){
                beetsPosition = i;
                beetsUnderlying = true;
            }
        }

        _giveAllowances(); //this will also need work
        harvestLog.push(Harvest({timestamp: block.timestamp, vaultSharePrice: IRFVault(_vault).getPricePerFullShare()}));
    }

    /**
     * @dev Function that puts the funds to work.
     * It gets called whenever someone deposits in the strategy's vault contract.
     * It deposits {lpToken} in the masterChef to farm {rewardToken}
     */
    function deposit() external {
        require(!depositsPaused, "cannot deposit at this time");
        _deposit();
    }

    function _deposit() internal whenNotPaused onActionHarvest{
        uint256 pairBal = IERC20(lpToken).balanceOf(address(this));

        if (pairBal > 0) {
            IMasterChefv2(masterChef).deposit(poolId, pairBal, address(this));
        }
    }

    /**
     * @dev Withdraws funds and sents them back to the vault.
     * It withdraws {lpToken} from the masterChef.
     * The available {lpToken} minus fees is returned to the vault.
     */
    function withdraw(uint256 _amount) external onActionHarvest{
    require(msg.sender == vault, "!vault");

      uint256 pairBal = IERC20(lpToken).balanceOf(address(this));

      if (pairBal < _amount) {
        IMasterChefv2(masterChef).withdrawAndHarvest(poolId, _amount.sub(pairBal), address(this));
        pairBal = IERC20(lpToken).balanceOf(address(this));
      }

      if (pairBal > _amount) {
        pairBal = _amount;
      }
      uint256 withdrawFee = pairBal.mul(securityFee).div(PERCENT_DIVISOR);
      IERC20(lpToken).safeTransfer(vault, pairBal.sub(withdrawFee));
    }

    function harvest() external {
        _harvest(false);
    }

    /**
     * @dev Core function of the strat, in charge of collecting and re-investing rewards.
     * 1. It claims rewards from the masterChef.
     * 2. It charges the system fees to simplify the split.
     * 3. It swaps the {rewardToken} token for {lpToken0} & {lpToken1}
     * 4. Adds more liquidity to the pool.
     * 5. It deposits the new LP tokens.
     */
    function _harvest(bool _remitStrategist) internal whenNotPaused {
        IMasterChefv2(masterChef).harvest(poolId, address(this));
        _chargeFees(_remitStrategist);

        if(secondReward){_swapSecondToken(secondRewardToken, secondRewardRoute);}

        _addLiquidity(rewardToken, beetsPosition);

        _enterX();

        _deposit();

        if (block.timestamp >= harvestLog[harvestLog.length - 1].timestamp + harvestLogCadence) {
            harvestLog.push(
                Harvest({timestamp: block.timestamp, vaultSharePrice: IRFVault(vault).getPricePerFullShare()})
            );
        }

        emit StratHarvest(msg.sender);
    }

    function _enterX() internal {
        uint256 amtLP = IERC20(underlyingLP).balanceOf(address(this));
        IBeetsBar(fBEETS).enter(amtLP);
    }

    /**
     * @dev Takes out fees from the rewards. Set by constructor
     * callFeeToUser is set as a percentage of the fee,
     * as is treasuryFeeToVault
     */
    function _chargeFees(bool _remitStrategist) internal {
        uint256 rewardBal = IERC20(rewardToken).balanceOf(address(this));
        uint256 wftmBal = IERC20(wftm).balanceOf(address(this));

        uint256 fees;
        uint256 wftmFees;

        

        fees = rewardBal.mul(totalFee).div(PERCENT_DIVISOR);
        _swap(rewardToken, wftm, wftmRoute_ID, fees);
        wftmFees = IERC20(wftm).balanceOf(address(this)).sub(wftmBal);

        uint256 callFeeToUser = wftmFees.mul(callFee).div(PERCENT_DIVISOR);
        IERC20(wftm).safeTransfer(msg.sender, callFeeToUser);


        uint256 treasuryFeeToVault = wftmFees.mul(treasuryFee).div(PERCENT_DIVISOR);
        if (_remitStrategist) {
            uint256 feeToStrategist = treasuryFeeToVault.mul(strategistFee).div(PERCENT_DIVISOR);
            treasuryFeeToVault = treasuryFeeToVault.sub(feeToStrategist);
            IERC20(wftm).safeTransfer(strategistRemitter, feeToStrategist);
        }
        IERC20(wftm).safeTransfer(treasury, treasuryFeeToVault);

    }


    //function to swap from one token to another given a pool containing them both
    function _swap(address _tokenIN, address _tokenOUT, bytes32 _pool, uint256 amount) internal{

        IVault.SingleSwap memory singleSwap;
        IVault.SwapKind swapKind = IVault.SwapKind.GIVEN_IN;

        singleSwap.poolId = _pool;
        singleSwap.kind = swapKind;
        singleSwap.assetIn = IAsset(_tokenIN);
        singleSwap.assetOut = IAsset(_tokenOUT);
        singleSwap.amount = amount;
        singleSwap.userData = abi.encode(0);

        IVault.FundManagement memory funds;
        funds.sender = address(this);
        funds.fromInternalBalance = false;
        funds.recipient = payable(address(this));
        funds.toInternalBalance = false;

        IERC20(_tokenIN).safeApprove(BeetVault, 0);
        IERC20(_tokenIN).safeApprove(BeetVault, amount);

        IVault(BeetVault).swap(singleSwap, funds, 1, (block.timestamp + 600));

    }

    /**
     * @dev Swaps {rewardToken} for {lpToken0}, {lpToken1} & {wftm} using SpookySwap.
     */
    function _addLiquidity(address token, uint8 position) internal {
        uint256 depositTokenBalance = IERC20(token).balanceOf(address(this));

        IERC20(token).safeApprove(BeetVault, 0);
        IERC20(token).safeApprove(BeetVault, depositTokenBalance);

        IBaseWeightedPool.JoinKind joinKind = IBaseWeightedPool.JoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT;
        uint256[] memory amountsIn = new uint256[](totalUnderlyingTokens);
        amountsIn[position] = depositTokenBalance;
        uint256 minAmountOut = 1;
        IAsset[] memory _assets = new IAsset[](totalUnderlyingTokens);
        for(uint8 i = 0; i < totalUnderlyingTokens; i++){
            _assets[i] = IAsset(LPs[i]);
        }



        bytes memory userData = abi.encode(joinKind, amountsIn, minAmountOut);

        IVault.JoinPoolRequest memory request;
        request.assets = _assets;
        request.maxAmountsIn = amountsIn;
        request.userData = userData;
        request.fromInternalBalance = false;

        IVault(BeetVault).joinPool(
            poolID_bytes,
            address(this),
            address(this),
            request
        );
    }

    /**
     * @dev Function to calculate the total underlaying {lpToken} held by the strat.
     * It takes into account both the funds in hand, as the funds allocated in the masterChef.
     */
    function balanceOf() public view returns (uint256) {
        return balanceOfLpPair().add(balanceOfPool());
    }

    /**
     * @dev It calculates how much {lpToken} the contract holds.
     */
    function balanceOfLpPair() public view returns (uint256) {
        return IERC20(lpToken).balanceOf(address(this));
    }

    /**
     * @dev It calculates how much {lpToken} the strategy has allocated in the masterChef
     */
    function balanceOfPool() public view returns (uint256) {
        (uint256 _amount,) = IMasterChef(masterChef).userInfo(poolId, address(this));
        return _amount;
    }

    /**
     * @dev Function that has to be called as part of strat migration. It sends all the available funds back to the
     * vault, ready to be migrated to the new strat.
     */
    function retireStrat() external {
        require(msg.sender == vault, "!vault");

        IMasterChefv2(masterChef).withdrawAndHarvest(poolId, balanceOfPool(), address(this));

        uint256 pairBal = IERC20(lpToken).balanceOf(address(this));
        IERC20(lpToken).transfer(vault, pairBal);
    }

    /**
     * @dev Pauses deposits. Withdraws all funds from the masterChef, leaving rewards behind
     */
    function panic() public onlyOwner {
        pause();
        IMasterChef(masterChef).emergencyWithdraw(poolId, address(this));
    }

    /**
     * @dev Pauses the strat.
     */
    function pause() public onlyOwner {
      _pause();
      _removeAllowances();
    }

    /**
     * @dev Unpauses the strat.
     */
    function unpause() external onlyOwner {
        _unpause();

        _giveAllowances();

        _deposit();
    }

    function _giveAllowances() internal {
        IERC20(underlyingLP).safeApprove(fBEETS, 0);
        IERC20(rewardToken).safeApprove(BeetVault, 0);
        IERC20(wftm).safeApprove(BeetVault, 0);
        IERC20(fBEETS).safeApprove(masterChef, 0);
        IERC20(underlyingLP).safeApprove(fBEETS, type(uint256).max);
        IERC20(rewardToken).safeApprove(BeetVault, type(uint256).max);
        IERC20(wftm).safeApprove(BeetVault, type(uint256).max);
        IERC20(fBEETS).safeApprove(masterChef, type(uint256).max);

    }

    function _removeAllowances() internal {
        IERC20(underlyingLP).safeApprove(fBEETS, 0);
        IERC20(rewardToken).safeApprove(BeetVault, 0);
        IERC20(wftm).safeApprove(BeetVault, 0);
        IERC20(fBEETS).safeApprove(masterChef, 0);
    }


    /**
     * @dev updates the total fee, capped at 5%
     */
    function updateTotalFee(uint _totalFee) external onlyOwner returns (bool) {
      require(_totalFee <= MAX_FEE, "Fee Too High");
      totalFee = _totalFee;
      emit TotalFeeUpdated(totalFee);
      return true;
    }

    /**
     * @dev updates the strategist fee, capped at 50% of treasury fee
     */
    function updateStrategistFee(uint256 _strategistFee) external onlyOwner {
      require(_strategistFee <= STRATEGIST_MAX_FEE, "Fee Too High");
      strategistFee = _strategistFee;
    }

    /**
     * @dev updates the call fee and adjusts the treasury fee to cover the difference
     */
    function updateCallFee(uint _callFee) external onlyOwner returns (bool) {
      callFee = _callFee;
      treasuryFee = PERCENT_DIVISOR.sub(callFee);
      emit CallFeeUpdated(callFee, treasuryFee);
      return true;
    }

    function harvestOnAction(bool _setting) external onlyOwner returns (bool){
        harvestOn = _setting;
        return true;
    }


    modifier onActionHarvest {
        if (harvestOn == true){
            _harvest(false);
        }
        _;
    }

    function updateRouteID(bytes32 newID) external onlyOwner {
        route_ID = newID;
    }

    function updateTreasury(address newTreasury) external onlyOwner returns (bool) {
      treasury = newTreasury;
      return true;
    }

    function _swapSecondToken(address token, bytes32 route) internal {

            uint256 wftmBal = IERC20(wftm).balanceOf(address(this));
            uint256 bal = IERC20(token).balanceOf(address(this));
            _swap(token, wftm, route, bal);
            uint256 fees = IERC20(wftm).balanceOf(address(this)).sub(wftmBal).mul(totalFee).div(PERCENT_DIVISOR);

            uint256 callFeeToUser = fees.mul(callFee).div(PERCENT_DIVISOR);
            IERC20(wftm).safeTransfer(msg.sender, callFeeToUser);

            uint256 treasuryFeeToVault = fees.mul(treasuryFee).div(PERCENT_DIVISOR);
            IERC20(wftm).safeTransfer(treasury, treasuryFeeToVault);

            
            wftmBal = IERC20(wftm).balanceOf(address(this));
            _swap(wftm, rewardToken, wftmRoute_ID, wftmBal);
            


    }

    // NOTE: this is a centralized, high trust function used to securely deliver a secondary reward payload to users in the vault
    // Please ensure anyone operating clones of this vault are trustworthy before putting your money in
    function secondRewardInformation(bool status, address token, bytes32 route) external onlyOwner {
        require(token != rewardToken, "rewardToken is already accounted for");
        secondReward = status;
        secondRewardToken = token;
        secondRewardRoute = route;
    }

    function updateSecurityFee(uint256 _fee) external onlyOwner {
        require(_fee <= 10, "fee too high");
        securityFee = _fee;
    }

    // ####################################################
    // ONLY-OWNER VOTING/BRIBE-RELATED FUNCTIONS
    // ####################################################
    function setDepositsPaused(bool _depositsPaused) external onlyOwner {
        depositsPaused = _depositsPaused;
    }

    function setDelegate(address _registry, bytes32 _id, address _delegate) external onlyOwner {
        IDelegateRegistry(_registry).setDelegate(_id, _delegate);
    }

    // swaps {_tokens[0]} to {rewardToken} using {_routes} (series of Beethoven swaps)
    function swapBribeToken(address[] calldata _tokens, bytes32[] calldata _routes) external onlyOwner {
        require(_tokens.length != 0 && _tokens.length == _routes.length, "bad arrays");
        for(uint256 i = 0; i < _tokens.length; i++) {
            address nextToken;
            if (i == _tokens.length - 1) {
                nextToken = rewardToken;
            } else {
                nextToken = _tokens[i + 1];
            }

            _swap(_tokens[i], nextToken, _routes[i], IERC20(_tokens[i]).balanceOf(address(this)));
        }
        _harvest(true); // charge strategist fee
    }

    // swaps {_path[0]} to {rewardToken} using {_path} (Uni router swap)
    function swapBribeTokenWithUniRouter(address _router, address[] calldata _path) external onlyOwner {
        IERC20 token = IERC20(_path[0]);
        uint256 tokenBal = token.balanceOf(address(this));
        token.safeIncreaseAllowance(_router, tokenBal);

        IUniRouterMinimal(_router).swapExactTokensForTokensSupportingFeeOnTransferTokens(
            tokenBal,
            0,
            _path,
            address(this),
            block.timestamp + 600
        );
        _harvest(true); // charge strategist fee
    }

    function wrapNativeBribe(address _wrappedNative) external onlyOwner {
        IWrappedNative wrapped = IWrappedNative(_wrappedNative);
        uint256 balance = address(this).balance;
        require(wrapped.deposit{value: balance}() == wrapped.ERR_NO_ERROR(), "wrapping error");
    }

    receive() external payable { }

    // ####################################################
    // ON-CHAIN APR CALCULATION FUNCTIONS
    // ####################################################
    function updateHarvestLogCadence(uint256 _newCadenceInSeconds) external onlyOwner {
        harvestLogCadence = _newCadenceInSeconds;
    }

    function harvestLogLength() external view returns (uint256) {
        return harvestLog.length;
    }

    /**
     * @dev Returns a slice of the harvest log containing the _n latest harvests.
     */
    function latestHarvestLogSlice(uint256 _n) external view returns (Harvest[] memory slice) {
        slice = new Harvest[](_n);
        uint256 sliceCounter = 0;

        for (uint256 i = harvestLog.length - _n; i < harvestLog.length; i++) {
            slice[sliceCounter++] = harvestLog[i];
        }
    }

    /**
     * @dev Traverses the harvest log backwards until it hits _timestamp,
     *      and returns the average APR calculated across all the included
     *      log entries. APR is multiplied by PERCENT_DIVISOR to retain precision.
     */
    function averageAPRSince(uint256 _timestamp) external view returns (int256) {
        require(harvestLog.length >= 2, "need at least 2 log entries");

        int256 runningAPRSum;
        int256 numLogsProcessed;

        for (uint256 i = harvestLog.length - 1; i > 0 && harvestLog[i].timestamp >= _timestamp; i--) {
            runningAPRSum += calculateAPRUsingLogs(i - 1, i);
            numLogsProcessed++;
        }

        return runningAPRSum / numLogsProcessed;
    }

    /**
     * @dev Traverses the harvest log backwards _n items,
     *      and returns the average APR calculated across all the included
     *      log entries. APR is multiplied by PERCENT_DIVISOR to retain precision.
     */
    function averageAPRAcrossLastNHarvests(int256 _n) external view returns (int256) {
        require(harvestLog.length >= 2, "need at least 2 log entries");

        int256 runningAPRSum;
        int256 numLogsProcessed;

        for (uint256 i = harvestLog.length - 1; i > 0 && numLogsProcessed < _n; i--) {
            runningAPRSum += calculateAPRUsingLogs(i - 1, i);
            numLogsProcessed++;
        }

        return runningAPRSum / numLogsProcessed;
    }

    function calculateAPRUsingLogs(uint256 _startIndex, uint256 _endIndex) public view returns (int256) {
        Harvest storage start = harvestLog[_startIndex];
        Harvest storage end = harvestLog[_endIndex];
        bool increasing = true;
        if (end.vaultSharePrice < start.vaultSharePrice) {
            increasing = false;
        }

        uint256 unsignedSharePriceChange;
        if (increasing) {
            unsignedSharePriceChange = end.vaultSharePrice - start.vaultSharePrice;
        } else {
            unsignedSharePriceChange = start.vaultSharePrice - end.vaultSharePrice;
        }

        uint256 unsignedPercentageChange = (unsignedSharePriceChange * 1e18) / start.vaultSharePrice;
        uint256 timeDifference = end.timestamp - start.timestamp;

        uint256 yearlyUnsignedPercentageChange = (unsignedPercentageChange * ONE_YEAR) / timeDifference;
        yearlyUnsignedPercentageChange /= 1e14; // restore basis points precision

        if (increasing) {
            return int256(yearlyUnsignedPercentageChange);
        }

        return -int256(yearlyUnsignedPercentageChange);
    }
}

Settings
{
  "metadata": {
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_lpToken","type":"address"},{"internalType":"uint256","name":"_poolId","type":"uint256"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_strategistRemitter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newCallFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTreasuryFee","type":"uint256"}],"name":"CallFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"harvester","type":"address"}],"name":"StratHarvest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"TotalFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"BeetVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"LPs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STRATEGIST_MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"_n","type":"int256"}],"name":"averageAPRAcrossLastNHarvests","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"averageAPRSince","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOfLpPair","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOfPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"beetsPosition","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"beetsUnderlying","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_startIndex","type":"uint256"},{"internalType":"uint256","name":"_endIndex","type":"uint256"}],"name":"calculateAPRUsingLogs","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fBEETS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"harvestLog","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"vaultSharePrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvestLogCadence","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvestLogLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvestOn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_setting","type":"bool"}],"name":"harvestOnAction","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"isEmitting","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_n","type":"uint256"}],"name":"latestHarvestLogSlice","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"vaultSharePrice","type":"uint256"}],"internalType":"struct ReaperAutoCompoundBeethoven_fBEETS.Harvest[]","name":"slice","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"masterChef","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"panic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolID_bytes","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"retireStrat","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"route_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secondReward","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"route","type":"bytes32"}],"name":"secondRewardInformation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"secondRewardRoute","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secondRewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"securityFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_registry","type":"address"},{"internalType":"bytes32","name":"_id","type":"bytes32"},{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_depositsPaused","type":"bool"}],"name":"setDepositsPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategistFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategistRemitter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"bytes32[]","name":"_routes","type":"bytes32[]"}],"name":"swapBribeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"address[]","name":"_path","type":"address[]"}],"name":"swapBribeTokenWithUniRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalUnderlyingTokens","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasuryFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingLP","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_callFee","type":"uint256"}],"name":"updateCallFee","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newCadenceInSeconds","type":"uint256"}],"name":"updateHarvestLogCadence","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newID","type":"bytes32"}],"name":"updateRouteID","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"updateSecurityFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_strategistFee","type":"uint256"}],"name":"updateStrategistFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalFee","type":"uint256"}],"name":"updateTotalFee","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTreasury","type":"address"}],"name":"updateTreasury","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wftm","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wftmPosition","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wftmRoute_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wftmUnderlying","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wrappedNative","type":"address"}],"name":"wrapNativeBribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6080604052600380546001600160b01b031916758166994d9ebbe5829ec86bd81258149b87facfd300001790556006805463ffffffff191690556008805460ff19169055610e10600b556103e8600f556123286010556109c4601155600a6012556101c26013553480156200007357600080fd5b5060405162004db338038062004db38339810160408190526200009691620009df565b620000a133620003a9565b6000805460ff60a01b19169055600180546001600160a01b038088166001600160a01b03199283161790925560048681557fcde5a11a4acb4ee4c805352cec57e236bdbc38370002000000000000000000196005819055600d8054888616908516179055600c8054878616908516179055600e80549486169490931693909317909155604051631f29a8cd60e31b815260609260008051602062004d938339815191529263f94d4668926200015b92910190815260200190565b60006040518083038186803b1580156200017457600080fd5b505afa15801562000189573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001b3919081019062000b35565b505080516001805460ff909216600160a01b0260ff60a01b19909216919091179055905060005b81518160ff161015620002e057818160ff1681518110620001ff57620001ff62000c10565b60209081029190910181015160ff831660009081526014909252604090912080546001600160a01b0319166001600160a01b0390921691821790557321be370d5312f44cb42ce377bc9b8a0cef1a4c8314156200027c576006805463ff0000001960ff8416610100021663ff00ff00199091161763010000001790555b60ff81166000908152601460205260409020546001600160a01b031673f24bcf4d1e507740041c9cfd2dddb29585adce1e1415620002cb576006805462ff00ff191660ff831617620100001790555b80620002d78162000c26565b915050620001da565b50620002eb620003f9565b600a6040518060400160405280428152602001866001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200033857600080fd5b505afa1580156200034d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000373919062000c55565b90528154600181810184556000938452602093849020835160029093020191825592909101519101555062000d19945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6200043b73cde5a11a4acb4ee4c805352cec57e236bdbc383773fcef8a994209d6916eb2c86cdd2afd60aa6f54b16000620005f9602090811b620021aa17901c565b6200047873f24bcf4d1e507740041c9cfd2dddb29585adce1e60008051602062004d938339815191526000620005f9602090811b620021aa17901c565b620004b57321be370d5312f44cb42ce377bc9b8a0cef1a4c8360008051602062004d938339815191526000620005f9602090811b620021aa17901c565b600354620004f69073fcef8a994209d6916eb2c86cdd2afd60aa6f54b1906201000090046001600160a01b03166000620005f9602090811b620021aa17901c565b6200053973cde5a11a4acb4ee4c805352cec57e236bdbc383773fcef8a994209d6916eb2c86cdd2afd60aa6f54b1600019620005f9602090811b620021aa17901c565b6200057773f24bcf4d1e507740041c9cfd2dddb29585adce1e60008051602062004d93833981519152600019620005f9602090811b620021aa17901c565b620005b57321be370d5312f44cb42ce377bc9b8a0cef1a4c8360008051602062004d93833981519152600019620005f9602090811b620021aa17901c565b600354620005f79073fcef8a994209d6916eb2c86cdd2afd60aa6f54b1906201000090046001600160a01b0316600019620005f9602090811b620021aa17901c565b565b801580620006875750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156200064a57600080fd5b505afa1580156200065f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000685919062000c55565b155b620006ff5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620007579185916200075c16565b505050565b6000620007b8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200083a60201b62002301179092919060201c565b805190915015620007575780806020019051810190620007d9919062000c6f565b620007575760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620006f6565b60606200084b848460008562000855565b90505b9392505050565b606082471015620008b85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620006f6565b843b620009085760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620006f6565b600080866001600160a01b0316858760405162000926919062000cc6565b60006040518083038185875af1925050503d806000811462000965576040519150601f19603f3d011682016040523d82523d6000602084013e6200096a565b606091505b5090925090506200097d82828662000988565b979650505050505050565b60608315620009995750816200084e565b825115620009aa5782518084602001fd5b8160405162461bcd60e51b8152600401620006f6919062000ce4565b6001600160a01b0381168114620009dc57600080fd5b50565b600080600080600060a08688031215620009f857600080fd5b855162000a0581620009c6565b60208701516040880151919650945062000a1f81620009c6565b606087015190935062000a3281620009c6565b608087015190925062000a4581620009c6565b809150509295509295909350565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171562000a945762000a9462000a53565b604052919050565b60006001600160401b0382111562000ab85762000ab862000a53565b5060051b60200190565b600082601f83011262000ad457600080fd5b8151602062000aed62000ae78362000a9c565b62000a69565b82815260059290921b8401810191818101908684111562000b0d57600080fd5b8286015b8481101562000b2a578051835291830191830162000b11565b509695505050505050565b60008060006060848603121562000b4b57600080fd5b83516001600160401b038082111562000b6357600080fd5b818601915086601f83011262000b7857600080fd5b8151602062000b8b62000ae78362000a9c565b82815260059290921b8401810191818101908a84111562000bab57600080fd5b948201945b8386101562000bd657855162000bc681620009c6565b8252948201949082019062000bb0565b9189015191975090935050508082111562000bf057600080fd5b5062000bff8682870162000ac2565b925050604084015190509250925092565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff81141562000c4c57634e487b7160e01b600052601160045260246000fd5b60010192915050565b60006020828403121562000c6857600080fd5b5051919050565b60006020828403121562000c8257600080fd5b815180151581146200084e57600080fd5b60005b8381101562000cb057818101518382015260200162000c96565b8381111562000cc0576000848401525b50505050565b6000825162000cda81846020870162000c93565b9190910192915050565b602081526000825180602084015262000d0581604085016020870162000c93565b601f01601f19169190910160400192915050565b61406a8062000d296000396000f3fe6080604052600436106104095760003560e01c80638838d13a11610213578063d68e130211610123578063f4f45b46116100ab578063f91154531161007a578063f911545314610bfb578063fb61778714610c1b578063fbfa77cf14610c30578063fec94ad114610c50578063ff08b97d14610c6a57600080fd5b8063f4f45b4614610b77578063f587cde914610b99578063f7c618c114610bb3578063f88fb68914610bdb57600080fd5b8063edf2d5d2116100f2578063edf2d5d214610ab5578063f0f4809214610ad5578063f2fde38b14610b02578063f37ae32814610b22578063f4852a8114610b5757600080fd5b8063d68e130214610a4f578063ec4942da14610a65578063ec90b12214610a7f578063ecf173ff14610a9f57600080fd5b8063aaf8561a116101a6578063c8212ce211610175578063c8212ce2146109c4578063cc32d176146109e4578063ced0883e146109fa578063d0e30db014610a1a578063d32b960414610a2f57600080fd5b8063aaf8561a14610962578063bc063e1a14610983578063bdd3105814610999578063c2351cdd146109af57600080fd5b80638da5cb5b116101e25780638da5cb5b146108d357806390321e1a146108f1578063949c12c3146109075780639a111c371461093d57600080fd5b80638838d13a146108435780638888f9f6146108635780638954ffeb146108835780638cf55882146108b357600080fd5b80634967117111610319578063682274e3116102a157806372c95e561161027057806372c95e56146107b05780637330d4b8146107c65780637380fa3f146107e65780637f51bb1f1461080e5780638456cb591461082e57600080fd5b8063682274e31461073e5780636f680bcf1461075e578063715018a614610786578063722713f71461079b57600080fd5b80635fcbd285116102e85780635fcbd285146106a957806360da3e83146106c957806361591149146106e857806361d027b314610708578063635f91d01461072857600080fd5b80634967117114610622578063526e108014610642578063575a86b2146106585780635c975abb1461067e57600080fd5b80632ae3af4b1161039c5780633e6b35cb1161036b5780633e6b35cb1461059c5780633f4ba83a146105cd5780634641257d146105e25780634700d305146105f75780634870dd9a1461060c57600080fd5b80632ae3af4b1461053b5780632d6f4baa146105515780632e1a7d4d146105665780633e0dc34e1461058657600080fd5b806316d3bfbb116103d857806316d3bfbb146104b95780631c481e2d146104d15780631df4ccfc146104f15780631eec45921461050757600080fd5b806303b17808146104155780630463b7de146104375780630537524b14610457578063115880861461049657600080fd5b3661041057005b600080fd5b34801561042157600080fd5b50610435610430366004613804565b610c8b565b005b34801561044357600080fd5b50610435610452366004613840565b610d25565b34801561046357600080fd5b5061047960008051602061401583398151915281565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156104a257600080fd5b506104ab610d95565b60405190815260200161048d565b3480156104c557600080fd5b506104ab6301e1338081565b3480156104dd57600080fd5b506104356104ec366004613867565b610e28565b3480156104fd57600080fd5b506104ab60135481565b34801561051357600080fd5b506104ab7fcde5a11a4acb4ee4c805352cec57e236bdbc383700020000000000000000001981565b34801561054757600080fd5b506104ab60095481565b34801561055d57600080fd5b50600a546104ab565b34801561057257600080fd5b50610435610581366004613840565b610e6c565b34801561059257600080fd5b506104ab60045481565b3480156105a857600080fd5b506006546105bb90610100900460ff1681565b60405160ff909116815260200161048d565b3480156105d957600080fd5b506104356110b3565b3480156105ee57600080fd5b506104356110f7565b34801561060357600080fd5b50610435611101565b34801561061857600080fd5b506104ab61271081565b34801561062e57600080fd5b5061043561063d366004613884565b61119f565b34801561064e57600080fd5b506104ab60115481565b34801561066457600080fd5b50600354610479906201000090046001600160a01b031681565b34801561068a57600080fd5b50600054600160a01b900460ff165b604051901515815260200161048d565b3480156106b557600080fd5b50600154610479906001600160a01b031681565b3480156106d557600080fd5b5060035461069990610100900460ff1681565b3480156106f457600080fd5b50610435610703366004613840565b6112f6565b34801561071457600080fd5b50600c54610479906001600160a01b031681565b34801561073457600080fd5b506104ab60075481565b34801561074a57600080fd5b506104ab610759366004613840565b611365565b34801561076a57600080fd5b5061047973fcef8a994209d6916eb2c86cdd2afd60aa6f54b181565b34801561079257600080fd5b50610435611461565b3480156107a757600080fd5b506104ab611495565b3480156107bc57600080fd5b506104ab600b5481565b3480156107d257600080fd5b506104356107e13660046138eb565b6114b5565b3480156107f257600080fd5b5061047973cde5a11a4acb4ee4c805352cec57e236bdbc383781565b34801561081a57600080fd5b50610699610829366004613884565b61169b565b34801561083a57600080fd5b506104356116ea565b34801561084f57600080fd5b5061043561085e366004613957565b611724565b34801561086f57600080fd5b50600e54610479906001600160a01b031681565b34801561088f57600080fd5b5061069961089e3660046139aa565b60026020526000908152604090205460ff1681565b3480156108bf57600080fd5b506104ab6108ce3660046139cd565b611890565b3480156108df57600080fd5b506000546001600160a01b0316610479565b3480156108fd57600080fd5b506104ab600f5481565b34801561091357600080fd5b506104796109223660046139aa565b6014602052600090815260409020546001600160a01b031681565b34801561094957600080fd5b506008546104799061010090046001600160a01b031681565b34801561096e57600080fd5b506001546105bb90600160a01b900460ff1681565b34801561098f57600080fd5b506104ab6101f481565b3480156109a557600080fd5b506104ab60055481565b3480156109bb57600080fd5b506104ab6119c5565b3480156109d057600080fd5b506104356109df366004613840565b611a41565b3480156109f057600080fd5b506104ab60105481565b348015610a0657600080fd5b506006546106999062010000900460ff1681565b348015610a2657600080fd5b50610435611a70565b348015610a3b57600080fd5b50610699610a4a366004613840565b611ac8565b348015610a5b57600080fd5b506104ab60125481565b348015610a7157600080fd5b506003546106999060ff1681565b348015610a8b57600080fd5b50610435610a9a366004613840565b611b75565b348015610aab57600080fd5b506104ab61138881565b348015610ac157600080fd5b50610435610ad03660046139ef565b611ba4565b348015610ae157600080fd5b50610af5610af0366004613840565b611c86565b60405161048d9190613a2d565b348015610b0e57600080fd5b50610435610b1d366004613884565b611d8d565b348015610b2e57600080fd5b50610b42610b3d366004613840565b611e28565b6040805192835260208301919091520161048d565b348015610b6357600080fd5b506104ab610b72366004613840565b611e56565b348015610b8357600080fd5b50610479600080516020613ff583398151915281565b348015610ba557600080fd5b506006546105bb9060ff1681565b348015610bbf57600080fd5b5061047973f24bcf4d1e507740041c9cfd2dddb29585adce1e81565b348015610be757600080fd5b50610699610bf6366004613840565b611f14565b348015610c0757600080fd5b50610699610c16366004613867565b611f8e565b348015610c2757600080fd5b50610435611fd0565b348015610c3c57600080fd5b50600d54610479906001600160a01b031681565b348015610c5c57600080fd5b506008546106999060ff1681565b348015610c7657600080fd5b50600654610699906301000000900460ff1681565b6000546001600160a01b03163314610cbe5760405162461bcd60e51b8152600401610cb590613a7c565b60405180910390fd5b6040516317b0dca160e31b8152600481018390526001600160a01b03828116602483015284169063bd86e50890604401600060405180830381600087803b158015610d0857600080fd5b505af1158015610d1c573d6000803e3d6000fd5b50505050505050565b6000546001600160a01b03163314610d4f5760405162461bcd60e51b8152600401610cb590613a7c565b611388811115610d905760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40a8dede4090d2ced60a31b6044820152606401610cb5565b601155565b600354600480546040516393f1a40b60e01b8152918201523060248201526000918291620100009091046001600160a01b0316906393f1a40b90604401604080518083038186803b158015610de957600080fd5b505afa158015610dfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e219190613ab1565b5092915050565b6000546001600160a01b03163314610e525760405162461bcd60e51b8152600401610cb590613a7c565b600380549115156101000261ff0019909216919091179055565b60035460ff16151560011415610e8657610e86600061231a565b600d546001600160a01b03163314610ec95760405162461bcd60e51b8152602060048201526006602482015265085d985d5b1d60d21b6044820152606401610cb5565b6001546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015610f0d57600080fd5b505afa158015610f21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f459190613ad5565b90508181101561105057600354600454620100009091046001600160a01b03169063d1abb90790610f76858561253c565b6040516001600160e01b031960e085901b16815260048101929092526024820152306044820152606401600060405180830381600087803b158015610fba57600080fd5b505af1158015610fce573d6000803e3d6000fd5b50506001546040516370a0823160e01b81523060048201526001600160a01b0390911692506370a08231915060240160206040518083038186803b15801561101557600080fd5b505afa158015611029573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104d9190613ad5565b90505b8181111561105b5750805b600061107e6127106110786012548561254890919063ffffffff16565b90612554565b600d549091506110ae906001600160a01b031661109b848461253c565b6001546001600160a01b03169190612560565b505050565b6000546001600160a01b031633146110dd5760405162461bcd60e51b8152600401610cb590613a7c565b6110e5612590565b6110ed61262d565b6110f56127ab565b565b6110f5600061231a565b6000546001600160a01b0316331461112b5760405162461bcd60e51b8152600401610cb590613a7c565b6111336116ea565b600354600480546040516302f940c760e41b815291820152306024820152620100009091046001600160a01b031690632f940c7090604401600060405180830381600087803b15801561118557600080fd5b505af1158015611199573d6000803e3d6000fd5b50505050565b6000546001600160a01b031633146111c95760405162461bcd60e51b8152600401610cb590613a7c565b60008190506000479050816001600160a01b03166335052d6e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561120c57600080fd5b505afa158015611220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112449190613ad5565b826001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016020604051808303818588803b15801561127f57600080fd5b505af1158015611293573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906112b89190613ad5565b146110ae5760405162461bcd60e51b815260206004820152600e60248201526d3bb930b83834b7339032b93937b960911b6044820152606401610cb5565b6000546001600160a01b031633146113205760405162461bcd60e51b8152600401610cb590613a7c565b600a8111156113605760405162461bcd60e51b815260206004820152600c60248201526b0cccaca40e8dede40d0d2ced60a31b6044820152606401610cb5565b601255565b600a54600090600211156113bb5760405162461bcd60e51b815260206004820152601b60248201527f6e656564206174206c656173742032206c6f6720656e747269657300000000006044820152606401610cb5565b60008060006001600a805490506113d29190613b04565b90505b600081118015611409575084600a82815481106113f4576113f4613b1b565b90600052602060002090600202016000015410155b1561144e5761142261141c600183613b04565b82611890565b61142c9084613b31565b92508161143881613b72565b925050808061144690613b92565b9150506113d5565b506114598183613bbf565b949350505050565b6000546001600160a01b0316331461148b5760405162461bcd60e51b8152600401610cb590613a7c565b6110f560006128e1565b60006114b06114a2610d95565b6114aa6119c5565b90612931565b905090565b6000546001600160a01b031633146114df5760405162461bcd60e51b8152600401610cb590613a7c565b82158015906114ed57508281145b6115265760405162461bcd60e51b815260206004820152600a6024820152696261642061727261797360b01b6044820152606401610cb5565b60005b8381101561169057600061153e600186613b04565b821415611560575073f24bcf4d1e507740041c9cfd2dddb29585adce1e611594565b858561156d846001613bed565b81811061157c5761157c613b1b565b90506020020160208101906115919190613884565b90505b61167d8686848181106115a9576115a9613b1b565b90506020020160208101906115be9190613884565b828686868181106115d1576115d1613b1b565b905060200201358989878181106115ea576115ea613b1b565b90506020020160208101906115ff9190613884565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561164057600080fd5b505afa158015611654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116789190613ad5565b61293d565b508061168881613c05565b915050611529565b50611199600161231a565b600080546001600160a01b031633146116c65760405162461bcd60e51b8152600401610cb590613a7c565b50600c80546001600160a01b0319166001600160a01b03831617905560015b919050565b6000546001600160a01b031633146117145760405162461bcd60e51b8152600401610cb590613a7c565b61171c612acf565b6110f5612b34565b6000546001600160a01b0316331461174e5760405162461bcd60e51b8152600401610cb590613a7c565b60008282600081811061176357611763613b1b565b90506020020160208101906117789190613884565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b1580156117bd57600080fd5b505afa1580156117d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f59190613ad5565b905061180b6001600160a01b0383168683612bf1565b6001600160a01b038516635c11d79582600087873061182c42610258613bed565b6040518763ffffffff1660e01b815260040161184d96959493929190613c19565b600060405180830381600087803b15801561186757600080fd5b505af115801561187b573d6000803e3d6000fd5b50505050611889600161231a565b5050505050565b600080600a84815481106118a6576118a6613b1b565b906000526020600020906002020190506000600a84815481106118cb576118cb613b1b565b906000526020600020906002020190506000600190508260010154826001015410156118f5575060005b6000811561191857836001015483600101546119119190613b04565b905061192f565b8260010154846001015461192c9190613b04565b90505b600184015460009061194983670de0b6b3a7640000613c8a565b6119539190613ca9565b855485549192506000916119679190613b04565b905060008161197a6301e1338085613c8a565b6119849190613ca9565b9050611996655af3107a400082613ca9565b905084156119ac5796506119bf95505050505050565b6119b581613cbd565b9750505050505050505b92915050565b6001546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015611a0957600080fd5b505afa158015611a1d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b09190613ad5565b6000546001600160a01b03163314611a6b5760405162461bcd60e51b8152600401610cb590613a7c565b600755565b600354610100900460ff16156110ed5760405162461bcd60e51b815260206004820152601b60248201527f63616e6e6f74206465706f73697420617420746869732074696d6500000000006044820152606401610cb5565b600080546001600160a01b03163314611af35760405162461bcd60e51b8152600401610cb590613a7c565b6101f4821115611b345760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40a8dede4090d2ced60a31b6044820152606401610cb5565b60138290556040518281527f2e59d502792bca3d730c472cd3acfbc16d0f9fe6ce0cddbdf0f80830251dfaca906020015b60405180910390a1506001919050565b6000546001600160a01b03163314611b9f5760405162461bcd60e51b8152600401610cb590613a7c565b600b55565b6000546001600160a01b03163314611bce5760405162461bcd60e51b8152600401610cb590613a7c565b6001600160a01b03821673f24bcf4d1e507740041c9cfd2dddb29585adce1e1415611c475760405162461bcd60e51b8152602060048201526024808201527f726577617264546f6b656e20697320616c7265616479206163636f756e746564604482015263103337b960e11b6064820152608401610cb5565b600880546001600160a01b0390931661010002610100600160a81b0319941515949094166001600160a81b031990931692909217929092179055600955565b60608167ffffffffffffffff811115611ca157611ca1613cda565b604051908082528060200260200182016040528015611ce657816020015b6040805180820190915260008082526020820152815260200190600190039081611cbf5790505b50905060008083600a80549050611cfd9190613b04565b90505b600a54811015611d8657600a8181548110611d1d57611d1d613b1b565b906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050838380611d5690613c05565b945081518110611d6857611d68613b1b565b60200260200101819052508080611d7e90613c05565b915050611d00565b5050919050565b6000546001600160a01b03163314611db75760405162461bcd60e51b8152600401610cb590613a7c565b6001600160a01b038116611e1c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610cb5565b611e25816128e1565b50565b600a8181548110611e3857600080fd5b60009182526020909120600290910201805460019091015490915082565b600a5460009060021115611eac5760405162461bcd60e51b815260206004820152601b60248201527f6e656564206174206c656173742032206c6f6720656e747269657300000000006044820152606401610cb5565b60008060006001600a80549050611ec39190613b04565b90505b600081118015611ed557508482125b1561144e57611ee861141c600183613b04565b611ef29084613b31565b925081611efe81613b72565b9250508080611f0c90613b92565b915050611ec6565b600080546001600160a01b03163314611f3f5760405162461bcd60e51b8152600401610cb590613a7c565b600f829055611f506127108361253c565b6010819055600f546040517f06a730aa61ec47f8cc95582be032daaf0ec4cb816c24b9c07b574ea41821048b92611b65928252602082015260400190565b600080546001600160a01b03163314611fb95760405162461bcd60e51b8152600401610cb590613a7c565b506003805460ff1916911515919091179055600190565b600d546001600160a01b031633146120135760405162461bcd60e51b8152602060048201526006602482015265085d985d5b1d60d21b6044820152606401610cb5565b600360029054906101000a90046001600160a01b03166001600160a01b031663d1abb907600454612042610d95565b6040516001600160e01b031960e085901b16815260048101929092526024820152306044820152606401600060405180830381600087803b15801561208657600080fd5b505af115801561209a573d6000803e3d6000fd5b50506001546040516370a0823160e01b8152306004820152600093506001600160a01b0390911691506370a082319060240160206040518083038186803b1580156120e457600080fd5b505afa1580156120f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211c9190613ad5565b600154600d5460405163a9059cbb60e01b81526001600160a01b03918216600482015260248101849052929350169063a9059cbb90604401602060405180830381600087803b15801561216e57600080fd5b505af1158015612182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a69190613cf0565b5050565b8015806122335750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156121f957600080fd5b505afa15801561220d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122319190613ad5565b155b61229e5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610cb5565b6040516001600160a01b0383166024820152604481018290526110ae90849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612cb2565b60606123108484600085612d84565b90505b9392505050565b600054600160a01b900460ff16156123445760405162461bcd60e51b8152600401610cb590613d0d565b60035460048054604051630c7e663b60e11b815291820152306024820152620100009091046001600160a01b0316906318fccc7690604401600060405180830381600087803b15801561239657600080fd5b505af11580156123aa573d6000803e3d6000fd5b505050506123b781612eac565b60085460ff16156123e0576008546009546123e09161010090046001600160a01b031690613185565b6006546124059073f24bcf4d1e507740041c9cfd2dddb29585adce1e9060ff16613438565b61240d6136f4565b6124156127ab565b600b54600a805461242890600190613b04565b8154811061243857612438613b1b565b9060005260206000209060020201600001546124549190613bed565b421061250e57604080518082018252428152600d548251631df1ee3f60e21b81529251600a936020808501936001600160a01b0316926377c7b8fc926004808201939291829003018186803b1580156124ac57600080fd5b505afa1580156124c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e49190613ad5565b90528154600181810184556000938452602093849020835160029093020191825592909101519101555b60405133907f577a37fdb49a88d66684922c6f913df5239b4f214b2b97c53ef8e3bbb2034cb590600090a250565b60006123138284613b04565b60006123138284613c8a565b60006123138284613ca9565b6040516001600160a01b0383166024820152604481018290526110ae90849063a9059cbb60e01b906064016122ca565b600054600160a01b900460ff166125e05760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610cb5565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b61266173cde5a11a4acb4ee4c805352cec57e236bdbc383773fcef8a994209d6916eb2c86cdd2afd60aa6f54b160006121aa565b61268f73f24bcf4d1e507740041c9cfd2dddb29585adce1e60008051602061401583398151915260006121aa565b6126b7600080516020613ff583398151915260008051602061401583398151915260006121aa565b6003546126ea9073fcef8a994209d6916eb2c86cdd2afd60aa6f54b1906201000090046001600160a01b031660006121aa565b61271f73cde5a11a4acb4ee4c805352cec57e236bdbc383773fcef8a994209d6916eb2c86cdd2afd60aa6f54b16000196121aa565b61274e73f24bcf4d1e507740041c9cfd2dddb29585adce1e6000805160206140158339815191526000196121aa565b612777600080516020613ff58339815191526000805160206140158339815191526000196121aa565b6003546110f59073fcef8a994209d6916eb2c86cdd2afd60aa6f54b1906201000090046001600160a01b03166000196121aa565b600054600160a01b900460ff16156127d55760405162461bcd60e51b8152600401610cb590613d0d565b60035460ff161515600114156127ef576127ef600061231a565b6001546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561283357600080fd5b505afa158015612847573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061286b9190613ad5565b90508015611e255760035460048054604051638dbdbe6d60e01b81529182015260248101839052306044820152620100009091046001600160a01b031690638dbdbe6d906064015b600060405180830381600087803b1580156128cd57600080fd5b505af1158015611889573d6000803e3d6000fd5b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006123138284613bed565b6129896040805160c0810190915260008082526020820190815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001606081525090565b828152600060208083018290526001600160a01b03878116604080860182905291881660608087019190915260808087018890528351808601879052845180820387018152908501855260a08801528351908101845293840185905283018490523080845291830191909152612a0e90600080516020614015833981519152846121aa565b612a306001600160a01b038816600080516020614015833981519152866121aa565b6000805160206140158339815191526352bbbe2984836001612a5442610258613bed565b6040518563ffffffff1660e01b8152600401612a739493929190613da5565b602060405180830381600087803b158015612a8d57600080fd5b505af1158015612aa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac59190613ad5565b5050505050505050565b600054600160a01b900460ff1615612af95760405162461bcd60e51b8152600401610cb590613d0d565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586126103390565b612b6873cde5a11a4acb4ee4c805352cec57e236bdbc383773fcef8a994209d6916eb2c86cdd2afd60aa6f54b160006121aa565b612b9673f24bcf4d1e507740041c9cfd2dddb29585adce1e60008051602061401583398151915260006121aa565b612bbe600080516020613ff583398151915260008051602061401583398151915260006121aa565b6003546110f59073fcef8a994209d6916eb2c86cdd2afd60aa6f54b1906201000090046001600160a01b031660006121aa565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b158015612c3d57600080fd5b505afa158015612c51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c759190613ad5565b612c7f9190613bed565b6040516001600160a01b03851660248201526044810182905290915061119990859063095ea7b360e01b906064016122ca565b6000612d07826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123019092919063ffffffff16565b8051909150156110ae5780806020019051810190612d259190613cf0565b6110ae5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610cb5565b606082471015612de55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610cb5565b843b612e335760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610cb5565b600080866001600160a01b03168587604051612e4f9190613e67565b60006040518083038185875af1925050503d8060008114612e8c576040519150601f19603f3d011682016040523d82523d6000602084013e612e91565b606091505b5091509150612ea18282866137b4565b979650505050505050565b6040516370a0823160e01b815230600482015260009073f24bcf4d1e507740041c9cfd2dddb29585adce1e906370a082319060240160206040518083038186803b158015612ef957600080fd5b505afa158015612f0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f319190613ad5565b6040516370a0823160e01b8152306004820152909150600090600080516020613ff5833981519152906370a082319060240160206040518083038186803b158015612f7b57600080fd5b505afa158015612f8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fb39190613ad5565b9050600080612fd36127106110786013548761254890919063ffffffff16565b915061302373f24bcf4d1e507740041c9cfd2dddb29585adce1e600080516020613ff58339815191527fcde5a11a4acb4ee4c805352cec57e236bdbc38370002000000000000000000198561293d565b6040516370a0823160e01b81523060048201526130ac908490600080516020613ff5833981519152906370a08231906024015b60206040518083038186803b15801561306e57600080fd5b505afa158015613082573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a69190613ad5565b9061253c565b905060006130cb612710611078600f548561254890919063ffffffff16565b90506130e6600080516020613ff58339815191523383612560565b60006131036127106110786010548661254890919063ffffffff16565b9050861561315f5760006131286127106110786011548561254890919063ffffffff16565b9050613134828261253c565b600e5490925061315d90600080516020613ff5833981519152906001600160a01b031683612560565b505b600c54610d1c90600080516020613ff5833981519152906001600160a01b031683612560565b6040516370a0823160e01b8152306004820152600090600080516020613ff5833981519152906370a082319060240160206040518083038186803b1580156131cc57600080fd5b505afa1580156131e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132049190613ad5565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038516906370a082319060240160206040518083038186803b15801561324957600080fd5b505afa15801561325d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132819190613ad5565b905061329d84600080516020613ff5833981519152858461293d565b6013546040516370a0823160e01b81523060048201526000916132ec9161271091611078916132e6908890600080516020613ff5833981519152906370a0823190602401613056565b90612548565b9050600061330b612710611078600f548561254890919063ffffffff16565b9050613326600080516020613ff58339815191523383612560565b60006133436127106110786010548661254890919063ffffffff16565b600c5490915061336c90600080516020613ff5833981519152906001600160a01b031683612560565b6040516370a0823160e01b8152306004820152600080516020613ff5833981519152906370a082319060240160206040518083038186803b1580156133b057600080fd5b505afa1580156133c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133e89190613ad5565b9450610d1c600080516020613ff583398151915273f24bcf4d1e507740041c9cfd2dddb29585adce1e7fcde5a11a4acb4ee4c805352cec57e236bdbc38370002000000000000000000198861293d565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a082319060240160206040518083038186803b15801561347a57600080fd5b505afa15801561348e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134b29190613ad5565b90506134d76001600160a01b03841660008051602061401583398151915260006121aa565b6134f96001600160a01b038416600080516020614015833981519152836121aa565b60018054600090600160a01b900460ff1667ffffffffffffffff81111561352257613522613cda565b60405190808252806020026020018201604052801561354b578160200160208202803683370190505b50905082818560ff168151811061356457613564613b1b565b602090810291909101015260018054600090600160a01b900460ff1667ffffffffffffffff81111561359857613598613cda565b6040519080825280602002602001820160405280156135c1578160200160208202803683370190505b50905060005b60015460ff600160a01b9091048116908216101561363a5760ff811660008181526014602052604090205483516001600160a01b03909116918491811061361057613610613b1b565b6001600160a01b03909216602092830291909101909101528061363281613e83565b9150506135c7565b50600084848460405160200161365293929190613ede565b60408051808303601f190181526080830182526000606084015284835260208301879052828201819052600554915163172b958560e31b81529093506000805160206140158339815191529163b95cac28916136b79190309081908790600401613f17565b600060405180830381600087803b1580156136d157600080fd5b505af11580156136e5573d6000803e3d6000fd5b50505050505050505050505050565b6040516370a0823160e01b815230600482015260009073cde5a11a4acb4ee4c805352cec57e236bdbc3837906370a082319060240160206040518083038186803b15801561374157600080fd5b505afa158015613755573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137799190613ad5565b604051632967cf8360e21b81526004810182905290915073fcef8a994209d6916eb2c86cdd2afd60aa6f54b19063a59f3e0c906024016128b3565b606083156137c3575081612313565b8251156137d35782518084602001fd5b8160405162461bcd60e51b8152600401610cb59190613fe1565b80356001600160a01b03811681146116e557600080fd5b60008060006060848603121561381957600080fd5b613822846137ed565b925060208401359150613837604085016137ed565b90509250925092565b60006020828403121561385257600080fd5b5035919050565b8015158114611e2557600080fd5b60006020828403121561387957600080fd5b813561231381613859565b60006020828403121561389657600080fd5b612313826137ed565b60008083601f8401126138b157600080fd5b50813567ffffffffffffffff8111156138c957600080fd5b6020830191508360208260051b85010111156138e457600080fd5b9250929050565b6000806000806040858703121561390157600080fd5b843567ffffffffffffffff8082111561391957600080fd5b6139258883890161389f565b9096509450602087013591508082111561393e57600080fd5b5061394b8782880161389f565b95989497509550505050565b60008060006040848603121561396c57600080fd5b613975846137ed565b9250602084013567ffffffffffffffff81111561399157600080fd5b61399d8682870161389f565b9497909650939450505050565b6000602082840312156139bc57600080fd5b813560ff8116811461231357600080fd5b600080604083850312156139e057600080fd5b50508035926020909101359150565b600080600060608486031215613a0457600080fd5b8335613a0f81613859565b9250613a1d602085016137ed565b9150604084013590509250925092565b602080825282518282018190526000919060409081850190868401855b82811015613a6f57815180518552860151868501529284019290850190600101613a4a565b5091979650505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60008060408385031215613ac457600080fd5b505080516020909101519092909150565b600060208284031215613ae757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082821015613b1657613b16613aee565b500390565b634e487b7160e01b600052603260045260246000fd5b600080821280156001600160ff1b0384900385131615613b5357613b53613aee565b600160ff1b8390038412811615613b6c57613b6c613aee565b50500190565b60006001600160ff1b03821415613b8b57613b8b613aee565b5060010190565b600081613ba157613ba1613aee565b506000190190565b634e487b7160e01b600052601260045260246000fd5b600082613bce57613bce613ba9565b600160ff1b821460001984141615613be857613be8613aee565b500590565b60008219821115613c0057613c00613aee565b500190565b6000600019821415613b8b57613b8b613aee565b868152602080820187905260a0604083018190528201859052600090869060c08401835b88811015613c69576001600160a01b03613c56856137ed565b1682529282019290820190600101613c3d565b506001600160a01b0396909616606085015250505060800152949350505050565b6000816000190483118215151615613ca457613ca4613aee565b500290565b600082613cb857613cb8613ba9565b500490565b6000600160ff1b821415613cd357613cd3613aee565b5060000390565b634e487b7160e01b600052604160045260246000fd5b600060208284031215613d0257600080fd5b815161231381613859565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b634e487b7160e01b600052602160045260246000fd5b60005b83811015613d68578181015183820152602001613d50565b838111156111995750506000910152565b60008151808452613d91816020860160208601613d4d565b601f01601f19169290920160200192915050565b60e08152845160e08201526000602086015160028110613dc757613dc7613d37565b61010083015260408601516001600160a01b03908116610120840152606087015116610140830152608086015161016083015260a086015160c0610180840152613e156101a0840182613d79565b915050613e55602083018680516001600160a01b039081168352602080830151151590840152604080830151909116908301526060908101511515910152565b60a082019390935260c0015292915050565b60008251613e79818460208701613d4d565b9190910192915050565b600060ff821660ff811415613e9a57613e9a613aee565b60010192915050565b600081518084526020808501945080840160005b83811015613ed357815187529582019590820190600101613eb7565b509495945050505050565b600060048510613ef057613ef0613d37565b84825260606020830152613f076060830185613ea3565b9050826040830152949350505050565b8481526000602060018060a01b038087168285015280861660408501526080606085015261010084018551608080870152818151808452610120880191508583019350600092505b80831015613f8157835185168252928501926001929092019190850190613f5f565b50848801519450607f199350838782030160a0880152613fa18186613ea3565b94505050506040850151818584030160c0860152613fbf8382613d79565b925050506060840151613fd660e085018215159052565b509695505050505050565b6020815260006123136020830184613d7956fe00000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c8300000000000000000000000020dd72ed959b6147912c2e529f0a0c651c33c9cea264697066735822122017c261cafae263a4586b1edaf080b482e7b68d49dec4e07e1ad79bea5073248764736f6c6343000809003300000000000000000000000020dd72ed959b6147912c2e529f0a0c651c33c9ce000000000000000000000000fcef8a994209d6916eb2c86cdd2afd60aa6f54b10000000000000000000000000000000000000000000000000000000000000016000000000000000000000000fb8dacdb058e84131d9c4a4bcd18a4f5704b48560000000000000000000000000e7c5313e9bb80b654734d9b7ab1fb01468dee3b00000000000000000000000063cbd4134c2253041f370472c130e92dae4ff174

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

000000000000000000000000fcef8a994209d6916eb2c86cdd2afd60aa6f54b10000000000000000000000000000000000000000000000000000000000000016000000000000000000000000fb8dacdb058e84131d9c4a4bcd18a4f5704b48560000000000000000000000000e7c5313e9bb80b654734d9b7ab1fb01468dee3b00000000000000000000000063cbd4134c2253041f370472c130e92dae4ff174

-----Decoded View---------------
Arg [0] : _lpToken (address): 0xfcef8a994209d6916eb2c86cdd2afd60aa6f54b1
Arg [1] : _poolId (uint256): 22
Arg [2] : _vault (address): 0xfb8dacdb058e84131d9c4a4bcd18a4f5704b4856
Arg [3] : _treasury (address): 0x0e7c5313e9bb80b654734d9b7ab1fb01468dee3b
Arg [4] : _strategistRemitter (address): 0x63cbd4134c2253041f370472c130e92dae4ff174

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000fcef8a994209d6916eb2c86cdd2afd60aa6f54b1
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000016
Arg [2] : 000000000000000000000000fb8dacdb058e84131d9c4a4bcd18a4f5704b4856
Arg [3] : 0000000000000000000000000e7c5313e9bb80b654734d9b7ab1fb01468dee3b
Arg [4] : 00000000000000000000000063cbd4134c2253041f370472c130e92dae4ff174


Deployed ByteCode Sourcemap

86090:22931:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103835:164;;;;;;;;;;-1:-1:-1;103835:164:0;;;;;:::i;:::-;;:::i;:::-;;101036:186;;;;;;;;;;-1:-1:-1;101036:186:0;;;;;:::i;:::-;;:::i;86953:87::-;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;86953:87:0;;;;;-1:-1:-1;;;;;874:32:1;;;856:51;;844:2;829:18;86953:87:0;;;;;;;;98653:172;;;;;;;;;;;;;:::i;:::-;;;1064:25:1;;;1052:2;1037:18;98653:172:0;918:177:1;88132:43:0;;;;;;;;;;;;88167:8;88132:43;;103712:117;;;;;;;;;;-1:-1:-1;103712:117:0;;;;;:::i;:::-;;:::i;89655:26::-;;;;;;;;;;;;;;;;87736:105;;;;;;;;;;-1:-1:-1;87736:105:0;87775:66;87736:105;;87923:32;;;;;;;;;;;;;;;;105942:101;;;;;;;;;;-1:-1:-1;106019:10:0;:17;105942:101;;92776:587;;;;;;;;;;-1:-1:-1;92776:587:0;;;;;:::i;:::-;;:::i;87497:18::-;;;;;;;;;;;;;;;;87591:29;;;;;;;;;;-1:-1:-1;87591:29:0;;;;;;;;;;;;;;1823:4:1;1811:17;;;1793:36;;1781:2;1766:18;87591:29:0;1651:184:1;99754:114:0;;;;;;;;;;;;;:::i;93369:60::-;;;;;;;;;;;;;:::i;99432:132::-;;;;;;;;;;;;;:::i;89782:45::-;;;;;;;;;;;;89822:5;89782:45;;105308:285;;;;;;;;;;-1:-1:-1;105308:285:0;;;;;:::i;:::-;;:::i;89580:35::-;;;;;;;;;;;;;;;;87412:79;;;;;;;;;;-1:-1:-1;87412:79:0;;;;;;;-1:-1:-1;;;;;87412:79:0;;;37725:84;;;;;;;;;;-1:-1:-1;37772:4:0;37795:7;-1:-1:-1;;;37795:7:0;;;;37725:84;;;2292:14:1;;2285:22;2267:41;;2255:2;2240:18;37725:84:0;2127:187:1;87046:22:0;;;;;;;;;;-1:-1:-1;87046:22:0;;;;-1:-1:-1;;;;;87046:22:0;;;87197:34;;;;;;;;;;-1:-1:-1;87197:34:0;;;;;;;;;;;103397:140;;;;;;;;;;-1:-1:-1;103397:140:0;;;;;:::i;:::-;;:::i;88353:23::-;;;;;;;;;;-1:-1:-1;88353:23:0;;;;-1:-1:-1;;;;;88353:23:0;;;87707;;;;;;;;;;;;;;;;106708:477;;;;;;;;;;-1:-1:-1;106708:477:0;;;;;:::i;:::-;;:::i;86754:84::-;;;;;;;;;;;;86795:42;86754:84;;2526:101;;;;;;;;;;;;;:::i;98220:113::-;;;;;;;;;;;;;:::i;88084:42::-;;;;;;;;;;;;;;;;104092:601;;;;;;;;;;-1:-1:-1;104092:601:0;;;;;:::i;:::-;;:::i;86658:90::-;;;;;;;;;;;;86705:42;86658:90;;101913:135;;;;;;;;;;-1:-1:-1;101913:135:0;;;;;:::i;:::-;;:::i;99616:84::-;;;;;;;;;;;;;:::i;104772:530::-;;;;;;;;;;-1:-1:-1;104772:530:0;;;;;:::i;:::-;;:::i;88408:33::-;;;;;;;;;;-1:-1:-1;88408:33:0;;;;-1:-1:-1;;;;;88408:33:0;;;87116:40;;;;;;;;;;-1:-1:-1;87116:40:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;107895:1124;;;;;;;;;;-1:-1:-1;107895:1124:0;;;;;:::i;:::-;;:::i;1894:85::-;;;;;;;;;;-1:-1:-1;1940:7:0;1966:6;-1:-1:-1;;;;;1966:6:0;1894:85;;89512:26;;;;;;;;;;;;;;;;90186:37;;;;;;;;;;-1:-1:-1;90186:37:0;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;90186:37:0;;;87885:32;;;;;;;;;;-1:-1:-1;87885:32:0;;;;;;;-1:-1:-1;;;;;87885:32:0;;;87075:34;;;;;;;;;;-1:-1:-1;87075:34:0;;;;-1:-1:-1;;;87075:34:0;;;;;;89687;;;;;;;;;;;;89718:3;89687:34;;87521:27;;;;;;;;;;;;;;;;98420:121;;;;;;;;;;;;;:::i;101817:90::-;;;;;;;;;;-1:-1:-1;101817:90:0;;;;;:::i;:::-;;:::i;89544:30::-;;;;;;;;;;;;;;;;87626:35;;;;;;;;;;-1:-1:-1;87626:35:0;;;;;;;;;;;92197:120;;;;;;;;;;;;;:::i;100725:219::-;;;;;;;;;;-1:-1:-1;100725:219:0;;;;;:::i;:::-;;:::i;89621:28::-;;;;;;;;;;;;;;;;87162:29;;;;;;;;;;-1:-1:-1;87162:29:0;;;;;;;;105797:139;;;;;;;;;;-1:-1:-1;105797:139:0;;;;;:::i;:::-;;:::i;89727:49::-;;;;;;;;;;;;89772:4;89727:49;;103109:282;;;;;;;;;;-1:-1:-1;103109:282:0;;;;;:::i;:::-;;:::i;106147:307::-;;;;;;;;;;-1:-1:-1;106147:307:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2776:198::-;;;;;;;;;;-1:-1:-1;2776:198:0;;;;;:::i;:::-;;:::i;88051:27::-;;;;;;;;;;-1:-1:-1;88051:27:0;;;;;:::i;:::-;;:::i;:::-;;;;6232:25:1;;;6288:2;6273:18;;6266:34;;;;6205:18;88051:27:0;6058:248:1;107423:466:0;;;;;;;;;;-1:-1:-1;107423:466:0;;;;;:::i;:::-;;:::i;86570:82::-;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;86570:82:0;;87555:30;;;;;;;;;;-1:-1:-1;87555:30:0;;;;;;;;86844:89;;;;;;;;;;;;86890:42;86844:89;;101330:223;;;;;;;;;;-1:-1:-1;101330:223:0;;;;;:::i;:::-;;:::i;101559:131::-;;;;;;;;;;-1:-1:-1;101559:131:0;;;;;:::i;:::-;;:::i;99016:301::-;;;;;;;;;;;;;:::i;88382:20::-;;;;;;;;;;-1:-1:-1;88382:20:0;;;;-1:-1:-1;;;;;88382:20:0;;;87847:32;;;;;;;;;;-1:-1:-1;87847:32:0;;;;;;;;87667:34;;;;;;;;;;-1:-1:-1;87667:34:0;;;;;;;;;;;103835:164;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;;;;;;;;;103936:56:::1;::::0;-1:-1:-1;;;103936:56:0;;::::1;::::0;::::1;7030:25:1::0;;;-1:-1:-1;;;;;7091:32:1;;;7071:18;;;7064:60;103936:40:0;::::1;::::0;::::1;::::0;7003:18:1;;103936:56:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;103835:164:::0;;;:::o;101036:186::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;89772:4:::1;101124:14;:36;;101116:61;;;::::0;-1:-1:-1;;;101116:61:0;;7337:2:1;101116:61:0::1;::::0;::::1;7319:21:1::0;7376:2;7356:18;;;7349:30;-1:-1:-1;;;7395:18:1;;;7388:42;7447:18;;101116:61:0::1;7135:336:1::0;101116:61:0::1;101185:13;:30:::0;101036:186::o;98653:172::-;98751:10;;98772:6;;;98739:55;;-1:-1:-1;;;98739:55:0;;;;;7030:25:1;98788:4:0;7071:18:1;;;7064:60;98699:7:0;;;;98751:10;;;;-1:-1:-1;;;;;98751:10:0;;98739:32;;7003:18:1;;98739:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;98718:76:0;98653:172;-1:-1:-1;;98653:172:0:o;103712:117::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;103790:14:::1;:32:::0;;;::::1;;;;-1:-1:-1::0;;103790:32:0;;::::1;::::0;;;::::1;::::0;;103712:117::o;92776:587::-;101736:9;;;;:17;;:9;:17;101732:62;;;101768:15;101777:5;101768:8;:15::i;:::-;92863:5:::1;::::0;-1:-1:-1;;;;;92863:5:0::1;92849:10;:19;92841:38;;;::::0;-1:-1:-1;;;92841:38:0;;8207:2:1;92841:38:0::1;::::0;::::1;8189:21:1::0;8246:1;8226:18;;;8219:29;-1:-1:-1;;;8264:18:1;;;8257:36;8310:18;;92841:38:0::1;8005:329:1::0;92841:38:0::1;92913:7;::::0;92906:40:::1;::::0;-1:-1:-1;;;92906:40:0;;92940:4:::1;92906:40;::::0;::::1;856:51:1::0;92888:15:0::1;::::0;-1:-1:-1;;;;;92913:7:0::1;::::0;92906:25:::1;::::0;829:18:1;;92906:40:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92888:58;;92969:7;92959;:17;92955:191;;;93002:10;::::0;93033:6:::1;::::0;93002:10;;;::::1;-1:-1:-1::0;;;;;93002:10:0::1;::::0;92988:44:::1;::::0;93041:20:::1;:7:::0;93053;93041:11:::1;:20::i;:::-;92988:89;::::0;-1:-1:-1;;;;;;92988:89:0::1;::::0;;;;;;::::1;::::0;::::1;8730:25:1::0;;;;8771:18;;;8764:34;93071:4:0::1;8814:18:1::0;;;8807:60;8703:18;;92988:89:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;93104:7:0::1;::::0;93097:40:::1;::::0;-1:-1:-1;;;93097:40:0;;93131:4:::1;93097:40;::::0;::::1;856:51:1::0;-1:-1:-1;;;;;93104:7:0;;::::1;::::0;-1:-1:-1;93097:25:0::1;::::0;-1:-1:-1;829:18:1;;93097:40:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93087:50;;92955:191;93168:7;93158;:17;93154:59;;;-1:-1:-1::0;93197:7:0;93154:59:::1;93220:19;93242:45;89822:5;93242:24;93254:11;;93242:7;:11;;:24;;;;:::i;:::-;:28:::0;::::1;:45::i;:::-;93324:5;::::0;93220:67;;-1:-1:-1;93295:61:0::1;::::0;-1:-1:-1;;;;;93324:5:0::1;93331:24;:7:::0;93220:67;93331:11:::1;:24::i;:::-;93302:7;::::0;-1:-1:-1;;;;;93302:7:0::1;::::0;93295:61;:28:::1;:61::i;:::-;92835:528;;92776:587:::0;:::o;99754:114::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;99802:10:::1;:8;:10::i;:::-;99823:17;:15;:17::i;:::-;99851:10;:8;:10::i;:::-;99754:114::o:0;93369:60::-;93407:15;93416:5;93407:8;:15::i;99432:132::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;99476:7:::1;:5;:7::i;:::-;99505:10;::::0;99535:6:::1;::::0;;99493:64:::1;::::0;-1:-1:-1;;;99493:64:0;;;;::::1;7030:25:1::0;99551:4:0::1;7071:18:1::0;;;7064:60;99505:10:0;;;::::1;-1:-1:-1::0;;;;;99505:10:0::1;::::0;99493:41:::1;::::0;7003:18:1;;99493:64:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;99432:132::o:0;105308:285::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;105386:22:::1;105426:14;105386:55;;105451:15;105469:21;105451:39;;105545:7;-1:-1:-1::0;;;;;105545:20:0::1;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;105508:7;-1:-1:-1::0;;;;;105508:15:0::1;;105531:7;105508:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:59;105500:86;;;::::0;-1:-1:-1;;;105500:86:0;;9080:2:1;105500:86:0::1;::::0;::::1;9062:21:1::0;9119:2;9099:18;;;9092:30;-1:-1:-1;;;9138:18:1;;;9131:44;9192:18;;105500:86:0::1;8878:338:1::0;103397:140:0;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;103483:2:::1;103475:4;:10;;103467:35;;;::::0;-1:-1:-1;;;103467:35:0;;9423:2:1;103467:35:0::1;::::0;::::1;9405:21:1::0;9462:2;9442:18;;;9435:30;-1:-1:-1;;;9481:18:1;;;9474:42;9533:18;;103467:35:0::1;9221:336:1::0;103467:35:0::1;103512:11;:18:::0;103397:140::o;106708:477::-;106802:10;:17;106776:6;;106823:1;-1:-1:-1;106802:22:0;106794:62;;;;-1:-1:-1;;;106794:62:0;;9764:2:1;106794:62:0;;;9746:21:1;9803:2;9783:18;;;9776:30;9842:29;9822:18;;;9815:57;9889:18;;106794:62:0;9562:351:1;106794:62:0;106867:20;106897:23;106936:9;106968:1;106948:10;:17;;;;:21;;;;:::i;:::-;106936:33;;106931:198;106975:1;106971;:5;:46;;;;;107007:10;106980;106991:1;106980:13;;;;;;;;:::i;:::-;;;;;;;;;;;:23;;;:37;;106971:46;106931:198;;;107055:31;107077:5;107081:1;107077;:5;:::i;:::-;107084:1;107055:21;:31::i;:::-;107038:48;;;;:::i;:::-;;-1:-1:-1;107100:18:0;;;;:::i;:::-;;;;107019:3;;;;;:::i;:::-;;;;106931:198;;;-1:-1:-1;107146:32:0;107162:16;107146:13;:32;:::i;:::-;107139:39;106708:477;-1:-1:-1;;;;106708:477:0:o;2526:101::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;2590:30:::1;2617:1;2590:18;:30::i;98220:113::-:0;98262:7;98288:38;98310:15;:13;:15::i;:::-;98288:17;:15;:17::i;:::-;:21;;:38::i;:::-;98281:45;;98220:113;:::o;104092:601::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;104209:19;;;::::1;::::0;:55:::1;;-1:-1:-1::0;104232:32:0;;::::1;104209:55;104201:78;;;::::0;-1:-1:-1;;;104201:78:0;;11407:2:1;104201:78:0::1;::::0;::::1;11389:21:1::0;11446:2;11426:18;;;11419:30;-1:-1:-1;;;11465:18:1;;;11458:40;11515:18;;104201:78:0::1;11205:334:1::0;104201:78:0::1;104293:9;104289:349;104308:18:::0;;::::1;104289:349;;;104347:17;104387:18;104404:1;104387:7:::0;:18:::1;:::i;:::-;104382:1;:23;104378:150;;;-1:-1:-1::0;86890:42:0::1;104378:150;;;104499:7:::0;;104507:5:::1;:1:::0;104511::::1;104507:5;:::i;:::-;104499:14;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;104487:26;;104378:150;104542:85;104548:7;;104556:1;104548:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;104560:9;104571:7;;104579:1;104571:10;;;;;;;:::i;:::-;;;;;;;104590:7;;104598:1;104590:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;104583:43;::::0;-1:-1:-1;;;104583:43:0;;104620:4:::1;104583:43;::::0;::::1;856:51:1::0;-1:-1:-1;;;;;104583:28:0;;;::::1;::::0;::::1;::::0;829:18:1;;104583:43:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104542:5;:85::i;:::-;-1:-1:-1::0;104328:3:0;::::1;::::0;::::1;:::i;:::-;;;;104289:349;;;;104647:14;104656:4;104647:8;:14::i;101913:135::-:0;101986:4;1966:6;;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;-1:-1:-1;102000:8:0::1;:22:::0;;-1:-1:-1;;;;;;102000:22:0::1;-1:-1:-1::0;;;;;102000:22:0;::::1;;::::0;;-1:-1:-1;2176:1:0::1;101913:135:::0;;;:::o;99616:84::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;99658:8:::1;:6;:8::i;:::-;99674:19;:17;:19::i;104772:530::-:0;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;104881:12:::1;104903:5;;104909:1;104903:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;104941:30;::::0;-1:-1:-1;;;104941:30:0;;104965:4:::1;104941:30;::::0;::::1;856:51:1::0;104881:31:0;;-1:-1:-1;104922:16:0::1;::::0;-1:-1:-1;;;;;104941:15:0;::::1;::::0;::::1;::::0;829:18:1;;104941:30:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104922:49:::0;-1:-1:-1;104981:46:0::1;-1:-1:-1::0;;;;;104981:27:0;::::1;105009:7:::0;104922:49;104981:27:::1;:46::i;:::-;-1:-1:-1::0;;;;;105038:80:0;::::1;;105132:8:::0;105154:1:::1;105169:5:::0;;105196:4:::1;105215:21;:15;105233:3;105215:21;:::i;:::-;105038:208;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;105256:14;105265:4;105256:8;:14::i;:::-;104871:431;;104772:530:::0;;;:::o;107895:1124::-;107987:6;108005:21;108029:10;108040:11;108029:23;;;;;;;;:::i;:::-;;;;;;;;;;;108005:47;;108062:19;108084:10;108095:9;108084:21;;;;;;;;:::i;:::-;;;;;;;;;;;108062:43;;108115:15;108133:4;108115:22;;108173:5;:21;;;108151:3;:19;;;:43;108147:92;;;-1:-1:-1;108223:5:0;108147:92;108249:32;108295:10;108291:212;;;108370:5;:21;;;108348:3;:19;;;:43;;;;:::i;:::-;108321:70;;108291:212;;;108473:3;:19;;;108449:5;:21;;;:43;;;;:::i;:::-;108422:70;;108291:212;108584:21;;;;108513:32;;108549:31;:24;108576:4;108549:31;:::i;:::-;108548:57;;;;:::i;:::-;108656:15;;108640:13;;108513:92;;-1:-1:-1;108615:22:0;;108640:31;;108656:15;108640:31;:::i;:::-;108615:56;-1:-1:-1;108682:38:0;108615:56;108724:35;88167:8;108724:24;:35;:::i;:::-;108723:54;;;;:::i;:::-;108682:95;-1:-1:-1;108787:38:0;108821:4;108682:95;108787:38;:::i;:::-;;;108874:10;108870:86;;;108914:30;-1:-1:-1;108900:45:0;;-1:-1:-1;;;;;;108900:45:0;108870:86;108973:39;108981:30;108973:39;:::i;:::-;108966:46;;;;;;;;;107895:1124;;;;;:::o;98420:121::-;98501:7;;98494:40;;-1:-1:-1;;;98494:40:0;;98528:4;98494:40;;;856:51:1;98468:7:0;;-1:-1:-1;;;;;98501:7:0;;98494:25;;829:18:1;;98494:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;101817:90::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;101884:8:::1;:16:::0;101817:90::o;92197:120::-;92244:14;;;;;;;92243:15;92235:55;;;;-1:-1:-1;;;92235:55:0;;13421:2:1;92235:55:0;;;13403:21:1;13460:2;13440:18;;;13433:30;13499:29;13479:18;;;13472:57;13546:18;;92235:55:0;13219:351:1;100725:219:0;100793:4;1966:6;;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;89718:3:::1;100815:9;:20;;100807:45;;;::::0;-1:-1:-1;;;100807:45:0;;7337:2:1;100807:45:0::1;::::0;::::1;7319:21:1::0;7376:2;7356:18;;;7349:30;-1:-1:-1;;;7395:18:1;;;7388:42;7447:18;;100807:45:0::1;7135:336:1::0;100807:45:0::1;100860:8;:20:::0;;;100893:25:::1;::::0;1064::1;;;100893::0::1;::::0;1052:2:1;1037:18;100893:25:0::1;;;;;;;;-1:-1:-1::0;100933:4:0::1;100725:219:::0;;;:::o;105797:139::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;105889:17:::1;:40:::0;105797:139::o;103109:282::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;103222:20:0;::::1;86890:42;103222:20;;103214:69;;;::::0;-1:-1:-1;;;103214:69:0;;13777:2:1;103214:69:0::1;::::0;::::1;13759:21:1::0;13816:2;13796:18;;;13789:30;13855:34;13835:18;;;13828:62;-1:-1:-1;;;13906:18:1;;;13899:34;13950:19;;103214:69:0::1;13575:400:1::0;103214:69:0::1;103293:12;:21:::0;;-1:-1:-1;;;;;103324:25:0;;::::1;103293:21;103324:25;-1:-1:-1::0;;;;;;103293:21:0;::::1;;103324:25:::0;;;;-1:-1:-1;;;;;;103324:25:0;;;;;;;;;;::::1;::::0;;103359:17:::1;:25:::0;103109:282::o;106147:307::-;106213:22;106269:2;106255:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;106255:17:0;;;;;;;;;;;;;;;;106247:25;;106282:20;106322:9;106354:2;106334:10;:17;;;;:22;;;;:::i;:::-;106322:34;;106317:131;106362:10;:17;106358:21;;106317:131;;;106424:10;106435:1;106424:13;;;;;;;;:::i;:::-;;;;;;;;;;;106400:37;;;;;;;;;;;;;;;;;;;;;;;;;:5;106406:14;;;;;:::i;:::-;;;106400:21;;;;;;;;:::i;:::-;;;;;;:37;;;;106381:3;;;;;:::i;:::-;;;;106317:131;;;;106237:217;106147:307;;;:::o;2776:198::-;1940:7;1966:6;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;2864:22:0;::::1;2856:73;;;::::0;-1:-1:-1;;;2856:73:0;;14314:2:1;2856:73:0::1;::::0;::::1;14296:21:1::0;14353:2;14333:18;;;14326:30;14392:34;14372:18;;;14365:62;-1:-1:-1;;;14443:18:1;;;14436:36;14489:19;;2856:73:0::1;14112:402:1::0;2856:73:0::1;2939:28;2958:8;2939:18;:28::i;:::-;2776:198:::0;:::o;88051:27::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;88051:27:0;:::o;107423:466::-;107522:10;:17;107496:6;;107543:1;-1:-1:-1;107522:22:0;107514:62;;;;-1:-1:-1;;;107514:62:0;;9764:2:1;107514:62:0;;;9746:21:1;9803:2;9783:18;;;9776:30;9842:29;9822:18;;;9815:57;9889:18;;107514:62:0;9562:351:1;107514:62:0;107587:20;107617:23;107656:9;107688:1;107668:10;:17;;;;:21;;;;:::i;:::-;107656:33;;107651:182;107695:1;107691;:5;:30;;;;;107719:2;107700:16;:21;107691:30;107651:182;;;107759:31;107781:5;107785:1;107781;:5;:::i;107759:31::-;107742:48;;;;:::i;:::-;;-1:-1:-1;107804:18:0;;;;:::i;:::-;;;;107723:3;;;;;:::i;:::-;;;;107651:182;;101330:223;101396:4;1966:6;;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;101410:7:::1;:18:::0;;;101450:28:::1;89822:5;101420:8:::0;101450:19:::1;:28::i;:::-;101436:11;:42:::0;;;101506:7:::1;::::0;101491:36:::1;::::0;::::1;::::0;::::1;::::0;6232:25:1;;6288:2;6273:18;;6266:34;6220:2;6205:18;;6058:248;101559:131:0;101627:4;1966:6;;-1:-1:-1;;;;;1966:6:0;797:10;2106:23;2098:68;;;;-1:-1:-1;;;2098:68:0;;;;;;;:::i;:::-;-1:-1:-1;101642:9:0::1;:20:::0;;-1:-1:-1;;101642:20:0::1;::::0;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;;101559:131:0:o;99016:301::-;99080:5;;-1:-1:-1;;;;;99080:5:0;99066:10;:19;99058:38;;;;-1:-1:-1;;;99058:38:0;;8207:2:1;99058:38:0;;;8189:21:1;8246:1;8226:18;;;8219:29;-1:-1:-1;;;8264:18:1;;;8257:36;8310:18;;99058:38:0;8005:329:1;99058:38:0;99121:10;;;;;;;;;-1:-1:-1;;;;;99121:10:0;-1:-1:-1;;;;;99107:44:0;;99152:6;;99160:15;:13;:15::i;:::-;99107:84;;-1:-1:-1;;;;;;99107:84:0;;;;;;;;;;8730:25:1;;;;8771:18;;;8764:34;99185:4:0;8814:18:1;;;8807:60;8703:18;;99107:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;99227:7:0;;99220:40;;-1:-1:-1;;;99220:40:0;;99254:4;99220:40;;;856:51:1;99202:15:0;;-1:-1:-1;;;;;;99227:7:0;;;;-1:-1:-1;99220:25:0;;829:18:1;;99220:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99277:7;;99295:5;;99270:40;;-1:-1:-1;;;99270:40:0;;-1:-1:-1;;;;;99295:5:0;;;99270:40;;;14693:51:1;14760:18;;;14753:34;;;99202:58:0;;-1:-1:-1;99277:7:0;;99270:24;;14666:18:1;;99270:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;99048:269;99016:301::o;34188:603::-;34543:10;;;34542:62;;-1:-1:-1;34559:39:0;;-1:-1:-1;;;34559:39:0;;34583:4;34559:39;;;15260:34:1;-1:-1:-1;;;;;15330:15:1;;;15310:18;;;15303:43;34559:15:0;;;;;15195:18:1;;34559:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;34542:62;34521:163;;;;-1:-1:-1;;;34521:163:0;;15559:2:1;34521:163:0;;;15541:21:1;15598:2;15578:18;;;15571:30;15637:34;15617:18;;;15610:62;-1:-1:-1;;;15688:18:1;;;15681:52;15750:19;;34521:163:0;15357:418:1;34521:163:0;34721:62;;-1:-1:-1;;;;;14711:32:1;;34721:62:0;;;14693:51:1;14760:18;;;14753:34;;;34694:90:0;;34714:5;;-1:-1:-1;;;34744:22:0;14666:18:1;;34721:62:0;;;;-1:-1:-1;;34721:62:0;;;;;;;;;;;;;;-1:-1:-1;;;;;34721:62:0;-1:-1:-1;;;;;;34721:62:0;;;;;;;;;;34694:19;:90::i;16274:223::-;16407:12;16438:52;16460:6;16468:4;16474:1;16477:12;16438:21;:52::i;:::-;16431:59;;16274:223;;;;;;:::o;93805:656::-;37772:4;37795:7;-1:-1:-1;;;37795:7:0;;;;38038:9;38030:38;;;;-1:-1:-1;;;38030:38:0;;;;;;;:::i;:::-;93893:10:::1;::::0;93913:6:::1;::::0;;93879:56:::1;::::0;-1:-1:-1;;;93879:56:0;;;;::::1;7030:25:1::0;93929:4:0::1;7071:18:1::0;;;7064:60;93893:10:0;;;::::1;-1:-1:-1::0;;;;;93893:10:0::1;::::0;93879:33:::1;::::0;7003:18:1;;93879:56:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;93945:29;93957:16;93945:11;:29::i;:::-;93988:12;::::0;::::1;;93985:73;;;94019:17;::::0;94038::::1;::::0;94002:54:::1;::::0;94019:17:::1;::::0;::::1;-1:-1:-1::0;;;;;94019:17:0::1;::::0;94002:16:::1;:54::i;:::-;94095:13;::::0;94068:41:::1;::::0;86890:42:::1;::::0;94095:13:::1;;94068;:41::i;:::-;94120:9;:7;:9::i;:::-;94140:10;:8;:10::i;:::-;94230:17;::::0;94184:10:::1;94195:17:::0;;:21:::1;::::0;94215:1:::1;::::0;94195:21:::1;:::i;:::-;94184:33;;;;;;;;:::i;:::-;;;;;;;;;;;:43;;;:63;;;;:::i;:::-;94165:15;:82;94161:254;;94296:94;::::0;;;;::::1;::::0;;94316:15:::1;94296:94:::0;;94359:5:::1;::::0;94350:38;;-1:-1:-1;;;94350:38:0;;;;94263:10:::1;::::0;94296:94:::1;::::0;;::::1;::::0;-1:-1:-1;;;;;94359:5:0::1;::::0;94350:36:::1;::::0;:38:::1;::::0;;::::1;::::0;94296:94;94350:38;;;;;;94359:5;94350:38;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94296:94:::0;;94263:141;;::::1;::::0;;::::1;::::0;;-1:-1:-1;94263:141:0;;;::::1;::::0;;;;;;::::1;::::0;;::::1;;::::0;;;;;;::::1;::::0;;::::1;::::0;94161:254:::1;94430:24;::::0;94443:10:::1;::::0;94430:24:::1;::::0;;;::::1;93805:656:::0;:::o;9131:96::-;9189:7;9215:5;9219:1;9215;:5;:::i;9474:96::-;9532:7;9558:5;9562:1;9558;:5;:::i;9859:96::-;9917:7;9943:5;9947:1;9943;:5;:::i;33476:205::-;33615:58;;-1:-1:-1;;;;;14711:32:1;;33615:58:0;;;14693:51:1;14760:18;;;14753:34;;;33588:86:0;;33608:5;;-1:-1:-1;;;33638:23:0;14666:18:1;;33615:58:0;14519:274:1;38737:117:0;37772:4;37795:7;-1:-1:-1;;;37795:7:0;;;;38296:41;;;;-1:-1:-1;;;38296:41:0;;16327:2:1;38296:41:0;;;16309:21:1;16366:2;16346:18;;;16339:30;-1:-1:-1;;;16385:18:1;;;16378:50;16445:18;;38296:41:0;16125:344:1;38296:41:0;38805:5:::1;38795:15:::0;;-1:-1:-1;;;;38795:15:0::1;::::0;;38825:22:::1;797:10:::0;38834:12:::1;38825:22;::::0;-1:-1:-1;;;;;874:32:1;;;856:51;;844:2;829:18;38825:22:0::1;;;;;;;38737:117::o:0;99874:522::-;99920:43;86705:42;86795;99961:1;99920:32;:43::i;:::-;99973:45;86890:42;-1:-1:-1;;;;;;;;;;;100016:1:0;99973:31;:45::i;:::-;100028:38;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;100064:1:0;100028:24;:38::i;:::-;100103:10;;100076:41;;86795:42;;100103:10;;;-1:-1:-1;;;;;100103:10:0;100115:1;100076:26;:41::i;:::-;100127:59;86705:42;86795;-1:-1:-1;;100127:32:0;:59::i;:::-;100196:61;86890:42;-1:-1:-1;;;;;;;;;;;;;100196:31:0;:61::i;:::-;100267:54;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;100267:24:0;:54::i;:::-;100358:10;;100331:57;;86795:42;;100358:10;;;-1:-1:-1;;;;;100358:10:0;-1:-1:-1;;100331:26:0;:57::i;92323:250::-;37772:4;37795:7;-1:-1:-1;;;37795:7:0;;;;38038:9;38030:38;;;;-1:-1:-1;;;38030:38:0;;;;;;;:::i;:::-;101736:9:::1;::::0;::::1;;:17;;:9:::0;:17:::1;101732:62;;;101768:15;101777:5;101768:8;:15::i;:::-;92416:7:::2;::::0;92409:40:::2;::::0;-1:-1:-1;;;92409:40:0;;92443:4:::2;92409:40;::::0;::::2;856:51:1::0;92391:15:0::2;::::0;-1:-1:-1;;;;;92416:7:0::2;::::0;92409:25:::2;::::0;829:18:1;;92409:40:0::2;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92391:58:::0;-1:-1:-1;92464:11:0;;92460:107:::2;;92505:10;::::0;92525:6:::2;::::0;;92491:65:::2;::::0;-1:-1:-1;;;92491:65:0;;;;::::2;8730:25:1::0;8771:18;;;8764:34;;;92550:4:0::2;8814:18:1::0;;;8807:60;92505:10:0;;;::::2;-1:-1:-1::0;;;;;92505:10:0::2;::::0;92491:33:::2;::::0;8703:18:1;;92491:65:0::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;3128:187:::0;3201:16;3220:6;;-1:-1:-1;;;;;3236:17:0;;;-1:-1:-1;;;;;;3236:17:0;;;;;;3268:40;;3220:6;;;;;;;3268:40;;3201:16;3268:40;3191:124;3128:187;:::o;8764:96::-;8822:7;8848:5;8852:1;8848;:5;:::i;95904:862::-;96006:35;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96006:35:0;96113:25;;;96051:24;96148:15;;;;:26;;;-1:-1:-1;;;;;96184:37:0;;;:18;;;;:37;;;96231:39;;;:19;;;;:39;;;;96280:17;;;;:26;;;96338:13;;;;;1793:36:1;;;96338:13:0;;;;;;;;;1766:18:1;;;96338:13:0;;96316:19;;;:35;-1:-1:-1;;;;;;;;;;;;;;;;;;96429:4:0;96406:28;;;-1:-1:-1;;;96487:40:0;;;;96579:42;;-1:-1:-1;;;;;;;;;;;96051:24:0;96579:28;:42::i;:::-;96631:47;-1:-1:-1;;;;;96631:28:0;;-1:-1:-1;;;;;;;;;;;96671:6:0;96631:28;:47::i;:::-;-1:-1:-1;;;;;;;;;;;96689:22:0;96712:10;96724:5;96731:1;96735:21;:15;96753:3;96735:21;:::i;:::-;96689:69;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;95995:771;;;95904:862;;;;:::o;38490:115::-;37772:4;37795:7;-1:-1:-1;;;37795:7:0;;;;38038:9;38030:38;;;;-1:-1:-1;;;38030:38:0;;;;;;;:::i;:::-;38549:7:::1;:14:::0;;-1:-1:-1;;;;38549:14:0::1;-1:-1:-1::0;;;38549:14:0::1;::::0;;38578:20:::1;38585:12;797:10:::0;;718:96;100402:252;100450:43;86705:42;86795;100491:1;100450:32;:43::i;:::-;100503:45;86890:42;-1:-1:-1;;;;;;;;;;;100546:1:0;100503:31;:45::i;:::-;100558:38;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;100594:1:0;100558:24;:38::i;:::-;100633:10;;100606:41;;86795:42;;100633:10;;;-1:-1:-1;;;;;100633:10:0;100645:1;100606:26;:41::i;34797:310::-;34946:39;;-1:-1:-1;;;34946:39:0;;34970:4;34946:39;;;15260:34:1;-1:-1:-1;;;;;15330:15:1;;;15310:18;;;15303:43;34923:20:0;;34988:5;;34946:15;;;;;15195:18:1;;34946:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;:::i;:::-;35030:69;;-1:-1:-1;;;;;14711:32:1;;35030:69:0;;;14693:51:1;14760:18;;;14753:34;;;34923:70:0;;-1:-1:-1;35003:97:0;;35023:5;;-1:-1:-1;;;35053:22:0;14666:18:1;;35030:69:0;14519:274:1;35982:706:0;36401:23;36427:69;36455:4;36427:69;;;;;;;;;;;;;;;;;36435:5;-1:-1:-1;;;;;36427:27:0;;;:69;;;;;:::i;:::-;36510:17;;36401:95;;-1:-1:-1;36510:21:0;36506:176;;36605:10;36594:30;;;;;;;;;;;;:::i;:::-;36586:85;;;;-1:-1:-1;;;36586:85:0;;19079:2:1;36586:85:0;;;19061:21:1;19118:2;19098:18;;;19091:30;19157:34;19137:18;;;19130:62;-1:-1:-1;;;19208:18:1;;;19201:40;19258:19;;36586:85:0;18877:406:1;17361:499:0;17526:12;17583:5;17558:21;:30;;17550:81;;;;-1:-1:-1;;;17550:81:0;;19490:2:1;17550:81:0;;;19472:21:1;19529:2;19509:18;;;19502:30;19568:34;19548:18;;;19541:62;-1:-1:-1;;;19619:18:1;;;19612:36;19665:19;;17550:81:0;19288:402:1;17550:81:0;13847:20;;17641:60;;;;-1:-1:-1;;;17641:60:0;;19897:2:1;17641:60:0;;;19879:21:1;19936:2;19916:18;;;19909:30;19975:31;19955:18;;;19948:59;20024:18;;17641:60:0;19695:353:1;17641:60:0;17713:12;17727:23;17754:6;-1:-1:-1;;;;;17754:11:0;17773:5;17780:4;17754:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17712:73;;;;17802:51;17819:7;17828:10;17840:12;17802:16;:51::i;:::-;17795:58;17361:499;-1:-1:-1;;;;;;;17361:499:0:o;94787:1027::-;94870:44;;-1:-1:-1;;;94870:44:0;;94908:4;94870:44;;;856:51:1;94850:17:0;;86890:42;;94870:29;;829:18:1;;94870:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94942:37;;-1:-1:-1;;;94942:37:0;;94973:4;94942:37;;;856:51:1;94850:64:0;;-1:-1:-1;94924:15:0;;-1:-1:-1;;;;;;;;;;;86609:42:0;94942:22;;829:18:1;;94942:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94924:55;;94990:12;95012:16;95056:44;89822:5;95056:23;95070:8;;95056:9;:13;;:23;;;;:::i;:44::-;95049:51;-1:-1:-1;95110:44:0;86890:42;-1:-1:-1;;;;;;;;;;;87775:66:0;95049:51;95110:5;:44::i;:::-;95175:37;;-1:-1:-1;;;95175:37:0;;95206:4;95175:37;;;856:51:1;95175:50:0;;95217:7;;-1:-1:-1;;;;;;;;;;;86609:42:0;95175:22;;829:18:1;;95175:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;:50::i;:::-;95164:61;;95236:21;95260:42;89822:5;95260:21;95273:7;;95260:8;:12;;:21;;;;:::i;:42::-;95236:66;-1:-1:-1;95312:52:0;-1:-1:-1;;;;;;;;;;;95338:10:0;95236:66;95312:25;:52::i;:::-;95376:26;95405:46;89822:5;95405:25;95418:11;;95405:8;:12;;:25;;;;:::i;:46::-;95376:75;;95465:16;95461:281;;;95497:23;95523:58;89822:5;95523:37;95546:13;;95523:18;:22;;:37;;;;:::i;:58::-;95497:84;-1:-1:-1;95616:39:0;:18;95497:84;95616:22;:39::i;:::-;95695:18;;95595:60;;-1:-1:-1;95669:62:0;;-1:-1:-1;;;;;;;;;;;86609:42:0;-1:-1:-1;;;;;95695:18:0;95715:15;95669:25;:62::i;:::-;95483:259;95461:281;95777:8;;95751:55;;-1:-1:-1;;;;;;;;;;;86609:42:0;-1:-1:-1;;;;;95777:8:0;95787:18;95751:25;:55::i;102054:815::-;102152:37;;-1:-1:-1;;;102152:37:0;;102183:4;102152:37;;;856:51:1;102134:15:0;;-1:-1:-1;;;;;;;;;;;86609:42:0;102152:22;;829:18:1;;102152:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102217:38;;-1:-1:-1;;;102217:38:0;;102249:4;102217:38;;;856:51:1;102134:55:0;;-1:-1:-1;102203:11:0;;-1:-1:-1;;;;;102217:23:0;;;;;829:18:1;;102217:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102203:52;;102269:30;102275:5;-1:-1:-1;;;;;;;;;;;102288:5:0;102295:3;102269:5;:30::i;:::-;102383:8;;102328:37;;-1:-1:-1;;;102328:37:0;;102359:4;102328:37;;;856:51:1;102313:12:0;;102328:85;;89822:5;;102328:64;;:50;;102370:7;;-1:-1:-1;;;;;;;;;;;86609:42:0;102328:22;;829:18:1;;102328:37:0;710:203:1;102328:50:0;:54;;:64::i;:85::-;102313:100;;102428:21;102452:38;89822:5;102452:17;102461:7;;102452:4;:8;;:17;;;;:::i;:38::-;102428:62;-1:-1:-1;102504:52:0;-1:-1:-1;;;;;;;;;;;102530:10:0;102428:62;102504:25;:52::i;:::-;102571:26;102600:42;89822:5;102600:21;102609:11;;102600:4;:8;;:21;;;;:::i;:42::-;102682:8;;102571:71;;-1:-1:-1;102656:55:0;;-1:-1:-1;;;;;;;;;;;86609:42:0;-1:-1:-1;;;;;102682:8:0;102571:71;102656:25;:55::i;:::-;102749:37;;-1:-1:-1;;;102749:37:0;;102780:4;102749:37;;;856:51:1;-1:-1:-1;;;;;;;;;;;86609:42:0;102749:22;;829:18:1;;102749:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102739:47;-1:-1:-1;102800:47:0;-1:-1:-1;;;;;;;;;;;86890:42:0;87775:66;102739:47;102800:5;:47::i;96874:1144::-;96977:38;;-1:-1:-1;;;96977:38:0;;97009:4;96977:38;;;856:51:1;96947:27:0;;-1:-1:-1;;;;;96977:23:0;;;;;829:18:1;;96977:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96947:68;-1:-1:-1;97026:39:0;-1:-1:-1;;;;;97026:25:0;;-1:-1:-1;;;;;;;;;;;97063:1:0;97026:25;:39::i;:::-;97075:57;-1:-1:-1;;;;;97075:25:0;;-1:-1:-1;;;;;;;;;;;97112:19:0;97075:25;:57::i;:::-;97181:54;97288:21;;97143:35;;-1:-1:-1;;;97288:21:0;;;;97274:36;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;97274:36:0;;97245:65;;97342:19;97320:9;97330:8;97320:19;;;;;;;;;;:::i;:::-;;;;;;;;;;:41;97394:1;97444:21;;97371:20;;-1:-1:-1;;;97444:21:0;;;;97431:35;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;97431:35:0;;97405:61;;97480:7;97476:100;97497:21;;;-1:-1:-1;;;97497:21:0;;;;;97493:25;;;;97476:100;;;97558:6;;;;;;;:3;:6;;;;;;97538:10;;-1:-1:-1;;;;;97558:6:0;;;;97538:7;;:10;;;;;;:::i;:::-;-1:-1:-1;;;;;97538:27:0;;;:10;;;;;;;;;;;:27;97520:3;;;;:::i;:::-;;;;97476:100;;;;97588:21;97623:8;97633:9;97644:12;97612:45;;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;97612:45:0;;;-1:-1:-1;;;;;;;;;;97715:24:0;;;97612:45;-1:-1:-1;;97749:32:0;;;-1:-1:-1;;;97791:27:0;;;97914:12;;97874:137;;-1:-1:-1;;;97874:137:0;;97612:45;;-1:-1:-1;;;;;;;;;;;;86997:42:0;97874:26;;:137;;97914:12;97948:4;;;;97612:45;;97874:137;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96937:1081;;;;;;;96874:1144;;:::o;94467:146::-;94521:45;;-1:-1:-1;;;94521:45:0;;94560:4;94521:45;;;856:51:1;94505:13:0;;86705:42;;94521:30;;829:18:1;;94521:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94576:30;;-1:-1:-1;;;94576:30:0;;;;;1064:25:1;;;94505:61:0;;-1:-1:-1;86795:42:0;;94576:23;;1037:18:1;;94576:30:0;918:177:1;19974:692:0;20120:12;20148:7;20144:516;;;-1:-1:-1;20178:10:0;20171:17;;20144:516;20289:17;;:21;20285:365;;20483:10;20477:17;20543:15;20530:10;20526:2;20522:19;20515:44;20285:365;20622:12;20615:20;;-1:-1:-1;;;20615:20:0;;;;;;;;:::i;14:173:1:-;82:20;;-1:-1:-1;;;;;131:31:1;;121:42;;111:70;;177:1;174;167:12;192:328;269:6;277;285;338:2;326:9;317:7;313:23;309:32;306:52;;;354:1;351;344:12;306:52;377:29;396:9;377:29;:::i;:::-;367:39;;453:2;442:9;438:18;425:32;415:42;;476:38;510:2;499:9;495:18;476:38;:::i;:::-;466:48;;192:328;;;;;:::o;525:180::-;584:6;637:2;625:9;616:7;612:23;608:32;605:52;;;653:1;650;643:12;605:52;-1:-1:-1;676:23:1;;525:180;-1:-1:-1;525:180:1:o;1100:118::-;1186:5;1179:13;1172:21;1165:5;1162:32;1152:60;;1208:1;1205;1198:12;1223:241;1279:6;1332:2;1320:9;1311:7;1307:23;1303:32;1300:52;;;1348:1;1345;1338:12;1300:52;1387:9;1374:23;1406:28;1428:5;1406:28;:::i;1840:186::-;1899:6;1952:2;1940:9;1931:7;1927:23;1923:32;1920:52;;;1968:1;1965;1958:12;1920:52;1991:29;2010:9;1991:29;:::i;2499:367::-;2562:8;2572:6;2626:3;2619:4;2611:6;2607:17;2603:27;2593:55;;2644:1;2641;2634:12;2593:55;-1:-1:-1;2667:20:1;;2710:18;2699:30;;2696:50;;;2742:1;2739;2732:12;2696:50;2779:4;2771:6;2767:17;2755:29;;2839:3;2832:4;2822:6;2819:1;2815:14;2807:6;2803:27;2799:38;2796:47;2793:67;;;2856:1;2853;2846:12;2793:67;2499:367;;;;;:::o;2871:773::-;2993:6;3001;3009;3017;3070:2;3058:9;3049:7;3045:23;3041:32;3038:52;;;3086:1;3083;3076:12;3038:52;3126:9;3113:23;3155:18;3196:2;3188:6;3185:14;3182:34;;;3212:1;3209;3202:12;3182:34;3251:70;3313:7;3304:6;3293:9;3289:22;3251:70;:::i;:::-;3340:8;;-1:-1:-1;3225:96:1;-1:-1:-1;3428:2:1;3413:18;;3400:32;;-1:-1:-1;3444:16:1;;;3441:36;;;3473:1;3470;3463:12;3441:36;;3512:72;3576:7;3565:8;3554:9;3550:24;3512:72;:::i;:::-;2871:773;;;;-1:-1:-1;3603:8:1;-1:-1:-1;;;;2871:773:1:o;3649:511::-;3744:6;3752;3760;3813:2;3801:9;3792:7;3788:23;3784:32;3781:52;;;3829:1;3826;3819:12;3781:52;3852:29;3871:9;3852:29;:::i;:::-;3842:39;;3932:2;3921:9;3917:18;3904:32;3959:18;3951:6;3948:30;3945:50;;;3991:1;3988;3981:12;3945:50;4030:70;4092:7;4083:6;4072:9;4068:22;4030:70;:::i;:::-;3649:511;;4119:8;;-1:-1:-1;4004:96:1;;-1:-1:-1;;;;3649:511:1:o;4165:269::-;4222:6;4275:2;4263:9;4254:7;4250:23;4246:32;4243:52;;;4291:1;4288;4281:12;4243:52;4330:9;4317:23;4380:4;4373:5;4369:16;4362:5;4359:27;4349:55;;4400:1;4397;4390:12;4439:248;4507:6;4515;4568:2;4556:9;4547:7;4543:23;4539:32;4536:52;;;4584:1;4581;4574:12;4536:52;-1:-1:-1;;4607:23:1;;;4677:2;4662:18;;;4649:32;;-1:-1:-1;4439:248:1:o;4877:383::-;4951:6;4959;4967;5020:2;5008:9;4999:7;4995:23;4991:32;4988:52;;;5036:1;5033;5026:12;4988:52;5075:9;5062:23;5094:28;5116:5;5094:28;:::i;:::-;5141:5;-1:-1:-1;5165:38:1;5199:2;5184:18;;5165:38;:::i;:::-;5155:48;;5250:2;5239:9;5235:18;5222:32;5212:42;;4877:383;;;;;:::o;5265:788::-;5486:2;5538:21;;;5608:13;;5511:18;;;5630:22;;;5457:4;;5486:2;5671;;5689:18;;;;5730:15;;;5457:4;5773:254;5787:6;5784:1;5781:13;5773:254;;;5846:13;;5884:9;;5872:22;;5934:11;;5928:18;5914:12;;;5907:40;5967:12;;;;6002:15;;;;5809:1;5802:9;5773:254;;;-1:-1:-1;6044:3:1;;5265:788;-1:-1:-1;;;;;;;5265:788:1:o;6495:356::-;6697:2;6679:21;;;6716:18;;;6709:30;6775:34;6770:2;6755:18;;6748:62;6842:2;6827:18;;6495:356::o;7755:245::-;7834:6;7842;7895:2;7883:9;7874:7;7870:23;7866:32;7863:52;;;7911:1;7908;7901:12;7863:52;-1:-1:-1;;7934:16:1;;7990:2;7975:18;;;7969:25;7934:16;;7969:25;;-1:-1:-1;7755:245:1:o;8339:184::-;8409:6;8462:2;8450:9;8441:7;8437:23;8433:32;8430:52;;;8478:1;8475;8468:12;8430:52;-1:-1:-1;8501:16:1;;8339:184;-1:-1:-1;8339:184:1:o;9918:127::-;9979:10;9974:3;9970:20;9967:1;9960:31;10010:4;10007:1;10000:15;10034:4;10031:1;10024:15;10050:125;10090:4;10118:1;10115;10112:8;10109:34;;;10123:18;;:::i;:::-;-1:-1:-1;10160:9:1;;10050:125::o;10180:127::-;10241:10;10236:3;10232:20;10229:1;10222:31;10272:4;10269:1;10262:15;10296:4;10293:1;10286:15;10312:265;10351:3;10379:9;;;10404:10;;-1:-1:-1;;;;;10423:27:1;;;10416:35;;10400:52;10397:78;;;10455:18;;:::i;:::-;-1:-1:-1;;;10502:19:1;;;10495:27;;10487:36;;10484:62;;;10526:18;;:::i;:::-;-1:-1:-1;;10562:9:1;;10312:265::o;10582:147::-;10620:3;-1:-1:-1;;;;;10641:30:1;;10638:56;;;10674:18;;:::i;:::-;-1:-1:-1;10721:1:1;10710:13;;10582:147::o;10734:136::-;10773:3;10801:5;10791:39;;10810:18;;:::i;:::-;-1:-1:-1;;;10846:18:1;;10734:136::o;10875:127::-;10936:10;10931:3;10927:20;10924:1;10917:31;10967:4;10964:1;10957:15;10991:4;10988:1;10981:15;11007:193;11046:1;11072;11062:35;;11077:18;;:::i;:::-;-1:-1:-1;;;11113:18:1;;-1:-1:-1;;11133:13:1;;11109:38;11106:64;;;11150:18;;:::i;:::-;-1:-1:-1;11184:10:1;;11007:193::o;11544:128::-;11584:3;11615:1;11611:6;11608:1;11605:13;11602:39;;;11621:18;;:::i;:::-;-1:-1:-1;11657:9:1;;11544:128::o;11677:135::-;11716:3;-1:-1:-1;;11737:17:1;;11734:43;;;11757:18;;:::i;11817:958::-;12150:25;;;12194:2;12212:18;;;12205:34;;;12137:3;12270:2;12255:18;;12248:31;;;12122:19;;12314:22;;;12089:4;;12394:6;;12367:3;12352:19;;12089:4;12428:208;12442:6;12439:1;12436:13;12428:208;;;-1:-1:-1;;;;;12507:26:1;12526:6;12507:26;:::i;:::-;12503:52;12491:65;;12611:15;;;;12576:12;;;;12464:1;12457:9;12428:208;;;-1:-1:-1;;;;;;12692:32:1;;;;12687:2;12672:18;;12665:60;-1:-1:-1;;;12756:3:1;12741:19;12734:35;12653:3;11817:958;-1:-1:-1;;;;11817:958:1:o;12780:168::-;12820:7;12886:1;12882;12878:6;12874:14;12871:1;12868:21;12863:1;12856:9;12849:17;12845:45;12842:71;;;12893:18;;:::i;:::-;-1:-1:-1;12933:9:1;;12780:168::o;12953:120::-;12993:1;13019;13009:35;;13024:18;;:::i;:::-;-1:-1:-1;13058:9:1;;12953:120::o;13078:136::-;13113:3;-1:-1:-1;;;13134:22:1;;13131:48;;;13159:18;;:::i;:::-;-1:-1:-1;13199:1:1;13195:13;;13078:136::o;13980:127::-;14041:10;14036:3;14032:20;14029:1;14022:31;14072:4;14069:1;14062:15;14096:4;14093:1;14086:15;14798:245;14865:6;14918:2;14906:9;14897:7;14893:23;14889:32;14886:52;;;14934:1;14931;14924:12;14886:52;14966:9;14960:16;14985:28;15007:5;14985:28;:::i;15780:340::-;15982:2;15964:21;;;16021:2;16001:18;;;15994:30;-1:-1:-1;;;16055:2:1;16040:18;;16033:46;16111:2;16096:18;;15780:340::o;16474:127::-;16535:10;16530:3;16526:20;16523:1;16516:31;16566:4;16563:1;16556:15;16590:4;16587:1;16580:15;16805:258;16877:1;16887:113;16901:6;16898:1;16895:13;16887:113;;;16977:11;;;16971:18;16958:11;;;16951:39;16923:2;16916:10;16887:113;;;17018:6;17015:1;17012:13;17009:48;;;-1:-1:-1;;17053:1:1;17035:16;;17028:27;16805:258::o;17068:257::-;17109:3;17147:5;17141:12;17174:6;17169:3;17162:19;17190:63;17246:6;17239:4;17234:3;17230:14;17223:4;17216:5;17212:16;17190:63;:::i;:::-;17307:2;17286:15;-1:-1:-1;;17282:29:1;17273:39;;;;17314:4;17269:50;;17068:257;-1:-1:-1;;17068:257:1:o;17690:1182::-;18031:3;18020:9;18013:22;18078:6;18072:13;18066:3;18055:9;18051:19;18044:42;17994:4;18133;18125:6;18121:17;18115:24;18175:1;18161:12;18158:19;18148:53;;18181:18;;:::i;:::-;18232:3;18217:19;;18210:41;18300:4;18288:17;;18282:24;-1:-1:-1;;;;;18381:23:1;;;18375:3;18360:19;;18353:52;18464:4;18452:17;;18446:24;18442:33;18436:3;18421:19;;18414:62;18531:4;18519:17;;18513:24;18507:3;18492:19;;18485:53;18333:3;18575:17;;18569:24;18630:4;18624:3;18609:19;;18602:33;18652:53;18700:3;18685:19;;18569:24;18652:53;:::i;:::-;18644:61;;;18714:62;18770:4;18759:9;18755:20;18747:6;17452:12;;-1:-1:-1;;;;;17448:21:1;;;17436:34;;17533:4;17522:16;;;17516:23;17509:31;17502:39;17486:14;;;17479:63;17595:4;17584:16;;;17578:23;17574:32;;;17558:14;;;17551:56;17670:4;17659:16;;;17653:23;17646:31;17639:39;17623:14;;17616:63;17330:355;18714:62;18807:4;18792:20;;18785:36;;;;18852:4;18837:20;18830:36;17690:1182;;-1:-1:-1;;17690:1182:1:o;20053:274::-;20182:3;20220:6;20214:13;20236:53;20282:6;20277:3;20270:4;20262:6;20258:17;20236:53;:::i;:::-;20305:16;;;;;20053:274;-1:-1:-1;;20053:274:1:o;20332:175::-;20369:3;20413:4;20406:5;20402:16;20442:4;20433:7;20430:17;20427:43;;;20450:18;;:::i;:::-;20499:1;20486:15;;20332:175;-1:-1:-1;;20332:175:1:o;20512:435::-;20565:3;20603:5;20597:12;20630:6;20625:3;20618:19;20656:4;20685:2;20680:3;20676:12;20669:19;;20722:2;20715:5;20711:14;20743:1;20753:169;20767:6;20764:1;20761:13;20753:169;;;20828:13;;20816:26;;20862:12;;;;20897:15;;;;20789:1;20782:9;20753:169;;;-1:-1:-1;20938:3:1;;20512:435;-1:-1:-1;;;;;20512:435:1:o;20952:470::-;21161:4;21201:1;21193:6;21190:13;21180:47;;21207:18;;:::i;:::-;21254:6;21243:9;21236:25;21297:2;21292;21281:9;21277:18;21270:30;21317:56;21369:2;21358:9;21354:18;21346:6;21317:56;:::i;:::-;21309:64;;21409:6;21404:2;21393:9;21389:18;21382:34;20952:470;;;;;;:::o;21427:1544::-;21706:6;21695:9;21688:25;21669:4;21732:2;21770:1;21766;21761:3;21757:11;21753:19;21820:2;21812:6;21808:15;21803:2;21792:9;21788:18;21781:43;21872:2;21864:6;21860:15;21855:2;21844:9;21840:18;21833:43;21912:3;21907:2;21896:9;21892:18;21885:31;21954:3;21943:9;21939:19;21993:6;21987:13;22037:3;22031;22020:9;22016:19;22009:32;22061:6;22096:12;22090:19;22133:6;22125;22118:22;22171:3;22160:9;22156:19;22149:26;;22216:2;22202:12;22198:21;22184:35;;22237:1;22228:10;;22247:178;22261:6;22258:1;22255:13;22247:178;;;22326:13;;22322:22;;22310:35;;22400:15;;;;22283:1;22276:9;;;;;22365:12;;;;22247:178;;;22251:3;22474:2;22466:6;22462:15;22456:22;22434:44;;22501:3;22497:8;22487:18;;22567:2;22555:9;22550:3;22546:19;22542:28;22536:3;22525:9;22521:19;22514:57;22594:49;22639:3;22623:14;22594:49;:::i;:::-;22580:63;;;;;22692:2;22684:6;22680:15;22674:22;22761:2;22749:9;22741:6;22737:22;22733:31;22727:3;22716:9;22712:19;22705:60;22788:40;22821:6;22805:14;22788:40;:::i;:::-;22774:54;;;;22877:2;22869:6;22865:15;22859:22;22890:52;22937:3;22926:9;22922:19;22906:14;2101:13;2094:21;2082:34;;2031:91;22890:52;-1:-1:-1;22959:6:1;21427:1544;-1:-1:-1;;;;;;21427:1544:1:o;22976:219::-;23125:2;23114:9;23107:21;23088:4;23145:44;23185:2;23174:9;23170:18;23162:6;23145:44;:::i

Swarm Source

ipfs://17c261cafae263a4586b1edaf080b482e7b68d49dec4e07e1ad79bea50732487
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Validator ID :
0 FTM

Amount Staked
0

Amount Delegated
0

Staking Total
0

Staking Start Epoch
0

Staking Start Time
0

Proof of Importance
0

Origination Score
0

Validation Score
0

Active
0

Online
0

Downtime
0 s
Address Amount claimed Rewards Created On Epoch Created On
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.