Contract 0x3ade2fe54ecd748fc86d3fdf86def612f9487309

Contract Overview

Balance:
0 HOO

HOO Value:
$0.00

Token:
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x230ac4c714e0b9df1d5e23404a7fbcedfb9316d0570d6c8b1184af0bd23de77eGet Reward75383402022-01-16 22:35:412 hrs 27 mins ago0x36b303daa6ff4722119632db1c0c890b33aa1fdf IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00061483275
0xbf9c2e394e3a6d1c5a39cb6bd26cb31fb1b341b060c155ea3ab9a67d0dd9cf7fGet Reward75383172022-01-16 22:34:322 hrs 29 mins ago0xc806bbbc44c4ccf2c86bd311df31778c05858124 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00061483275
0xb48b2d48792dbaf02bef4ea9bddc04ccb5702dc7a87b1890113bcdd5a090011cStake75371262022-01-16 21:34:593 hrs 28 mins ago0xcc6a751a0e644b445984d74f176e9babf46b2a97 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00058905525
0x7d90cac74b2cb2d85d2b0ae8fad14603e340899d78f51abf259aea02a9e8647eExit75370002022-01-16 21:28:413 hrs 34 mins ago0xcc6a751a0e644b445984d74f176e9babf46b2a97 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.001307523
0xf484c6ef61182cff2962383eee0f3e322014548b146fb57e72fb991004636537Get Reward75353922022-01-16 20:08:174 hrs 55 mins ago0xbd2c0bd7258ddf86c6ada7a84404b0dd68b323c9 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00061483275
0x76256712f27d998376434bd01435434580fc0ec89f0524103282805522a3d1f6Get Reward75349472022-01-16 19:46:025 hrs 17 mins ago0x14d2744a347b13f7cb7a0f2f9e4725db065f7dd9 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00061483275
0x8e2c33fbb7495c3e4bec451207a6807e25680eaf05e2f7fe4aa721a401676b0fGet Reward75341322022-01-16 19:05:175 hrs 58 mins ago0x579559d7ef42eb337aedde360fdf2046b955f2db IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00061483275
0xf933cc9238fd9624105bd16385702f501827e0980efa2c3657a7da1e2ac2ce0bGet Reward75322802022-01-16 17:32:417 hrs 30 mins ago0x47f40bfe57a4345d6352941f645bff2bb2c9825f IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00053608275
0xdc24bdd47081c60e6e9a2d1417715406a6e2805c7e6b394dad45172c5a7434e4Get Reward75252962022-01-16 11:43:2913 hrs 20 mins ago0x14d2744a347b13f7cb7a0f2f9e4725db065f7dd9 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00061483275
0x6c9ba4a4adabe428b7400efc61ad81b782d7f37cf5d8bebac8327a5b527ea3efGet Reward75246352022-01-16 11:10:2613 hrs 53 mins ago0xb8ad7ad1f6a9245faa6360e36ea3257af134931b IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00053608275
0x544d89d8495de2ce4c7361c75e34062c69e42da625300666050c4ed1cd673236Get Reward75230552022-01-16 9:51:2615 hrs 12 mins ago0x260e50dfc9ee172919fe947ce2c98704a5d33894 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00061483275
0x4a8fca61ebaa40840d1b45adc2e5c01675b0470286392c85832df65a3d249d20Get Reward75227582022-01-16 9:36:3515 hrs 27 mins ago0xfe5b98dd559dc4b9ffe3c6e96331f4bd2eb65daf IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00053608275
0x1606ed3cca9e906a7fc279184b24bd2913ed6798ee1b75600105bbf0153770caGet Reward75220562022-01-16 9:01:2916 hrs 2 mins ago0x5918644832c9c9f4e53470b83e460195ffa0ef51 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.000585555
0xfa522593c8bb9fb115f95badd896903c23d5b95326786a28ce8d7e87f1049833Get Reward75217592022-01-16 8:46:3816 hrs 16 mins ago0x86e1db5308c3a960d7755d6050bf8fba3dea5261 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.000585555
0x2385d9958df17a79abb82426d2feaf6abf321070e1b31f12e5e8c4ace09d2294Stake With Permi...75212282022-01-16 8:20:0516 hrs 43 mins ago0x29db7f6dee7eccecf79da574edfee51fd73fffe0 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00068392
0x8747be870993f6251fd6d2a7005c1b5ba2260826b302acc9e3961fd4f45be51fGet Reward75211842022-01-16 8:17:5316 hrs 45 mins ago0x29db7f6dee7eccecf79da574edfee51fd73fffe0 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.000531555
0x345ae2212ccc3a7ea6a9039aeb388b24dd57cd9aa4a35d90b88bf20287201cebGet Reward75195902022-01-16 6:58:1118 hrs 5 mins ago0xcc6a751a0e644b445984d74f176e9babf46b2a97 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.000585555
0x461874d974a0294da96d1c5579da10e226c8693180d4046579c696d26387f021Get Reward75190462022-01-16 6:30:5918 hrs 32 mins ago0x62da02bbd8bcf896fc9747f0092a2d9c4705face IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.000510555
0xec066a637a72791e014817565d4f85426bc14dd36dfa46a2b5afbc3f76bc49c2Get Reward75183192022-01-16 5:54:3819 hrs 8 mins ago0x5dbb5d3a974c556266c8469a345400a80a671153 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.000585555
0xaa9c8f1e33c1442b11b6bcdd5a54f5ac2dcad6edf6324a97223b2e745ce53d5eGet Reward75176622022-01-16 5:21:4719 hrs 41 mins ago0x9aa31ed4572848c062ab68c451e7862cf214b31b IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.000585555
0xa3a09ba8ae2600da8b2541d6ee8ab7ca921c8561cd6523c4f51e59039087ee31Start Emission75122152022-01-16 0:49:261 day 14 mins ago0x99821e91b85495dcd8d8e2697ab534425b107bf1 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.00041279175
0xf876c7725e16774611e39630cad89afb415a88bb4f677c00870b7213f5a90c0cStop Emission75122052022-01-16 0:48:561 day 14 mins ago0x99821e91b85495dcd8d8e2697ab534425b107bf1 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.000308106
0xe96e6e7b4e71aaaefa7a3ec0f644b735d984b3c61923f9e31406d0888d6acadaGet Reward75108862022-01-15 23:42:591 day 1 hr ago0x1ea0e7e04e28674855eea35c03e511bffa5f1203 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.000585555
0xebf6867d79ff8ee3676f0752e6387de4b831662fcbdc8dc553aa3e9c517524f8Get Reward75103142022-01-15 23:14:231 day 1 hr ago0x51e9c095a913791de6bbadafdd4342608063e6c0 IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.000585555
0x777a76598329869750d110ccb902236ba1cdfdcc751d6fa375a94da133f5d7b5Get Reward75083912022-01-15 21:38:141 day 3 hrs ago0x36b303daa6ff4722119632db1c0c890b33aa1fdf IN  0x3ade2fe54ecd748fc86d3fdf86def612f94873090 HOO0.000585555
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0x66edC364336a2C644149F8529101bCEeCF49dBE2

Contract Name:
StakingRewards

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at hooscan.com on 2021-10-31
*/

// File: contracts/interfaces/IElkERC20.sol



pragma solidity >=0.5.0;

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

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
}
// File: @openzeppelin/[email protected]/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);
            }
        }
    }
}

// File: @openzeppelin/[email protected]/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/[email protected]/token/ERC20/utils/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/[email protected]/security/ReentrancyGuard.sol



pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// File: @openzeppelin/[email protected]/utils/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/[email protected]/utils/math/Math.sol



pragma solidity ^0.8.0;

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

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

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

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a / b + (a % b == 0 ? 0 : 1);
    }
}

// File: @openzeppelin/[email protected]/utils/Context.sol



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/[email protected]/security/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());
    }
}

// File: @openzeppelin/[email protected]/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() {
        _setOwner(_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 {
        _setOwner(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");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// File: contracts/StakingContractNew.sol



pragma solidity ^0.8.0;









contract StakingRewards is ReentrancyGuard, Ownable, Pausable {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    /* ========== STATE VARIABLES ========== */

    IERC20 public rewardsToken;
    IERC20 public stakingToken;
    uint256 public periodFinish;
    uint256 public rewardRate;
    uint256 public rewardsDuration;
    uint256 public lastUpdateTime;
    uint256 public rewardPerTokenStored;

    mapping(address => uint256) public userRewardPerTokenPaid;
    mapping(address => uint256) public rewards;
    
    IERC20 public boosterToken;
    uint256 public boosterRewardRate;
    uint256 public boosterRewardPerTokenStored;
    
    mapping(address => uint256) public userBoosterRewardPerTokenPaid;
    mapping(address => uint256) public boosterRewards;
    
    mapping(address => uint256) public coverages;
    uint256 public totalCoverage;
    
    uint256[] public feeSchedule;
    uint256[] public withdrawalFeesPct;
    mapping(address => uint256) public lastStakedTime;
    uint256 public totalFees;
    
    uint256 private _totalSupply;
    mapping(address => uint256) private _balances;

    /* ========== CONSTRUCTOR ========== */

    constructor(
        address _rewardsToken,
        address _stakingToken,
        address _boosterToken,
        uint256 _rewardsDuration,
        uint256[] memory _feeSchedule,       // assumes a sorted array
        uint256[] memory _withdrawalFeesPct  // aligned to fee schedule, percentage (/1000)
    ) public {
        require(_boosterToken != _rewardsToken, "The booster token must be different from the reward token");
        require(_boosterToken != _stakingToken, "The booster token must be different from the staking token");
        rewardsToken = IERC20(_rewardsToken);
        stakingToken = IERC20(_stakingToken);
        boosterToken = IERC20(_boosterToken);
        rewardsDuration = _rewardsDuration;
        _setWithdrawalFees(_feeSchedule, _withdrawalFeesPct);
        _pause();
    }

    /* ========== VIEWS ========== */

    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) external view returns (uint256) {
        return _balances[account];
    }

    function lastTimeRewardApplicable() public view returns (uint256) {
        return Math.min(block.timestamp, periodFinish);
    }

    function rewardPerToken() public view returns (uint256) {
        if (_totalSupply == 0) {
            return rewardPerTokenStored;
        }
        return
            rewardPerTokenStored.add(
                lastTimeRewardApplicable().sub(lastUpdateTime).mul(rewardRate).mul(1e18).div(_totalSupply)
            );
    }

    function earned(address account) public view returns (uint256) {
        return _balances[account].mul(rewardPerToken().sub(userRewardPerTokenPaid[account])).div(1e18).add(rewards[account]);
    }

    function getRewardForDuration() external view returns (uint256) {
        return rewardRate.mul(rewardsDuration);
    }
    
    function boosterRewardPerToken() public view returns (uint256) {
        if (_totalSupply == 0) {
            return boosterRewardPerTokenStored;
        }
        return
            boosterRewardPerTokenStored.add(
                lastTimeRewardApplicable().sub(lastUpdateTime).mul(boosterRewardRate).mul(1e18).div(_totalSupply)
            );
    }
    
    function boosterEarned(address account) public view returns (uint256) {
        return _balances[account].mul(boosterRewardPerToken().sub(userBoosterRewardPerTokenPaid[account])).div(1e18).add(boosterRewards[account]);
    }
    
    function getBoosterRewardForDuration() external view returns (uint256) {
        return boosterRewardRate.mul(rewardsDuration);
    }
    
    function exitFee(address account) public view returns (uint256) {
        return fee(account, _balances[account]);
    }
    
    function fee(address account, uint256 withdrawalAmount) public view returns (uint256) {
        for (uint i=0; i < feeSchedule.length; ++i) {
            if (block.timestamp.sub(lastStakedTime[account]) < feeSchedule[i]) {
                return withdrawalAmount.mul(withdrawalFeesPct[i]).div(1000);
            }
        }
        return 0;
    }

    /* ========== MUTATIVE FUNCTIONS ========== */

    function stake(uint256 amount) external nonReentrant whenNotPaused updateReward(msg.sender) {
        require(amount > 0, "Cannot stake 0");
        _totalSupply = _totalSupply.add(amount);
        _balances[msg.sender] = _balances[msg.sender].add(amount);
        stakingToken.safeTransferFrom(msg.sender, address(this), amount);
        lastStakedTime[msg.sender] = block.timestamp;
        emit Staked(msg.sender, amount);
    }
    
    function stakeWithPermit(uint256 amount, uint deadline, uint8 v, bytes32 r, bytes32 s) external nonReentrant whenNotPaused updateReward(msg.sender) {
        require(amount > 0, "Cannot stake 0");
        _totalSupply = _totalSupply.add(amount);
        _balances[msg.sender] = _balances[msg.sender].add(amount);

        // permit
        IElkERC20(address(stakingToken)).permit(msg.sender, address(this), amount, deadline, v, r, s);

        stakingToken.safeTransferFrom(msg.sender, address(this), amount);
        lastStakedTime[msg.sender] = block.timestamp;
        emit Staked(msg.sender, amount);
    }
    
    function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) {
        _withdraw(amount);
    }
    
    function emergencyWithdraw(uint256 amount) public nonReentrant {
        _withdraw(amount);
    }
    
    function _withdraw(uint256 amount) private {
        require(amount > 0, "Cannot withdraw 0");
        _totalSupply = _totalSupply.sub(amount);
        uint256 collectedFee = fee(msg.sender, amount);
        _balances[msg.sender] = _balances[msg.sender].sub(amount);
        uint256 withdrawableBalance = amount.sub(collectedFee);
        stakingToken.safeTransfer(msg.sender, withdrawableBalance);
        emit Withdrawn(msg.sender, withdrawableBalance);
        if (collectedFee > 0) {
            emit FeesCollected(msg.sender, collectedFee);
            totalFees = totalFees.add(collectedFee);
        }
    }
    
    function getReward() public nonReentrant updateReward(msg.sender) {
        uint256 reward = rewards[msg.sender];
        if (reward > 0) {
            rewards[msg.sender] = 0;
            rewardsToken.safeTransfer(msg.sender, reward);
            emit RewardPaid(msg.sender, reward);
        }
    }
    
    function getBoosterReward() public nonReentrant updateReward(msg.sender) {
        if (address(boosterToken) != address(0)) {
            uint256 reward = boosterRewards[msg.sender];
            if (reward > 0) {
                boosterRewards[msg.sender] = 0;
                boosterToken.safeTransfer(msg.sender, reward);
                emit BoosterRewardPaid(msg.sender, reward);
            }
        }
    }
    
    function getCoverage() public nonReentrant {
        uint256 coverageAmount = coverages[msg.sender];
        if (coverageAmount > 0) {
            totalCoverage = totalCoverage.sub(coverages[msg.sender]);
            coverages[msg.sender] = 0;
            rewardsToken.safeTransfer(msg.sender, coverageAmount);
            emit CoveragePaid(msg.sender, coverageAmount);
        }
    }

    function exit() external {
        withdraw(_balances[msg.sender]);
        getReward();
        getBoosterReward();
        getCoverage();
    }

    /* ========== RESTRICTED FUNCTIONS ========== */
    
    function sendRewardsAndStartEmission(uint256 reward, uint256 boosterReward, uint256 duration) external onlyOwner  {
        rewardsToken.safeTransferFrom(owner(), address(this), reward);
        if (address(boosterToken) != address(0) && boosterReward > 0) {
            boosterToken.safeTransferFrom(owner(), address(this), boosterReward);
        }
        _startEmission(reward, boosterReward, duration);
    }
    
    function startEmission(uint256 reward, uint256 boosterReward, uint256 duration) external onlyOwner  {
        _startEmission(reward, boosterReward, duration);
    }
    
    function stopEmission() external onlyOwner whenNotPaused {
        require(block.timestamp < periodFinish, "Cannot stop rewards emissions if not started or already finished");
        
        uint256 tokensToBurn;
        uint256 boosterTokensToBurn;

        if (_totalSupply == 0) {
            tokensToBurn = rewardsToken.balanceOf(address(this));
            if (address(boosterToken) != address(0)) {
                boosterTokensToBurn = boosterToken.balanceOf(address(this));
            } else {
                boosterTokensToBurn = 0;
            }
        } else {
            uint256 remaining = periodFinish.sub(block.timestamp);
            tokensToBurn = rewardRate.mul(remaining);
            boosterTokensToBurn = boosterRewardRate.mul(remaining);
        }

        periodFinish = block.timestamp;
        if (tokensToBurn > 0) {
            rewardsToken.safeTransfer(owner(), tokensToBurn);
        }
        if (address(boosterToken) != address(0) && boosterTokensToBurn > 0) {
            boosterToken.safeTransfer(owner(), boosterTokensToBurn);
        }
        
        _pause();
        
        emit RewardsEmissionEnded(tokensToBurn);
    }

    function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner {
        require(tokenAddress != address(stakingToken), "Cannot withdraw the staking token");
        IERC20(tokenAddress).safeTransfer(owner(), tokenAmount);
        emit Recovered(tokenAddress, tokenAmount);
    }
    
    function recoverLeftoverReward() external onlyOwner {
        require(_totalSupply == 0 && rewardsToken == stakingToken, "Cannot recover leftover reward if it is not the staking token or there are still staked tokens");
        uint256 tokensToBurn = rewardsToken.balanceOf(address(this));
        if (tokensToBurn > 0) {
            rewardsToken.safeTransfer(owner(), tokensToBurn);
        }
        emit LeftoverRewardRecovered(tokensToBurn);
    }
    
    function recoverLeftoverBooster() external onlyOwner {
        require(address(boosterToken) != address(0), "Cannot recover leftover booster if there was no booster token set");
        require(_totalSupply == 0, "Cannot recover leftover booster if there are still staked tokens");
        uint256 tokensToBurn = boosterToken.balanceOf(address(this));
        if (tokensToBurn > 0) {
            boosterToken.safeTransfer(owner(), tokensToBurn);
        }
        emit LeftoverBoosterRecovered(tokensToBurn);
    }

    function recoverFees() external onlyOwner {
        stakingToken.safeTransfer(owner(), totalFees);
        emit FeesRecovered(totalFees);
        totalFees = 0;
    }

    function setReward(address addr, uint256 amount) public onlyOwner {
        rewards[addr] = amount;
    }
    
    function setRewards(address[] memory addresses, uint256[] memory amounts) external onlyOwner {
        require(addresses.length == amounts.length, "The same number of addresses and amounts must be provided");
        for (uint i=0; i < addresses.length; ++i) {
            setReward(addresses[i], amounts[i]);
        }
    }
    
    function setRewardsDuration(uint256 duration) external onlyOwner {
        require(
            block.timestamp > periodFinish,
            "Previous rewards period must be complete before changing the duration for the new period"
        );
        _setRewardsDuration(duration);
    }
    
    // Booster Rewards
    
    function setBoosterToken(address _boosterToken) external onlyOwner {
        require(_boosterToken != address(rewardsToken), "The booster token must be different from the reward token");
        require(_boosterToken != address(stakingToken), "The booster token must be different from the staking token");
        boosterToken = IERC20(_boosterToken);
        emit BoosterRewardSet(_boosterToken);
    }
    
    function setBoosterReward(address addr, uint256 amount) public onlyOwner {
        boosterRewards[addr] = amount;
    }
    
    function setBoosterRewards(address[] memory addresses, uint256[] memory amounts) external onlyOwner {
        require(addresses.length == amounts.length, "The same number of addresses and amounts must be provided");
        for (uint i=0; i < addresses.length; ++i) {
            setBoosterReward(addresses[i], amounts[i]);
        }
    }
    
    // ILP
    
    function setCoverageAmount(address addr, uint256 amount) public onlyOwner {
        totalCoverage = totalCoverage.sub(coverages[addr]);
        coverages[addr] = amount;
        totalCoverage = totalCoverage.add(coverages[addr]);
    }
    
    function setCoverageAmounts(address[] memory addresses, uint256[] memory amounts) external onlyOwner {
        require(addresses.length == amounts.length, "The same number of addresses and amounts must be provided");
        for (uint i=0; i < addresses.length; ++i) {
            setCoverageAmount(addresses[i], amounts[i]);
        }
    }
    
    function pause() public virtual {
        _pause();
    }

    function unpause() public virtual {
        _unpause();
    }
    
    // Withdrawal Fees
    
    function setWithdrawalFees(uint256[] memory _feeSchedule, uint256[] memory _withdrawalFees) external onlyOwner {
        _setWithdrawalFees(_feeSchedule, _withdrawalFees);
    }
    
    // Private functions
    
    function _setRewardsDuration(uint256 duration) private {
        rewardsDuration = duration;
        emit RewardsDurationUpdated(rewardsDuration);
    }
    
    function _setWithdrawalFees(uint256[] memory _feeSchedule, uint256[] memory _withdrawalFeesPct) private {
        require(_feeSchedule.length == _withdrawalFeesPct.length, "Fee schedule and withdrawal fees arrays must be the same length!");
        feeSchedule = _feeSchedule;
        withdrawalFeesPct = _withdrawalFeesPct;
        emit WithdrawalFeesSet(_feeSchedule, _withdrawalFeesPct);
    }
    
    // Must send reward before calling this!
    function _startEmission(uint256 reward, uint256 boosterReward, uint256 duration) private updateReward(address(0)) {
        if (duration > 0) {
            _setRewardsDuration(duration);
        }
        
        if (block.timestamp >= periodFinish) {
            rewardRate = reward.div(rewardsDuration);
            boosterRewardRate = boosterReward.div(rewardsDuration);
        } else {
            uint256 remaining = periodFinish.sub(block.timestamp);
            uint256 leftover = remaining.mul(rewardRate);
            rewardRate = reward.add(leftover).div(rewardsDuration);
            uint256 boosterLeftover = remaining.mul(boosterRewardRate);
            boosterRewardRate = boosterReward.add(boosterLeftover).div(rewardsDuration);
        }
        
        // Ensure the provided reward amount is not more than the balance in the contract.
        // This keeps the reward rate in the right range, preventing overflows due to
        // very high values of rewardRate in the earned and rewardsPerToken functions;
        // Reward + leftover must be less than 2^256 / 10^18 to avoid overflow.
        uint balance = rewardsToken.balanceOf(address(this));
        require(rewardRate <= balance.div(rewardsDuration) || (rewardsToken == stakingToken && rewardRate <= balance.div(rewardsDuration).sub(_totalSupply)), "Provided reward too high");
        
        if (address(boosterToken) != address(0)) {
            uint boosterBalance = boosterToken.balanceOf(address(this));
            require(boosterRewardRate <= boosterBalance.div(rewardsDuration), "Provided booster reward too high");
        }

        lastUpdateTime = block.timestamp;
        periodFinish = block.timestamp.add(rewardsDuration);
        
        _unpause();
        
        emit RewardsEmissionStarted(reward, boosterReward, duration);
    }

    /* ========== DEPRECATED ========== */
    
    function coverageOf(address account) external view returns (uint256) {
        return coverages[account];
    }
    
    function updateLastTime(uint timestamp) external onlyOwner {
	    lastUpdateTime = timestamp;
    }

    /* ========== MODIFIERS ========== */

    modifier updateReward(address account) {
        rewardPerTokenStored = rewardPerToken();
        boosterRewardPerTokenStored = boosterRewardPerToken();
        lastUpdateTime = lastTimeRewardApplicable();
        if (account != address(0)) {
            rewards[account] = earned(account);
            userRewardPerTokenPaid[account] = rewardPerTokenStored;
            boosterRewards[account] = boosterEarned(account);
            userBoosterRewardPerTokenPaid[account] = boosterRewardPerTokenStored;
        }
        _;
    }

    /* ========== EVENTS ========== */
    
    event Staked(address indexed user, uint256 amount);
    event Withdrawn(address indexed user, uint256 amount);
    event CoveragePaid(address indexed user, uint256 amount);
    event RewardPaid(address indexed user, uint256 reward);
    event BoosterRewardPaid(address indexed user, uint256 reward);
    event RewardsDurationUpdated(uint256 newDuration);
    event Recovered(address token, uint256 amount);
    event LeftoverRewardRecovered(uint256 amount);
    event LeftoverBoosterRecovered(uint256 amount);
    event RewardsEmissionStarted(uint256 reward, uint256 boosterReward, uint256 duration);
    event RewardsEmissionEnded(uint256 amount);
    event BoosterRewardSet(address token);
    event WithdrawalFeesSet(uint256[] _feeSchedule, uint256[] _withdrawalFees);
    event FeesCollected(address indexed user, uint256 amount);
    event FeesRecovered(uint256 amount);
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_rewardsToken","type":"address"},{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_boosterToken","type":"address"},{"internalType":"uint256","name":"_rewardsDuration","type":"uint256"},{"internalType":"uint256[]","name":"_feeSchedule","type":"uint256[]"},{"internalType":"uint256[]","name":"_withdrawalFeesPct","type":"uint256[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"BoosterRewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"BoosterRewardSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CoveragePaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LeftoverBoosterRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LeftoverRewardRecovered","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":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDuration","type":"uint256"}],"name":"RewardsDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsEmissionEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"boosterReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"RewardsEmissionStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"_feeSchedule","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"_withdrawalFees","type":"uint256[]"}],"name":"WithdrawalFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"boosterEarned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boosterRewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boosterRewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boosterRewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"boosterRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boosterToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"coverageOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"coverages","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"exitFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"withdrawalAmount","type":"uint256"}],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"feeSchedule","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBoosterReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBoosterRewardForDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCoverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardForDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastStakedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverLeftoverBooster","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverLeftoverReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"boosterReward","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"sendRewardsAndStartEmission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setBoosterReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"setBoosterRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_boosterToken","type":"address"}],"name":"setBoosterToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setCoverageAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"setCoverageAmounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"setRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"setRewardsDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_feeSchedule","type":"uint256[]"},{"internalType":"uint256[]","name":"_withdrawalFees","type":"uint256[]"}],"name":"setWithdrawalFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"stakeWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"boosterReward","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"startEmission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopEmission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalCoverage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"updateLastTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBoosterRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawalFeesPct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b5060405162003f4a38038062003f4a8339810160408190526200003491620004ca565b60016000556200004433620001a5565b6001805460ff60a01b191690556001600160a01b038481169087161415620000c85760405162461bcd60e51b8152602060048201526039602482015260008051602062003f2a83398151915260448201527f656e742066726f6d207468652072657761726420746f6b656e0000000000000060648201526084015b60405180910390fd5b846001600160a01b0316846001600160a01b03161415620001415760405162461bcd60e51b815260206004820152603a602482015260008051602062003f2a83398151915260448201527f656e742066726f6d20746865207374616b696e6720746f6b656e0000000000006064820152608401620000bf565b600280546001600160a01b038089166001600160a01b03199283161790925560038054888416908316179055600b80549287169290911691909117905560068390556200018f8282620001f7565b62000199620002dd565b505050505050620005e4565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b805182511462000272576040805162461bcd60e51b81526020600482015260248101919091527f466565207363686564756c6520616e64207769746864726177616c206665657360448201527f20617272617973206d757374206265207468652073616d65206c656e677468216064820152608401620000bf565b8151620002879060129060208501906200038c565b5080516200029d9060139060208401906200038c565b507fe5a2c1e4acf2a2da539a1183c56fbbcec4b66dbc828b76f1c1bf365f1887886b8282604051620002d1929190620005b2565b60405180910390a15050565b620002f1600154600160a01b900460ff1690565b15620003335760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401620000bf565b6001805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586200036f3390565b6040516001600160a01b03909116815260200160405180910390a1565b828054828255906000526020600020908101928215620003ca579160200282015b82811115620003ca578251825591602001919060010190620003ad565b50620003d8929150620003dc565b5090565b5b80821115620003d85760008155600101620003dd565b80516001600160a01b03811681146200040b57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200043857600080fd5b815160206001600160401b038083111562000457576200045762000410565b8260051b604051601f19603f830116810181811084821117156200047f576200047f62000410565b6040529384528581018301938381019250878511156200049e57600080fd5b83870191505b84821015620004bf57815183529183019190830190620004a4565b979650505050505050565b60008060008060008060c08789031215620004e457600080fd5b620004ef87620003f3565b9550620004ff60208801620003f3565b94506200050f60408801620003f3565b6060880151608089015191955093506001600160401b03808211156200053457600080fd5b620005428a838b0162000426565b935060a08901519150808211156200055957600080fd5b506200056889828a0162000426565b9150509295509295509295565b600081518084526020808501945080840160005b83811015620005a75781518752958201959082019060010162000589565b509495945050505050565b604081526000620005c7604083018562000575565b8281036020840152620005db818562000575565b95945050505050565b61393680620005f46000396000f3fe608060405234801561001057600080fd5b50600436106103c45760003560e01c806380faa57d116101ff578063cd3daf9d1161011a578063ebe2b12b116100ad578063f3f0ffda1161007c578063f3f0ffda146107cd578063f86e55ca146107d5578063faef375e146107e8578063ffb13208146107f057600080fd5b8063ebe2b12b1461077e578063ecd9ba8214610787578063f22797d81461079a578063f2fde38b146107ba57600080fd5b8063d9142bbe116100e9578063d9142bbe14610747578063df136d651461075a578063e9fad8ee14610763578063eacccaf01461076b57600080fd5b8063cd3daf9d1461071b578063cdeae37114610723578063d1af0c7d1461072b578063d51942e21461073e57600080fd5b80639292052211610192578063be0bf75111610161578063be0bf751146106d6578063c57a202c146106df578063c8f33c91146106ff578063cc1a378f1461070857600080fd5b8063929205221461068a5780639465d4a11461069d5780639e6eda18146106b0578063a694fc3a146106c357600080fd5b80638bb95b45116101ce5780638bb95b45146106405780638da5cb5b146106535780638f0bb79c14610664578063905b7d3c1461067757600080fd5b806380faa57d146105fd5780638456cb59146106055780638980f11f1461060d5780638b8763471461062057600080fd5b80633f4ba83a116102ef57806366a03c7f1161028257806372f702f31161025157806372f702f3146105bb57806377075130146105ce57806377191605146105e15780637b0a47ee146105f457600080fd5b806366a03c7f146105795780636de4ab871461058257806370a082311461058a578063715018a6146105b357600080fd5b8063576c23ab116102be578063576c23ab146105095780635c975abb146105345780635d129544146105515780636439ea4c1461057157600080fd5b80633f4ba83a146104c857806343d45c17146104d05780634b03f2e9146104e35780635312ea8e146104f657600080fd5b80631c1f78eb1161036757806335ceec0f1161033657806335ceec0f14610491578063386a9525146104a45780633b8e4f7e146104ad5780633d18b912146104c057600080fd5b80631c1f78eb146104665780632459a6991461046e5780632cbe61d3146104765780632e1a7d4d1461047e57600080fd5b806310cbbe38116103a357806310cbbe3814610419578063120459871461042c57806313114a9d1461045557806318160ddd1461045e57600080fd5b80628cc262146103c95780630700037d146103ef5780630e9bb0a31461040f575b600080fd5b6103dc6103d736600461344e565b610810565b6040519081526020015b60405180910390f35b6103dc6103fd36600461344e565b600a6020526000908152604090205481565b61041761088e565b005b6103dc61042736600461344e565b610bb5565b6103dc61043a36600461344e565b6001600160a01b031660009081526010602052604090205490565b6103dc60155481565b6016546103dc565b6103dc610bd9565b610417610bf7565b610417610d7a565b61041761048c366004613469565b610f5d565b6103dc61049f366004613469565b611058565b6103dc60065481565b6103dc6104bb36600461344e565b611079565b6104176110c0565b610417611223565b6104176104de366004613482565b61122d565b6104176104f1366004613482565b6112cc565b610417610504366004613469565b611330565b600b5461051c906001600160a01b031681565b6040516001600160a01b0390911681526020016103e6565b600154600160a01b900460ff1660405190151581526020016103e6565b6103dc61055f36600461344e565b600e6020526000908152604090205481565b6103dc611391565b6103dc600d5481565b6104176113dd565b6103dc61059836600461344e565b6001600160a01b031660009081526017602052604090205490565b6104176114cf565b60035461051c906001600160a01b031681565b6104176105dc366004613582565b611521565b6104176105ef3660046135e6565b611577565b6103dc60055481565b6103dc611640565b61041761164e565b61041761061b366004613482565b611656565b6103dc61062e36600461344e565b60096020526000908152604090205481565b61041761064e3660046135e6565b611787565b6001546001600160a01b031661051c565b6103dc610672366004613469565b6117cf565b610417610685366004613612565b6117df565b610417610698366004613612565b6118f6565b6104176106ab36600461344e565b611a0d565b6103dc6106be366004613482565b611bb8565b6104176106d1366004613469565b611c67565b6103dc600c5481565b6103dc6106ed36600461344e565b60146020526000908152604090205481565b6103dc60075481565b610417610716366004613469565b611e91565b6103dc611f82565b610417611fc8565b60025461051c906001600160a01b031681565b6103dc60115481565b610417610755366004613469565b61207d565b6103dc60085481565b6104176120ca565b610417610779366004613482565b6120fb565b6103dc60045481565b6104176107953660046136bb565b61215f565b6103dc6107a836600461344e565b600f6020526000908152604090205481565b6104176107c836600461344e565b612441565b6103dc61250e565b6104176107e3366004613612565b612527565b61041761263e565b6103dc6107fe36600461344e565b60106020526000908152604090205481565b6001600160a01b0381166000908152600a60209081526040808320546009909252822054610888919061088290670de0b6b3a76400009061087c9061085d90610857611f82565b9061286b565b6001600160a01b0388166000908152601760205260409020549061287e565b9061288a565b90612896565b92915050565b6001546001600160a01b031633146108db5760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064015b60405180910390fd5b600154600160a01b900460ff16156109285760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016108d2565b60045442106109a1576040805162461bcd60e51b81526020600482015260248101919091527f43616e6e6f742073746f70207265776172647320656d697373696f6e7320696660448201527f206e6f742073746172746564206f7220616c72656164792066696e697368656460648201526084016108d2565b60008060165460001415610ac8576002546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b1580156109f257600080fd5b505afa158015610a06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2a919061370a565b600b549092506001600160a01b031615610ac057600b546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015610a8157600080fd5b505afa158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab9919061370a565b9050610afc565b506000610afc565b600454600090610ad8904261286b565b600554909150610ae8908261287e565b600c54909350610af8908261287e565b9150505b426004558115610b2e57610b2e610b1b6001546001600160a01b031690565b6002546001600160a01b031690846128a2565b600b546001600160a01b031615801590610b485750600081115b15610b7557610b75610b626001546001600160a01b031690565b600b546001600160a01b031690836128a2565b610b7d61294b565b6040518281527f6d815f6a8a51efb6f4140923189859b9e9caaa228c9334179e8eb7edefc6838e906020015b60405180910390a15050565b6001600160a01b038116600090815260176020526040812054610888908390611bb8565b6000610bf260065460055461287e90919063ffffffff16565b905090565b60026000541415610c4a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108d2565b600260005533610c58611f82565b600855610c63611391565b600d55610c6e611640565b6007556001600160a01b03811615610ce957610c8981610810565b6001600160a01b0382166000908152600a6020908152604080832093909355600854600990915291902055610cbd81611079565b6001600160a01b0382166000908152600f6020908152604080832093909355600d54600e909152919020555b600b546001600160a01b031615610d7257336000908152600f60205260409020548015610d7057336000818152600f6020526040812055600b54610d39916001600160a01b0390911690836128a2565b60405181815233907fd1e5531ac01ffc9c7971b52c82806a6e5ae8907ddedd2e3153afaafcfdf175d6906020015b60405180910390a25b505b506001600055565b6001546001600160a01b03163314610dc25760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b601654158015610de257506003546002546001600160a01b039081169116145b610e7a5760405162461bcd60e51b815260206004820152605e60248201527f43616e6e6f74207265636f766572206c6566746f76657220726577617264206960448201527f66206974206973206e6f7420746865207374616b696e6720746f6b656e206f7260648201527f20746865726520617265207374696c6c207374616b656420746f6b656e730000608482015260a4016108d2565b6002546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015610ebe57600080fd5b505afa158015610ed2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef6919061370a565b90508015610f2657610f26610f136001546001600160a01b031690565b6002546001600160a01b031690836128a2565b6040518181527ff6d91c6a1bf05d7c0f2c157905a97d3bc2f860a1402d71dd52a27fabb5bcaf8d906020015b60405180910390a150565b60026000541415610fb05760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108d2565b600260005533610fbe611f82565b600855610fc9611391565b600d55610fd4611640565b6007556001600160a01b0381161561104f57610fef81610810565b6001600160a01b0382166000908152600a602090815260408083209390935560085460099091529190205561102381611079565b6001600160a01b0382166000908152600f6020908152604080832093909355600d54600e909152919020555b610d70826129f0565b6012818154811061106857600080fd5b600091825260209091200154905081565b6001600160a01b0381166000908152600f6020908152604080832054600e909252822054610888919061088290670de0b6b3a76400009061087c9061085d90610857611391565b600260005414156111135760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108d2565b600260005533611121611f82565b60085561112c611391565b600d55611137611640565b6007556001600160a01b038116156111b25761115281610810565b6001600160a01b0382166000908152600a602090815260408083209390935560085460099091529190205561118681611079565b6001600160a01b0382166000908152600f6020908152604080832093909355600d54600e909152919020555b336000908152600a60205260409020548015610d7057336000818152600a60205260408120556002546111f1916001600160a01b0390911690836128a2565b60405181815233907fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e048690602001610d67565b61122b612b35565b565b6001546001600160a01b031633146112755760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b6001600160a01b03821660009081526010602052604090205460115461129a9161286b565b60119081556001600160a01b0383166000908152601060205260409020829055546112c59082612896565b6011555050565b6001546001600160a01b031633146113145760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b6001600160a01b039091166000908152600f6020526040902055565b600260005414156113835760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108d2565b6002600055610d72816129f0565b6000601654600014156113a55750600d5490565b610bf26113d460165461087c670de0b6b3a76400006113ce600c546113ce600754610857611640565b9061287e565b600d5490612896565b600260005414156114305760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108d2565b60026000908155338152601060205260409020548015610d7257336000908152601060205260409020546011546114669161286b565b60115533600081815260106020526040812055600254611492916001600160a01b0390911690836128a2565b60405181815233907fef4696bdcf47e292773442e4169d670e1b2d0d3f5ceff2a5c1e236c10109ee809060200160405180910390a2506001600055565b6001546001600160a01b031633146115175760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b61122b6000612bc2565b6001546001600160a01b031633146115695760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b6115738282612c21565b5050565b6001546001600160a01b031633146115bf5760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b6115e86115d46001546001600160a01b031690565b6002546001600160a01b0316903086612cf3565b600b546001600160a01b0316158015906116025750600082115b156116305761163061161c6001546001600160a01b031690565b600b546001600160a01b0316903085612cf3565b61163b838383612d4a565b505050565b6000610bf242600454613113565b61122b61294b565b6001546001600160a01b0316331461169e5760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b6003546001600160a01b03838116911614156117225760405162461bcd60e51b815260206004820152602160248201527f43616e6e6f7420776974686472617720746865207374616b696e6720746f6b6560448201527f6e0000000000000000000000000000000000000000000000000000000000000060648201526084016108d2565b6117486117376001546001600160a01b031690565b6001600160a01b03841690836128a2565b604080516001600160a01b0384168152602081018390527f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa289101610ba9565b6001546001600160a01b031633146116305760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b6013818154811061106857600080fd5b6001546001600160a01b031633146118275760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b805182511461189e5760405162461bcd60e51b815260206004820152603960248201527f5468652073616d65206e756d626572206f662061646472657373657320616e6460448201527f20616d6f756e7473206d7573742062652070726f76696465640000000000000060648201526084016108d2565b60005b825181101561163b576118e68382815181106118bf576118bf613723565b60200260200101518383815181106118d9576118d9613723565b602002602001015161122d565b6118ef8161374f565b90506118a1565b6001546001600160a01b0316331461193e5760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b80518251146119b55760405162461bcd60e51b815260206004820152603960248201527f5468652073616d65206e756d626572206f662061646472657373657320616e6460448201527f20616d6f756e7473206d7573742062652070726f76696465640000000000000060648201526084016108d2565b60005b825181101561163b576119fd8382815181106119d6576119d6613723565b60200260200101518383815181106119f0576119f0613723565b60200260200101516120fb565b611a068161374f565b90506119b8565b6001546001600160a01b03163314611a555760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b6002546001600160a01b0382811691161415611ad95760405162461bcd60e51b815260206004820152603960248201527f54686520626f6f7374657220746f6b656e206d7573742062652064696666657260448201527f656e742066726f6d207468652072657761726420746f6b656e0000000000000060648201526084016108d2565b6003546001600160a01b0382811691161415611b5d5760405162461bcd60e51b815260206004820152603a60248201527f54686520626f6f7374657220746f6b656e206d7573742062652064696666657260448201527f656e742066726f6d20746865207374616b696e6720746f6b656e00000000000060648201526084016108d2565b600b805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f0c6fec5b80219c372da56cb4d1ef3e172069953fa5c72ececf0d0dfe1109260b90602001610f52565b6000805b601254811015611c5d5760128181548110611bd957611bd9613723565b60009182526020808320909101546001600160a01b03871683526014909152604090912054611c0990429061286b565b1015611c4d57611c456103e861087c60138481548110611c2b57611c2b613723565b90600052602060002001548661287e90919063ffffffff16565b915050610888565b611c568161374f565b9050611bbc565b5060009392505050565b60026000541415611cba5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108d2565b6002600055600154600160a01b900460ff1615611d0c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016108d2565b33611d15611f82565b600855611d20611391565b600d55611d2b611640565b6007556001600160a01b03811615611da657611d4681610810565b6001600160a01b0382166000908152600a6020908152604080832093909355600854600990915291902055611d7a81611079565b6001600160a01b0382166000908152600f6020908152604080832093909355600d54600e909152919020555b60008211611df65760405162461bcd60e51b815260206004820152600e60248201527f43616e6e6f74207374616b65203000000000000000000000000000000000000060448201526064016108d2565b601654611e039083612896565b60165533600090815260176020526040902054611e209083612896565b33600081815260176020526040902091909155600354611e4d916001600160a01b03909116903085612cf3565b3360008181526014602052604090819020429055517f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d90610d679085815260200190565b6001546001600160a01b03163314611ed95760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b6004544211611f765760405162461bcd60e51b815260206004820152605860248201527f50726576696f7573207265776172647320706572696f64206d7573742062652060448201527f636f6d706c657465206265666f7265206368616e67696e67207468652064757260648201527f6174696f6e20666f7220746865206e657720706572696f640000000000000000608482015260a4016108d2565b611f7f81613129565b50565b600060165460001415611f96575060085490565b610bf2611fbf60165461087c670de0b6b3a76400006113ce6005546113ce600754610857611640565b60085490612896565b6001546001600160a01b031633146120105760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b61203b6120256001546001600160a01b031690565b6015546003546001600160a01b031691906128a2565b7f6857c770f3cb43e9c19050a37dd914ec876241c1f4b487d26a1d4f5d3054f49b60155460405161206e91815260200190565b60405180910390a16000601555565b6001546001600160a01b031633146120c55760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b600755565b336000908152601760205260409020546120e390610f5d565b6120eb6110c0565b6120f3610bf7565b61122b6113dd565b6001546001600160a01b031633146121435760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b6001600160a01b039091166000908152600a6020526040902055565b600260005414156121b25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108d2565b6002600055600154600160a01b900460ff16156122045760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016108d2565b3361220d611f82565b600855612218611391565b600d55612223611640565b6007556001600160a01b0381161561229e5761223e81610810565b6001600160a01b0382166000908152600a602090815260408083209390935560085460099091529190205561227281611079565b6001600160a01b0382166000908152600f6020908152604080832093909355600d54600e909152919020555b600086116122ee5760405162461bcd60e51b815260206004820152600e60248201527f43616e6e6f74207374616b65203000000000000000000000000000000000000060448201526064016108d2565b6016546122fb9087612896565b601655336000908152601760205260409020546123189087612896565b33600081815260176020526040908190209290925560035491517fd505accf0000000000000000000000000000000000000000000000000000000081526004810191909152306024820152604481018890526064810187905260ff8616608482015260a4810185905260c481018490526001600160a01b039091169063d505accf9060e401600060405180830381600087803b1580156123b757600080fd5b505af11580156123cb573d6000803e3d6000fd5b50506003546123e892506001600160a01b03169050333089612cf3565b3360008181526014602052604090819020429055517f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d9061242c9089815260200190565b60405180910390a25050600160005550505050565b6001546001600160a01b031633146124895760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b6001600160a01b0381166125055760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016108d2565b611f7f81612bc2565b6000610bf2600654600c5461287e90919063ffffffff16565b6001546001600160a01b0316331461256f5760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b80518251146125e65760405162461bcd60e51b815260206004820152603960248201527f5468652073616d65206e756d626572206f662061646472657373657320616e6460448201527f20616d6f756e7473206d7573742062652070726f76696465640000000000000060648201526084016108d2565b60005b825181101561163b5761262e83828151811061260757612607613723565b602002602001015183838151811061262157612621613723565b60200260200101516112cc565b6126378161374f565b90506125e9565b6001546001600160a01b031633146126865760405162461bcd60e51b815260206004820181905260248201526000805160206138e183398151915260448201526064016108d2565b600b546001600160a01b031661272a5760405162461bcd60e51b815260206004820152604160248201527f43616e6e6f74207265636f766572206c6566746f76657220626f6f737465722060448201527f696620746865726520776173206e6f20626f6f7374657220746f6b656e20736560648201527f7400000000000000000000000000000000000000000000000000000000000000608482015260a4016108d2565b601654156127a2576040805162461bcd60e51b81526020600482015260248101919091527f43616e6e6f74207265636f766572206c6566746f76657220626f6f737465722060448201527f696620746865726520617265207374696c6c207374616b656420746f6b656e7360648201526084016108d2565b600b546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b1580156127e657600080fd5b505afa1580156127fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281e919061370a565b9050801561283b5761283b610b626001546001600160a01b031690565b6040518181527fa075ee3dcd38efb87f0f97160a935b6a43768378263338beea06b9681f66151d90602001610f52565b6000612877828461376a565b9392505050565b60006128778284613781565b600061287782846137a0565b600061287782846137c2565b6040516001600160a01b03831660248201526044810182905261163b9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261315e565b600154600160a01b900460ff16156129985760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016108d2565b6001805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586129d33390565b6040516001600160a01b03909116815260200160405180910390a1565b60008111612a405760405162461bcd60e51b815260206004820152601160248201527f43616e6e6f74207769746864726177203000000000000000000000000000000060448201526064016108d2565b601654612a4d908261286b565b6016556000612a5c3383611bb8565b33600090815260176020526040902054909150612a79908361286b565b33600090815260176020526040812091909155612a96838361286b565b600354909150612ab0906001600160a01b031633836128a2565b60405181815233907f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d59060200160405180910390a2811561163b5760405182815233907f9dc46f23cfb5ddcad0ae7ea2be38d47fec07bb9382ec7e564efc69e036dd66ce9060200160405180910390a2601554612b2d9083612896565b601555505050565b600154600160a01b900460ff16612b8e5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016108d2565b6001805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336129d3565b600180546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8051825114612c9a576040805162461bcd60e51b81526020600482015260248101919091527f466565207363686564756c6520616e64207769746864726177616c206665657360448201527f20617272617973206d757374206265207468652073616d65206c656e6774682160648201526084016108d2565b8151612cad9060129060208501906133d2565b508051612cc19060139060208401906133d2565b507fe5a2c1e4acf2a2da539a1183c56fbbcec4b66dbc828b76f1c1bf365f1887886b8282604051610ba9929190613815565b6040516001600160a01b0380851660248301528316604482015260648101829052612d449085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016128e7565b50505050565b6000612d54611f82565b600855612d5f611391565b600d55612d6a611640565b6007556001600160a01b03811615612de557612d8581610810565b6001600160a01b0382166000908152600a6020908152604080832093909355600854600990915291902055612db981611079565b6001600160a01b0382166000908152600f6020908152604080832093909355600d54600e909152919020555b8115612df457612df482613129565b6004544210612e2457600654612e0b90859061288a565b600555600654612e1c90849061288a565b600c55612e90565b600454600090612e34904261286b565b90506000612e4d6005548361287e90919063ffffffff16565b600654909150612e619061087c8884612896565b600555600c54600090612e7590849061287e565b600654909150612e899061087c8884612896565b600c555050505b6002546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015612ed457600080fd5b505afa158015612ee8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f0c919061370a565b9050612f236006548261288a90919063ffffffff16565b600554111580612f6a57506003546002546001600160a01b039081169116148015612f6a5750612f646016546108576006548461288a90919063ffffffff16565b60055411155b612fb65760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f2068696768000000000000000060448201526064016108d2565b600b546001600160a01b0316156130ad57600b546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561300b57600080fd5b505afa15801561301f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613043919061370a565b905061305a6006548261288a90919063ffffffff16565b600c5411156130ab5760405162461bcd60e51b815260206004820181905260248201527f50726f766964656420626f6f737465722072657761726420746f6f206869676860448201526064016108d2565b505b4260078190556006546130c09190612896565b6004556130cb612b35565b60408051868152602081018690529081018490527f748824204e79acdab8f1a9977cbc584250e206ad90d05ef198799f9d6ee93a7d9060600160405180910390a15050505050565b60008183106131225781612877565b5090919050565b60068190556040518181527ffb46ca5a5e06d4540d6387b930a7c978bce0db5f449ec6b3f5d07c6e1d44f2d390602001610f52565b60006131b3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132439092919063ffffffff16565b80519091501561163b57808060200190518101906131d19190613843565b61163b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016108d2565b6060613252848460008561325a565b949350505050565b6060824710156132d25760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016108d2565b843b6133205760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108d2565b600080866001600160a01b0316858760405161333c9190613891565b60006040518083038185875af1925050503d8060008114613379576040519150601f19603f3d011682016040523d82523d6000602084013e61337e565b606091505b509150915061338e828286613399565b979650505050505050565b606083156133a8575081612877565b8251156133b85782518084602001fd5b8160405162461bcd60e51b81526004016108d291906138ad565b82805482825590600052602060002090810192821561340d579160200282015b8281111561340d5782518255916020019190600101906133f2565b5061341992915061341d565b5090565b5b80821115613419576000815560010161341e565b80356001600160a01b038116811461344957600080fd5b919050565b60006020828403121561346057600080fd5b61287782613432565b60006020828403121561347b57600080fd5b5035919050565b6000806040838503121561349557600080fd5b61349e83613432565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156134eb576134eb6134ac565b604052919050565b600067ffffffffffffffff82111561350d5761350d6134ac565b5060051b60200190565b600082601f83011261352857600080fd5b8135602061353d613538836134f3565b6134c2565b82815260059290921b8401810191818101908684111561355c57600080fd5b8286015b848110156135775780358352918301918301613560565b509695505050505050565b6000806040838503121561359557600080fd5b823567ffffffffffffffff808211156135ad57600080fd5b6135b986838701613517565b935060208501359150808211156135cf57600080fd5b506135dc85828601613517565b9150509250929050565b6000806000606084860312156135fb57600080fd5b505081359360208301359350604090920135919050565b6000806040838503121561362557600080fd5b823567ffffffffffffffff8082111561363d57600080fd5b818501915085601f83011261365157600080fd5b81356020613661613538836134f3565b82815260059290921b8401810191818101908984111561368057600080fd5b948201945b838610156136a55761369686613432565b82529482019490820190613685565b965050860135925050808211156135cf57600080fd5b600080600080600060a086880312156136d357600080fd5b8535945060208601359350604086013560ff811681146136f257600080fd5b94979396509394606081013594506080013592915050565b60006020828403121561371c57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060001982141561376357613763613739565b5060010190565b60008282101561377c5761377c613739565b500390565b600081600019048311821515161561379b5761379b613739565b500290565b6000826137bd57634e487b7160e01b600052601260045260246000fd5b500490565b600082198211156137d5576137d5613739565b500190565b600081518084526020808501945080840160005b8381101561380a578151875295820195908201906001016137ee565b509495945050505050565b60408152600061382860408301856137da565b828103602084015261383a81856137da565b95945050505050565b60006020828403121561385557600080fd5b8151801515811461287757600080fd5b60005b83811015613880578181015183820152602001613868565b83811115612d445750506000910152565b600082516138a3818460208701613865565b9190910192915050565b60208152600082518060208401526138cc816040850160208701613865565b601f01601f1916919091016040019291505056fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a2646970667358221220ef72ab563752f2c2def7be1656915aca7e472bf440aeb68879dd5a46b322691664736f6c6343000809003354686520626f6f7374657220746f6b656e206d75737420626520646966666572000000000000000000000000e1c110e1b1b4a1ded0caf3e42bfbdbb7b5d7ce1c00000000000000000000000049defc77d9b33af88b44777a4f985fc184be646700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000375f0000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Deployed ByteCode Sourcemap

32473:18108:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35255:198;;;;;;:::i;:::-;;:::i;:::-;;;552:25:1;;;540:2;525:18;35255:198:0;;;;;;;;32974:42;;;;;;:::i;:::-;;;;;;;;;;;;;;40839:1198;;;:::i;:::-;;36349:122;;;;;;:::i;:::-;;:::i;48816:113::-;;;;;;:::i;:::-;-1:-1:-1;;;;;48903:18:0;48876:7;48903:18;;;:9;:18;;;;;;;48816:113;33513:24;;;;;;34557:93;34630:12;;34557:93;;35461:121;;;:::i;39177:422::-;;;:::i;42361:458::-;;;:::i;37982:115::-;;;;;;:::i;:::-;;:::i;33381:28::-;;;;;;:::i;:::-;;:::i;32793:30::-;;;;;;35964:226;;;;;;:::i;:::-;;:::i;38858:307::-;;;:::i;45937:63::-;;;:::i;45261:239::-;;;;;;:::i;:::-;;:::i;44754:121::-;;;;;;:::i;:::-;;:::i;38109:99::-;;;;;;:::i;:::-;;:::i;33029:26::-;;;;;-1:-1:-1;;;;;33029:26:0;;;;;;-1:-1:-1;;;;;1210:55:1;;;1192:74;;1180:2;1165:18;33029:26:0;1032:240:1;28911:86:0;28982:7;;-1:-1:-1;;;28982:7:0;;;;28911:86;;1442:14:1;;1435:22;1417:41;;1405:2;1390:18;28911:86:0;1277:187:1;33156:64:0;;;;;;:::i;:::-;;;;;;;;;;;;;;35594:358;;;:::i;33101:42::-;;;;;;39611:393;;;:::i;34658:112::-;;;;;;:::i;:::-;-1:-1:-1;;;;;34744:18:0;34717:7;34744:18;;;:9;:18;;;;;;;34658:112;31752:94;;;:::i;32694:26::-;;;;;-1:-1:-1;;;;;32694:26:0;;;46042:179;;;;;;:::i;:::-;;:::i;40230:419::-;;;;;;:::i;:::-;;:::i;32761:25::-;;;;;;34778:131;;;:::i;45870:59::-;;;:::i;42045:304::-;;;;;;:::i;:::-;;:::i;32910:57::-;;;;;;:::i;:::-;;;;;;;;;;;;;;40661:166;;;;;;:::i;:::-;;:::i;31101:87::-;31174:6;;-1:-1:-1;;;;;31174:6:0;31101:87;;33416:34;;;;;;:::i;:::-;;:::i;45512:346::-;;;;;;:::i;:::-;;:::i;43658:330::-;;;;;;:::i;:::-;;:::i;44334:408::-;;;;;;:::i;:::-;;:::i;36483:354::-;;;;;;:::i;:::-;;:::i;36899:438::-;;;;;;:::i;:::-;;:::i;33062:32::-;;;;;;33457:49;;;;;;:::i;:::-;;;;;;;;;;;;;;32830:29;;;;;;44000:292;;;;;;:::i;:::-;;:::i;34917:330::-;;;:::i;43361:170::-;;;:::i;32661:26::-;;;;;-1:-1:-1;;;;;32661:26:0;;;33340:28;;;;;;48941:101;;;;;;:::i;:::-;;:::i;32866:35::-;;;;;;40012:150;;;:::i;43539:107::-;;;;;;:::i;:::-;;:::i;32727:27::-;;;;;;37349:621;;;;;;:::i;:::-;;:::i;33227:49::-;;;;;;:::i;:::-;;;;;;;;;;;;;;32001:192;;;;;;:::i;:::-;;:::i;36202:135::-;;;:::i;44887:344::-;;;;;;:::i;:::-;;:::i;42831:522::-;;;:::i;33289:44::-;;;;;;:::i;:::-;;;;;;;;;;;;;;35255:198;-1:-1:-1;;;;;35428:16:0;;35309:7;35428:16;;;:7;:16;;;;;;;;;35380:22;:31;;;;;;35336:109;;35428:16;35336:87;;35418:4;;35336:77;;35359:53;;:16;:14;:16::i;:::-;:20;;:53::i;:::-;-1:-1:-1;;;;;35336:18:0;;;;;;:9;:18;;;;;;;:22;:77::i;:::-;:81;;:87::i;:::-;:91;;:109::i;:::-;35329:116;35255:198;-1:-1:-1;;35255:198:0:o;40839:1198::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;;;;;;;;;28982:7;;-1:-1:-1;;;28982:7:0;;;;29236:9:::1;29228:38;;;::::0;-1:-1:-1;;;29228:38:0;;6207:2:1;29228:38:0::1;::::0;::::1;6189:21:1::0;6246:2;6226:18;;;6219:30;-1:-1:-1;;;6265:18:1;;;6258:46;6321:18;;29228:38:0::1;6005:340:1::0;29228:38:0::1;40933:12:::2;;40915:15;:30;40907:107;;;::::0;;-1:-1:-1;;;40907:107:0;;6552:2:1;40907:107:0::2;::::0;::::2;6534:21:1::0;6571:18;;;6564:30;;;;6630:34;6610:18;;;6603:62;6701:34;6681:18;;;6674:62;6753:19;;40907:107:0::2;6350:428:1::0;40907:107:0::2;41035:20;41066:27:::0;41110:12:::2;;41126:1;41110:17;41106:525;;;41159:12;::::0;:37:::2;::::0;-1:-1:-1;;;41159:37:0;;41190:4:::2;41159:37;::::0;::::2;1192:74:1::0;-1:-1:-1;;;;;41159:12:0;;::::2;::::0;:22:::2;::::0;1165:18:1;;41159:37:0::2;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41223:12;::::0;41144:52;;-1:-1:-1;;;;;;41223:12:0::2;41215:35:::0;41211:199:::2;;41293:12;::::0;:37:::2;::::0;-1:-1:-1;;;41293:37:0;;41324:4:::2;41293:37;::::0;::::2;1192:74:1::0;-1:-1:-1;;;;;41293:12:0;;::::2;::::0;:22:::2;::::0;1165:18:1;;41293:37:0::2;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41271:59;;41106:525;;41211:199;-1:-1:-1::0;41393:1:0::2;41106:525;;;41462:12;::::0;41442:17:::2;::::0;41462:33:::2;::::0;41479:15:::2;41462:16;:33::i;:::-;41525:10;::::0;41442:53;;-1:-1:-1;41525:25:0::2;::::0;41442:53;41525:14:::2;:25::i;:::-;41587:17;::::0;41510:40;;-1:-1:-1;41587:32:0::2;::::0;41609:9;41587:21:::2;:32::i;:::-;41565:54;;41427:204;41106:525;41658:15;41643:12;:30:::0;41688:16;;41684:97:::2;;41721:48;41747:7;31174:6:::0;;-1:-1:-1;;;;;31174:6:0;;31101:87;41747:7:::2;41721:12;::::0;-1:-1:-1;;;;;41721:12:0::2;::::0;41756;41721:25:::2;:48::i;:::-;41803:12;::::0;-1:-1:-1;;;;;41803:12:0::2;41795:35:::0;;::::2;::::0;:62:::2;;;41856:1;41834:19;:23;41795:62;41791:150;;;41874:55;41900:7;31174:6:::0;;-1:-1:-1;;;;;31174:6:0;;31101:87;41900:7:::2;41874:12;::::0;-1:-1:-1;;;;;41874:12:0::2;::::0;41909:19;41874:25:::2;:55::i;:::-;41961:8;:6;:8::i;:::-;41995:34;::::0;552:25:1;;;41995:34:0::2;::::0;540:2:1;525:18;41995:34:0::2;;;;;;;;40896:1141;;40839:1198::o:0;36349:122::-;-1:-1:-1;;;;;36444:18:0;;36404:7;36444:18;;;:9;:18;;;;;;36431:32;;36435:7;;36431:3;:32::i;35461:121::-;35516:7;35543:31;35558:15;;35543:10;;:14;;:31;;;;:::i;:::-;35536:38;;35461:121;:::o;39177:422::-;17846:1;18442:7;;:19;;18434:63;;;;-1:-1:-1;;;18434:63:0;;7174:2:1;18434:63:0;;;7156:21:1;7213:2;7193:18;;;7186:30;7252:33;7232:18;;;7225:61;7303:18;;18434:63:0;6972:355:1;18434:63:0;17846:1;18575:7;:18;39238:10:::1;49168:16;:14;:16::i;:::-;49145:20;:39:::0;49225:23:::1;:21;:23::i;:::-;49195:27;:53:::0;49276:26:::1;:24;:26::i;:::-;49259:14;:43:::0;-1:-1:-1;;;;;49317:21:0;::::1;::::0;49313:303:::1;;49374:15;49381:7;49374:6;:15::i;:::-;-1:-1:-1::0;;;;;49355:16:0;::::1;;::::0;;;:7:::1;:16;::::0;;;;;;;:34;;;;49438:20:::1;::::0;49404:22:::1;:31:::0;;;;;;:54;49499:22:::1;49363:7:::0;49499:13:::1;:22::i;:::-;-1:-1:-1::0;;;;;49473:23:0;::::1;;::::0;;;:14:::1;:23;::::0;;;;;;;:48;;;;49577:27:::1;::::0;49536:29:::1;:38:::0;;;;;;:68;49313:303:::1;39273:12:::2;::::0;-1:-1:-1;;;;;39273:12:0::2;39265:35:::0;39261:331:::2;;39349:10;39317:14;39334:26:::0;;;:14:::2;:26;::::0;;;;;39379:10;;39375:206:::2;;39425:10;39439:1;39410:26:::0;;;:14:::2;:26;::::0;;;;:30;39459:12:::2;::::0;:45:::2;::::0;-1:-1:-1;;;;;39459:12:0;;::::2;::::0;39497:6;39459:25:::2;:45::i;:::-;39528:37;::::0;552:25:1;;;39546:10:0::2;::::0;39528:37:::2;::::0;540:2:1;525:18;39528:37:0::2;;;;;;;;39375:206;39302:290;39261:331;-1:-1:-1::0;17802:1:0;18754:7;:22;39177:422::o;42361:458::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;42432:12:::1;::::0;:17;:49;::::1;;;-1:-1:-1::0;42469:12:0::1;::::0;42453::::1;::::0;-1:-1:-1;;;;;42453:12:0;;::::1;42469::::0;::::1;42453:28;42432:49;42424:156;;;::::0;-1:-1:-1;;;42424:156:0;;7534:2:1;42424:156:0::1;::::0;::::1;7516:21:1::0;7573:2;7553:18;;;7546:30;7612:34;7592:18;;;7585:62;7683:34;7663:18;;;7656:62;7755:32;7734:19;;;7727:61;7805:19;;42424:156:0::1;7332:498:1::0;42424:156:0::1;42614:12;::::0;:37:::1;::::0;-1:-1:-1;;;42614:37:0;;42645:4:::1;42614:37;::::0;::::1;1192:74:1::0;42591:20:0::1;::::0;-1:-1:-1;;;;;42614:12:0::1;::::0;:22:::1;::::0;1165:18:1;;42614:37:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42591:60:::0;-1:-1:-1;42666:16:0;;42662:97:::1;;42699:48;42725:7;31174:6:::0;;-1:-1:-1;;;;;31174:6:0;;31101:87;42725:7:::1;42699:12;::::0;-1:-1:-1;;;;;42699:12:0::1;::::0;42734;42699:25:::1;:48::i;:::-;42774:37;::::0;552:25:1;;;42774:37:0::1;::::0;540:2:1;525:18;42774:37:0::1;;;;;;;;42413:406;42361:458::o:0;37982:115::-;17846:1;18442:7;;:19;;18434:63;;;;-1:-1:-1;;;18434:63:0;;7174:2:1;18434:63:0;;;7156:21:1;7213:2;7193:18;;;7186:30;7252:33;7232:18;;;7225:61;7303:18;;18434:63:0;6972:355:1;18434:63:0;17846:1;18575:7;:18;38049:10:::1;49168:16;:14;:16::i;:::-;49145:20;:39:::0;49225:23:::1;:21;:23::i;:::-;49195:27;:53:::0;49276:26:::1;:24;:26::i;:::-;49259:14;:43:::0;-1:-1:-1;;;;;49317:21:0;::::1;::::0;49313:303:::1;;49374:15;49381:7;49374:6;:15::i;:::-;-1:-1:-1::0;;;;;49355:16:0;::::1;;::::0;;;:7:::1;:16;::::0;;;;;;;:34;;;;49438:20:::1;::::0;49404:22:::1;:31:::0;;;;;;:54;49499:22:::1;49363:7:::0;49499:13:::1;:22::i;:::-;-1:-1:-1::0;;;;;49473:23:0;::::1;;::::0;;;:14:::1;:23;::::0;;;;;;;:48;;;;49577:27:::1;::::0;49536:29:::1;:38:::0;;;;;;:68;49313:303:::1;38072:17:::2;38082:6;38072:9;:17::i;33381:28::-:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33381:28:0;:::o;35964:226::-;-1:-1:-1;;;;;36158:23:0;;36025:7;36158:23;;;:14;:23;;;;;;;;;36103:29;:38;;;;;;36052:130;;36158:23;36052:101;;36148:4;;36052:91;;36075:67;;:23;:21;:23::i;38858:307::-;17846:1;18442:7;;:19;;18434:63;;;;-1:-1:-1;;;18434:63:0;;7174:2:1;18434:63:0;;;7156:21:1;7213:2;7193:18;;;7186:30;7252:33;7232:18;;;7225:61;7303:18;;18434:63:0;6972:355:1;18434:63:0;17846:1;18575:7;:18;38912:10:::1;49168:16;:14;:16::i;:::-;49145:20;:39:::0;49225:23:::1;:21;:23::i;:::-;49195:27;:53:::0;49276:26:::1;:24;:26::i;:::-;49259:14;:43:::0;-1:-1:-1;;;;;49317:21:0;::::1;::::0;49313:303:::1;;49374:15;49381:7;49374:6;:15::i;:::-;-1:-1:-1::0;;;;;49355:16:0;::::1;;::::0;;;:7:::1;:16;::::0;;;;;;;:34;;;;49438:20:::1;::::0;49404:22:::1;:31:::0;;;;;;:54;49499:22:::1;49363:7:::0;49499:13:::1;:22::i;:::-;-1:-1:-1::0;;;;;49473:23:0;::::1;;::::0;;;:14:::1;:23;::::0;;;;;;;:48;;;;49577:27:::1;::::0;49536:29:::1;:38:::0;;;;;;:68;49313:303:::1;38960:10:::2;38935:14;38952:19:::0;;;:7:::2;:19;::::0;;;;;38986:10;;38982:176:::2;;39021:10;39035:1;39013:19:::0;;;:7:::2;:19;::::0;;;;:23;39051:12:::2;::::0;:45:::2;::::0;-1:-1:-1;;;;;39051:12:0;;::::2;::::0;39089:6;39051:25:::2;:45::i;:::-;39116:30;::::0;552:25:1;;;39127:10:0::2;::::0;39116:30:::2;::::0;540:2:1;525:18;39116:30:0::2;406:177:1::0;45937:63:0;45982:10;:8;:10::i;:::-;45937:63::o;45261:239::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;-1:-1:-1;;;;;45380:15:0;::::1;;::::0;;;:9:::1;:15;::::0;;;;;45362:13:::1;::::0;:34:::1;::::0;:17:::1;:34::i;:::-;45346:13;:50:::0;;;-1:-1:-1;;;;;45407:15:0;::::1;;::::0;;;:9:::1;:15;::::0;;;;:24;;;45458:13;:34:::1;::::0;45425:6;45458:17:::1;:34::i;:::-;45442:13;:50:::0;-1:-1:-1;;45261:239:0:o;44754:121::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;-1:-1:-1;;;;;44838:20:0;;::::1;;::::0;;;:14:::1;:20;::::0;;;;:29;44754:121::o;38109:99::-;17846:1;18442:7;;:19;;18434:63;;;;-1:-1:-1;;;18434:63:0;;7174:2:1;18434:63:0;;;7156:21:1;7213:2;7193:18;;;7186:30;7252:33;7232:18;;;7225:61;7303:18;;18434:63:0;6972:355:1;18434:63:0;17846:1;18575:7;:18;38183:17:::1;38193:6:::0;38183:9:::1;:17::i;35594:358::-:0;35648:7;35672:12;;35688:1;35672:17;35668:84;;;-1:-1:-1;35713:27:0;;;35594:358::o;35668:84::-;35782:162;35832:97;35916:12;;35832:79;35906:4;35832:69;35883:17;;35832:46;35863:14;;35832:26;:24;:26::i;:46::-;:50;;:69::i;:97::-;35782:27;;;:31;:162::i;39611:393::-;17846:1;18442:7;;:19;;18434:63;;;;-1:-1:-1;;;18434:63:0;;7174:2:1;18434:63:0;;;7156:21:1;7213:2;7193:18;;;7186:30;7252:33;7232:18;;;7225:61;7303:18;;18434:63:0;6972:355:1;18434:63:0;17846:1;18575:7;:18;;;39700:10:::1;39690:21:::0;;:9:::1;:21;::::0;;;;;39726:18;;39722:275:::1;;39805:10;39795:21;::::0;;;:9:::1;:21;::::0;;;;;39777:13:::1;::::0;:40:::1;::::0;:17:::1;:40::i;:::-;39761:13;:56:::0;39842:10:::1;39856:1;39832:21:::0;;;:9:::1;:21;::::0;;;;:25;39872:12:::1;::::0;:53:::1;::::0;-1:-1:-1;;;;;39872:12:0;;::::1;::::0;39910:14;39872:25:::1;:53::i;:::-;39945:40;::::0;552:25:1;;;39958:10:0::1;::::0;39945:40:::1;::::0;540:2:1;525:18;39945:40:0::1;;;;;;;-1:-1:-1::0;17802:1:0;18754:7;:22;39611:393::o;31752:94::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;31817:21:::1;31835:1;31817:9;:21::i;46042:179::-:0;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;46164:49:::1;46183:12;46197:15;46164:18;:49::i;:::-;46042:179:::0;;:::o;40230:419::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;40355:61:::1;40385:7;31174:6:::0;;-1:-1:-1;;;;;31174:6:0;;31101:87;40385:7:::1;40355:12;::::0;-1:-1:-1;;;;;40355:12:0::1;::::0;40402:4:::1;40409:6:::0;40355:29:::1;:61::i;:::-;40439:12;::::0;-1:-1:-1;;;;;40439:12:0::1;40431:35:::0;;::::1;::::0;:56:::1;;;40486:1;40470:13;:17;40431:56;40427:157;;;40504:68;40534:7;31174:6:::0;;-1:-1:-1;;;;;31174:6:0;;31101:87;40534:7:::1;40504:12;::::0;-1:-1:-1;;;;;40504:12:0::1;::::0;40551:4:::1;40558:13:::0;40504:29:::1;:68::i;:::-;40594:47;40609:6;40617:13;40632:8;40594:14;:47::i;:::-;40230:419:::0;;;:::o;34778:131::-;34835:7;34862:39;34871:15;34888:12;;34862:8;:39::i;45870:59::-;45913:8;:6;:8::i;42045:304::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;42172:12:::1;::::0;-1:-1:-1;;;;;42148:37:0;;::::1;42172:12:::0;::::1;42148:37;;42140:83;;;::::0;-1:-1:-1;;;42140:83:0;;8037:2:1;42140:83:0::1;::::0;::::1;8019:21:1::0;8076:2;8056:18;;;8049:30;8115:34;8095:18;;;8088:62;8186:3;8166:18;;;8159:31;8207:19;;42140:83:0::1;7835:397:1::0;42140:83:0::1;42234:55;42268:7;31174:6:::0;;-1:-1:-1;;;;;31174:6:0;;31101:87;42268:7:::1;-1:-1:-1::0;;;;;42234:33:0;::::1;::::0;42277:11;42234:33:::1;:55::i;:::-;42305:36;::::0;;-1:-1:-1;;;;;8429:55:1;;8411:74;;8516:2;8501:18;;8494:34;;;42305:36:0::1;::::0;8384:18:1;42305:36:0::1;8237:297:1::0;40661:166:0;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;33416:34:0;;;;;;;;;;;;45512:346;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;45652:7:::1;:14;45632:9;:16;:34;45624:104;;;::::0;-1:-1:-1;;;45624:104:0;;8741:2:1;45624:104:0::1;::::0;::::1;8723:21:1::0;8780:2;8760:18;;;8753:30;8819:34;8799:18;;;8792:62;8890:27;8870:18;;;8863:55;8935:19;;45624:104:0::1;8539:421:1::0;45624:104:0::1;45744:6;45739:112;45758:9;:16;45754:1;:20;45739:112;;;45796:43;45814:9;45824:1;45814:12;;;;;;;;:::i;:::-;;;;;;;45828:7;45836:1;45828:10;;;;;;;;:::i;:::-;;;;;;;45796:17;:43::i;:::-;45776:3;::::0;::::1;:::i;:::-;;;45739:112;;43658:330:::0;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;43790:7:::1;:14;43770:9;:16;:34;43762:104;;;::::0;-1:-1:-1;;;43762:104:0;;8741:2:1;43762:104:0::1;::::0;::::1;8723:21:1::0;8780:2;8760:18;;;8753:30;8819:34;8799:18;;;8792:62;8890:27;8870:18;;;8863:55;8935:19;;43762:104:0::1;8539:421:1::0;43762:104:0::1;43882:6;43877:104;43896:9;:16;43892:1;:20;43877:104;;;43934:35;43944:9;43954:1;43944:12;;;;;;;;:::i;:::-;;;;;;;43958:7;43966:1;43958:10;;;;;;;;:::i;:::-;;;;;;;43934:9;:35::i;:::-;43914:3;::::0;::::1;:::i;:::-;;;43877:104;;44334:408:::0;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;44445:12:::1;::::0;-1:-1:-1;;;;;44420:38:0;;::::1;44445:12:::0;::::1;44420:38;;44412:108;;;::::0;-1:-1:-1;;;44412:108:0;;9685:2:1;44412:108:0::1;::::0;::::1;9667:21:1::0;9724:2;9704:18;;;9697:30;9763:34;9743:18;;;9736:62;9834:27;9814:18;;;9807:55;9879:19;;44412:108:0::1;9483:421:1::0;44412:108:0::1;44564:12;::::0;-1:-1:-1;;;;;44539:38:0;;::::1;44564:12:::0;::::1;44539:38;;44531:109;;;::::0;-1:-1:-1;;;44531:109:0;;10111:2:1;44531:109:0::1;::::0;::::1;10093:21:1::0;10150:2;10130:18;;;10123:30;10189:34;10169:18;;;10162:62;10260:28;10240:18;;;10233:56;10306:19;;44531:109:0::1;9909:422:1::0;44531:109:0::1;44651:12;:36:::0;;-1:-1:-1;;44651:36:0::1;-1:-1:-1::0;;;;;44651:36:0;::::1;::::0;;::::1;::::0;;;44703:31:::1;::::0;1192:74:1;;;44703:31:0::1;::::0;1180:2:1;1165:18;44703:31:0::1;1032:240:1::0;36483:354:0;36560:7;;36580:231;36599:11;:18;36595:22;;36580:231;;;36690:11;36702:1;36690:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;36663:23:0;;;;:14;:23;;;;;;;;36643:44;;:15;;:19;:44::i;:::-;:61;36639:161;;;36732:52;36779:4;36732:42;36753:17;36771:1;36753:20;;;;;;;;:::i;:::-;;;;;;;;;36732:16;:20;;:42;;;;:::i;:52::-;36725:59;;;;;36639:161;36619:3;;;:::i;:::-;;;36580:231;;;-1:-1:-1;36828:1:0;;36483:354;-1:-1:-1;;;36483:354:0:o;36899:438::-;17846:1;18442:7;;:19;;18434:63;;;;-1:-1:-1;;;18434:63:0;;7174:2:1;18434:63:0;;;7156:21:1;7213:2;7193:18;;;7186:30;7252:33;7232:18;;;7225:61;7303:18;;18434:63:0;6972:355:1;18434:63:0;17846:1;18575:7;:18;28982:7;;-1:-1:-1;;;28982:7:0;;;;29236:9:::1;29228:38;;;::::0;-1:-1:-1;;;29228:38:0;;6207:2:1;29228:38:0::1;::::0;::::1;6189:21:1::0;6246:2;6226:18;;;6219:30;-1:-1:-1;;;6265:18:1;;;6258:46;6321:18;;29228:38:0::1;6005:340:1::0;29228:38:0::1;36979:10:::2;49168:16;:14;:16::i;:::-;49145:20;:39:::0;49225:23:::2;:21;:23::i;:::-;49195:27;:53:::0;49276:26:::2;:24;:26::i;:::-;49259:14;:43:::0;-1:-1:-1;;;;;49317:21:0;::::2;::::0;49313:303:::2;;49374:15;49381:7;49374:6;:15::i;:::-;-1:-1:-1::0;;;;;49355:16:0;::::2;;::::0;;;:7:::2;:16;::::0;;;;;;;:34;;;;49438:20:::2;::::0;49404:22:::2;:31:::0;;;;;;:54;49499:22:::2;49363:7:::0;49499:13:::2;:22::i;:::-;-1:-1:-1::0;;;;;49473:23:0;::::2;;::::0;;;:14:::2;:23;::::0;;;;;;;:48;;;;49577:27:::2;::::0;49536:29:::2;:38:::0;;;;;;:68;49313:303:::2;37019:1:::3;37010:6;:10;37002:37;;;::::0;-1:-1:-1;;;37002:37:0;;10538:2:1;37002:37:0::3;::::0;::::3;10520:21:1::0;10577:2;10557:18;;;10550:30;10616:16;10596:18;;;10589:44;10650:18;;37002:37:0::3;10336:338:1::0;37002:37:0::3;37065:12;::::0;:24:::3;::::0;37082:6;37065:16:::3;:24::i;:::-;37050:12;:39:::0;37134:10:::3;37124:21;::::0;;;:9:::3;:21;::::0;;;;;:33:::3;::::0;37150:6;37124:25:::3;:33::i;:::-;37110:10;37100:21;::::0;;;:9:::3;:21;::::0;;;;:57;;;;37168:12:::3;::::0;:64:::3;::::0;-1:-1:-1;;;;;37168:12:0;;::::3;::::0;37218:4:::3;37225:6:::0;37168:29:::3;:64::i;:::-;37258:10;37243:26;::::0;;;:14:::3;:26;::::0;;;;;;37272:15:::3;37243:44:::0;;37303:26;::::3;::::0;::::3;::::0;37322:6;552:25:1;;540:2;525:18;;406:177;44000:292:0;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;44116:12:::1;;44098:15;:30;44076:168;;;::::0;-1:-1:-1;;;44076:168:0;;10881:2:1;44076:168:0::1;::::0;::::1;10863:21:1::0;10920:2;10900:18;;;10893:30;10959:34;10939:18;;;10932:62;11030:34;11010:18;;;11003:62;11102:26;11081:19;;;11074:55;11146:19;;44076:168:0::1;10679:492:1::0;44076:168:0::1;44255:29;44275:8;44255:19;:29::i;:::-;44000:292:::0;:::o;34917:330::-;34964:7;34988:12;;35004:1;34988:17;34984:77;;;-1:-1:-1;35029:20:0;;;34917:330::o;34984:77::-;35091:148;35134:90;35211:12;;35134:72;35201:4;35134:62;35185:10;;35134:46;35165:14;;35134:26;:24;:26::i;:90::-;35091:20;;;:24;:148::i;43361:170::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;43414:45:::1;43440:7;31174:6:::0;;-1:-1:-1;;;;;31174:6:0;;31101:87;43440:7:::1;43449:9;::::0;43414:12:::1;::::0;-1:-1:-1;;;;;43414:12:0::1;::::0;:45;:25:::1;:45::i;:::-;43475:24;43489:9;;43475:24;;;;552:25:1::0;;540:2;525:18;;406:177;43475:24:0::1;;;;;;;;43522:1;43510:9;:13:::0;43361:170::o;48941:101::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;49008:14:::1;:26:::0;48941:101::o;40012:150::-;40067:10;40057:21;;;;:9;:21;;;;;;40048:31;;:8;:31::i;:::-;40090:11;:9;:11::i;:::-;40112:18;:16;:18::i;:::-;40141:13;:11;:13::i;43539:107::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;-1:-1:-1;;;;;43616:13:0;;::::1;;::::0;;;:7:::1;:13;::::0;;;;:22;43539:107::o;37349:621::-;17846:1;18442:7;;:19;;18434:63;;;;-1:-1:-1;;;18434:63:0;;7174:2:1;18434:63:0;;;7156:21:1;7213:2;7193:18;;;7186:30;7252:33;7232:18;;;7225:61;7303:18;;18434:63:0;6972:355:1;18434:63:0;17846:1;18575:7;:18;28982:7;;-1:-1:-1;;;28982:7:0;;;;29236:9:::1;29228:38;;;::::0;-1:-1:-1;;;29228:38:0;;6207:2:1;29228:38:0::1;::::0;::::1;6189:21:1::0;6246:2;6226:18;;;6219:30;-1:-1:-1;;;6265:18:1;;;6258:46;6321:18;;29228:38:0::1;6005:340:1::0;29228:38:0::1;37485:10:::2;49168:16;:14;:16::i;:::-;49145:20;:39:::0;49225:23:::2;:21;:23::i;:::-;49195:27;:53:::0;49276:26:::2;:24;:26::i;:::-;49259:14;:43:::0;-1:-1:-1;;;;;49317:21:0;::::2;::::0;49313:303:::2;;49374:15;49381:7;49374:6;:15::i;:::-;-1:-1:-1::0;;;;;49355:16:0;::::2;;::::0;;;:7:::2;:16;::::0;;;;;;;:34;;;;49438:20:::2;::::0;49404:22:::2;:31:::0;;;;;;:54;49499:22:::2;49363:7:::0;49499:13:::2;:22::i;:::-;-1:-1:-1::0;;;;;49473:23:0;::::2;;::::0;;;:14:::2;:23;::::0;;;;;;;:48;;;;49577:27:::2;::::0;49536:29:::2;:38:::0;;;;;;:68;49313:303:::2;37525:1:::3;37516:6;:10;37508:37;;;::::0;-1:-1:-1;;;37508:37:0;;10538:2:1;37508:37:0::3;::::0;::::3;10520:21:1::0;10577:2;10557:18;;;10550:30;10616:16;10596:18;;;10589:44;10650:18;;37508:37:0::3;10336:338:1::0;37508:37:0::3;37571:12;::::0;:24:::3;::::0;37588:6;37571:16:::3;:24::i;:::-;37556:12;:39:::0;37640:10:::3;37630:21;::::0;;;:9:::3;:21;::::0;;;;;:33:::3;::::0;37656:6;37630:25:::3;:33::i;:::-;37616:10;37606:21;::::0;;;:9:::3;:21;::::0;;;;;;:57;;;;37713:12:::3;::::0;37695:93;;;;;::::3;::::0;::::3;11548:34:1::0;;;;37755:4:0::3;11598:18:1::0;;;11591:43;11650:18;;;11643:34;;;11693:18;;;11686:34;;;11769:4;11757:17;;11736:19;;;11729:46;11791:19;;;11784:35;;;11835:19;;;11828:35;;;-1:-1:-1;;;;;37713:12:0;;::::3;::::0;37695:39:::3;::::0;11459:19:1;;37695:93:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;-1:-1:-1::0;;37801:12:0::3;::::0;:64:::3;::::0;-1:-1:-1;;;;;;37801:12:0::3;::::0;-1:-1:-1;37831:10:0::3;37851:4;37858:6:::0;37801:29:::3;:64::i;:::-;37891:10;37876:26;::::0;;;:14:::3;:26;::::0;;;;;;37905:15:::3;37876:44:::0;;37936:26;::::3;::::0;::::3;::::0;37955:6;552:25:1;;540:2;525:18;;406:177;37936:26:0::3;;;;;;;;-1:-1:-1::0;;17802:1:0;18754:7;:22;-1:-1:-1;;;;37349:621:0:o;32001:192::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;-1:-1:-1;;;;;32090:22:0;::::1;32082:73;;;::::0;-1:-1:-1;;;32082:73:0;;12076:2:1;32082:73:0::1;::::0;::::1;12058:21:1::0;12115:2;12095:18;;;12088:30;12154:34;12134:18;;;12127:62;12225:8;12205:18;;;12198:36;12251:19;;32082:73:0::1;11874:402:1::0;32082:73:0::1;32166:19;32176:8;32166:9;:19::i;36202:135::-:0;36264:7;36291:38;36313:15;;36291:17;;:21;;:38;;;;:::i;44887:344::-;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;45026:7:::1;:14;45006:9;:16;:34;44998:104;;;::::0;-1:-1:-1;;;44998:104:0;;8741:2:1;44998:104:0::1;::::0;::::1;8723:21:1::0;8780:2;8760:18;;;8753:30;8819:34;8799:18;;;8792:62;8890:27;8870:18;;;8863:55;8935:19;;44998:104:0::1;8539:421:1::0;44998:104:0::1;45118:6;45113:111;45132:9;:16;45128:1;:20;45113:111;;;45170:42;45187:9;45197:1;45187:12;;;;;;;;:::i;:::-;;;;;;;45201:7;45209:1;45201:10;;;;;;;;:::i;:::-;;;;;;;45170:16;:42::i;:::-;45150:3;::::0;::::1;:::i;:::-;;;45113:111;;42831:522:::0;31174:6;;-1:-1:-1;;;;;31174:6:0;27697:10;31321:23;31313:68;;;;-1:-1:-1;;;31313:68:0;;5846:2:1;31313:68:0;;;5828:21:1;;;5865:18;;;5858:30;-1:-1:-1;;;;;;;;;;;5904:18:1;;;5897:62;5976:18;;31313:68:0;5644:356:1;31313:68:0;42911:12:::1;::::0;-1:-1:-1;;;;;42911:12:0::1;42895:113;;;::::0;-1:-1:-1;;;42895:113:0;;12483:2:1;42895:113:0::1;::::0;::::1;12465:21:1::0;12522:2;12502:18;;;12495:30;12561:34;12541:18;;;12534:62;12632:34;12612:18;;;12605:62;12704:3;12683:19;;;12676:32;12725:19;;42895:113:0::1;12281:469:1::0;42895:113:0::1;43027:12;::::0;:17;43019:94:::1;;;::::0;;-1:-1:-1;;;43019:94:0;;12957:2:1;43019:94:0::1;::::0;::::1;12939:21:1::0;12976:18;;;12969:30;;;;13035:34;13015:18;;;13008:62;13106:34;13086:18;;;13079:62;13158:19;;43019:94:0::1;12755:428:1::0;43019:94:0::1;43147:12;::::0;:37:::1;::::0;-1:-1:-1;;;43147:37:0;;43178:4:::1;43147:37;::::0;::::1;1192:74:1::0;43124:20:0::1;::::0;-1:-1:-1;;;;;43147:12:0::1;::::0;:22:::1;::::0;1165:18:1;;43147:37:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43124:60:::0;-1:-1:-1;43199:16:0;;43195:97:::1;;43232:48;43258:7;31174:6:::0;;-1:-1:-1;;;;;31174:6:0;;31101:87;43232:48:::1;43307:38;::::0;552:25:1;;;43307:38:0::1;::::0;540:2:1;525:18;43307:38:0::1;406:177:1::0;21970:98:0;22028:7;22055:5;22059:1;22055;:5;:::i;:::-;22048:12;21970:98;-1:-1:-1;;;21970:98:0:o;22327:::-;22385:7;22412:5;22416:1;22412;:5;:::i;22726:98::-;22784:7;22811:5;22815:1;22811;:5;:::i;21589:98::-;21647:7;21674:5;21678:1;21674;:5;:::i;12797:211::-;12941:58;;-1:-1:-1;;;;;8429:55:1;;12941:58:0;;;8411:74:1;8501:18;;;8494:34;;;12914:86:0;;12934:5;;12964:23;;8384:18:1;;12941:58:0;;;;-1:-1:-1;;12941:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;12914:19;:86::i;29711:118::-;28982:7;;-1:-1:-1;;;28982:7:0;;;;29236:9;29228:38;;;;-1:-1:-1;;;29228:38:0;;6207:2:1;29228:38:0;;;6189:21:1;6246:2;6226:18;;;6219:30;-1:-1:-1;;;6265:18:1;;;6258:46;6321:18;;29228:38:0;6005:340:1;29228:38:0;29781:4:::1;29771:14:::0;;-1:-1:-1;;;;29771:14:0::1;-1:-1:-1::0;;;29771:14:0::1;::::0;;29801:20:::1;29808:12;27697:10:::0;;27617:98;29808:12:::1;29801:20;::::0;-1:-1:-1;;;;;1210:55:1;;;1192:74;;1180:2;1165:18;29801:20:0::1;;;;;;;29711:118::o:0;38220:626::-;38291:1;38282:6;:10;38274:40;;;;-1:-1:-1;;;38274:40:0;;14105:2:1;38274:40:0;;;14087:21:1;14144:2;14124:18;;;14117:30;14183:19;14163:18;;;14156:47;14220:18;;38274:40:0;13903:341:1;38274:40:0;38340:12;;:24;;38357:6;38340:16;:24::i;:::-;38325:12;:39;38375:20;38398:23;38402:10;38414:6;38398:3;:23::i;:::-;38466:10;38456:21;;;;:9;:21;;;;;;38375:46;;-1:-1:-1;38456:33:0;;38482:6;38456:25;:33::i;:::-;38442:10;38432:21;;;;:9;:21;;;;;:57;;;;38530:24;:6;38541:12;38530:10;:24::i;:::-;38565:12;;38500:54;;-1:-1:-1;38565:58:0;;-1:-1:-1;;;;;38565:12:0;38591:10;38500:54;38565:25;:58::i;:::-;38639:42;;552:25:1;;;38649:10:0;;38639:42;;540:2:1;525:18;38639:42:0;;;;;;;38696:16;;38692:147;;38734:39;;552:25:1;;;38748:10:0;;38734:39;;540:2:1;525:18;38734:39:0;;;;;;;38800:9;;:27;;38814:12;38800:13;:27::i;:::-;38788:9;:39;38263:583;;38220:626;:::o;29970:120::-;28982:7;;-1:-1:-1;;;28982:7:0;;;;29506:41;;;;-1:-1:-1;;;29506:41:0;;14451:2:1;29506:41:0;;;14433:21:1;14490:2;14470:18;;;14463:30;14529:22;14509:18;;;14502:50;14569:18;;29506:41:0;14249:344:1;29506:41:0;30029:7:::1;:15:::0;;-1:-1:-1;;;;30029:15:0::1;::::0;;30060:22:::1;27697:10:::0;30069:12:::1;27617:98:::0;32201:173;32276:6;;;-1:-1:-1;;;;;32293:17:0;;;-1:-1:-1;;32293:17:0;;;;;;;32326:40;;32276:6;;;32293:17;32276:6;;32326:40;;32257:16;;32326:40;32246:128;32201:173;:::o;46432:401::-;46578:18;:25;46555:12;:19;:48;46547:125;;;;;-1:-1:-1;;;46547:125:0;;14800:2:1;46547:125:0;;;14782:21:1;14819:18;;;14812:30;;;;14878:34;14858:18;;;14851:62;14949:34;14929:18;;;14922:62;15001:19;;46547:125:0;14598:428:1;46547:125:0;46683:26;;;;:11;;:26;;;;;:::i;:::-;-1:-1:-1;46720:38:0;;;;:17;;:38;;;;;:::i;:::-;;46774:51;46792:12;46806:18;46774:51;;;;;;;:::i;13016:248::-;13187:68;;-1:-1:-1;;;;;16222:15:1;;;13187:68:0;;;16204:34:1;16274:15;;16254:18;;;16247:43;16306:18;;;16299:34;;;13160:96:0;;13180:5;;13210:27;;16116:18:1;;13187:68:0;15941:398:1;13160:96:0;13016:248;;;;:::o;46891:1867::-;47001:1;49168:16;:14;:16::i;:::-;49145:20;:39;49225:23;:21;:23::i;:::-;49195:27;:53;49276:26;:24;:26::i;:::-;49259:14;:43;-1:-1:-1;;;;;49317:21:0;;;49313:303;;49374:15;49381:7;49374:6;:15::i;:::-;-1:-1:-1;;;;;49355:16:0;;;;;;:7;:16;;;;;;;;:34;;;;49438:20;;49404:22;:31;;;;;;:54;49499:22;49363:7;49499:13;:22::i;:::-;-1:-1:-1;;;;;49473:23:0;;;;;;:14;:23;;;;;;;;:48;;;;49577:27;;49536:29;:38;;;;;;:68;49313:303;47020:12;;47016:74:::1;;47049:29;47069:8;47049:19;:29::i;:::-;47133:12;;47114:15;:31;47110:550;;47186:15;::::0;47175:27:::1;::::0;:6;;:10:::1;:27::i;:::-;47162:10;:40:::0;47255:15:::1;::::0;47237:34:::1;::::0;:13;;:17:::1;:34::i;:::-;47217:17;:54:::0;47110:550:::1;;;47324:12;::::0;47304:17:::1;::::0;47324:33:::1;::::0;47341:15:::1;47324:16;:33::i;:::-;47304:53;;47372:16;47391:25;47405:10;;47391:9;:13;;:25;;;;:::i;:::-;47469:15;::::0;47372:44;;-1:-1:-1;47444:41:0::1;::::0;:20:::1;:6:::0;47372:44;47444:10:::1;:20::i;:41::-;47431:10;:54:::0;47540:17:::1;::::0;47500:23:::1;::::0;47526:32:::1;::::0;:9;;:13:::1;:32::i;:::-;47632:15;::::0;47500:58;;-1:-1:-1;47593:55:0::1;::::0;:34:::1;:13:::0;47500:58;47593:17:::1;:34::i;:55::-;47573:17;:75:::0;-1:-1:-1;;;47110:550:0::1;48043:12;::::0;:37:::1;::::0;-1:-1:-1;;;48043:37:0;;48074:4:::1;48043:37;::::0;::::1;1192:74:1::0;48028:12:0::1;::::0;-1:-1:-1;;;;;48043:12:0::1;::::0;:22:::1;::::0;1165:18:1;;48043:37:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48028:52;;48113:28;48125:15;;48113:7;:11;;:28;;;;:::i;:::-;48099:10;;:42;;:140;;;-1:-1:-1::0;48162:12:0::1;::::0;48146::::1;::::0;-1:-1:-1;;;;;48146:12:0;;::::1;48162::::0;::::1;48146:28;:92:::0;::::1;;;;48192:46;48225:12;;48192:28;48204:15;;48192:7;:11;;:28;;;;:::i;:46::-;48178:10;;:60;;48146:92;48091:177;;;::::0;-1:-1:-1;;;48091:177:0;;16546:2:1;48091:177:0::1;::::0;::::1;16528:21:1::0;16585:2;16565:18;;;16558:30;16624:26;16604:18;;;16597:54;16668:18;;48091:177:0::1;16344:348:1::0;48091:177:0::1;48301:12;::::0;-1:-1:-1;;;;;48301:12:0::1;48293:35:::0;48289:243:::1;;48367:12;::::0;:37:::1;::::0;-1:-1:-1;;;48367:37:0;;48398:4:::1;48367:37;::::0;::::1;1192:74:1::0;48345:19:0::1;::::0;-1:-1:-1;;;;;48367:12:0::1;::::0;:22:::1;::::0;1165:18:1;;48367:37:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48345:59;;48448:35;48467:15;;48448:14;:18;;:35;;;;:::i;:::-;48427:17;;:56;;48419:101;;;::::0;-1:-1:-1;;;48419:101:0;;16899:2:1;48419:101:0::1;::::0;::::1;16881:21:1::0;;;16918:18;;;16911:30;16977:34;16957:18;;;16950:62;17029:18;;48419:101:0::1;16697:356:1::0;48419:101:0::1;48330:202;48289:243;48561:15;48544:14;:32:::0;;;48622:15:::1;::::0;48602:36:::1;::::0;48561:15;48602:19:::1;:36::i;:::-;48587:12;:51:::0;48659:10:::1;:8;:10::i;:::-;48695:55;::::0;;17260:25:1;;;17316:2;17301:18;;17294:34;;;17344:18;;;17337:34;;;48695:55:0::1;::::0;17248:2:1;17233:18;48695:55:0::1;;;;;;;47005:1753;46891:1867:::0;;;;:::o;26194:106::-;26252:7;26283:1;26279;:5;:13;;26291:1;26279:13;;;-1:-1:-1;26287:1:0;;26194:106;-1:-1:-1;26194:106:0:o;46265:155::-;46331:15;:26;;;46373:39;;552:25:1;;;46373:39:0;;540:2:1;525:18;46373:39:0;406:177:1;15370:716:0;15794:23;15820:69;15848:4;15820:69;;;;;;;;;;;;;;;;;15828:5;-1:-1:-1;;;;;15820:27:0;;;:69;;;;;:::i;:::-;15904:17;;15794:95;;-1:-1:-1;15904:21:0;15900:179;;16001:10;15990:30;;;;;;;;;;;;:::i;:::-;15982:85;;;;-1:-1:-1;;;15982:85:0;;17866:2:1;15982:85:0;;;17848:21:1;17905:2;17885:18;;;17878:30;17944:34;17924:18;;;17917:62;18015:12;17995:18;;;17988:40;18045:19;;15982:85:0;17664:406:1;4794:229:0;4931:12;4963:52;4985:6;4993:4;4999:1;5002:12;4963:21;:52::i;:::-;4956:59;4794:229;-1:-1:-1;;;;4794:229:0:o;5914:510::-;6084:12;6142:5;6117:21;:30;;6109:81;;;;-1:-1:-1;;;6109:81:0;;18277:2:1;6109:81:0;;;18259:21:1;18316:2;18296:18;;;18289:30;18355:34;18335:18;;;18328:62;18426:8;18406:18;;;18399:36;18452:19;;6109:81:0;18075:402:1;6109:81:0;2311:20;;6201:60;;;;-1:-1:-1;;;6201:60:0;;18684:2:1;6201:60:0;;;18666:21:1;18723:2;18703:18;;;18696:30;18762:31;18742:18;;;18735:59;18811:18;;6201:60:0;18482:353:1;6201:60:0;6275:12;6289:23;6316:6;-1:-1:-1;;;;;6316:11:0;6335:5;6342:4;6316:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6274:73;;;;6365:51;6382:7;6391:10;6403:12;6365:16;:51::i;:::-;6358:58;5914:510;-1:-1:-1;;;;;;;5914:510:0:o;8600:712::-;8750:12;8779:7;8775:530;;;-1:-1:-1;8810:10:0;8803:17;;8775:530;8924:17;;:21;8920:374;;9122:10;9116:17;9183:15;9170:10;9166:2;9162:19;9155:44;8920:374;9265:12;9258:20;;-1:-1:-1;;;9258:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:196:1;82:20;;-1:-1:-1;;;;;131:54:1;;121:65;;111:93;;200:1;197;190:12;111:93;14:196;;;:::o;215:186::-;274:6;327:2;315:9;306:7;302:23;298:32;295:52;;;343:1;340;333:12;295:52;366:29;385:9;366:29;:::i;588:180::-;647:6;700:2;688:9;679:7;675:23;671:32;668:52;;;716:1;713;706:12;668:52;-1:-1:-1;739:23:1;;588:180;-1:-1:-1;588:180:1:o;773:254::-;841:6;849;902:2;890:9;881:7;877:23;873:32;870:52;;;918:1;915;908:12;870:52;941:29;960:9;941:29;:::i;:::-;931:39;1017:2;1002:18;;;;989:32;;-1:-1:-1;;;773:254:1:o;1469:184::-;-1:-1:-1;;;1518:1:1;1511:88;1618:4;1615:1;1608:15;1642:4;1639:1;1632:15;1658:275;1729:2;1723:9;1794:2;1775:13;;-1:-1:-1;;1771:27:1;1759:40;;1829:18;1814:34;;1850:22;;;1811:62;1808:88;;;1876:18;;:::i;:::-;1912:2;1905:22;1658:275;;-1:-1:-1;1658:275:1:o;1938:183::-;1998:4;2031:18;2023:6;2020:30;2017:56;;;2053:18;;:::i;:::-;-1:-1:-1;2098:1:1;2094:14;2110:4;2090:25;;1938:183::o;2126:662::-;2180:5;2233:3;2226:4;2218:6;2214:17;2210:27;2200:55;;2251:1;2248;2241:12;2200:55;2287:6;2274:20;2313:4;2337:60;2353:43;2393:2;2353:43;:::i;:::-;2337:60;:::i;:::-;2431:15;;;2517:1;2513:10;;;;2501:23;;2497:32;;;2462:12;;;;2541:15;;;2538:35;;;2569:1;2566;2559:12;2538:35;2605:2;2597:6;2593:15;2617:142;2633:6;2628:3;2625:15;2617:142;;;2699:17;;2687:30;;2737:12;;;;2650;;2617:142;;;-1:-1:-1;2777:5:1;2126:662;-1:-1:-1;;;;;;2126:662:1:o;2793:595::-;2911:6;2919;2972:2;2960:9;2951:7;2947:23;2943:32;2940:52;;;2988:1;2985;2978:12;2940:52;3028:9;3015:23;3057:18;3098:2;3090:6;3087:14;3084:34;;;3114:1;3111;3104:12;3084:34;3137:61;3190:7;3181:6;3170:9;3166:22;3137:61;:::i;:::-;3127:71;;3251:2;3240:9;3236:18;3223:32;3207:48;;3280:2;3270:8;3267:16;3264:36;;;3296:1;3293;3286:12;3264:36;;3319:63;3374:7;3363:8;3352:9;3348:24;3319:63;:::i;:::-;3309:73;;;2793:595;;;;;:::o;3393:316::-;3470:6;3478;3486;3539:2;3527:9;3518:7;3514:23;3510:32;3507:52;;;3555:1;3552;3545:12;3507:52;-1:-1:-1;;3578:23:1;;;3648:2;3633:18;;3620:32;;-1:-1:-1;3699:2:1;3684:18;;;3671:32;;3393:316;-1:-1:-1;3393:316:1:o;3945:1146::-;4063:6;4071;4124:2;4112:9;4103:7;4099:23;4095:32;4092:52;;;4140:1;4137;4130:12;4092:52;4180:9;4167:23;4209:18;4250:2;4242:6;4239:14;4236:34;;;4266:1;4263;4256:12;4236:34;4304:6;4293:9;4289:22;4279:32;;4349:7;4342:4;4338:2;4334:13;4330:27;4320:55;;4371:1;4368;4361:12;4320:55;4407:2;4394:16;4429:4;4453:60;4469:43;4509:2;4469:43;:::i;4453:60::-;4547:15;;;4629:1;4625:10;;;;4617:19;;4613:28;;;4578:12;;;;4653:19;;;4650:39;;;4685:1;4682;4675:12;4650:39;4709:11;;;;4729:148;4745:6;4740:3;4737:15;4729:148;;;4811:23;4830:3;4811:23;:::i;:::-;4799:36;;4762:12;;;;4855;;;;4729:148;;;4896:5;-1:-1:-1;;4939:18:1;;4926:32;;-1:-1:-1;;4970:16:1;;;4967:36;;;4999:1;4996;4989:12;5096:543;5189:6;5197;5205;5213;5221;5274:3;5262:9;5253:7;5249:23;5245:33;5242:53;;;5291:1;5288;5281:12;5242:53;5327:9;5314:23;5304:33;;5384:2;5373:9;5369:18;5356:32;5346:42;;5438:2;5427:9;5423:18;5410:32;5482:4;5475:5;5471:16;5464:5;5461:27;5451:55;;5502:1;5499;5492:12;5451:55;5096:543;;;;-1:-1:-1;5525:5:1;;5577:2;5562:18;;5549:32;;-1:-1:-1;5628:3:1;5613:19;5600:33;;5096:543;-1:-1:-1;;5096:543:1:o;6783:184::-;6853:6;6906:2;6894:9;6885:7;6881:23;6877:32;6874:52;;;6922:1;6919;6912:12;6874:52;-1:-1:-1;6945:16:1;;6783:184;-1:-1:-1;6783:184:1:o;8965:::-;-1:-1:-1;;;9014:1:1;9007:88;9114:4;9111:1;9104:15;9138:4;9135:1;9128:15;9154:184;-1:-1:-1;;;9203:1:1;9196:88;9303:4;9300:1;9293:15;9327:4;9324:1;9317:15;9343:135;9382:3;-1:-1:-1;;9403:17:1;;9400:43;;;9423:18;;:::i;:::-;-1:-1:-1;9470:1:1;9459:13;;9343:135::o;13188:125::-;13228:4;13256:1;13253;13250:8;13247:34;;;13261:18;;:::i;:::-;-1:-1:-1;13298:9:1;;13188:125::o;13318:168::-;13358:7;13424:1;13420;13416:6;13412:14;13409:1;13406:21;13401:1;13394:9;13387:17;13383:45;13380:71;;;13431:18;;:::i;:::-;-1:-1:-1;13471:9:1;;13318:168::o;13491:274::-;13531:1;13557;13547:189;;-1:-1:-1;;;13589:1:1;13582:88;13693:4;13690:1;13683:15;13721:4;13718:1;13711:15;13547:189;-1:-1:-1;13750:9:1;;13491:274::o;13770:128::-;13810:3;13841:1;13837:6;13834:1;13831:13;13828:39;;;13847:18;;:::i;:::-;-1:-1:-1;13883:9:1;;13770:128::o;15031:435::-;15084:3;15122:5;15116:12;15149:6;15144:3;15137:19;15175:4;15204:2;15199:3;15195:12;15188:19;;15241:2;15234:5;15230:14;15262:1;15272:169;15286:6;15283:1;15280:13;15272:169;;;15347:13;;15335:26;;15381:12;;;;15416:15;;;;15308:1;15301:9;15272:169;;;-1:-1:-1;15457:3:1;;15031:435;-1:-1:-1;;;;;15031:435:1:o;15471:465::-;15728:2;15717:9;15710:21;15691:4;15754:56;15806:2;15795:9;15791:18;15783:6;15754:56;:::i;:::-;15858:9;15850:6;15846:22;15841:2;15830:9;15826:18;15819:50;15886:44;15923:6;15915;15886:44;:::i;:::-;15878:52;15471:465;-1:-1:-1;;;;;15471:465:1:o;17382:277::-;17449:6;17502:2;17490:9;17481:7;17477:23;17473:32;17470:52;;;17518:1;17515;17508:12;17470:52;17550:9;17544:16;17603:5;17596:13;17589:21;17582:5;17579:32;17569:60;;17625:1;17622;17615:12;18840:258;18912:1;18922:113;18936:6;18933:1;18930:13;18922:113;;;19012:11;;;19006:18;18993:11;;;18986:39;18958:2;18951:10;18922:113;;;19053:6;19050:1;19047:13;19044:48;;;-1:-1:-1;;19088:1:1;19070:16;;19063:27;18840:258::o;19103:274::-;19232:3;19270:6;19264:13;19286:53;19332:6;19327:3;19320:4;19312:6;19308:17;19286:53;:::i;:::-;19355:16;;;;;19103:274;-1:-1:-1;;19103:274:1:o;19382:383::-;19531:2;19520:9;19513:21;19494:4;19563:6;19557:13;19606:6;19601:2;19590:9;19586:18;19579:34;19622:66;19681:6;19676:2;19665:9;19661:18;19656:2;19648:6;19644:15;19622:66;:::i;:::-;19749:2;19728:15;-1:-1:-1;;19724:29:1;19709:45;;;;19756:2;19705:54;;19382:383;-1:-1:-1;;19382:383:1:o

Swarm Source

ipfs://ef72ab563752f2c2def7be1656915aca7e472bf440aeb68879dd5a46b3226916
Block Transaction Gas Used Reward
Age Block Fee Address Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading