ETH Price: $2,953.38 (-0.11%)

Contract

0x623741035bf302DFe954828F08f626D0247864ac

Overview

ETH Balance

Taiko Alethia LogoTaiko Alethia LogoTaiko Alethia Logo0 ETH

ETH Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Un Stake Mst11700642025-05-23 13:10:59246 days ago1748005859IN
0x62374103...0247864ac
0 ETH0.000000380.01021106
Un Stake Mst11700642025-05-23 13:10:59246 days ago1748005859IN
0x62374103...0247864ac
0 ETH0.000001530.01021106
Increwards Per W...11123222025-04-27 21:17:23271 days ago1745788643IN
0x62374103...0247864ac
0 ETH0.000003590.061
Increwards Per W...11096392025-04-26 21:15:23272 days ago1745702123IN
0x62374103...0247864ac
0 ETH0.000003470.059
Increwards Per W...11072082025-04-25 21:12:11273 days ago1745615531IN
0x62374103...0247864ac
0 ETH0.000003460.05884718
Increwards Per W...11049442025-04-24 21:09:11274 days ago1745528951IN
0x62374103...0247864ac
0 ETH0.000003530.06
Increwards Per W...11029062025-04-23 21:06:11275 days ago1745442371IN
0x62374103...0247864ac
0 ETH0.000004550.06
Increwards Per W...11010262025-04-22 21:01:59276 days ago1745355719IN
0x62374103...0247864ac
0 ETH0.000003240.06
Increwards Per W...10980982025-04-21 20:58:47277 days ago1745269127IN
0x62374103...0247864ac
0 ETH0.000003530.06
Increwards Per W...10950962025-04-20 20:55:35278 days ago1745182535IN
0x62374103...0247864ac
0 ETH0.000003530.06
Increwards Per W...10915182025-04-19 20:51:23279 days ago1745095883IN
0x62374103...0247864ac
0 ETH0.000003590.061
Increwards Per W...10880402025-04-18 20:47:59280 days ago1745009279IN
0x62374103...0247864ac
0 ETH0.000003470.059
Increwards Per W...10859742025-04-17 20:45:35281 days ago1744922735IN
0x62374103...0247864ac
0 ETH0.000003470.059
Increwards Per W...10833722025-04-16 20:41:23282 days ago1744836083IN
0x62374103...0247864ac
0 ETH0.000003530.06
Increwards Per W...10799932025-04-15 20:37:59283 days ago1744749479IN
0x62374103...0247864ac
0 ETH0.000004550.06
Increwards Per W...10765522025-04-14 20:34:59284 days ago1744662899IN
0x62374103...0247864ac
0 ETH0.000003240.06
Increwards Per W...10732862025-04-13 20:31:11285 days ago1744576271IN
0x62374103...0247864ac
0 ETH0.000003530.06
Increwards Per W...10696442025-04-12 20:27:23286 days ago1744489643IN
0x62374103...0247864ac
0 ETH0.000005880.1000009
Increwards Per W...10659172025-04-11 20:24:23287 days ago1744403063IN
0x62374103...0247864ac
0 ETH0.000003590.061
Increwards Per W...10623702025-04-10 20:20:59288 days ago1744316459IN
0x62374103...0247864ac
0 ETH0.000003530.06
Increwards Per W...10591982025-04-09 20:17:59289 days ago1744229879IN
0x62374103...0247864ac
0 ETH0.000003590.061
Increwards Per W...10559792025-04-08 20:14:47290 days ago1744143287IN
0x62374103...0247864ac
0 ETH0.00000470.08
Increwards Per W...10525292025-04-07 20:10:47291 days ago1744056647IN
0x62374103...0247864ac
0 ETH0.000004550.06
Increwards Per W...10501402025-04-06 20:07:11292 days ago1743970031IN
0x62374103...0247864ac
0 ETH0.000003950.0732
Increwards Per W...10463842025-04-05 20:04:35293 days ago1743883475IN
0x62374103...0247864ac
0 ETH0.000005880.1000001
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MeridianMultiPoolStaking

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at taikoscan.io on 2024-08-22
*/

// File: contracts/utils/CheckContract.sol

pragma experimental ABIEncoderV2;


pragma solidity 0.6.12;


contract CheckContract {
    /**
     * Check that the account is an already deployed non-destroyed contract.
     * See: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol#L12
     */
    function checkContract(address _account) internal view {
        require(_account != address(0), "Account cannot be zero address");

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(_account) }
        require(size > 0, "Account code size cannot be zero");
    }
}

// File: contracts/utils/ReentrancyGuard.sol



pragma solidity 0.6.12;

/**
 * @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].
 */
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 () internal {
        _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: contracts/utils/SafeMath.sol



pragma solidity 0.6.12;

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

        return c;
    }

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

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

        return c;
    }

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

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

        return c;
    }

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

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

        return c;
    }

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

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

// File: contracts/utils/IERC20.sol



pragma solidity 0.6.12;

/**
 * @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: contracts/utils/Address.sol



pragma solidity ^0.6.2;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

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

// File: contracts/utils/SafeERC20.sol



pragma solidity 0.6.12;




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

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

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

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

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

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

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

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

// File: contracts/InvestmentPools.sol



pragma solidity ^0.6.12;

// Users can invest in a set of predefined investment pools
// Each pool has a min redemption period and staking multiplier.  The longer the duration the greater the multiplier
// The base pool has a multiplier of 1 and allows for immediate withdrawls.  
// The pool multiplier is applied to the amount invested to give the users weighted stake in that pool
// Vesting starts immediately the deposit is made  
// A user can only redeem an investment from a pool once the vesting period ends
// A user can redeem all or part of a fully vested investment in a pool
// A max limit is placed on the number of live investments in any pool in order to avoid gas or security issues


contract InvestmentPools {
    using SafeMath for uint256;

    // Note that if the number of Pools in InvestmentType is changed then the isValidInvestmentType function MUST be updated
    enum InvestmentType {Pool1, Pool2, Pool3, Pool4, Pool5, Pool6, Pool7, Pool8, Pool9, Pool10}
    uint constant public MAX_NUM_OF_POOLS = 10; //  NOTE This MUST be equal to the number of Pools in InvestmentType
    uint constant public ONE_HUNDRED_PCNT = 1000;
    uint constant public MIN_MULTIPLIER = 1000;     // = multiplier of 1
    uint constant public MAX_MULTIPLIER = 3000;     // = multiplier of 3
    uint constant public MAX_INVESTMENTS_PER_POOL = 10;  //  restricts the number of investments for each pool to prevent gas issues
    uint constant public ONE_DAY_IN_SECONDS = 86400;

    bool public investmentsInitialized;
    address public gov;
    uint public numberOfPools;

    // user stakes weighted based on lock up period
    mapping (address => uint) public weightedStake;
    mapping(InvestmentType => uint256) public presetMultipliers;
    mapping(InvestmentType => uint256) public presetDurations;
    
    struct Investment {
        uint256 amount;
        uint256 multiplier;
        uint256 vestingTimestamp;
    }

    struct UserInvestmentPool {
        uint256 total;
        Investment[] investments;
    }

    // mapping of user investments user => investment type => User Investment Pool
    mapping(address => mapping(InvestmentType => UserInvestmentPool)) public userInvestments;

    constructor() public {
        gov = msg.sender;
    }

    event GovChanged(address _gov);

    modifier onlyGov() {
        require(msg.sender == gov, "MeridianStaking: Forbidden");
        _;
    }

    function setGov(address _newGov) external onlyGov {
        require(_newGov != address(0),"MeridianStaking: Invalid address");
        gov = _newGov;
        emit GovChanged(_newGov);
    }

    function renounceGov(bool _renounce) external onlyGov {
        require(_renounce == true,"MeridianStaking: renounce must be true");
        gov = address(0);
        emit GovChanged(gov);
    }

    // Note duration set in days where 1 = 1 day
    // Note multipliers must be >= 1000 where 1000 = multiply by 1.  eg a multiplier of 1100 will add 10% to the actual investent amount
    function initializeInvestments(uint256[] memory multipliers, uint256[] memory durations) external onlyGov {
        require(!investmentsInitialized, "Already Initialized");
        require(multipliers.length < MAX_NUM_OF_POOLS,"Too many pools");
        require(multipliers.length == durations.length, "Invalid input arrays");

        investmentsInitialized = true;
        presetMultipliers[InvestmentType.Pool1] = MIN_MULTIPLIER; // base pool multiplier = 1
        presetDurations[InvestmentType.Pool1] = 0;              // base pool duration zero i.e., immediate withdrawals

        for (uint256 i = 0; i < multipliers.length; i++) {
            require(multipliers[i] >= MIN_MULTIPLIER && multipliers[i] <= MAX_MULTIPLIER, "Invalid investment multiplier");
            require(durations[i] >= 0, "Invalid investment duration");
            InvestmentType poolType = InvestmentType(uint256(InvestmentType.Pool1) + i + 1);
            presetMultipliers[poolType] = multipliers[i];
            presetDurations[poolType] = durations[i];
        }
        numberOfPools = multipliers.length+1;
    }

    function adjustInvestment(uint256 _multiplier, uint256 _duration, InvestmentType _pool) external onlyGov {
        require(investmentsInitialized, "Use initializeInvestments to first setup pools");
        require(isValidInvestmentType(_pool), "Invalid InvestmentType");
        require(uint(_pool) <= numberOfPools,"Not next pool. Pools must be set up sequentially");
        require(_multiplier >= MIN_MULTIPLIER && _multiplier <= MAX_MULTIPLIER, "Invalid investment multiplier");
        // The duration of a pool cannot be reduced once set it can only be increased
        require(_duration >= 0 && _duration >= presetDurations[_pool], "Invalid investment duration");
        presetMultipliers[_pool] = _multiplier;
        presetDurations[_pool] = _duration;
        if (uint(_pool) == numberOfPools) {numberOfPools = numberOfPools + 1;} 
    }

    // Function takes in an _amount of tokens to stake and an investment type (min lockup period and multiplier)
    // calculates the investment uplift due to the agreed lockup period and adds uplifted amount to the users wighted investment
    // sets up a new deposit with appropriate vesting end time and
    // returns the total weighted staking value for this user for all investments
    
    function StakeRequest(address _user, uint256 _amount, InvestmentType _type) internal returns (uint256) {
        require(investmentsInitialized, "Contract not yet initialized");
        require(_amount > 0,"Invalid stake");
        require(isValidInvestmentType(_type), "Invalid InvestmentType");
        require(userInvestments[_user][_type].investments.length < MAX_INVESTMENTS_PER_POOL, "Max number of investments exceeded for this pool");
        // add the new stake to the appropriate investment pool for this user
        userInvestments[_user][_type].total = userInvestments[_user][_type].total.add(_amount);
        uint256 vestingEndTime = block.timestamp.add(ONE_DAY_IN_SECONDS.mul(presetDurations[_type]));
        userInvestments[_user][_type].investments.push(Investment({
            amount: _amount,
            multiplier: presetMultipliers[_type],
            vestingTimestamp: vestingEndTime
        }));
        // update the weighted investment stake
        weightedStake[_user]= weightedStake[_user].add(_amount.mul(presetMultipliers[_type]).div(ONE_HUNDRED_PCNT));
        return weightedStake[_user];
    }

    // Note Investments are managed using a priority queue system where investments that vest later are further down the queue.
    // This allows searching from the start of the array for the investments that are ready to be redeemed
    // If the value of investments avaiable to redeem is greater than _amount then the investment array is adjusted appropriatly
    // and the new overall weighted investment for this user is returned.
    // If the value of investments ready to redeem is less than _amount then the function returns without any changes 
    // and returns the original weighted average for the investments
    // Note The calling function must check to see if the weighted average has changed to confirm that the redemption is valid

    function redemptionRequest(address _user, uint256 _amount) internal returns (uint256) {
        require(investmentsInitialized, "Contract not yet initialized");
        require(_amount > 0,"Invalid amount");        
        uint256 availableToRedeem;
        uint256 priorAmount;
        uint256 adjustedWeightedStake; 
        uint256 partRedemption;
        uint256[] memory poolRedemptionIndex = new uint256[](numberOfPools);
        InvestmentType pool;
        // Loop through each Pool and each investment until sufficient available funds identified
        // Looping is limited due to MAX_INVESTMENTS_PER_POOL and MAX_NUM_OF_POOLS
        for (uint256 poolPtr = 0; poolPtr < numberOfPools; poolPtr++) {
            pool = InvestmentType(poolPtr);
            uint256 numOfInvestments = userInvestments[_user][pool].investments.length;
            // check if _amount is available for redemption from this investment pool
            for (uint256 i = 0; i < numOfInvestments; i++) {
                if (userInvestments[_user][pool].investments[i].vestingTimestamp <= block.timestamp) {  
                    priorAmount = availableToRedeem;              
                    availableToRedeem = availableToRedeem.add(userInvestments[_user][pool].investments[i].amount);
                    poolRedemptionIndex[poolPtr] = i+1;  // capture the highest entry +1 in each pool to redeem 
                    if (availableToRedeem >= _amount) { // valid redemption achieved so process request
                        partRedemption = _amount.sub(priorAmount);
                        adjustedWeightedStake = processRedemption (_user, pool, partRedemption, poolRedemptionIndex);                     
                        return(adjustedWeightedStake);
                    }
                } else {
                    break;  // exit the loop if next entry timestamp beyond the current timestamp
                }
            }
        }
        // in the event that the redemption is not valid then leave the weighted stake unchanged
        // calling code will need to use this to confirm if a redemption is ok
        return(weightedStake[_user]);
    }

    
    function processRedemption (address _user, InvestmentType _type, uint256 _partRedemption, uint256[] memory _poolRedemptionIndex) private returns (uint256){
        uint256 adjustedWeightedStake = weightedStake[_user];    
        uint lastPool = uint(_type);
        // Iterate through each pool that will be used in the redemption removing redeemed entries and adjusting weightedStake
        for (uint256 poolPtr = 0; poolPtr < lastPool + 1; poolPtr++) {
            if(_poolRedemptionIndex[poolPtr] > 0){
                adjustedWeightedStake = adjustedWeightedStake.sub(redeemThisPool(_user, poolPtr, lastPool, _poolRedemptionIndex[poolPtr]-1, _partRedemption));
            }
        }    
        weightedStake[_user] = adjustedWeightedStake;
        return adjustedWeightedStake;
    }

    function redeemThisPool(address _user, uint _poolPtr, uint _lastPool, uint _lastIndex, uint256 _partRedemption) private returns(uint256){
        uint256 redeemFromThisPool;
        uint256 adjustedWeightedStake;
        uint256 popFromStack = _lastIndex +1;
        InvestmentType thisPool = InvestmentType(_poolPtr);
        if(_poolPtr == _lastPool){
            // last pool to be used in the redemption so check for part redemption of final element            
            if(_partRedemption != userInvestments[_user][thisPool].investments[_lastIndex].amount){
                // part redemption of element at last position so adjust this element and pop one less element from the array
                userInvestments[_user][thisPool].investments[_lastIndex].amount = userInvestments[_user][thisPool].investments[_lastIndex].amount.sub(_partRedemption);
                redeemFromThisPool = _partRedemption;                    
                adjustedWeightedStake = adjustedWeightedStake.add(weightAdjustment(_partRedemption,_user, thisPool, _lastIndex));
                popFromStack = _lastIndex;
            }
        }
        // now remove fully redeemed elements
        uint iterations;
        if (userInvestments[_user][thisPool].investments.length.sub(popFromStack) > popFromStack){
            iterations = userInvestments[_user][thisPool].investments.length.sub(popFromStack);
        } else {            
            iterations = popFromStack;
        }
        for (uint256 j = 0; j < iterations; j++) {
            if (j < popFromStack) { 
                // adjust stake weighting for those elements that are being removed
                redeemFromThisPool = redeemFromThisPool.add(userInvestments[_user][thisPool].investments[j].amount);                    
                adjustedWeightedStake = adjustedWeightedStake.add(weightAdjustment(userInvestments[_user][thisPool].investments[j].amount,_user,thisPool,j));
            }
            if (j < userInvestments[_user][thisPool].investments.length - popFromStack){
                // shift remaining array elements down stack to remove redeemed elements
                userInvestments[_user][thisPool].investments[j] = userInvestments[_user][thisPool].investments[j+popFromStack];
            }
        }
        // and resize the array
        for (uint256 j = 0; j < popFromStack; j++) {
            userInvestments[_user][thisPool].investments.pop();
        }   
        userInvestments[_user][thisPool].total = userInvestments[_user][thisPool].total.sub(redeemFromThisPool); 
        return adjustedWeightedStake;  
    }

    function weightAdjustment(uint256 _amount, address _user, InvestmentType _thisPool, uint _ptr ) private view returns(uint256) {   
        return (_amount.mul(userInvestments[_user][_thisPool].investments[_ptr].multiplier).div(ONE_HUNDRED_PCNT));                
    }


    // Helper functions

    function isValidInvestmentType(InvestmentType _type) internal pure returns (bool) {
            return _type >= InvestmentType.Pool1 && _type <= InvestmentType.Pool10;
    }

    // getter functions

    function getNumberOfInvestments(address _user, InvestmentType _type) external view returns(uint256) {
        return userInvestments[_user][_type].investments.length;
    }

    function getUserInvestmentTotal(address _user, InvestmentType _type) external view returns(uint256) {
        return userInvestments[_user][_type].total;
    }

    function getUserInvestments(address _user, InvestmentType _type) external view returns(Investment[] memory) {
        return userInvestments[_user][_type].investments;
    }

    function getPresetMultipliers(InvestmentType _type) external view returns(uint256) {
        return presetMultipliers[_type];
    }

    function getPresetDurations(InvestmentType _type) external view returns(uint256) {
        return presetDurations[_type];
    }

}
// File: contracts/MeridianMultiPoolStaking.sol




pragma solidity ^0.6.12;







contract MeridianMultiPoolStaking is InvestmentPools, ReentrancyGuard, CheckContract {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    // public constants and variables

    uint constant public DECIMAL_PRECISION = 1e18;
    uint constant public MAX_REWARD_TOKENS = 12;

    IERC20 public MST;

    bool public isInitialized;
    bool public enableMultiPool;  
    uint256 public totalMSTStaked;
    uint256 public totalOfWeightedStakes;
    uint256 public currentRateIndex;
    uint256 public lastRateSnapshotTimestamp; // used to track timestamp for interest calculations    
    
    mapping( address => bool) public auth;  // authorized updaters
    mapping( address => uint) public rewardsPerWeightedStake;  // Running sum of rewardToken fees per-MST-staked
    mapping( address => uint) public rewardTokenBalances; // latest contract balance for each reward token
    address[] public rewardTokens;
    mapping( address => uint) public mstStakes;  // user actual tokens staked 
    mapping( address => uint) public weightedStakes;  // user staked balances after uplift for lockup period
    
    // snapshot of rewardsPerWeightedStake per user at point of last deposit/withdrawl User => token => value
    mapping (address => mapping(address => uint)) public snapshots; 
    mapping(address => uint256[8]) public dailyRateSnapshots;   // used to capture rewardsPerWeightedStake each day over 8 days for each reward token

    // Events
    
    event NewAuth(address _auth);
    event RemoveAuth(address _auth);
    event MultiPoolChanged(bool _setting);
    event NewRewardToken(address _token);
    event RemovedRewardToken(address _token);
    event TotalMSTStakedUpdated(uint _totalMSTStaked);
    event StakeChanged(address indexed staker, uint newStake);
    event WeightedStakeChanged(address indexed staker, uint newStake);
    event StakingGainsWithdrawn(address indexed staker, uint256[] userPendingRewards);

    // authorized updaters of the rewards tracker
    modifier onlyAuth() {
        require(auth[msg.sender] == true, "MeridianStaking: Forbidden");
        _;
    }

    // Governance functions

    function initialize(address _mst) external onlyGov {
        require(!isInitialized, "Already Initialized");
        require (investmentsInitialized,"Must initialize investment pools first");
        checkContract(_mst);
        isInitialized = true;
        MST = IERC20(_mst);   
    }

    function setAuth(address _newAuth) external onlyGov {
        require(_newAuth != address(0),"MeridianStaking: Invalid address");
        auth[_newAuth] = true;
        emit NewAuth(_newAuth);
    }

    function removeAuth(address _auth) external onlyGov {
        require(_auth != address(0),"MeridianStaking: Invalid address");
        delete auth[_auth];
        emit RemoveAuth(_auth);
    }

    // Setting enableMultiPool allows investment across all pools rather than just the base pool
    // if set to false the users can still withdraw from existing pools but can only stake to Pool1
    function setMultiPool(bool _setting) external onlyGov {        
        enableMultiPool = _setting;
        emit MultiPoolChanged(_setting);
    }

    function addRewardToken(address _token) external onlyGov {        
        checkContract(_token);
        require(rewardTokens.length <= MAX_REWARD_TOKENS, "MeridianStaking: Too many reward tokens");
        rewardTokens.push(_token);
        emit NewRewardToken(_token);
    }

    function removeRewardToken(address _token) external onlyGov {
        checkContract(_token);
        IERC20 token = IERC20(_token);
        require (token.balanceOf(address(this)) == 0,"MeridianStaking: Cannot remove token with non-zero rewards");
        for (uint256 i = 0; i < rewardTokens.length; i++) {
            if (rewardTokens[i] == _token) {
                // Remove the address by shifting elements
                for (uint256 j = i; j < rewardTokens.length - 1; j++) {
                    rewardTokens[j] = rewardTokens[j + 1];
                }
                // Resize the array by removing the last element
                rewardTokens.pop();
                // Remove the mapping entry
                delete rewardsPerWeightedStake[_token];
                emit RemovedRewardToken(_token);
                break; // Exit the loop once the address is found and removed
            }
        }
    }

    // Core contract functions

    function stakeMst(uint256 _amount, InvestmentType _type) external nonReentrant {
        _stakeMst(msg.sender, _amount, _type);
    }

    function stakeMstOnBehalfOf(address _user, uint256 _amount, InvestmentType _type) external nonReentrant {
        _stakeMst(_user, _amount, _type);
    }

    function _stakeMst(address _user, uint256 _amount, InvestmentType _type) internal {
        require(isInitialized, "Contract not yet initialized");
        require(_amount > 0,"MeridianStaking: Invalid stake");
        require(enableMultiPool || _type == InvestmentType.Pool1, "MeridianStaking: Investment Pool not enabled");
        // First update the rewards trakers to capture any rewards that have been sent to the contract since the last interaction
        _increwardsPerWeightedStake();

        uint256[] memory userPendingRewards;
        uint currentWeightedStake = weightedStakes[_user];
        if (currentWeightedStake != 0 ) {
            userPendingRewards = _getUserPendingRewards(_user);
        }
        _updateUserSnapshots(_user);
        uint256 newStake = StakeRequest(_user, _amount, _type);

        // Increase user’s stake and total MST staked
        totalOfWeightedStakes = totalOfWeightedStakes.add(newStake.sub(currentWeightedStake));
        weightedStakes[_user] = newStake;
        mstStakes[_user] = mstStakes[_user].add(_amount);
        totalMSTStaked = totalMSTStaked.add(_amount);
        emit TotalMSTStakedUpdated(totalMSTStaked);

        require(MST.transferFrom(msg.sender, address(this), _amount),"Token transfer failed");
        emit StakeChanged(_user, mstStakes[_user]);
        emit WeightedStakeChanged(_user, newStake);        
        
        if (currentWeightedStake != 0 ) {
            emit StakingGainsWithdrawn(_user, userPendingRewards);
            _sendRewardsToUser(_user, userPendingRewards);
        }

     }

    function unStakeMst(uint256 _amount) external nonReentrant {
        require(isInitialized, "Contract not yet initialized");
        require(_amount > 0,"MeridianStaking: Invalid amount");
        // First update the rewards trakers to capture any rewards that have been sent to the contract since the last interaction
        _increwardsPerWeightedStake();

        uint MstToWithdraw = _amount < mstStakes[msg.sender] ? _amount : mstStakes[msg.sender];
        uint currentWeightedStake = weightedStakes[msg.sender];
        uint newStake = redemptionRequest(msg.sender, MstToWithdraw);
        require(newStake < currentWeightedStake, "MeridianStaking: Insufficient funds available to redeem");

        uint256[] memory userPendingRewards = _getUserPendingRewards(msg.sender);
        _updateUserSnapshots(msg.sender);

        // Decrease user's stake and total MST staked
        totalOfWeightedStakes = totalOfWeightedStakes.sub(currentWeightedStake.sub(newStake));
        weightedStakes[msg.sender] = newStake;
        mstStakes[msg.sender] = mstStakes[msg.sender].sub(MstToWithdraw);
        totalMSTStaked = totalMSTStaked.sub(MstToWithdraw);
        
        emit TotalMSTStakedUpdated(totalMSTStaked);

        // Transfer unstaked MST back to user
        require(MST.transfer(msg.sender, MstToWithdraw),"MeridianStaking: Token transfer failed");
        emit StakeChanged(msg.sender, mstStakes[msg.sender]);
        emit WeightedStakeChanged(msg.sender, newStake);

        emit StakingGainsWithdrawn(msg.sender, userPendingRewards);        
        _sendRewardsToUser(msg.sender, userPendingRewards);
     }

    function claimRewards() external nonReentrant {     
        require(isInitialized, "Contract not yet initialized");   
        // First update the rewards trakers to capture any rewards that have been sent to the contract since the last interaction
        _increwardsPerWeightedStake();

        uint currentWeightedStake = weightedStakes[msg.sender];
        require(currentWeightedStake > 0, "MeridianStaking: User must have non-zero stake");
        uint256[] memory userPendingRewards = _getUserPendingRewards(msg.sender);
        _updateUserSnapshots(msg.sender);

        emit StakingGainsWithdrawn(msg.sender, userPendingRewards);        
        _sendRewardsToUser(msg.sender, userPendingRewards);
     }


    // Helper functions

    function _sendRewardsToUser(address _user, uint256[] memory _pendingRewards) private {
        uint256 numOfRewardTokens = rewardTokens.length;
        for (uint256 i = 0; i < numOfRewardTokens; i++) {
            IERC20 token = IERC20(rewardTokens[i]);
            uint256 currentBalance = token.balanceOf(address(this));
            require(currentBalance >= _pendingRewards[i],"MeridianStaking: Insufficient contract balance");            
            require(rewardTokenBalances[rewardTokens[i]] >= _pendingRewards[i],"MeridianStaking: Insufficient rewards balance");
            rewardTokenBalances[rewardTokens[i]] = rewardTokenBalances[rewardTokens[i]].sub(_pendingRewards[i]);
            token.transfer(_user, _pendingRewards[i]);
        }
    }

    function _updateUserSnapshots(address _user) private {
        uint256 numOfRewardTokens = rewardTokens.length;
        for (uint256 i = 0; i < numOfRewardTokens; i++) {
            snapshots[_user][rewardTokens[i]] = rewardsPerWeightedStake[rewardTokens[i]];
        }
    }

    // enables forced update of rewards tracker for better frontend balances sync
    function increwardsPerWeightedStake() external onlyAuth {
        _increwardsPerWeightedStake();
    }

    // Called at the start of every user contract call to update rewards tracker.
    // For each reward token check if more rewards have been added since the last interaction
    // if they have then update the rewardsPerWeightedStake accordingly
    function _increwardsPerWeightedStake() private {
        if (totalMSTStaked > 0) {
            uint256 numOfRewardTokens = rewardTokens.length;
            for (uint256 i = 0; i < numOfRewardTokens; i++) {
                uint256 lastBalance = rewardTokenBalances[rewardTokens[i]];
                IERC20 token = IERC20(rewardTokens[i]);
                uint256 currentBalance = token.balanceOf(address(this));
                // if tokens have been added since last interaction then update rewardsPerWeightedStake
                if (currentBalance > lastBalance) { 
                    uint256 newRewards = currentBalance.sub(lastBalance);
                    rewardsPerWeightedStake[rewardTokens[i]] = rewardsPerWeightedStake[rewardTokens[i]].add(newRewards.mul(DECIMAL_PRECISION).div(totalOfWeightedStakes));
                    rewardTokenBalances[rewardTokens[i]] = currentBalance;
                }
            }
            _setDailySnapshots();
        }
    }

    // Triggers once per day to create a circular buffer of 8 days of dailyRateSnapshots for the rewardsPerWeightedStakes
    // dailyRateSnapshots can then be used externally to calculate the weekly change in snapshots
    // dailyRateSnapshots[token][currentRateIndex % 8] - dailyRateSnapshots[token][(currentRateIndex + 1) % 8]
    // and this can be used to approximate the interest rate for the frontend
    function _setDailySnapshots() private {
        if(block.timestamp >= lastRateSnapshotTimestamp + 1 days){
            for (uint256 i = 0; i < rewardTokens.length; i++) {
                dailyRateSnapshots[rewardTokens[i]][(currentRateIndex + 1) % 8] = rewardsPerWeightedStake[rewardTokens[i]];
            }
            lastRateSnapshotTimestamp = block.timestamp;
            currentRateIndex = (currentRateIndex + 1) % 8;
        }
    }
    

    // getter functions
    
    function getMstStake(address _user) external view returns (uint256) {
        return mstStakes[_user];
    }
    
    function getWeightedStake(address _user) external view returns (uint256) {
        return weightedStakes[_user];
    }

    function getSnapshot(address _user,address _token ) external view returns (uint256) {
        return snapshots[_user][_token];
    }

    function getRewardTokens() external view returns (address[] memory) {
        return rewardTokens;
    }

    function getCurrentrewardPerWeightedStake(address _token) external view returns (uint256) {
        return rewardsPerWeightedStake[_token];
    }

    function getDailyRateSnapshots(address _token) external view returns (uint256[8] memory) {
        return dailyRateSnapshots[_token];
    }

    function getCurrentrewardsPerWeightedStake() external view returns (uint256[] memory) {
        uint256 numOfRewardTokens = rewardTokens.length;
        uint256[] memory returnArray = new uint256[](numOfRewardTokens);
        for (uint256 i = 0; i < numOfRewardTokens; i++) {
            address currentAddress = rewardTokens[i];
            returnArray[i] = rewardsPerWeightedStake[currentAddress];
        }
        return returnArray;
    }

    function getRewardTokenBalance(address _token) external view returns (uint256) {
        return rewardTokenBalances[_token];
    }

    function getRewardTokenBalances() external view returns (uint256[] memory) {
        uint256 numOfRewardTokens = rewardTokens.length;
        uint256[] memory returnArray = new uint256[](numOfRewardTokens);
        for (uint256 i = 0; i < numOfRewardTokens; i++) {
            address currentAddress = rewardTokens[i];
            returnArray[i] = rewardTokenBalances[currentAddress];
        }
        return returnArray;
    }

    function getUserPendingRewards(address _account) external view returns (uint256[] memory) {
        return _getUserPendingRewards(_account);
    }

    function _getUserPendingRewards(address _account) internal view returns (uint256[] memory) {
        uint256 numOfRewardTokens = rewardTokens.length;
        uint256[] memory returnArray = new uint256[](numOfRewardTokens);
        for (uint256 i = 0; i < numOfRewardTokens; i++) {
            returnArray[i] = _getPendingReward(_account,rewardTokens[i]);
        }
        return returnArray;
    }

    function getPendingReward(address _user, address _rewardToken) external view returns (uint) {
        return _getPendingReward(_user, _rewardToken);
    }

    function _getPendingReward(address _user, address _rewardToken) internal view returns (uint) {
        uint usersnapshot = snapshots[_user][_rewardToken];
        uint pendingReward = weightedStakes[_user].mul(rewardsPerWeightedStake[_rewardToken].sub(usersnapshot)).div(DECIMAL_PRECISION);
        return pendingReward;
    }

    function getIsAuthorizedUpdater (address _updater) external view returns(bool) {
        return auth[_updater];
    }
}

Contract Security Audit

Contract ABI

API
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_gov","type":"address"}],"name":"GovChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_setting","type":"bool"}],"name":"MultiPoolChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_auth","type":"address"}],"name":"NewAuth","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"}],"name":"NewRewardToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_auth","type":"address"}],"name":"RemoveAuth","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"}],"name":"RemovedRewardToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"newStake","type":"uint256"}],"name":"StakeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"userPendingRewards","type":"uint256[]"}],"name":"StakingGainsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_totalMSTStaked","type":"uint256"}],"name":"TotalMSTStakedUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"newStake","type":"uint256"}],"name":"WeightedStakeChanged","type":"event"},{"inputs":[],"name":"DECIMAL_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_INVESTMENTS_PER_POOL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NUM_OF_POOLS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REWARD_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MST","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_DAY_IN_SECONDS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_HUNDRED_PCNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"addRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_multiplier","type":"uint256"},{"internalType":"uint256","name":"_duration","type":"uint256"},{"internalType":"enum InvestmentPools.InvestmentType","name":"_pool","type":"uint8"}],"name":"adjustInvestment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"auth","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentRateIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"dailyRateSnapshots","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enableMultiPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getCurrentrewardPerWeightedStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentrewardsPerWeightedStake","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getDailyRateSnapshots","outputs":[{"internalType":"uint256[8]","name":"","type":"uint256[8]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_updater","type":"address"}],"name":"getIsAuthorizedUpdater","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getMstStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"enum InvestmentPools.InvestmentType","name":"_type","type":"uint8"}],"name":"getNumberOfInvestments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"}],"name":"getPendingReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum InvestmentPools.InvestmentType","name":"_type","type":"uint8"}],"name":"getPresetDurations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum InvestmentPools.InvestmentType","name":"_type","type":"uint8"}],"name":"getPresetMultipliers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getRewardTokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardTokenBalances","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"getSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"enum InvestmentPools.InvestmentType","name":"_type","type":"uint8"}],"name":"getUserInvestmentTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"enum InvestmentPools.InvestmentType","name":"_type","type":"uint8"}],"name":"getUserInvestments","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"multiplier","type":"uint256"},{"internalType":"uint256","name":"vestingTimestamp","type":"uint256"}],"internalType":"struct InvestmentPools.Investment[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getUserPendingRewards","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getWeightedStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gov","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"increwardsPerWeightedStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mst","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"multipliers","type":"uint256[]"},{"internalType":"uint256[]","name":"durations","type":"uint256[]"}],"name":"initializeInvestments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"investmentsInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRateSnapshotTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mstStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numberOfPools","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum InvestmentPools.InvestmentType","name":"","type":"uint8"}],"name":"presetDurations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum InvestmentPools.InvestmentType","name":"","type":"uint8"}],"name":"presetMultipliers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_auth","type":"address"}],"name":"removeAuth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"removeRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_renounce","type":"bool"}],"name":"renounceGov","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardTokenBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardsPerWeightedStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newAuth","type":"address"}],"name":"setAuth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGov","type":"address"}],"name":"setGov","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_setting","type":"bool"}],"name":"setMultiPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"snapshots","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"enum InvestmentPools.InvestmentType","name":"_type","type":"uint8"}],"name":"stakeMst","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"enum InvestmentPools.InvestmentType","name":"_type","type":"uint8"}],"name":"stakeMstOnBehalfOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalMSTStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalOfWeightedStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unStakeMst","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"enum InvestmentPools.InvestmentType","name":"","type":"uint8"}],"name":"userInvestments","outputs":[{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"weightedStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"weightedStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50600080546101003302610100600160a81b031990911617905560016006556141798061003e6000396000f3fe608060405234801561001057600080fd5b50600436106103ba5760003560e01c806385c7b427116101f4578063c4f59f9b1161011a578063e04664ca116100ad578063ed03e78c1161007c578063ed03e78c14610496578063fa6886ec14610779578063fbf6924e1461078c578063fe0f3a131461079f576103ba565b8063e04664ca14610743578063e10182b114610756578063e95f26981461075e578063ebc54c7c14610771576103ba565b8063cfad57a2116100e9578063cfad57a2146106f7578063d64efe9c1461070a578063da54c29d1461071d578063dd93e06a14610730576103ba565b8063c4f59f9b146106a9578063c9c313d9146106be578063cd5d2118146106d1578063cf7c11fa146106e4576103ba565b8063a905dbb011610192578063b4559d1011610161578063b4559d10146103fb578063b977965b1461066e578063bc825d2314610676578063c4d66de814610696576103ba565b8063a905dbb014610622578063aadcef8614610635578063b041337314610648578063b1f5de401461065b576103ba565b806390c87f13116101ce57806390c87f13146105e15780639e37c281146105f45780639e57dade14610607578063a20baee61461061a576103ba565b806385c7b427146105b357806389c23dba146105c65780638a5cc320146105d9576103ba565b8063392e53cd116102e45780636a8cb20f116102775780637bb7bed1116102465780637bb7bed1146105725780637ec475a8146105855780637f3fd918146105985780638281511c146105ab576103ba565b80636a8cb20f146105525780636f682a531461055a57806371860c4f146105625780637645ff1a1461056a576103ba565b80634d1df007116102b35780634d1df007146105275780635ce7b15f1461053a5780635d0cde97146105425780635d6a618d1461054a576103ba565b8063392e53cd146104d95780633d509c97146104ee5780633e40c5c6146105015780634cc4bc4114610514576103ba565b80631c03e6cc1161035c5780632a46d7251161032b5780632a46d725146104965780632b2e05c11461049e5780632d788644146104b1578063372500ab146104d1576103ba565b80631c03e6cc146104535780631e74d25714610466578063240dc9321461047b578063288f68661461048e576103ba565b806312d43a511161039857806312d43a511461040357806313a0c44314610418578063157d1c7e1461042b5780631b01df911461043e576103ba565b806307701cc3146103bf5780630ada74e9146103e85780630cec3148146103fb575b600080fd5b6103d26103cd36600461358c565b6107b2565b6040516103df919061412c565b60405180910390f35b6103d26103f6366004613712565b6107cd565b6103d26107df565b61040b6107e4565b6040516103df91906137ac565b6103d261042636600461358c565b6107f8565b6103d261043936600461358c565b61080a565b61045161044c36600461363c565b61081c565b005b61045161046136600461358c565b610862565b61046e610943565b6040516103df91906138d5565b6104516104893660046136da565b6109fa565b6103d2610a70565b6103d2610a76565b6104516104ac36600461358c565b610a7c565b6104c46104bf36600461358c565b610b24565b6040516103df91906138a3565b610451610b77565b6104e1610c67565b6040516103df919061390d565b6104516104fc36600461358c565b610c77565b6104e161050f36600461358c565b610e93565b6103d2610522366004613712565b610eb1565b6103d26105353660046135a7565b610ee4565b6103d2610f11565b6103d2610f17565b6103d2610f1c565b61046e610f22565b6103d2610fd2565b6104e1610fd8565b61040b610fe1565b61040b61058036600461372d565b610ff0565b6103d26105933660046135a7565b611017565b6104516105a636600461358c565b611034565b6104e16110d9565b6103d26105c136600461358c565b6110e9565b6103d26105d436600461358c565b6110fb565b6103d2611116565b6103d26105ef3660046135db565b61111d565b610451610602366004613679565b611165565b6103d261061536600461358c565b611394565b6103d26113af565b6103d2610630366004613712565b6113bb565b6103d261064336600461358c565b6113cd565b6103d26106563660046135db565b6113df565b61045161066936600461375d565b6113fc565b6103d261142f565b6106896106843660046135db565b611435565b6040516103df919061384a565b6104516106a436600461358c565b6114f4565b6106b16115a9565b6040516103df91906137fd565b6103d26106cc36600461358c565b61160b565b6104e16106df36600461358c565b611626565b61046e6106f236600461358c565b61163b565b61045161070536600461358c565b611646565b610451610718366004613780565b6116eb565b6103d261072b3660046135db565b611884565b6103d261073e36600461358c565b6118cf565b6104516107513660046136da565b6118e1565b6103d2611983565b6103d261076c366004613612565b611989565b6104516119ab565b61045161078736600461372d565b6119e9565b6103d261079a366004613712565b611cfb565b6103d26107ad3660046135a7565b611d0d565b6001600160a01b03166000908152600e602052604090205490565b60036020526000908152604090205481565b600a81565b60005461010090046001600160a01b031681565b600d6020526000908152604090205481565b60116020526000908152604090205481565b600260065414156108485760405162461bcd60e51b815260040161083f906140a7565b60405180910390fd5b6002600655610858838383611d20565b5050600160065550565b60005461010090046001600160a01b031633146108915760405162461bcd60e51b815260040161083f90613f0a565b61089a8161202c565b600f54600c10156108bd5760405162461bcd60e51b815260040161083f90613ec3565b600f80546001810182556000919091527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020180546001600160a01b0319166001600160a01b0383161790556040517fc69f61e4bef149d13a9bb253756b4b6e0b1c2cd402efb69dfec416c6201d0bf1906109389083906137ac565b60405180910390a150565b600f54606090818167ffffffffffffffff8111801561096157600080fd5b5060405190808252806020026020018201604052801561098b578160200160208202803683370190505b50905060005b828110156109f3576000600f82815481106109a857fe5b60009182526020808320909101546001600160a01b0316808352600d9091526040909120548451919250908490849081106109df57fe5b602090810291909101015250600101610991565b5091505090565b60005461010090046001600160a01b03163314610a295760405162461bcd60e51b815260040161083f90613f0a565b6007805460ff60a81b1916600160a81b831515021790556040517ff07c2a5f22b138bfc567e9aa9624d0f15f436d28d49abe1c65e92a72c74a832e9061093890839061390d565b60095481565b6103e881565b60005461010090046001600160a01b03163314610aab5760405162461bcd60e51b815260040161083f90613f0a565b6001600160a01b038116610ad15760405162461bcd60e51b815260040161083f90613d63565b6001600160a01b0381166000908152600c602052604090819020805460ff19166001179055517f9f511455548a603e61f1cc70bb0a622d2ad70cb8b318198695efc90b5fce4e4c906109389083906137ac565b610b2c6134b4565b6001600160a01b0382166000908152601360205260409081902081516101008101928390529160089082845b815481526020019060010190808311610b585750505050509050919050565b60026006541415610b9a5760405162461bcd60e51b815260040161083f906140a7565b6002600655600754600160a01b900460ff16610bc85760405162461bcd60e51b815260040161083f90613b65565b610bd0612075565b3360009081526011602052604090205480610bfd5760405162461bcd60e51b815260040161083f90613e1f565b6060610c083361226a565b9050610c1333612312565b336001600160a01b03167f20236d1f813fa1fbd42714507db9d3f2ef3b56e82163c2f91f4df6aacefca6c582604051610c4c91906138d5565b60405180910390a2610c5e33826123a5565b50506001600655565b600754600160a01b900460ff1681565b60005461010090046001600160a01b03163314610ca65760405162461bcd60e51b815260040161083f90613f0a565b610caf8161202c565b6040516370a0823160e01b815281906001600160a01b038216906370a0823190610cdd9030906004016137ac565b60206040518083038186803b158015610cf557600080fd5b505afa158015610d09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2d9190613745565b15610d4a5760405162461bcd60e51b815260040161083f90613ffd565b60005b600f54811015610e8e57826001600160a01b0316600f8281548110610d6e57fe5b6000918252602090912001546001600160a01b03161415610e8657805b600f5460001901811015610e0057600f8160010181548110610da957fe5b600091825260209091200154600f80546001600160a01b039092169183908110610dcf57fe5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600101610d8b565b50600f805480610e0c57fe5b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0385168252600d9052604080822091909155517fb5494e609b7d7189b9fd268eb38adea381bfc53fb5eeeab9dd8ecc3f8af9539e90610e799085906137ac565b60405180910390a1610e8e565b600101610d4d565b505050565b6001600160a01b03166000908152600c602052604090205460ff1690565b600060036000836009811115610ec357fe5b6009811115610ece57fe5b8152602001908152602001600020549050919050565b6001600160a01b038083166000908152601260209081526040808320938516835292905220545b92915050565b600b5481565b600c81565b610bb881565b600f54606090818167ffffffffffffffff81118015610f4057600080fd5b50604051908082528060200260200182016040528015610f6a578160200160208202803683370190505b50905060005b828110156109f3576000600f8281548110610f8757fe5b60009182526020808320909101546001600160a01b0316808352600e909152604090912054845191925090849084908110610fbe57fe5b602090810291909101015250600101610f70565b60015481565b60005460ff1681565b6007546001600160a01b031681565b600f8181548110610ffd57fe5b6000918252602090912001546001600160a01b0316905081565b601260209081526000928352604080842090915290825290205481565b60005461010090046001600160a01b031633146110635760405162461bcd60e51b815260040161083f90613f0a565b6001600160a01b0381166110895760405162461bcd60e51b815260040161083f90613d63565b6001600160a01b0381166000908152600c602052604090819020805460ff19169055517f54cba8c838ee951b9ccef4916ea25b653956ac3302498f6c4f28f0473ff4c583906109389083906137ac565b600754600160a81b900460ff1681565b600e6020526000908152604090205481565b6001600160a01b03166000908152600d602052604090205490565b6201518081565b6001600160a01b03821660009081526005602052604081208183600981111561114257fe5b600981111561114d57fe5b81526020810191909152604001600020549392505050565b60005461010090046001600160a01b031633146111945760405162461bcd60e51b815260040161083f90613f0a565b60005460ff16156111b75760405162461bcd60e51b815260040161083f90613ad1565b600a8251106111d85760405162461bcd60e51b815260040161083f90613e6d565b80518251146111f95760405162461bcd60e51b815260040161083f90613e95565b6000805460ff191660011781558080526103e87f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff5560046020527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec8190555b8251811015611388576103e883828151811061127057fe5b60200260200101511015801561129b5750610bb883828151811061129057fe5b602002602001015111155b6112b75760405162461bcd60e51b815260040161083f90613afe565b60008282815181106112c557fe5b602002602001015110156112eb5760405162461bcd60e51b815260040161083f90613be2565b60006001820160098111156112fc57fe5b905083828151811061130a57fe5b60200260200101516003600083600981111561132257fe5b600981111561132d57fe5b81526020019081526020016000208190555082828151811061134b57fe5b60200260200101516004600083600981111561136357fe5b600981111561136e57fe5b815260208101919091526040016000205550600101611258565b50505160019081019055565b6001600160a01b031660009081526010602052604090205490565b670de0b6b3a764000081565b60046020526000908152604090205481565b60026020526000908152604090205481565b600560209081526000928352604080842090915290825290205481565b6002600654141561141f5760405162461bcd60e51b815260040161083f906140a7565b6002600655610c5e338383611d20565b600a5481565b6001600160a01b038216600090815260056020526040812060609183600981111561145c57fe5b600981111561146757fe5b8152602001908152602001600020600101805480602002602001604051908101604052809291908181526020016000905b828210156114e85783829060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505081526020019060010190611498565b50505050905092915050565b60005461010090046001600160a01b031633146115235760405162461bcd60e51b815260040161083f90613f0a565b600754600160a01b900460ff161561154d5760405162461bcd60e51b815260040161083f90613ad1565b60005460ff1661156f5760405162461bcd60e51b815260040161083f90613d98565b6115788161202c565b60078054600160a01b60ff60a01b19909116176001600160a01b0319166001600160a01b0392909216919091179055565b6060600f80548060200260200160405190810160405280929190818152602001828054801561160157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116115e3575b5050505050905090565b6001600160a01b031660009081526011602052604090205490565b600c6020526000908152604090205460ff1681565b6060610f0b8261226a565b60005461010090046001600160a01b031633146116755760405162461bcd60e51b815260040161083f90613f0a565b6001600160a01b03811661169b5760405162461bcd60e51b815260040161083f90613d63565b60008054610100600160a81b0319166101006001600160a01b038416021790556040517f3b7bfe3d10f9653af5256b806dc7064214844fd6646f0606f57a58397d66b4cc906109389083906137ac565b60005461010090046001600160a01b0316331461171a5760405162461bcd60e51b815260040161083f90613f0a565b60005460ff1661173c5760405162461bcd60e51b815260040161083f906139d8565b61174581612634565b6117615760405162461bcd60e51b815260040161083f90613b35565b60015481600981111561177057fe5b111561178e5760405162461bcd60e51b815260040161083f90613fad565b6103e883101580156117a25750610bb88311155b6117be5760405162461bcd60e51b815260040161083f90613afe565b600460008260098111156117ce57fe5b60098111156117d957fe5b8152602001908152602001600020548210156118075760405162461bcd60e51b815260040161083f90613be2565b826003600083600981111561181857fe5b600981111561182357fe5b815260200190815260200160002081905550816004600083600981111561184657fe5b600981111561185157fe5b815260208101919091526040016000205560015481600981111561187157fe5b1415610e8e576001805481019055505050565b6001600160a01b0382166000908152600560205260408120818360098111156118a957fe5b60098111156118b457fe5b81526020810191909152604001600020600101549392505050565b60106020526000908152604090205481565b60005461010090046001600160a01b031633146119105760405162461bcd60e51b815260040161083f90613f0a565b6001811515146119325760405162461bcd60e51b815260040161083f90613b9c565b60008054610100600160a81b031916908190556040517f3b7bfe3d10f9653af5256b806dc7064214844fd6646f0606f57a58397d66b4cc91610938916101009091046001600160a01b0316906137ac565b60085481565b601360205281600052604060002081600881106119a257fe5b01549150829050565b336000908152600c602052604090205460ff1615156001146119df5760405162461bcd60e51b815260040161083f90613f0a565b6119e7612075565b565b60026006541415611a0c5760405162461bcd60e51b815260040161083f906140a7565b6002600655600754600160a01b900460ff16611a3a5760405162461bcd60e51b815260040161083f90613b65565b60008111611a5a5760405162461bcd60e51b815260040161083f90613c19565b611a62612075565b336000908152601060205260408120548210611a8d5733600090815260106020526040902054611a8f565b815b3360008181526011602052604081205492935090611aad9084612662565b9050818110611ace5760405162461bcd60e51b815260040161083f90613d06565b6060611ad93361226a565b9050611ae433612312565b611afa611af184846128c3565b600954906128c3565b6009553360009081526011602090815260408083208590556010909152902054611b2490856128c3565b33600090815260106020526040902055600854611b4190856128c3565b60088190556040517f39658f9da14624f3526fe2a3a57af76cafe8623274ef4cefb09a1f313be6241991611b749161412c565b60405180910390a160075460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90611bae90339088906004016137e4565b602060405180830381600087803b158015611bc857600080fd5b505af1158015611bdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c0091906136f6565b611c1c5760405162461bcd60e51b815260040161083f9061396b565b33600081815260106020526040908190205490517f39df0e5286a3ef2f42a0bf52f32cfe2c58e5b0405f47fe512f2c2439e4cfe20491611c5b9161412c565b60405180910390a2336001600160a01b03167ff743583723cf40a86b06c9242edf63fe465e613d29e9e58b2560aa3306bcef6b83604051611c9c919061412c565b60405180910390a2336001600160a01b03167f20236d1f813fa1fbd42714507db9d3f2ef3b56e82163c2f91f4df6aacefca6c582604051611cdd91906138d5565b60405180910390a2611cef33826123a5565b50506001600655505050565b600060046000836009811115610ec357fe5b6000611d198383612905565b9392505050565b600754600160a01b900460ff16611d495760405162461bcd60e51b815260040161083f90613b65565b60008211611d695760405162461bcd60e51b815260040161083f90613f41565b600754600160a81b900460ff1680611d8c57506000816009811115611d8a57fe5b145b611da85760405162461bcd60e51b815260040161083f90613a26565b611db0612075565b6001600160a01b0383166000908152601160205260409020546060908015611dde57611ddb8561226a565b91505b611de785612312565b6000611df486868661297f565b9050611e0c611e0382846128c3565b60095490612c72565b6009556001600160a01b03861660009081526011602090815260408083208490556010909152902054611e3f9086612c72565b6001600160a01b038716600090815260106020526040902055600854611e659086612c72565b60088190556040517f39658f9da14624f3526fe2a3a57af76cafe8623274ef4cefb09a1f313be6241991611e989161412c565b60405180910390a16007546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611ed490339030908a906004016137c0565b602060405180830381600087803b158015611eee57600080fd5b505af1158015611f02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2691906136f6565b611f425760405162461bcd60e51b815260040161083f90613c87565b6001600160a01b038616600081815260106020526040908190205490517f39df0e5286a3ef2f42a0bf52f32cfe2c58e5b0405f47fe512f2c2439e4cfe20491611f8a9161412c565b60405180910390a2856001600160a01b03167ff743583723cf40a86b06c9242edf63fe465e613d29e9e58b2560aa3306bcef6b82604051611fcb919061412c565b60405180910390a2811561202457856001600160a01b03167f20236d1f813fa1fbd42714507db9d3f2ef3b56e82163c2f91f4df6aacefca6c58460405161201291906138d5565b60405180910390a261202486846123a5565b505050505050565b6001600160a01b0381166120525760405162461bcd60e51b815260040161083f90613c50565b803b806120715760405162461bcd60e51b815260040161083f90613f78565b5050565b600854156119e757600f5460005b8181101561225e576000600e6000600f848154811061209e57fe5b60009182526020808320909101546001600160a01b03168352820192909252604001812054600f805491935090849081106120d557fe5b60009182526020822001546040516370a0823160e01b81526001600160a01b03909116925082906370a08231906121109030906004016137ac565b60206040518083038186803b15801561212857600080fd5b505afa15801561213c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121609190613745565b90508281111561225357600061217682856128c3565b90506121de6121a260095461219c670de0b6b3a764000085612c9790919063ffffffff16565b90612cd1565b600d6000600f89815481106121b357fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205490612c72565b600d6000600f88815481106121ef57fe5b60009182526020808320909101546001600160a01b03168352820192909252604001812091909155600f80548492600e9290918990811061222c57fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902055505b505050600101612083565b50612267612d13565b50565b600f54606090818167ffffffffffffffff8111801561228857600080fd5b506040519080825280602002602001820160405280156122b2578160200160208202803683370190505b50905060005b8281101561230a576122eb85600f83815481106122d157fe5b6000918252602090912001546001600160a01b0316612905565b8282815181106122f757fe5b60209081029190910101526001016122b8565b509392505050565b600f5460005b81811015610e8e57600d6000600f838154811061233157fe5b60009182526020808320909101546001600160a01b039081168452838201949094526040928301822054938716825260129052908120600f80549192918590811061237857fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902055600101612318565b600f5460005b8181101561262e576000600f82815481106123c257fe5b60009182526020822001546040516370a0823160e01b81526001600160a01b03909116925082906370a08231906123fd9030906004016137ac565b60206040518083038186803b15801561241557600080fd5b505afa158015612429573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244d9190613745565b905084838151811061245b57fe5b60200260200101518110156124825760405162461bcd60e51b815260040161083f906140de565b84838151811061248e57fe5b6020026020010151600e6000600f86815481106124a757fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205410156124ea5760405162461bcd60e51b815260040161083f9061405a565b61253d8584815181106124f957fe5b6020026020010151600e6000600f878154811061251257fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902054906128c3565b600e6000600f868154811061254e57fe5b9060005260206000200160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002081905550816001600160a01b031663a9059cbb878786815181106125ac57fe5b60200260200101516040518363ffffffff1660e01b81526004016125d19291906137e4565b602060405180830381600087803b1580156125eb57600080fd5b505af11580156125ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262391906136f6565b5050506001016123ab565b50505050565b60008082600981111561264357fe5b10158015610f0b5750600982600981111561265a57fe5b111592915050565b6000805460ff166126855760405162461bcd60e51b815260040161083f90613b65565b600082116126a55760405162461bcd60e51b815260040161083f90613a72565b600080600080606060015467ffffffffffffffff811180156126c657600080fd5b506040519080825280602002602001820160405280156126f0578160200160208202803683370190505b5090506000805b60015481101561289b5780600981111561270d57fe5b6001600160a01b038b166000908152600560205260408120919350908184600981111561273657fe5b600981111561274157fe5b815260200190815260200160002060010180549050905060005b81811015612891576001600160a01b038c166000908152600560205260408120429186600981111561278957fe5b600981111561279457fe5b815260200190815260200160002060010182815481106127b057fe5b90600052602060002090600302016002015411612884576001600160a01b038c1660009081526005602052604081208a9950612831918660098111156127f257fe5b60098111156127fd57fe5b8152602001908152602001600020600101828154811061281957fe5b60009182526020909120600390910201548a90612c72565b98508060010185848151811061284357fe5b6020026020010181815250508a891061287f576128608b896128c3565b955061286e8c858888612de5565b9950610f0b98505050505050505050565b612889565b612891565b60010161275b565b50506001016126f7565b5050506001600160a01b03871660009081526002602052604090205494505050505092915050565b6000611d1983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612e96565b6001600160a01b038083166000908152601260209081526040808320938516835292815282822054600d90915291812054909190829061297690670de0b6b3a76400009061219c9061295790866128c3565b6001600160a01b03891660009081526011602052604090205490612c97565b95945050505050565b6000805460ff166129a25760405162461bcd60e51b815260040161083f90613b65565b600083116129c25760405162461bcd60e51b815260040161083f906139b1565b6129cb82612634565b6129e75760405162461bcd60e51b815260040161083f90613b35565b6001600160a01b0384166000908152600560205260408120600a91846009811115612a0e57fe5b6009811115612a1957fe5b815260208101919091526040016000206001015410612a4a5760405162461bcd60e51b815260040161083f90613cb6565b6001600160a01b0384166000908152600560205260408120612a9791859190856009811115612a7557fe5b6009811115612a8057fe5b815260208101919091526040016000205490612c72565b6001600160a01b038516600090815260056020526040812090846009811115612abc57fe5b6009811115612ac757fe5b8152602001908152602001600020600001819055506000612b27612b2060046000866009811115612af457fe5b6009811115612aff57fe5b81526020019081526020016000205462015180612c9790919063ffffffff16565b4290612c72565b6001600160a01b0386166000908152600560205260408120919250846009811115612b4e57fe5b6009811115612b5957fe5b8152602001908152602001600020600101604051806060016040528086815260200160036000876009811115612b8b57fe5b6009811115612b9657fe5b8152602080820192909252604090810160009081205484529282018690528454600181810187559584528284208551600392830290910190815592850151958301959095559290920151600290920191909155612c4d91612c2e916103e89161219c91886009811115612c0557fe5b6009811115612c1057fe5b81526020019081526020016000205488612c9790919063ffffffff16565b6001600160a01b03871660009081526002602052604090205490612c72565b6001600160a01b03861660009081526002602052604090208190559150509392505050565b600082820183811015611d195760405162461bcd60e51b815260040161083f90613a9a565b600082612ca657506000610f0b565b82820282848281612cb357fe5b0414611d195760405162461bcd60e51b815260040161083f90613dde565b6000611d1983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612ec2565b600b54620151800142106119e75760005b600f54811015612dd157600d6000600f8381548110612d3f57fe5b9060005260206000200160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020019081526020016000205460136000600f8481548110612d8f57fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020600a546008906001010660088110612dc757fe5b0155600101612d24565b5042600b55600a5460089060010106600a55565b6001600160a01b03841660009081526002602052604081205481856009811115612e0b57fe5b905060005b81600101811015612e6f576000858281518110612e2957fe5b60200260200101511115612e6757612e64612e5d89838560018a8781518110612e4e57fe5b6020026020010151038b612ef9565b84906128c3565b92505b600101612e10565b50506001600160a01b03861660009081526002602052604090208190559050949350505050565b60008184841115612eba5760405162461bcd60e51b815260040161083f9190613918565b505050900390565b60008183612ee35760405162461bcd60e51b815260040161083f9190613918565b506000838581612eef57fe5b0495945050505050565b600080806001850181886009811115612f0e57fe5b905087891415613061576001600160a01b038a16600090815260056020526040812090826009811115612f3d57fe5b6009811115612f4857fe5b81526020019081526020016000206001018781548110612f6457fe5b9060005260206000209060030201600001548614613061576001600160a01b038a166000908152600560205260408120612fe591889190846009811115612fa757fe5b6009811115612fb257fe5b81526020019081526020016000206001018981548110612fce57fe5b6000918252602090912060039091020154906128c3565b6001600160a01b038b1660009081526005602052604081209083600981111561300a57fe5b600981111561301557fe5b8152602001908152602001600020600101888154811061303157fe5b600091825260209091206003909102015585935061305b613054858c848b61343b565b8490612c72565b92508691505b6001600160a01b038a16600090815260056020526040812083906130b39082908486600981111561308e57fe5b600981111561309957fe5b8152602081019190915260400160002060010154906128c3565b11156130eb576001600160a01b038b1660009081526005602052604081206130e49185919085600981111561308e57fe5b90506130ee565b50815b60005b8181101561331657838110156131e2576001600160a01b038c1660009081526005602052604081206131689185600981111561312957fe5b600981111561313457fe5b8152602001908152602001600020600101828154811061315057fe5b60009182526020909120600390910201548790612c72565b6001600160a01b038d1660009081526005602052604081209197506131df916131d89186600981111561319757fe5b60098111156131a257fe5b815260200190815260200160002060010183815481106131be57fe5b9060005260206000209060030201600001548e868561343b565b8690612c72565b94505b6001600160a01b038c166000908152600560205260408120859185600981111561320857fe5b600981111561321357fe5b81526020810191909152604001600020600101540381101561330e576001600160a01b038c1660009081526005602052604081209084600981111561325457fe5b600981111561325f57fe5b81526020019081526020016000206001018482018154811061327d57fe5b9060005260206000209060030201600560008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008560098111156132be57fe5b60098111156132c957fe5b815260200190815260200160002060010182815481106132e557fe5b600091825260209091208254600390920201908155600180830154908201556002918201549101555b6001016130f1565b5060005b8381101561339d576001600160a01b038c1660009081526005602052604081209084600981111561334757fe5b600981111561335257fe5b815260200190815260200160002060010180548061336c57fe5b600082815260208120600360001990930192830201818155600181810183905560029091019190915591550161331a565b506001600160a01b038b1660009081526005602052604081206133eb918791908560098111156133c957fe5b60098111156133d457fe5b8152602081019190915260400160002054906128c3565b6001600160a01b038c1660009081526005602052604081209084600981111561341057fe5b600981111561341b57fe5b815260208101919091526040016000205550919998505050505050505050565b6001600160a01b0383166000908152600560205260408120612976906103e89061219c908487600981111561346c57fe5b600981111561347757fe5b8152602001908152602001600020600101858154811061349357fe5b90600052602060002090600302016001015488612c9790919063ffffffff16565b6040518061010001604052806008906020820280368337509192915050565b80356001600160a01b0381168114610f0b57600080fd5b600082601f8301126134fa578081fd5b813567ffffffffffffffff80821115613511578283fd5b60208083026040518282820101818110858211171561352e578687fd5b60405284815294508185019250858201818701830188101561354f57600080fd5b600091505b84821015613572578035845292820192600191909101908201613554565b505050505092915050565b8035600a8110610f0b57600080fd5b60006020828403121561359d578081fd5b611d1983836134d3565b600080604083850312156135b9578081fd5b6135c384846134d3565b91506135d284602085016134d3565b90509250929050565b600080604083850312156135ed578182fd5b82356001600160a01b0381168114613603578283fd5b91506135d2846020850161357d565b60008060408385031215613624578182fd5b61362e84846134d3565b946020939093013593505050565b600080600060608486031215613650578081fd5b61365a85856134d3565b925060208401359150613670856040860161357d565b90509250925092565b6000806040838503121561368b578182fd5b823567ffffffffffffffff808211156136a2578384fd5b6136ae868387016134ea565b935060208501359150808211156136c3578283fd5b506136d0858286016134ea565b9150509250929050565b6000602082840312156136eb578081fd5b8135611d1981614135565b600060208284031215613707578081fd5b8151611d1981614135565b600060208284031215613723578081fd5b611d19838361357d565b60006020828403121561373e578081fd5b5035919050565b600060208284031215613756578081fd5b5051919050565b6000806040838503121561376f578182fd5b823591506135d2846020850161357d565b600080600060608486031215613794578283fd5b8335925060208401359150613670856040860161357d565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b8181101561383e5783516001600160a01b031683529284019291840191600101613819565b50909695505050505050565b602080825282518282018190526000919060409081850190868401855b828110156138965781518051855286810151878601528501518585015260609093019290850190600101613867565b5091979650505050505050565b6101008101818360005b60088110156138cc5781518352602092830192909101906001016138ad565b50505092915050565b6020808252825182820181905260009190848201906040850190845b8181101561383e578351835292840192918401916001016138f1565b901515815260200190565b6000602080835283518082850152825b8181101561394457858101830151858201604001528201613928565b818111156139555783604083870101525b50601f01601f1916929092016040019392505050565b60208082526026908201527f4d6572696469616e5374616b696e673a20546f6b656e207472616e736665722060408201526519985a5b195960d21b606082015260800190565b6020808252600d908201526c496e76616c6964207374616b6560981b604082015260600190565b6020808252602e908201527f55736520696e697469616c697a65496e766573746d656e747320746f2066697260408201526d737420736574757020706f6f6c7360901b606082015260800190565b6020808252602c908201527f4d6572696469616e5374616b696e673a20496e766573746d656e7420506f6f6c60408201526b081b9bdd08195b98589b195960a21b606082015260800190565b6020808252600e908201526d125b9d985b1a5908185b5bdd5b9d60921b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b602080825260139082015272105b1c9958591e48125b9a5d1a585b1a5e9959606a1b604082015260600190565b6020808252601d908201527f496e76616c696420696e766573746d656e74206d756c7469706c696572000000604082015260600190565b602080825260169082015275496e76616c696420496e766573746d656e745479706560501b604082015260600190565b6020808252601c908201527f436f6e7472616374206e6f742079657420696e697469616c697a656400000000604082015260600190565b60208082526026908201527f4d6572696469616e5374616b696e673a2072656e6f756e6365206d757374206260408201526565207472756560d01b606082015260800190565b6020808252601b908201527f496e76616c696420696e766573746d656e74206475726174696f6e0000000000604082015260600190565b6020808252601f908201527f4d6572696469616e5374616b696e673a20496e76616c696420616d6f756e7400604082015260600190565b6020808252601e908201527f4163636f756e742063616e6e6f74206265207a65726f20616464726573730000604082015260600190565b602080825260159082015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b604082015260600190565b60208082526030908201527f4d6178206e756d626572206f6620696e766573746d656e74732065786365656460408201526f195908199bdc881d1a1a5cc81c1bdbdb60821b606082015260800190565b60208082526037908201527f4d6572696469616e5374616b696e673a20496e73756666696369656e7420667560408201527f6e647320617661696c61626c6520746f2072656465656d000000000000000000606082015260800190565b6020808252818101527f4d6572696469616e5374616b696e673a20496e76616c69642061646472657373604082015260600190565b60208082526026908201527f4d75737420696e697469616c697a6520696e766573746d656e7420706f6f6c7360408201526508199a5c9cdd60d21b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602e908201527f4d6572696469616e5374616b696e673a2055736572206d75737420686176652060408201526d6e6f6e2d7a65726f207374616b6560901b606082015260800190565b6020808252600e908201526d546f6f206d616e7920706f6f6c7360901b604082015260600190565b602080825260149082015273496e76616c696420696e7075742061727261797360601b604082015260600190565b60208082526027908201527f4d6572696469616e5374616b696e673a20546f6f206d616e792072657761726460408201526620746f6b656e7360c81b606082015260800190565b6020808252601a908201527f4d6572696469616e5374616b696e673a20466f7262696464656e000000000000604082015260600190565b6020808252601e908201527f4d6572696469616e5374616b696e673a20496e76616c6964207374616b650000604082015260600190565b6020808252818101527f4163636f756e7420636f64652073697a652063616e6e6f74206265207a65726f604082015260600190565b60208082526030908201527f4e6f74206e65787420706f6f6c2e20506f6f6c73206d7573742062652073657460408201526f2075702073657175656e7469616c6c7960801b606082015260800190565b6020808252603a908201527f4d6572696469616e5374616b696e673a2043616e6e6f742072656d6f7665207460408201527f6f6b656e2077697468206e6f6e2d7a65726f2072657761726473000000000000606082015260800190565b6020808252602d908201527f4d6572696469616e5374616b696e673a20496e73756666696369656e7420726560408201526c77617264732062616c616e636560981b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602e908201527f4d6572696469616e5374616b696e673a20496e73756666696369656e7420636f60408201526d6e74726163742062616c616e636560901b606082015260800190565b90815260200190565b801515811461226757600080fdfea264697066735822122071f9d7de36bb6be53dc576498f0cdba64e39e59f2f31b3d93ba12cb1af148cc464736f6c634300060c0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106103ba5760003560e01c806385c7b427116101f4578063c4f59f9b1161011a578063e04664ca116100ad578063ed03e78c1161007c578063ed03e78c14610496578063fa6886ec14610779578063fbf6924e1461078c578063fe0f3a131461079f576103ba565b8063e04664ca14610743578063e10182b114610756578063e95f26981461075e578063ebc54c7c14610771576103ba565b8063cfad57a2116100e9578063cfad57a2146106f7578063d64efe9c1461070a578063da54c29d1461071d578063dd93e06a14610730576103ba565b8063c4f59f9b146106a9578063c9c313d9146106be578063cd5d2118146106d1578063cf7c11fa146106e4576103ba565b8063a905dbb011610192578063b4559d1011610161578063b4559d10146103fb578063b977965b1461066e578063bc825d2314610676578063c4d66de814610696576103ba565b8063a905dbb014610622578063aadcef8614610635578063b041337314610648578063b1f5de401461065b576103ba565b806390c87f13116101ce57806390c87f13146105e15780639e37c281146105f45780639e57dade14610607578063a20baee61461061a576103ba565b806385c7b427146105b357806389c23dba146105c65780638a5cc320146105d9576103ba565b8063392e53cd116102e45780636a8cb20f116102775780637bb7bed1116102465780637bb7bed1146105725780637ec475a8146105855780637f3fd918146105985780638281511c146105ab576103ba565b80636a8cb20f146105525780636f682a531461055a57806371860c4f146105625780637645ff1a1461056a576103ba565b80634d1df007116102b35780634d1df007146105275780635ce7b15f1461053a5780635d0cde97146105425780635d6a618d1461054a576103ba565b8063392e53cd146104d95780633d509c97146104ee5780633e40c5c6146105015780634cc4bc4114610514576103ba565b80631c03e6cc1161035c5780632a46d7251161032b5780632a46d725146104965780632b2e05c11461049e5780632d788644146104b1578063372500ab146104d1576103ba565b80631c03e6cc146104535780631e74d25714610466578063240dc9321461047b578063288f68661461048e576103ba565b806312d43a511161039857806312d43a511461040357806313a0c44314610418578063157d1c7e1461042b5780631b01df911461043e576103ba565b806307701cc3146103bf5780630ada74e9146103e85780630cec3148146103fb575b600080fd5b6103d26103cd36600461358c565b6107b2565b6040516103df919061412c565b60405180910390f35b6103d26103f6366004613712565b6107cd565b6103d26107df565b61040b6107e4565b6040516103df91906137ac565b6103d261042636600461358c565b6107f8565b6103d261043936600461358c565b61080a565b61045161044c36600461363c565b61081c565b005b61045161046136600461358c565b610862565b61046e610943565b6040516103df91906138d5565b6104516104893660046136da565b6109fa565b6103d2610a70565b6103d2610a76565b6104516104ac36600461358c565b610a7c565b6104c46104bf36600461358c565b610b24565b6040516103df91906138a3565b610451610b77565b6104e1610c67565b6040516103df919061390d565b6104516104fc36600461358c565b610c77565b6104e161050f36600461358c565b610e93565b6103d2610522366004613712565b610eb1565b6103d26105353660046135a7565b610ee4565b6103d2610f11565b6103d2610f17565b6103d2610f1c565b61046e610f22565b6103d2610fd2565b6104e1610fd8565b61040b610fe1565b61040b61058036600461372d565b610ff0565b6103d26105933660046135a7565b611017565b6104516105a636600461358c565b611034565b6104e16110d9565b6103d26105c136600461358c565b6110e9565b6103d26105d436600461358c565b6110fb565b6103d2611116565b6103d26105ef3660046135db565b61111d565b610451610602366004613679565b611165565b6103d261061536600461358c565b611394565b6103d26113af565b6103d2610630366004613712565b6113bb565b6103d261064336600461358c565b6113cd565b6103d26106563660046135db565b6113df565b61045161066936600461375d565b6113fc565b6103d261142f565b6106896106843660046135db565b611435565b6040516103df919061384a565b6104516106a436600461358c565b6114f4565b6106b16115a9565b6040516103df91906137fd565b6103d26106cc36600461358c565b61160b565b6104e16106df36600461358c565b611626565b61046e6106f236600461358c565b61163b565b61045161070536600461358c565b611646565b610451610718366004613780565b6116eb565b6103d261072b3660046135db565b611884565b6103d261073e36600461358c565b6118cf565b6104516107513660046136da565b6118e1565b6103d2611983565b6103d261076c366004613612565b611989565b6104516119ab565b61045161078736600461372d565b6119e9565b6103d261079a366004613712565b611cfb565b6103d26107ad3660046135a7565b611d0d565b6001600160a01b03166000908152600e602052604090205490565b60036020526000908152604090205481565b600a81565b60005461010090046001600160a01b031681565b600d6020526000908152604090205481565b60116020526000908152604090205481565b600260065414156108485760405162461bcd60e51b815260040161083f906140a7565b60405180910390fd5b6002600655610858838383611d20565b5050600160065550565b60005461010090046001600160a01b031633146108915760405162461bcd60e51b815260040161083f90613f0a565b61089a8161202c565b600f54600c10156108bd5760405162461bcd60e51b815260040161083f90613ec3565b600f80546001810182556000919091527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020180546001600160a01b0319166001600160a01b0383161790556040517fc69f61e4bef149d13a9bb253756b4b6e0b1c2cd402efb69dfec416c6201d0bf1906109389083906137ac565b60405180910390a150565b600f54606090818167ffffffffffffffff8111801561096157600080fd5b5060405190808252806020026020018201604052801561098b578160200160208202803683370190505b50905060005b828110156109f3576000600f82815481106109a857fe5b60009182526020808320909101546001600160a01b0316808352600d9091526040909120548451919250908490849081106109df57fe5b602090810291909101015250600101610991565b5091505090565b60005461010090046001600160a01b03163314610a295760405162461bcd60e51b815260040161083f90613f0a565b6007805460ff60a81b1916600160a81b831515021790556040517ff07c2a5f22b138bfc567e9aa9624d0f15f436d28d49abe1c65e92a72c74a832e9061093890839061390d565b60095481565b6103e881565b60005461010090046001600160a01b03163314610aab5760405162461bcd60e51b815260040161083f90613f0a565b6001600160a01b038116610ad15760405162461bcd60e51b815260040161083f90613d63565b6001600160a01b0381166000908152600c602052604090819020805460ff19166001179055517f9f511455548a603e61f1cc70bb0a622d2ad70cb8b318198695efc90b5fce4e4c906109389083906137ac565b610b2c6134b4565b6001600160a01b0382166000908152601360205260409081902081516101008101928390529160089082845b815481526020019060010190808311610b585750505050509050919050565b60026006541415610b9a5760405162461bcd60e51b815260040161083f906140a7565b6002600655600754600160a01b900460ff16610bc85760405162461bcd60e51b815260040161083f90613b65565b610bd0612075565b3360009081526011602052604090205480610bfd5760405162461bcd60e51b815260040161083f90613e1f565b6060610c083361226a565b9050610c1333612312565b336001600160a01b03167f20236d1f813fa1fbd42714507db9d3f2ef3b56e82163c2f91f4df6aacefca6c582604051610c4c91906138d5565b60405180910390a2610c5e33826123a5565b50506001600655565b600754600160a01b900460ff1681565b60005461010090046001600160a01b03163314610ca65760405162461bcd60e51b815260040161083f90613f0a565b610caf8161202c565b6040516370a0823160e01b815281906001600160a01b038216906370a0823190610cdd9030906004016137ac565b60206040518083038186803b158015610cf557600080fd5b505afa158015610d09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2d9190613745565b15610d4a5760405162461bcd60e51b815260040161083f90613ffd565b60005b600f54811015610e8e57826001600160a01b0316600f8281548110610d6e57fe5b6000918252602090912001546001600160a01b03161415610e8657805b600f5460001901811015610e0057600f8160010181548110610da957fe5b600091825260209091200154600f80546001600160a01b039092169183908110610dcf57fe5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600101610d8b565b50600f805480610e0c57fe5b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0385168252600d9052604080822091909155517fb5494e609b7d7189b9fd268eb38adea381bfc53fb5eeeab9dd8ecc3f8af9539e90610e799085906137ac565b60405180910390a1610e8e565b600101610d4d565b505050565b6001600160a01b03166000908152600c602052604090205460ff1690565b600060036000836009811115610ec357fe5b6009811115610ece57fe5b8152602001908152602001600020549050919050565b6001600160a01b038083166000908152601260209081526040808320938516835292905220545b92915050565b600b5481565b600c81565b610bb881565b600f54606090818167ffffffffffffffff81118015610f4057600080fd5b50604051908082528060200260200182016040528015610f6a578160200160208202803683370190505b50905060005b828110156109f3576000600f8281548110610f8757fe5b60009182526020808320909101546001600160a01b0316808352600e909152604090912054845191925090849084908110610fbe57fe5b602090810291909101015250600101610f70565b60015481565b60005460ff1681565b6007546001600160a01b031681565b600f8181548110610ffd57fe5b6000918252602090912001546001600160a01b0316905081565b601260209081526000928352604080842090915290825290205481565b60005461010090046001600160a01b031633146110635760405162461bcd60e51b815260040161083f90613f0a565b6001600160a01b0381166110895760405162461bcd60e51b815260040161083f90613d63565b6001600160a01b0381166000908152600c602052604090819020805460ff19169055517f54cba8c838ee951b9ccef4916ea25b653956ac3302498f6c4f28f0473ff4c583906109389083906137ac565b600754600160a81b900460ff1681565b600e6020526000908152604090205481565b6001600160a01b03166000908152600d602052604090205490565b6201518081565b6001600160a01b03821660009081526005602052604081208183600981111561114257fe5b600981111561114d57fe5b81526020810191909152604001600020549392505050565b60005461010090046001600160a01b031633146111945760405162461bcd60e51b815260040161083f90613f0a565b60005460ff16156111b75760405162461bcd60e51b815260040161083f90613ad1565b600a8251106111d85760405162461bcd60e51b815260040161083f90613e6d565b80518251146111f95760405162461bcd60e51b815260040161083f90613e95565b6000805460ff191660011781558080526103e87f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff5560046020527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec8190555b8251811015611388576103e883828151811061127057fe5b60200260200101511015801561129b5750610bb883828151811061129057fe5b602002602001015111155b6112b75760405162461bcd60e51b815260040161083f90613afe565b60008282815181106112c557fe5b602002602001015110156112eb5760405162461bcd60e51b815260040161083f90613be2565b60006001820160098111156112fc57fe5b905083828151811061130a57fe5b60200260200101516003600083600981111561132257fe5b600981111561132d57fe5b81526020019081526020016000208190555082828151811061134b57fe5b60200260200101516004600083600981111561136357fe5b600981111561136e57fe5b815260208101919091526040016000205550600101611258565b50505160019081019055565b6001600160a01b031660009081526010602052604090205490565b670de0b6b3a764000081565b60046020526000908152604090205481565b60026020526000908152604090205481565b600560209081526000928352604080842090915290825290205481565b6002600654141561141f5760405162461bcd60e51b815260040161083f906140a7565b6002600655610c5e338383611d20565b600a5481565b6001600160a01b038216600090815260056020526040812060609183600981111561145c57fe5b600981111561146757fe5b8152602001908152602001600020600101805480602002602001604051908101604052809291908181526020016000905b828210156114e85783829060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505081526020019060010190611498565b50505050905092915050565b60005461010090046001600160a01b031633146115235760405162461bcd60e51b815260040161083f90613f0a565b600754600160a01b900460ff161561154d5760405162461bcd60e51b815260040161083f90613ad1565b60005460ff1661156f5760405162461bcd60e51b815260040161083f90613d98565b6115788161202c565b60078054600160a01b60ff60a01b19909116176001600160a01b0319166001600160a01b0392909216919091179055565b6060600f80548060200260200160405190810160405280929190818152602001828054801561160157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116115e3575b5050505050905090565b6001600160a01b031660009081526011602052604090205490565b600c6020526000908152604090205460ff1681565b6060610f0b8261226a565b60005461010090046001600160a01b031633146116755760405162461bcd60e51b815260040161083f90613f0a565b6001600160a01b03811661169b5760405162461bcd60e51b815260040161083f90613d63565b60008054610100600160a81b0319166101006001600160a01b038416021790556040517f3b7bfe3d10f9653af5256b806dc7064214844fd6646f0606f57a58397d66b4cc906109389083906137ac565b60005461010090046001600160a01b0316331461171a5760405162461bcd60e51b815260040161083f90613f0a565b60005460ff1661173c5760405162461bcd60e51b815260040161083f906139d8565b61174581612634565b6117615760405162461bcd60e51b815260040161083f90613b35565b60015481600981111561177057fe5b111561178e5760405162461bcd60e51b815260040161083f90613fad565b6103e883101580156117a25750610bb88311155b6117be5760405162461bcd60e51b815260040161083f90613afe565b600460008260098111156117ce57fe5b60098111156117d957fe5b8152602001908152602001600020548210156118075760405162461bcd60e51b815260040161083f90613be2565b826003600083600981111561181857fe5b600981111561182357fe5b815260200190815260200160002081905550816004600083600981111561184657fe5b600981111561185157fe5b815260208101919091526040016000205560015481600981111561187157fe5b1415610e8e576001805481019055505050565b6001600160a01b0382166000908152600560205260408120818360098111156118a957fe5b60098111156118b457fe5b81526020810191909152604001600020600101549392505050565b60106020526000908152604090205481565b60005461010090046001600160a01b031633146119105760405162461bcd60e51b815260040161083f90613f0a565b6001811515146119325760405162461bcd60e51b815260040161083f90613b9c565b60008054610100600160a81b031916908190556040517f3b7bfe3d10f9653af5256b806dc7064214844fd6646f0606f57a58397d66b4cc91610938916101009091046001600160a01b0316906137ac565b60085481565b601360205281600052604060002081600881106119a257fe5b01549150829050565b336000908152600c602052604090205460ff1615156001146119df5760405162461bcd60e51b815260040161083f90613f0a565b6119e7612075565b565b60026006541415611a0c5760405162461bcd60e51b815260040161083f906140a7565b6002600655600754600160a01b900460ff16611a3a5760405162461bcd60e51b815260040161083f90613b65565b60008111611a5a5760405162461bcd60e51b815260040161083f90613c19565b611a62612075565b336000908152601060205260408120548210611a8d5733600090815260106020526040902054611a8f565b815b3360008181526011602052604081205492935090611aad9084612662565b9050818110611ace5760405162461bcd60e51b815260040161083f90613d06565b6060611ad93361226a565b9050611ae433612312565b611afa611af184846128c3565b600954906128c3565b6009553360009081526011602090815260408083208590556010909152902054611b2490856128c3565b33600090815260106020526040902055600854611b4190856128c3565b60088190556040517f39658f9da14624f3526fe2a3a57af76cafe8623274ef4cefb09a1f313be6241991611b749161412c565b60405180910390a160075460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90611bae90339088906004016137e4565b602060405180830381600087803b158015611bc857600080fd5b505af1158015611bdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c0091906136f6565b611c1c5760405162461bcd60e51b815260040161083f9061396b565b33600081815260106020526040908190205490517f39df0e5286a3ef2f42a0bf52f32cfe2c58e5b0405f47fe512f2c2439e4cfe20491611c5b9161412c565b60405180910390a2336001600160a01b03167ff743583723cf40a86b06c9242edf63fe465e613d29e9e58b2560aa3306bcef6b83604051611c9c919061412c565b60405180910390a2336001600160a01b03167f20236d1f813fa1fbd42714507db9d3f2ef3b56e82163c2f91f4df6aacefca6c582604051611cdd91906138d5565b60405180910390a2611cef33826123a5565b50506001600655505050565b600060046000836009811115610ec357fe5b6000611d198383612905565b9392505050565b600754600160a01b900460ff16611d495760405162461bcd60e51b815260040161083f90613b65565b60008211611d695760405162461bcd60e51b815260040161083f90613f41565b600754600160a81b900460ff1680611d8c57506000816009811115611d8a57fe5b145b611da85760405162461bcd60e51b815260040161083f90613a26565b611db0612075565b6001600160a01b0383166000908152601160205260409020546060908015611dde57611ddb8561226a565b91505b611de785612312565b6000611df486868661297f565b9050611e0c611e0382846128c3565b60095490612c72565b6009556001600160a01b03861660009081526011602090815260408083208490556010909152902054611e3f9086612c72565b6001600160a01b038716600090815260106020526040902055600854611e659086612c72565b60088190556040517f39658f9da14624f3526fe2a3a57af76cafe8623274ef4cefb09a1f313be6241991611e989161412c565b60405180910390a16007546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611ed490339030908a906004016137c0565b602060405180830381600087803b158015611eee57600080fd5b505af1158015611f02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2691906136f6565b611f425760405162461bcd60e51b815260040161083f90613c87565b6001600160a01b038616600081815260106020526040908190205490517f39df0e5286a3ef2f42a0bf52f32cfe2c58e5b0405f47fe512f2c2439e4cfe20491611f8a9161412c565b60405180910390a2856001600160a01b03167ff743583723cf40a86b06c9242edf63fe465e613d29e9e58b2560aa3306bcef6b82604051611fcb919061412c565b60405180910390a2811561202457856001600160a01b03167f20236d1f813fa1fbd42714507db9d3f2ef3b56e82163c2f91f4df6aacefca6c58460405161201291906138d5565b60405180910390a261202486846123a5565b505050505050565b6001600160a01b0381166120525760405162461bcd60e51b815260040161083f90613c50565b803b806120715760405162461bcd60e51b815260040161083f90613f78565b5050565b600854156119e757600f5460005b8181101561225e576000600e6000600f848154811061209e57fe5b60009182526020808320909101546001600160a01b03168352820192909252604001812054600f805491935090849081106120d557fe5b60009182526020822001546040516370a0823160e01b81526001600160a01b03909116925082906370a08231906121109030906004016137ac565b60206040518083038186803b15801561212857600080fd5b505afa15801561213c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121609190613745565b90508281111561225357600061217682856128c3565b90506121de6121a260095461219c670de0b6b3a764000085612c9790919063ffffffff16565b90612cd1565b600d6000600f89815481106121b357fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205490612c72565b600d6000600f88815481106121ef57fe5b60009182526020808320909101546001600160a01b03168352820192909252604001812091909155600f80548492600e9290918990811061222c57fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902055505b505050600101612083565b50612267612d13565b50565b600f54606090818167ffffffffffffffff8111801561228857600080fd5b506040519080825280602002602001820160405280156122b2578160200160208202803683370190505b50905060005b8281101561230a576122eb85600f83815481106122d157fe5b6000918252602090912001546001600160a01b0316612905565b8282815181106122f757fe5b60209081029190910101526001016122b8565b509392505050565b600f5460005b81811015610e8e57600d6000600f838154811061233157fe5b60009182526020808320909101546001600160a01b039081168452838201949094526040928301822054938716825260129052908120600f80549192918590811061237857fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902055600101612318565b600f5460005b8181101561262e576000600f82815481106123c257fe5b60009182526020822001546040516370a0823160e01b81526001600160a01b03909116925082906370a08231906123fd9030906004016137ac565b60206040518083038186803b15801561241557600080fd5b505afa158015612429573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244d9190613745565b905084838151811061245b57fe5b60200260200101518110156124825760405162461bcd60e51b815260040161083f906140de565b84838151811061248e57fe5b6020026020010151600e6000600f86815481106124a757fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205410156124ea5760405162461bcd60e51b815260040161083f9061405a565b61253d8584815181106124f957fe5b6020026020010151600e6000600f878154811061251257fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902054906128c3565b600e6000600f868154811061254e57fe5b9060005260206000200160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002081905550816001600160a01b031663a9059cbb878786815181106125ac57fe5b60200260200101516040518363ffffffff1660e01b81526004016125d19291906137e4565b602060405180830381600087803b1580156125eb57600080fd5b505af11580156125ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262391906136f6565b5050506001016123ab565b50505050565b60008082600981111561264357fe5b10158015610f0b5750600982600981111561265a57fe5b111592915050565b6000805460ff166126855760405162461bcd60e51b815260040161083f90613b65565b600082116126a55760405162461bcd60e51b815260040161083f90613a72565b600080600080606060015467ffffffffffffffff811180156126c657600080fd5b506040519080825280602002602001820160405280156126f0578160200160208202803683370190505b5090506000805b60015481101561289b5780600981111561270d57fe5b6001600160a01b038b166000908152600560205260408120919350908184600981111561273657fe5b600981111561274157fe5b815260200190815260200160002060010180549050905060005b81811015612891576001600160a01b038c166000908152600560205260408120429186600981111561278957fe5b600981111561279457fe5b815260200190815260200160002060010182815481106127b057fe5b90600052602060002090600302016002015411612884576001600160a01b038c1660009081526005602052604081208a9950612831918660098111156127f257fe5b60098111156127fd57fe5b8152602001908152602001600020600101828154811061281957fe5b60009182526020909120600390910201548a90612c72565b98508060010185848151811061284357fe5b6020026020010181815250508a891061287f576128608b896128c3565b955061286e8c858888612de5565b9950610f0b98505050505050505050565b612889565b612891565b60010161275b565b50506001016126f7565b5050506001600160a01b03871660009081526002602052604090205494505050505092915050565b6000611d1983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612e96565b6001600160a01b038083166000908152601260209081526040808320938516835292815282822054600d90915291812054909190829061297690670de0b6b3a76400009061219c9061295790866128c3565b6001600160a01b03891660009081526011602052604090205490612c97565b95945050505050565b6000805460ff166129a25760405162461bcd60e51b815260040161083f90613b65565b600083116129c25760405162461bcd60e51b815260040161083f906139b1565b6129cb82612634565b6129e75760405162461bcd60e51b815260040161083f90613b35565b6001600160a01b0384166000908152600560205260408120600a91846009811115612a0e57fe5b6009811115612a1957fe5b815260208101919091526040016000206001015410612a4a5760405162461bcd60e51b815260040161083f90613cb6565b6001600160a01b0384166000908152600560205260408120612a9791859190856009811115612a7557fe5b6009811115612a8057fe5b815260208101919091526040016000205490612c72565b6001600160a01b038516600090815260056020526040812090846009811115612abc57fe5b6009811115612ac757fe5b8152602001908152602001600020600001819055506000612b27612b2060046000866009811115612af457fe5b6009811115612aff57fe5b81526020019081526020016000205462015180612c9790919063ffffffff16565b4290612c72565b6001600160a01b0386166000908152600560205260408120919250846009811115612b4e57fe5b6009811115612b5957fe5b8152602001908152602001600020600101604051806060016040528086815260200160036000876009811115612b8b57fe5b6009811115612b9657fe5b8152602080820192909252604090810160009081205484529282018690528454600181810187559584528284208551600392830290910190815592850151958301959095559290920151600290920191909155612c4d91612c2e916103e89161219c91886009811115612c0557fe5b6009811115612c1057fe5b81526020019081526020016000205488612c9790919063ffffffff16565b6001600160a01b03871660009081526002602052604090205490612c72565b6001600160a01b03861660009081526002602052604090208190559150509392505050565b600082820183811015611d195760405162461bcd60e51b815260040161083f90613a9a565b600082612ca657506000610f0b565b82820282848281612cb357fe5b0414611d195760405162461bcd60e51b815260040161083f90613dde565b6000611d1983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612ec2565b600b54620151800142106119e75760005b600f54811015612dd157600d6000600f8381548110612d3f57fe5b9060005260206000200160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020019081526020016000205460136000600f8481548110612d8f57fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020600a546008906001010660088110612dc757fe5b0155600101612d24565b5042600b55600a5460089060010106600a55565b6001600160a01b03841660009081526002602052604081205481856009811115612e0b57fe5b905060005b81600101811015612e6f576000858281518110612e2957fe5b60200260200101511115612e6757612e64612e5d89838560018a8781518110612e4e57fe5b6020026020010151038b612ef9565b84906128c3565b92505b600101612e10565b50506001600160a01b03861660009081526002602052604090208190559050949350505050565b60008184841115612eba5760405162461bcd60e51b815260040161083f9190613918565b505050900390565b60008183612ee35760405162461bcd60e51b815260040161083f9190613918565b506000838581612eef57fe5b0495945050505050565b600080806001850181886009811115612f0e57fe5b905087891415613061576001600160a01b038a16600090815260056020526040812090826009811115612f3d57fe5b6009811115612f4857fe5b81526020019081526020016000206001018781548110612f6457fe5b9060005260206000209060030201600001548614613061576001600160a01b038a166000908152600560205260408120612fe591889190846009811115612fa757fe5b6009811115612fb257fe5b81526020019081526020016000206001018981548110612fce57fe5b6000918252602090912060039091020154906128c3565b6001600160a01b038b1660009081526005602052604081209083600981111561300a57fe5b600981111561301557fe5b8152602001908152602001600020600101888154811061303157fe5b600091825260209091206003909102015585935061305b613054858c848b61343b565b8490612c72565b92508691505b6001600160a01b038a16600090815260056020526040812083906130b39082908486600981111561308e57fe5b600981111561309957fe5b8152602081019190915260400160002060010154906128c3565b11156130eb576001600160a01b038b1660009081526005602052604081206130e49185919085600981111561308e57fe5b90506130ee565b50815b60005b8181101561331657838110156131e2576001600160a01b038c1660009081526005602052604081206131689185600981111561312957fe5b600981111561313457fe5b8152602001908152602001600020600101828154811061315057fe5b60009182526020909120600390910201548790612c72565b6001600160a01b038d1660009081526005602052604081209197506131df916131d89186600981111561319757fe5b60098111156131a257fe5b815260200190815260200160002060010183815481106131be57fe5b9060005260206000209060030201600001548e868561343b565b8690612c72565b94505b6001600160a01b038c166000908152600560205260408120859185600981111561320857fe5b600981111561321357fe5b81526020810191909152604001600020600101540381101561330e576001600160a01b038c1660009081526005602052604081209084600981111561325457fe5b600981111561325f57fe5b81526020019081526020016000206001018482018154811061327d57fe5b9060005260206000209060030201600560008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008560098111156132be57fe5b60098111156132c957fe5b815260200190815260200160002060010182815481106132e557fe5b600091825260209091208254600390920201908155600180830154908201556002918201549101555b6001016130f1565b5060005b8381101561339d576001600160a01b038c1660009081526005602052604081209084600981111561334757fe5b600981111561335257fe5b815260200190815260200160002060010180548061336c57fe5b600082815260208120600360001990930192830201818155600181810183905560029091019190915591550161331a565b506001600160a01b038b1660009081526005602052604081206133eb918791908560098111156133c957fe5b60098111156133d457fe5b8152602081019190915260400160002054906128c3565b6001600160a01b038c1660009081526005602052604081209084600981111561341057fe5b600981111561341b57fe5b815260208101919091526040016000205550919998505050505050505050565b6001600160a01b0383166000908152600560205260408120612976906103e89061219c908487600981111561346c57fe5b600981111561347757fe5b8152602001908152602001600020600101858154811061349357fe5b90600052602060002090600302016001015488612c9790919063ffffffff16565b6040518061010001604052806008906020820280368337509192915050565b80356001600160a01b0381168114610f0b57600080fd5b600082601f8301126134fa578081fd5b813567ffffffffffffffff80821115613511578283fd5b60208083026040518282820101818110858211171561352e578687fd5b60405284815294508185019250858201818701830188101561354f57600080fd5b600091505b84821015613572578035845292820192600191909101908201613554565b505050505092915050565b8035600a8110610f0b57600080fd5b60006020828403121561359d578081fd5b611d1983836134d3565b600080604083850312156135b9578081fd5b6135c384846134d3565b91506135d284602085016134d3565b90509250929050565b600080604083850312156135ed578182fd5b82356001600160a01b0381168114613603578283fd5b91506135d2846020850161357d565b60008060408385031215613624578182fd5b61362e84846134d3565b946020939093013593505050565b600080600060608486031215613650578081fd5b61365a85856134d3565b925060208401359150613670856040860161357d565b90509250925092565b6000806040838503121561368b578182fd5b823567ffffffffffffffff808211156136a2578384fd5b6136ae868387016134ea565b935060208501359150808211156136c3578283fd5b506136d0858286016134ea565b9150509250929050565b6000602082840312156136eb578081fd5b8135611d1981614135565b600060208284031215613707578081fd5b8151611d1981614135565b600060208284031215613723578081fd5b611d19838361357d565b60006020828403121561373e578081fd5b5035919050565b600060208284031215613756578081fd5b5051919050565b6000806040838503121561376f578182fd5b823591506135d2846020850161357d565b600080600060608486031215613794578283fd5b8335925060208401359150613670856040860161357d565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b8181101561383e5783516001600160a01b031683529284019291840191600101613819565b50909695505050505050565b602080825282518282018190526000919060409081850190868401855b828110156138965781518051855286810151878601528501518585015260609093019290850190600101613867565b5091979650505050505050565b6101008101818360005b60088110156138cc5781518352602092830192909101906001016138ad565b50505092915050565b6020808252825182820181905260009190848201906040850190845b8181101561383e578351835292840192918401916001016138f1565b901515815260200190565b6000602080835283518082850152825b8181101561394457858101830151858201604001528201613928565b818111156139555783604083870101525b50601f01601f1916929092016040019392505050565b60208082526026908201527f4d6572696469616e5374616b696e673a20546f6b656e207472616e736665722060408201526519985a5b195960d21b606082015260800190565b6020808252600d908201526c496e76616c6964207374616b6560981b604082015260600190565b6020808252602e908201527f55736520696e697469616c697a65496e766573746d656e747320746f2066697260408201526d737420736574757020706f6f6c7360901b606082015260800190565b6020808252602c908201527f4d6572696469616e5374616b696e673a20496e766573746d656e7420506f6f6c60408201526b081b9bdd08195b98589b195960a21b606082015260800190565b6020808252600e908201526d125b9d985b1a5908185b5bdd5b9d60921b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b602080825260139082015272105b1c9958591e48125b9a5d1a585b1a5e9959606a1b604082015260600190565b6020808252601d908201527f496e76616c696420696e766573746d656e74206d756c7469706c696572000000604082015260600190565b602080825260169082015275496e76616c696420496e766573746d656e745479706560501b604082015260600190565b6020808252601c908201527f436f6e7472616374206e6f742079657420696e697469616c697a656400000000604082015260600190565b60208082526026908201527f4d6572696469616e5374616b696e673a2072656e6f756e6365206d757374206260408201526565207472756560d01b606082015260800190565b6020808252601b908201527f496e76616c696420696e766573746d656e74206475726174696f6e0000000000604082015260600190565b6020808252601f908201527f4d6572696469616e5374616b696e673a20496e76616c696420616d6f756e7400604082015260600190565b6020808252601e908201527f4163636f756e742063616e6e6f74206265207a65726f20616464726573730000604082015260600190565b602080825260159082015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b604082015260600190565b60208082526030908201527f4d6178206e756d626572206f6620696e766573746d656e74732065786365656460408201526f195908199bdc881d1a1a5cc81c1bdbdb60821b606082015260800190565b60208082526037908201527f4d6572696469616e5374616b696e673a20496e73756666696369656e7420667560408201527f6e647320617661696c61626c6520746f2072656465656d000000000000000000606082015260800190565b6020808252818101527f4d6572696469616e5374616b696e673a20496e76616c69642061646472657373604082015260600190565b60208082526026908201527f4d75737420696e697469616c697a6520696e766573746d656e7420706f6f6c7360408201526508199a5c9cdd60d21b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602e908201527f4d6572696469616e5374616b696e673a2055736572206d75737420686176652060408201526d6e6f6e2d7a65726f207374616b6560901b606082015260800190565b6020808252600e908201526d546f6f206d616e7920706f6f6c7360901b604082015260600190565b602080825260149082015273496e76616c696420696e7075742061727261797360601b604082015260600190565b60208082526027908201527f4d6572696469616e5374616b696e673a20546f6f206d616e792072657761726460408201526620746f6b656e7360c81b606082015260800190565b6020808252601a908201527f4d6572696469616e5374616b696e673a20466f7262696464656e000000000000604082015260600190565b6020808252601e908201527f4d6572696469616e5374616b696e673a20496e76616c6964207374616b650000604082015260600190565b6020808252818101527f4163636f756e7420636f64652073697a652063616e6e6f74206265207a65726f604082015260600190565b60208082526030908201527f4e6f74206e65787420706f6f6c2e20506f6f6c73206d7573742062652073657460408201526f2075702073657175656e7469616c6c7960801b606082015260800190565b6020808252603a908201527f4d6572696469616e5374616b696e673a2043616e6e6f742072656d6f7665207460408201527f6f6b656e2077697468206e6f6e2d7a65726f2072657761726473000000000000606082015260800190565b6020808252602d908201527f4d6572696469616e5374616b696e673a20496e73756666696369656e7420726560408201526c77617264732062616c616e636560981b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602e908201527f4d6572696469616e5374616b696e673a20496e73756666696369656e7420636f60408201526d6e74726163742062616c616e636560901b606082015260800190565b90815260200190565b801515811461226757600080fdfea264697066735822122071f9d7de36bb6be53dc576498f0cdba64e39e59f2f31b3d93ba12cb1af148cc464736f6c634300060c0033

Deployed Bytecode Sourcemap

37773:15332:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51328:132;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;25011:59;;;;;;:::i;:::-;;:::i;24298:42::-;;;:::i;24846:18::-;;;:::i;:::-;;;;;;;:::i;38467:56::-;;;;;;:::i;:::-;;:::i;38805:47::-;;;;;;:::i;:::-;;:::i;42451:155::-;;;;;;:::i;:::-;;:::i;:::-;;41040:282;;;;;;:::i;:::-;;:::i;50869:451::-;;;:::i;:::-;;;;;;;:::i;40883:149::-;;;;;;:::i;:::-;;:::i;38208:36::-;;;:::i;24416:44::-;;;:::i;40270:202::-;;;;;;:::i;:::-;;:::i;50720:141::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;45890:726::-;;;:::i;38104:25::-;;;:::i;:::-;;;;;;;:::i;41330:936::-;;;;;;:::i;:::-;;:::i;52983:119::-;;;;;;:::i;:::-;;:::i;37399:133::-;;;;;;:::i;:::-;;:::i;50309:134::-;;;;;;:::i;:::-;;:::i;38289:40::-;;;:::i;38026:43::-;;;:::i;24541:42::-;;;:::i;51468:436::-;;;:::i;24871:25::-;;;:::i;24805:34::-;;;:::i;38078:17::-;;;:::i;38689:29::-;;;;;;:::i;:::-;;:::i;39032:62::-;;;;;;:::i;:::-;;:::i;40480:196::-;;;;;;:::i;:::-;;:::i;38136:27::-;;;:::i;38581:52::-;;;;;;:::i;:::-;;:::i;50565:147::-;;;;;;:::i;:::-;;:::i;24749:47::-;;;:::i;37047:161::-;;;;;;:::i;:::-;;:::i;26364:1118::-;;;;;;:::i;:::-;;:::i;50059:110::-;;;;;;:::i;:::-;;:::i;37974:45::-;;;:::i;25077:57::-;;;;;;:::i;:::-;;:::i;24958:46::-;;;;;;:::i;:::-;;:::i;25455:88::-;;;;;;:::i;:::-;;:::i;42308:135::-;;;;;;:::i;:::-;;:::i;38251:31::-;;;:::i;37216:175::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;39969:293::-;;;;;;:::i;:::-;;:::i;50451:106::-;;;:::i;:::-;;;;;;;:::i;50181:120::-;;;;;;:::i;:::-;;:::i;38399:37::-;;;;;;:::i;:::-;;:::i;51912:148::-;;;;;;:::i;:::-;;:::i;25769:193::-;;;;;;:::i;:::-;;:::i;27490:859::-;;;;;;:::i;:::-;;:::i;36865:174::-;;;;;;:::i;:::-;;:::i;38725:42::-;;;;;;:::i;:::-;;:::i;25970:198::-;;;;;;:::i;:::-;;:::i;38172:29::-;;;:::i;39102:56::-;;;;;;:::i;:::-;;:::i;47797:104::-;;;:::i;44230:1652::-;;;;;;:::i;:::-;;:::i;37540:129::-;;;;;;:::i;:::-;;:::i;52481:156::-;;;;;;:::i;:::-;;:::i;51328:132::-;-1:-1:-1;;;;;51425:27:0;51398:7;51425:27;;;:19;:27;;;;;;;51328:132::o;25011:59::-;;;;;;;;;;;;;:::o;24298:42::-;24338:2;24298:42;:::o;24846:18::-;;;;;;-1:-1:-1;;;;;24846:18:0;;:::o;38467:56::-;;;;;;;;;;;;;:::o;38805:47::-;;;;;;;;;;;;;:::o;42451:155::-;2417:1;3023:7;;:19;;3015:63;;;;-1:-1:-1;;;3015:63:0;;;;;;;:::i;:::-;;;;;;;;;2417:1;3156:7;:18;42566:32:::1;42576:5:::0;42583:7;42592:5;42566:9:::1;:32::i;:::-;-1:-1:-1::0;;2373:1:0;3335:7;:22;-1:-1:-1;42451:155:0:o;41040:282::-;25707:3;;;;;-1:-1:-1;;;;;25707:3:0;25693:10;:17;25685:56;;;;-1:-1:-1;;;25685:56:0;;;;;;;:::i;:::-;41116:21:::1;41130:6;41116:13;:21::i;:::-;41156:12;:19:::0;38067:2:::1;-1:-1:-1::0;41156:40:0::1;41148:92;;;;-1:-1:-1::0;;;41148:92:0::1;;;;;;;:::i;:::-;41251:12;:25:::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;41251:25:0;;;;;::::1;::::0;;-1:-1:-1;;;;;;41251:25:0::1;-1:-1:-1::0;;;;;41251:25:0;::::1;;::::0;;41292:22:::1;::::0;::::1;::::0;::::1;::::0;41251:25;;41292:22:::1;:::i;:::-;;;;;;;;41040:282:::0;:::o;50869:451::-;50994:12;:19;50937:16;;;50994:19;51055:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;51055:32:0;;51024:63;;51103:9;51098:186;51122:17;51118:1;:21;51098:186;;;51161:22;51186:12;51199:1;51186:15;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;51186:15:0;51233:39;;;:23;:39;;;;;;;;51216:14;;51186:15;;-1:-1:-1;51233:39:0;51216:11;;51228:1;;51216:14;;;;;;;;;;;;;;;:56;-1:-1:-1;51141:3:0;;51098:186;;;-1:-1:-1;51301:11:0;-1:-1:-1;;50869:451:0;:::o;40883:149::-;25707:3;;;;;-1:-1:-1;;;;;25707:3:0;25693:10;:17;25685:56;;;;-1:-1:-1;;;25685:56:0;;;;;;;:::i;:::-;40956:15:::1;:26:::0;;-1:-1:-1;;;;40956:26:0::1;-1:-1:-1::0;;;40956:26:0;::::1;;;;::::0;;40998::::1;::::0;::::1;::::0;::::1;::::0;40956;;40998::::1;:::i;38208:36::-:0;;;;:::o;24416:44::-;24456:4;24416:44;:::o;40270:202::-;25707:3;;;;;-1:-1:-1;;;;;25707:3:0;25693:10;:17;25685:56;;;;-1:-1:-1;;;25685:56:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;40341:22:0;::::1;40333:66;;;;-1:-1:-1::0;;;40333:66:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;40410:14:0;::::1;;::::0;;;:4:::1;:14;::::0;;;;;;:21;;-1:-1:-1;;40410:21:0::1;40427:4;40410:21;::::0;;40447:17;::::1;::::0;::::1;::::0;40415:8;;40447:17:::1;:::i;50720:141::-:0;50790:17;;:::i;:::-;-1:-1:-1;;;;;50827:26:0;;;;;;:18;:26;;;;;;;50820:33;;;;;;;;;;;;50827:26;50820:33;;;;;;;;;;;;;;;;;;;;;;;;50720:141;;;:::o;45890:726::-;2417:1;3023:7;;:19;;3015:63;;;;-1:-1:-1;;;3015:63:0;;;;;;;:::i;:::-;2417:1;3156:7;:18;45960:13:::1;::::0;-1:-1:-1;;;45960:13:0;::::1;;;45952:54;;;;-1:-1:-1::0;;;45952:54:0::1;;;;;;;:::i;:::-;46151:29;:27;:29::i;:::-;46236:10;46193:25;46221:26:::0;;;:14:::1;:26;::::0;;;;;46266:24;46258:83:::1;;;;-1:-1:-1::0;;;46258:83:0::1;;;;;;;:::i;:::-;46352:35;46390:34;46413:10;46390:22;:34::i;:::-;46352:72;;46435:32;46456:10;46435:20;:32::i;:::-;46507:10;-1:-1:-1::0;;;;;46485:53:0::1;;46519:18;46485:53;;;;;;:::i;:::-;;;;;;;;46557:50;46576:10;46588:18;46557;:50::i;:::-;-1:-1:-1::0;;2373:1:0;3335:7;:22;45890:726::o;38104:25::-;;;-1:-1:-1;;;38104:25:0;;;;;:::o;41330:936::-;25707:3;;;;;-1:-1:-1;;;;;25707:3:0;25693:10;:17;25685:56;;;;-1:-1:-1;;;25685:56:0;;;;;;;:::i;:::-;41401:21:::1;41415:6;41401:13;:21::i;:::-;41482:30;::::0;-1:-1:-1;;;41482:30:0;;41455:6;;-1:-1:-1;;;;;41482:15:0;::::1;::::0;::::1;::::0;:30:::1;::::0;41506:4:::1;::::0;41482:30:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:35:::0;41473:106:::1;;;;-1:-1:-1::0;;;41473:106:0::1;;;;;;;:::i;:::-;41595:9;41590:669;41614:12;:19:::0;41610:23;::::1;41590:669;;;41678:6;-1:-1:-1::0;;;;;41659:25:0::1;:12;41672:1;41659:15;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;-1:-1:-1;;;;;41659:15:0::1;:25;41655:593;;;41782:1:::0;41765:134:::1;41789:12;:19:::0;-1:-1:-1;;41789:23:0;41785:27;::::1;41765:134;;;41860:12;41873:1;41877;41873:5;41860:19;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;41842:12:::1;:15:::0;;-1:-1:-1;;;;;41860:19:0;;::::1;::::0;41855:1;;41842:15;::::1;;;;;;::::0;;;::::1;::::0;;;::::1;:37:::0;;-1:-1:-1;;;;;;41842:37:0::1;-1:-1:-1::0;;;;;41842:37:0;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;41814:3:0::1;41765:134;;;;41983:12;:18;;;;;;;;::::0;;;::::1;::::0;;;;;-1:-1:-1;;41983:18:0;;;;;-1:-1:-1;;;;;;41983:18:0::1;::::0;;;;;;;;-1:-1:-1;;;;;42072:31:0;::::1;::::0;;:23:::1;:31:::0;;;;;;42065:38;;;;42127:26;::::1;::::0;::::1;::::0;42096:6;;42127:26:::1;:::i;:::-;;;;;;;;42172:5;;41655:593;41635:3;;41590:669;;;;25752:1;41330:936:::0;:::o;52983:119::-;-1:-1:-1;;;;;53080:14:0;53056:4;53080:14;;;:4;:14;;;;;;;;;52983:119::o;37399:133::-;37473:7;37500:17;:24;37518:5;37500:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;37493:31;;37399:133;;;:::o;50309:134::-;-1:-1:-1;;;;;50411:16:0;;;50384:7;50411:16;;;:9;:16;;;;;;;;:24;;;;;;;;;;50309:134;;;;;:::o;38289:40::-;;;;:::o;38026:43::-;38067:2;38026:43;:::o;24541:42::-;24579:4;24541:42;:::o;51468:436::-;51582:12;:19;51525:16;;;51582:19;51643:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;51643:32:0;;51612:63;;51691:9;51686:182;51710:17;51706:1;:21;51686:182;;;51749:22;51774:12;51787:1;51774:15;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;51774:15:0;51821:35;;;:19;:35;;;;;;;;51804:14;;51774:15;;-1:-1:-1;51821:35:0;51804:11;;51816:1;;51804:14;;;;;;;;;;;;;;;:52;-1:-1:-1;51729:3:0;;51686:182;;24871:25;;;;:::o;24805:34::-;;;;;;:::o;38078:17::-;;;-1:-1:-1;;;;;38078:17:0;;:::o;38689:29::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;38689:29:0;;-1:-1:-1;38689:29:0;:::o;39032:62::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;40480:196::-;25707:3;;;;;-1:-1:-1;;;;;25707:3:0;25693:10;:17;25685:56;;;;-1:-1:-1;;;25685:56:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;40551:19:0;::::1;40543:63;;;;-1:-1:-1::0;;;40543:63:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;40624:11:0;::::1;;::::0;;;:4:::1;:11;::::0;;;;;;40617:18;;-1:-1:-1;;40617:18:0::1;::::0;;40651:17;::::1;::::0;::::1;::::0;40629:5;;40651:17:::1;:::i;38136:27::-:0;;;-1:-1:-1;;;38136:27:0;;;;;:::o;38581:52::-;;;;;;;;;;;;;:::o;50565:147::-;-1:-1:-1;;;;;50673:31:0;50646:7;50673:31;;;:23;:31;;;;;;;50565:147::o;24749:47::-;24791:5;24749:47;:::o;37047:161::-;-1:-1:-1;;;;;37165:22:0;;37138:7;37165:22;;;:15;:22;;;;;37138:7;37188:5;37165:29;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;37165:29:0;:35;;37047:161;-1:-1:-1;;;37047:161:0:o;26364:1118::-;25707:3;;;;;-1:-1:-1;;;;;25707:3:0;25693:10;:17;25685:56;;;;-1:-1:-1;;;25685:56:0;;;;;;;:::i;:::-;26490:22:::1;::::0;::::1;;26489:23;26481:55;;;;-1:-1:-1::0;;;26481:55:0::1;;;;;;;:::i;:::-;24338:2;26555:11;:18;:37;26547:63;;;;-1:-1:-1::0;;;26547:63:0::1;;;;;;;:::i;:::-;26651:9;:16;26629:11;:18;:38;26621:71;;;;-1:-1:-1::0;;;26621:71:0::1;;;;;;;:::i;:::-;26705:22;:29:::0;;-1:-1:-1;;26705:29:0::1;26730:4;26705:29;::::0;;26745:39;;;24505:4:::1;26745:39:::0;:56;26840:15:::1;26745:39;26840:37:::0;;:41;;;26962:466:::1;26986:11;:18;26982:1;:22;26962:466;;;24505:4;27034:11;27046:1;27034:14;;;;;;;;;;;;;;:32;;:68;;;;;24579:4;27070:11;27082:1;27070:14;;;;;;;;;;;;;;:32;;27034:68;27026:110;;;;-1:-1:-1::0;;;27026:110:0::1;;;;;;;:::i;:::-;27175:1;27159:9;27169:1;27159:12;;;;;;;;;;;;;;:17;;27151:57;;;;-1:-1:-1::0;;;27151:57:0::1;;;;;;;:::i;:::-;27223:23;27300:1;27264:37:::0;::::1;27249:53;::::0;::::1;;;;;;27223:79;;27347:11;27359:1;27347:14;;;;;;;;;;;;;;27317:17;:27;27335:8;27317:27;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;;;;27404:9;27414:1;27404:12;;;;;;;;;;;;;;27376:15;:25;27392:8;27376:25;;;;;;;;;;;;;;;;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;27376:25:0;:40;-1:-1:-1;27006:3:0::1;;26962:466;;;-1:-1:-1::0;;27454:18:0;27473:1:::1;27454:20:::0;;::::1;27438:36:::0;;26364:1118::o;50059:110::-;-1:-1:-1;;;;;50145:16:0;50118:7;50145:16;;;:9;:16;;;;;;;50059:110::o;37974:45::-;38015:4;37974:45;:::o;25077:57::-;;;;;;;;;;;;;:::o;24958:46::-;;;;;;;;;;;;;:::o;25455:88::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;42308:135::-;2417:1;3023:7;;:19;;3015:63;;;;-1:-1:-1;;;3015:63:0;;;;;;;:::i;:::-;2417:1;3156:7;:18;42398:37:::1;42408:10;42420:7:::0;42429:5;42398:9:::1;:37::i;38251:31::-:0;;;;:::o;37216:175::-;-1:-1:-1;;;;;37342:22:0;;;;;;:15;:22;;;;;37303:19;;37365:5;37342:29;;;;;;;;;;;;;;;;;;;;;;;;;;;:41;;37335:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37216:175;;;;:::o;39969:293::-;25707:3;;;;;-1:-1:-1;;;;;25707:3:0;25693:10;:17;25685:56;;;;-1:-1:-1;;;25685:56:0;;;;;;;:::i;:::-;40040:13:::1;::::0;-1:-1:-1;;;40040:13:0;::::1;;;40039:14;40031:46;;;;-1:-1:-1::0;;;40031:46:0::1;;;;;;;:::i;:::-;40097:22;::::0;::::1;;40088:73;;;;-1:-1:-1::0;;;40088:73:0::1;;;;;;;:::i;:::-;40172:19;40186:4;40172:13;:19::i;:::-;40202:13;:20:::0;;-1:-1:-1;;;;;;;40202:20:0;;::::1;;-1:-1:-1::0;;;;;;40233:18:0::1;-1:-1:-1::0;;;;;40233:18:0;;;::::1;::::0;;;::::1;::::0;;39969:293::o;50451:106::-;50501:16;50537:12;50530:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;50530:19:0;;;;;;;;;;;;;;;;;;;;;;;50451:106;:::o;50181:120::-;-1:-1:-1;;;;;50272:21:0;50245:7;50272:21;;;:14;:21;;;;;;;50181:120::o;38399:37::-;;;;;;;;;;;;;;;:::o;51912:148::-;51984:16;52020:32;52043:8;52020:22;:32::i;25769:193::-;25707:3;;;;;-1:-1:-1;;;;;25707:3:0;25693:10;:17;25685:56;;;;-1:-1:-1;;;25685:56:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;25838:21:0;::::1;25830:65;;;;-1:-1:-1::0;;;25830:65:0::1;;;;;;;:::i;:::-;25906:3;:13:::0;;-1:-1:-1;;;;;;25906:13:0::1;;-1:-1:-1::0;;;;;25906:13:0;::::1;;;::::0;;25935:19:::1;::::0;::::1;::::0;::::1;::::0;25906:13;;25935:19:::1;:::i;27490:859::-:0;25707:3;;;;;-1:-1:-1;;;;;25707:3:0;25693:10;:17;25685:56;;;;-1:-1:-1;;;25685:56:0;;;;;;;:::i;:::-;27614:22:::1;::::0;::::1;;27606:81;;;;-1:-1:-1::0;;;27606:81:0::1;;;;;;;:::i;:::-;27706:28;27728:5;27706:21;:28::i;:::-;27698:63;;;;-1:-1:-1::0;;;27698:63:0::1;;;;;;;:::i;:::-;27795:13;;27785:5;27780:11;;;;;;;;:28;;27772:88;;;;-1:-1:-1::0;;;27772:88:0::1;;;;;;;:::i;:::-;24505:4;27879:11;:29;;:62;;;;;24579:4;27912:11;:29;;27879:62;27871:104;;;;-1:-1:-1::0;;;27871:104:0::1;;;;;;;:::i;:::-;28112:15;:22;28128:5;28112:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;28099:9;:35;;28073:93;;;;-1:-1:-1::0;;;28073:93:0::1;;;;;;;:::i;:::-;28204:11;28177:17;:24;28195:5;28177:24;;;;;;;;;;;;;;;;;;;;;;;;;;;:38;;;;28251:9;28226:15;:22;28242:5;28226:22;;;;;;;;;;;;;;;;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;28226:22:0;:34;28290:13:::1;::::0;28280:5;28275:11:::1;::::0;::::1;;;;;;:28;28271:70;;;28322:13;::::0;;:17;::::1;28306:33:::0;;27490:859;;;:::o;36865:174::-;-1:-1:-1;;;;;36983:22:0;;36956:7;36983:22;;;:15;:22;;;;;36956:7;37006:5;36983:29;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;36983:29:0;:41;;:48;;36865:174;-1:-1:-1;;;36865:174:0:o;38725:42::-;;;;;;;;;;;;;:::o;25970:198::-;25707:3;;;;;-1:-1:-1;;;;;25707:3:0;25693:10;:17;25685:56;;;;-1:-1:-1;;;25685:56:0;;;;;;;:::i;:::-;26056:4:::1;26043:17:::0;::::1;;;26035:67;;;;-1:-1:-1::0;;;26035:67:0::1;;;;;;;:::i;:::-;26127:1;26113:16:::0;;-1:-1:-1;;;;;;26113:16:0::1;::::0;;;;26145:15:::1;::::0;::::1;::::0;::::1;::::0;26113:16:::1;26156:3:::0;;::::1;-1:-1:-1::0;;;;;26156:3:0::1;::::0;26145:15:::1;:::i;38172:29::-:0;;;;:::o;39102:56::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;39102:56:0;;-1:-1:-1;39102:56:0:o;47797:104::-;39860:10;39855:16;;;;:4;:16;;;;;;;;:24;;:16;:24;39847:63;;;;-1:-1:-1;;;39847:63:0;;;;;;;:::i;:::-;47864:29:::1;:27;:29::i;:::-;47797:104::o:0;44230:1652::-;2417:1;3023:7;;:19;;3015:63;;;;-1:-1:-1;;;3015:63:0;;;;;;;:::i;:::-;2417:1;3156:7;:18;44308:13:::1;::::0;-1:-1:-1;;;44308:13:0;::::1;;;44300:54;;;;-1:-1:-1::0;;;44300:54:0::1;;;;;;;:::i;:::-;44383:1;44373:7;:11;44365:54;;;;-1:-1:-1::0;;;44365:54:0::1;;;;;;;:::i;:::-;44561:29;:27;:29::i;:::-;44644:10;44603:18;44634:21:::0;;;:9:::1;:21;::::0;;;;;44624:31;::::1;:65;;44678:10;44668:21;::::0;;;:9:::1;:21;::::0;;;;;44624:65:::1;;;44658:7;44624:65;44743:10;44700:25;44728:26:::0;;;:14:::1;:26;::::0;;;;;44603:86;;-1:-1:-1;44700:25:0;44781:44:::1;::::0;44603:86;44781:17:::1;:44::i;:::-;44765:60;;44855:20;44844:8;:31;44836:99;;;;-1:-1:-1::0;;;44836:99:0::1;;;;;;;:::i;:::-;44948:35;44986:34;45009:10;44986:22;:34::i;:::-;44948:72;;45031:32;45052:10;45031:20;:32::i;:::-;45155:61;45181:34;:20:::0;45206:8;45181:24:::1;:34::i;:::-;45155:21;::::0;;:25:::1;:61::i;:::-;45131:21;:85:::0;45242:10:::1;45227:26;::::0;;;:14:::1;:26;::::0;;;;;;;:37;;;45299:9:::1;:21:::0;;;;;;:40:::1;::::0;45325:13;45299:25:::1;:40::i;:::-;45285:10;45275:21;::::0;;;:9:::1;:21;::::0;;;;:64;45367:14:::1;::::0;:33:::1;::::0;45386:13;45367:18:::1;:33::i;:::-;45350:14;:50:::0;;;45426:37:::1;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;;;;;;;;45531:3;::::0;:39:::1;::::0;-1:-1:-1;;;45531:39:0;;-1:-1:-1;;;;;45531:3:0;;::::1;::::0;:12:::1;::::0;:39:::1;::::0;45544:10:::1;::::0;45556:13;;45531:39:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;45523:89;;;;-1:-1:-1::0;;;45523:89:0::1;;;;;;;:::i;:::-;45641:10;45653:21;::::0;;;:9:::1;:21;::::0;;;;;;;45628:47;;::::1;::::0;::::1;::::0;::::1;:::i;:::-;;;;;;;;45712:10;-1:-1:-1::0;;;;;45691:42:0::1;;45724:8;45691:42;;;;;;:::i;:::-;;;;;;;;45773:10;-1:-1:-1::0;;;;;45751:53:0::1;;45785:18;45751:53;;;;;;:::i;:::-;;;;;;;;45823:50;45842:10;45854:18;45823;:50::i;:::-;-1:-1:-1::0;;2373:1:0;3335:7;:22;-1:-1:-1;;;44230:1652:0:o;37540:129::-;37612:7;37639:15;:22;37655:5;37639:22;;;;;;;52481:156;52567:4;52591:38;52609:5;52616:12;52591:17;:38::i;:::-;52584:45;52481:156;-1:-1:-1;;;52481:156:0:o;42614:1608::-;42715:13;;-1:-1:-1;;;42715:13:0;;;;42707:54;;;;-1:-1:-1;;;42707:54:0;;;;;;;:::i;:::-;42790:1;42780:7;:11;42772:53;;;;-1:-1:-1;;;42772:53:0;;;;;;;:::i;:::-;42844:15;;-1:-1:-1;;;42844:15:0;;;;;:48;;-1:-1:-1;42872:20:0;42863:5;:29;;;;;;;;;42844:48;42836:105;;;;-1:-1:-1;;;42836:105:0;;;;;;;:::i;:::-;43083:29;:27;:29::i;:::-;-1:-1:-1;;;;;43199:21:0;;43171:25;43199:21;;;:14;:21;;;;;;43125:35;;43235:25;;43231:109;;43299:29;43322:5;43299:22;:29::i;:::-;43278:50;;43231:109;43350:27;43371:5;43350:20;:27::i;:::-;43388:16;43407:35;43420:5;43427:7;43436:5;43407:12;:35::i;:::-;43388:54;-1:-1:-1;43536:61:0;43562:34;43388:54;43575:20;43562:12;:34::i;:::-;43536:21;;;:25;:61::i;:::-;43512:21;:85;-1:-1:-1;;;;;43608:21:0;;;;;;:14;:21;;;;;;;;:32;;;43670:9;:16;;;;;;:29;;43691:7;43670:20;:29::i;:::-;-1:-1:-1;;;;;43651:16:0;;;;;;:9;:16;;;;;:48;43727:14;;:27;;43746:7;43727:18;:27::i;:::-;43710:14;:44;;;43770:37;;;;;;;:::i;:::-;;;;;;;;43828:3;;:52;;-1:-1:-1;;;43828:52:0;;-1:-1:-1;;;;;43828:3:0;;;;:16;;:52;;43845:10;;43865:4;;43872:7;;43828:52;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43820:85;;;;-1:-1:-1;;;43820:85:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;43921:37:0;;43941:16;;;;:9;:16;;;;;;;;43921:37;;;;;;;:::i;:::-;;;;;;;;43995:5;-1:-1:-1;;;;;43974:37:0;;44002:8;43974:37;;;;;;:::i;:::-;;;;;;;;44044:25;;44040:172;;44114:5;-1:-1:-1;;;;;44092:48:0;;44121:18;44092:48;;;;;;:::i;:::-;;;;;;;;44155:45;44174:5;44181:18;44155;:45::i;:::-;42614:1608;;;;;;:::o;352:337::-;-1:-1:-1;;;;;426:22:0;;418:65;;;;-1:-1:-1;;;418:65:0;;;;;;;:::i;:::-;595:21;;636:8;628:53;;;;-1:-1:-1;;;628:53:0;;;;;;;:::i;:::-;352:337;;:::o;48160:985::-;48222:14;;:18;48218:920;;48285:12;:19;48257:25;48319:773;48343:17;48339:1;:21;48319:773;;;48386:19;48408;:36;48428:12;48441:1;48428:15;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;48428:15:0;48408:36;;;;;;;;;;;;;48485:12;:15;;48408:36;;-1:-1:-1;48485:12:0;48498:1;;48485:15;;;;;;;;;;;;;;;48545:30;;-1:-1:-1;;;48545:30:0;;-1:-1:-1;;;;;48485:15:0;;;;-1:-1:-1;48485:15:0;;48545;;:30;;48569:4;;48545:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48520:55;;48720:11;48703:14;:28;48699:378;;;48757:18;48778:31;:14;48797:11;48778:18;:31::i;:::-;48757:52;;48875:106;48920:60;48958:21;;48920:33;38015:4;48920:10;:14;;:33;;;;:::i;:::-;:37;;:60::i;:::-;48875:23;:40;48899:12;48912:1;48899:15;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;48899:15:0;48875:40;;;;;;;;;;;;;;:44;:106::i;:::-;48832:23;:40;48856:12;48869:1;48856:15;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;48856:15:0;48832:40;;;;;;;;;;;;:149;;;;49024:12;:15;;49043:14;;49004:19;;48856:15;;49037:1;;49024:15;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;49024:15:0;49004:36;;;;;;;;;;;;:53;-1:-1:-1;48699:378:0;-1:-1:-1;;;48362:3:0;;48319:773;;;;49106:20;:18;:20::i;:::-;48218:920;48160:985::o;52068:405::-;52198:12;:19;52141:16;;;52198:19;52259:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52259:32:0;;52228:63;;52307:9;52302:135;52326:17;52322:1;:21;52302:135;;;52382:43;52400:8;52409:12;52422:1;52409:15;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;52409:15:0;52382:17;:43::i;:::-;52365:11;52377:1;52365:14;;;;;;;;;;;;;;;;;:60;52345:3;;52302:135;;;-1:-1:-1;52454:11:0;52068:405;-1:-1:-1;;;52068:405:0:o;47426:280::-;47518:12;:19;47490:25;47548:151;47572:17;47568:1;:21;47548:151;;;47647:23;:40;47671:12;47684:1;47671:15;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;47671:15:0;;;47647:40;;;;;;;;;;;;;;;;47611:16;;;;;:9;:16;;;;;47628:12;:15;;47611:16;;47671:15;47641:1;;47628:15;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;47628:15:0;47611:33;;;;;;;;;;;;:76;47628:15;47591:3;47548:151;;46653:765;46777:12;:19;46749:25;46807:604;46831:17;46827:1;:21;46807:604;;;46870:12;46892;46905:1;46892:15;;;;;;;;;;;;;;;;;46948:30;;-1:-1:-1;;;46948:30:0;;-1:-1:-1;;;;;46892:15:0;;;;-1:-1:-1;46892:15:0;;46948;;:30;;46972:4;;46948:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46923:55;;47019:15;47035:1;47019:18;;;;;;;;;;;;;;47001:14;:36;;46993:94;;;;-1:-1:-1;;;46993:94:0;;;;;;;:::i;:::-;47162:15;47178:1;47162:18;;;;;;;;;;;;;;47122:19;:36;47142:12;47155:1;47142:15;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;47142:15:0;47122:36;;;;;;;;;;;;;:58;;47114:115;;;;-1:-1:-1;;;47114:115:0;;;;;;;:::i;:::-;47283:60;47324:15;47340:1;47324:18;;;;;;;;;;;;;;47283:19;:36;47303:12;47316:1;47303:15;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;47303:15:0;47283:36;;;;;;;;;;;;;;:40;:60::i;:::-;47244:19;:36;47264:12;47277:1;47264:15;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;47264:15:0;-1:-1:-1;;;;;47244:36:0;-1:-1:-1;;;;;47244:36:0;;;;;;;;;;;;:99;;;;47358:5;-1:-1:-1;;;;;47358:14:0;;47373:5;47380:15;47396:1;47380:18;;;;;;;;;;;;;;47358:41;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;46850:3:0;;46807:604;;;;46653:765;;;:::o;36655:175::-;36731:4;;36759:5;:29;;;;;;;;;;:63;;;;-1:-1:-1;36801:21:0;36792:5;:30;;;;;;;;;;;36655:175;-1:-1:-1;;36655:175:0:o;30675:2194::-;30752:7;30780:22;;;;30772:63;;;;-1:-1:-1;;;30772:63:0;;;;;;;:::i;:::-;30864:1;30854:7;:11;30846:37;;;;-1:-1:-1;;;30846:37:0;;;;;;;:::i;:::-;30902:25;30938:19;30968:29;31009:22;31042:36;31095:13;;31081:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;31081:28:0;-1:-1:-1;31042:67:0;-1:-1:-1;31120:19:0;;31333:1312;31369:13;;31359:7;:23;31333:1312;;;31432:7;31417:23;;;;;;;;-1:-1:-1;;;;;31482:22:0;;31455:24;31482:22;;;:15;:22;;;;;31410:30;;-1:-1:-1;31455:24:0;;31410:30;31482:28;;;;;;;;;;;;;;;;;;;;;;;;;;;:40;;:47;;;;31455:74;;31636:9;31631:1003;31655:16;31651:1;:20;31631:1003;;;-1:-1:-1;;;;;31701:22:0;;;;;;:15;:22;;;;;31765:15;;31724:4;31701:28;;;;;;;;;;;;;;;;;;;;;;;;;;;:40;;31742:1;31701:43;;;;;;;;;;;;;;;;;;:60;;;:79;31697:922;;-1:-1:-1;;;;;31917:22:0;;;;;;:15;:22;;;;;31821:17;;-1:-1:-1;31895:73:0;;31940:4;31917:28;;;;;;;;;;;;;;;;;;;;;;;;;;;:40;;31958:1;31917:43;;;;;;;;;;;;;;;;;;;;;:50;31895:17;;:21;:73::i;:::-;31875:93;;32022:1;32024;32022:3;31991:19;32011:7;31991:28;;;;;;;;;;;;;:34;;;;;32130:7;32109:17;:28;32105:370;;32231:24;:7;32243:11;32231;:24::i;:::-;32214:41;;32306:68;32325:5;32332:4;32338:14;32354:19;32306:17;:68::i;:::-;32282:92;-1:-1:-1;32422:29:0;;-1:-1:-1;;;;;;;;;32422:29:0;32105:370;31697:922;;;32523:5;;31697:922;31673:3;;31631:1003;;;-1:-1:-1;;31384:9:0;;31333:1312;;;-1:-1:-1;;;;;;;;32840:20:0;;;;;;:13;:20;;;;;;;-1:-1:-1;;;;;30675:2194:0;;;;:::o;4746:136::-;4804:7;4831:43;4835:1;4838;4831:43;;;;;;;;;;;;;;;;;:3;:43::i;52645:330::-;-1:-1:-1;;;;;52769:16:0;;;52732:4;52769:16;;;:9;:16;;;;;;;;:30;;;;;;;;;;;;52857:23;:37;;;;;;;52732:4;;52769:30;52732:4;;52831:105;;38015:4;;52831:82;;52857:55;;52769:30;52857:41;:55::i;:::-;-1:-1:-1;;;;;52831:21:0;;;;;;:14;:21;;;;;;;:25;:82::i;:105::-;52810:126;52645:330;-1:-1:-1;;;;;52645:330:0:o;28758:1147::-;28852:7;28880:22;;;;28872:63;;;;-1:-1:-1;;;28872:63:0;;;;;;;:::i;:::-;28964:1;28954:7;:11;28946:36;;;;-1:-1:-1;;;28946:36:0;;;;;;;:::i;:::-;29001:28;29023:5;29001:21;:28::i;:::-;28993:63;;;;-1:-1:-1;;;28993:63:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;29075:22:0;;;;;;:15;:22;;;;;24663:2;;29098:5;29075:29;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;29075:29:0;:41;;:48;:75;29067:136;;;;-1:-1:-1;;;29067:136:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;29331:22:0;;;;;;:15;:22;;;;;:48;;29371:7;;29331:22;29354:5;29331:29;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;29331:29:0;:35;;:39;:48::i;:::-;-1:-1:-1;;;;;29293:22:0;;;;;;:15;:22;;;;;;29316:5;29293:29;;;;;;;;;;;;;;;;;;;;;;;;;;;:35;;:86;;;;29390:22;29415:67;29435:46;29458:15;:22;29474:5;29458:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;24791:5;29435:22;;:46;;;;:::i;:::-;29415:15;;:19;:67::i;:::-;-1:-1:-1;;;;;29493:22:0;;;;;;:15;:22;;;;;29390:92;;-1:-1:-1;29516:5:0;29493:29;;;;;;;;;;;;;;;;;;;;;;;;;;;:41;;29540:151;;;;;;;;29574:7;29540:151;;;;29608:17;:24;29626:5;29608:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;29608:24:0;;;;29540:151;;;;;;;;29493:199;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29774:85;;29799:59;;24456:4;;29799:37;;29829:5;29811:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;29799:7;:11;;:37;;;;:::i;:59::-;-1:-1:-1;;;;;29774:20:0;;;;;;:13;:20;;;;;;;:24;:85::i;:::-;-1:-1:-1;;;;;29752:20:0;;;;;;:13;:20;;;;;:107;;;;-1:-1:-1;;28758:1147:0;;;;;:::o;4282:181::-;4340:7;4372:5;;;4396:6;;;;4388:46;;;;-1:-1:-1;;;4388:46:0;;;;;;;:::i;5636:471::-;5694:7;5939:6;5935:47;;-1:-1:-1;5969:1:0;5962:8;;5935:47;6006:5;;;6010:1;6006;:5;:1;6030:5;;;;;:10;6022:56;;;;-1:-1:-1;;;6022:56:0;;;;;;;:::i;6583:132::-;6641:7;6668:39;6672:1;6675;6668:39;;;;;;;;;;;;;;;;;:3;:39::i;49566:448::-;49637:25;;49665:6;49637:34;49618:15;:53;49615:392;;49692:9;49687:191;49711:12;:19;49707:23;;49687:191;;;49822:23;:40;49846:12;49859:1;49846:15;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;49846:15:0;-1:-1:-1;;;;;49822:40:0;-1:-1:-1;;;;;49822:40:0;;;;;;;;;;;;;49756:18;:35;49775:12;49788:1;49775:15;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;49775:15:0;49756:35;;;;;;;;;;;;49793:16;;49817:1;;49775:15;49793:20;49792:26;49756:63;;;;;;;;:106;49732:3;;49687:191;;;-1:-1:-1;49920:15:0;49892:25;:43;49970:16;;49994:1;;49989;49970:20;49969:26;49950:16;:45;49566:448::o;32883:803::-;-1:-1:-1;;;;;33080:20:0;;33029:7;33080:20;;;:13;:20;;;;;;33029:7;33136:5;33131:11;;;;;;;;33115:27;;33286:15;33281:300;33317:8;33328:1;33317:12;33307:7;:22;33281:300;;;33392:1;33360:20;33381:7;33360:29;;;;;;;;;;;;;;:33;33357:213;;;33437:117;33463:90;33478:5;33485:7;33494:8;33534:1;33504:20;33525:7;33504:29;;;;;;;;;;;;;;:31;33537:15;33463:14;:90::i;:::-;33437:21;;:25;:117::i;:::-;33413:141;;33357:213;33331:9;;33281:300;;;-1:-1:-1;;;;;;;33595:20:0;;;;;;:13;:20;;;;;:44;;;33618:21;-1:-1:-1;32883:803:0;;;;;;:::o;5185:192::-;5271:7;5307:12;5299:6;;;;5291:29;;;;-1:-1:-1;;;5291:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;5343:5:0;;;5185:192::o;7211:278::-;7297:7;7332:12;7325:5;7317:28;;;;-1:-1:-1;;;7317:28:0;;;;;;;;:::i;:::-;;7356:9;7372:1;7368;:5;;;;;;;7211:278;-1:-1:-1;;;;;7211:278:0:o;33694:2646::-;33822:7;;;33953:1;33941:13;;33822:7;34006:8;33991:24;;;;;;;;33965:50;;34041:9;34029:8;:21;34026:812;;;-1:-1:-1;;;;;34201:22:0;;;;;;:15;:22;;;;;;34224:8;34201:32;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;;34246:10;34201:56;;;;;;;;;;;;;;;;;;:63;;;34182:15;:82;34179:648;;-1:-1:-1;;;;;34477:22:0;;;;;;:15;:22;;;;;:84;;34545:15;;34477:22;34500:8;34477:32;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;;34522:10;34477:56;;;;;;;;;;;;;;;;;;;;;:63;;:67;:84::i;:::-;-1:-1:-1;;;;;34411:22:0;;;;;;:15;:22;;;;;;34434:8;34411:32;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;;34456:10;34411:56;;;;;;;;;;;;;;;;;;;;;:150;34601:15;;-1:-1:-1;34679:88:0;34705:61;34601:15;34738:5;34745:8;34755:10;34705:16;:61::i;:::-;34679:21;;:25;:88::i;:::-;34655:112;;34801:10;34786:25;;34179:648;-1:-1:-1;;;;;34925:22:0;;34895:15;34925:22;;;:15;:22;;;;;34997:12;;34925:69;;34997:12;;34895:15;34948:8;34925:32;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;34925:32:0;:44;;:51;;:55;:69::i;:::-;:84;34921:268;;;-1:-1:-1;;;;;35038:22:0;;;;;;:15;:22;;;;;:69;;35094:12;;35038:22;35061:8;35038:32;;;;;;;:69;35025:82;;34921:268;;;-1:-1:-1;35165:12:0;34921:268;35204:9;35199:812;35223:10;35219:1;:14;35199:812;;;35263:12;35259:1;:16;35255:421;;;-1:-1:-1;;;;;35426:22:0;;;;;;:15;:22;;;;;35403:78;;35449:8;35426:32;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;;35471:1;35426:47;;;;;;;;;;;;;;;;;;;;;:54;35403:18;;:22;:78::i;:::-;-1:-1:-1;;;;;35587:22:0;;;;;;:15;:22;;;;;35382:99;;-1:-1:-1;35544:116:0;;35570:89;;35610:8;35587:32;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;;35632:1;35587:47;;;;;;;;;;;;;;;;;;:54;;;35642:5;35648:8;35657:1;35570:16;:89::i;:::-;35544:21;;:25;:116::i;:::-;35520:140;;35255:421;-1:-1:-1;;;;;35698:22:0;;;;;;:15;:22;;;;;35752:12;;35721:8;35698:32;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;35698:32:0;:44;;:51;:66;35694:70;;35690:310;;;-1:-1:-1;;;;;35924:22:0;;;;;;:15;:22;;;;;;35947:8;35924:32;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;;35971:12;35969:1;:14;35924:60;;;;;;;;;;;;;;;;;;35874:15;:22;35890:5;-1:-1:-1;;;;;35874:22:0;-1:-1:-1;;;;;35874:22:0;;;;;;;;;;;;:32;35897:8;35874:32;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;;35919:1;35874:47;;;;;;;;;;;;;;;;:110;;:47;;;;;:110;;;;;;;;;;;;;;;;;;;;35690:310;35235:3;;35199:812;;;;36059:9;36054:120;36078:12;36074:1;:16;36054:120;;;-1:-1:-1;;;;;36112:22:0;;;;;;:15;:22;;;;;;36135:8;36112:32;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;;:50;;;;;;;;;;;;;;;-1:-1:-1;;36112:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;36092:3;36054:120;;;-1:-1:-1;;;;;;36228:22:0;;;;;;:15;:22;;;;;:62;;36271:18;;36228:22;36251:8;36228:32;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;36228:32:0;:38;;:42;:62::i;:::-;-1:-1:-1;;;;;36187:22:0;;;;;;:15;:22;;;;;;36210:8;36187:32;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;36187:32:0;:103;-1:-1:-1;36309:21:0;;33694:2646;-1:-1:-1;;;;;;;;;33694:2646:0:o;36348:270::-;-1:-1:-1;;;;;36508:22:0;;36465:7;36508:22;;;:15;:22;;;;;36496:97;;24456:4;;36496:75;;36465:7;36531:9;36508:33;;;;;;;;;;;;;;;;;;;;;;;;;;;:45;;36554:4;36508:51;;;;;;;;;;;;;;;;;;:62;;;36496:7;:11;;:75;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;:::o;5:130::-;72:20;;-1:-1;;;;;44709:54;;45959:35;;45949:2;;46008:1;;45998:12;160:707;;277:3;270:4;262:6;258:17;254:27;244:2;;-1:-1;;285:12;244:2;332:6;319:20;41603:18;;41595:6;41592:30;41589:2;;;-1:-1;;41625:12;41589:2;41670:4;;41662:6;41658:17;41243:2;41237:9;41670:4;41658:17;41273:6;41269:17;;41380:6;41368:10;41365:22;41603:18;41332:10;41329:34;41326:62;41323:2;;;-1:-1;;41391:12;41323:2;41243;41410:22;462:21;;;345:89;-1:-1;519:14;;;;-1:-1;494:17;;;599:27;;;;;596:36;-1:-1;593:2;;;645:1;;635:12;593:2;670:1;661:10;;655:206;680:6;677:1;674:13;655:206;;;1381:20;;748:50;;812:14;;;;702:1;695:9;;;;;840:14;;655:206;;;659:14;;;;;237:630;;;;:::o;1141:166::-;1226:20;;46229:2;46219:13;;46209:2;;46246:1;;46236:12;1592:241;;1696:2;1684:9;1675:7;1671:23;1667:32;1664:2;;;-1:-1;;1702:12;1664:2;1764:53;1809:7;1785:22;1764:53;:::i;1840:366::-;;;1961:2;1949:9;1940:7;1936:23;1932:32;1929:2;;;-1:-1;;1967:12;1929:2;2029:53;2074:7;2050:22;2029:53;:::i;:::-;2019:63;;2137:53;2182:7;2119:2;2162:9;2158:22;2137:53;:::i;:::-;2127:63;;1923:283;;;;;:::o;2213:402::-;;;2352:2;2340:9;2331:7;2327:23;2323:32;2320:2;;;-1:-1;;2358:12;2320:2;72:20;;-1:-1;;;;;44709:54;;45959:35;;45949:2;;-1:-1;;45998:12;45949:2;2410:63;-1:-1;2528:71;2591:7;2510:2;2567:22;;2528:71;:::i;2622:366::-;;;2743:2;2731:9;2722:7;2718:23;2714:32;2711:2;;;-1:-1;;2749:12;2711:2;2811:53;2856:7;2832:22;2811:53;:::i;:::-;2801:63;2901:2;2940:22;;;;1381:20;;-1:-1;;;2705:283::o;2995:527::-;;;;3151:2;3139:9;3130:7;3126:23;3122:32;3119:2;;;-1:-1;;3157:12;3119:2;3219:53;3264:7;3240:22;3219:53;:::i;:::-;3209:63;;3309:2;3352:9;3348:22;1381:20;3317:63;;3435:71;3498:7;3417:2;3478:9;3474:22;3435:71;:::i;:::-;3425:81;;3113:409;;;;;:::o;3529:638::-;;;3700:2;3688:9;3679:7;3675:23;3671:32;3668:2;;;-1:-1;;3706:12;3668:2;3764:17;3751:31;3802:18;;3794:6;3791:30;3788:2;;;-1:-1;;3824:12;3788:2;3854:78;3924:7;3915:6;3904:9;3900:22;3854:78;:::i;:::-;3844:88;;3997:2;3986:9;3982:18;3969:32;3955:46;;3802:18;4013:6;4010:30;4007:2;;;-1:-1;;4043:12;4007:2;;4073:78;4143:7;4134:6;4123:9;4119:22;4073:78;:::i;:::-;4063:88;;;3662:505;;;;;:::o;4174:235::-;;4275:2;4263:9;4254:7;4250:23;4246:32;4243:2;;;-1:-1;;4281:12;4243:2;952:6;939:20;964:30;988:5;964:30;:::i;4416:257::-;;4528:2;4516:9;4507:7;4503:23;4499:32;4496:2;;;-1:-1;;4534:12;4496:2;1087:6;1081:13;1099:30;1123:5;1099:30;:::i;4680:277::-;;4802:2;4790:9;4781:7;4777:23;4773:32;4770:2;;;-1:-1;;4808:12;4770:2;4870:71;4933:7;4909:22;4870:71;:::i;4964:241::-;;5068:2;5056:9;5047:7;5043:23;5039:32;5036:2;;;-1:-1;;5074:12;5036:2;-1:-1;1381:20;;5030:175;-1:-1;5030:175::o;5212:263::-;;5327:2;5315:9;5306:7;5302:23;5298:32;5295:2;;;-1:-1;;5333:12;5295:2;-1:-1;1529:13;;5289:186;-1:-1;5289:186::o;5482:402::-;;;5621:2;5609:9;5600:7;5596:23;5592:32;5589:2;;;-1:-1;;5627:12;5589:2;1394:6;1381:20;5679:63;;5797:71;5860:7;5779:2;5840:9;5836:22;5797:71;:::i;5891:527::-;;;;6047:2;6035:9;6026:7;6022:23;6018:32;6015:2;;;-1:-1;;6053:12;6015:2;1394:6;1381:20;6105:63;;6205:2;6248:9;6244:22;1381:20;6213:63;;6331:71;6394:7;6313:2;6374:9;6370:22;6331:71;:::i;23672:222::-;-1:-1;;;;;44709:54;;;;7289:37;;23799:2;23784:18;;23770:124::o;23901:460::-;-1:-1;;;;;44709:54;;;7158:58;;44709:54;;;;24264:2;24249:18;;7289:37;24347:2;24332:18;;23503:37;;;;24092:2;24077:18;;24063:298::o;24368:349::-;-1:-1;;;;;44709:54;;;;7158:58;;24703:2;24688:18;;23503:37;24531:2;24516:18;;24502:215::o;25064:370::-;25241:2;25255:47;;;42463:12;;25226:18;;;43667:19;;;25064:370;;25241:2;41870:14;;;;43707;;;;25064:370;7897:260;7922:6;7919:1;7916:13;7897:260;;;7983:13;;-1:-1;;;;;44709:54;7289:37;;43152:14;;;;6579;;;;44720:42;7937:9;7897:260;;;-1:-1;25308:116;;25212:222;-1:-1;;;;;;25212:222::o;25441:478::-;25672:2;25686:47;;;42463:12;;25657:18;;;43667:19;;;25441:478;;25672:2;43707:14;;;;;;41870;;;25441:478;8813:341;8838:6;8835:1;8832:13;8813:341;;;8899:13;;22996:23;;23503:37;;23162:16;;;23156:23;23233:14;;;23503:37;23328:16;;23322:23;23399:14;;;23503:37;6878:4;6869:14;;;;43152;;;;8860:1;8853:9;8813:341;;;-1:-1;25739:170;;25643:276;-1:-1;;;;;;;25643:276::o;25926:315::-;26099:3;26084:19;;26088:9;9580:21;25926:315;9607:258;42769:4;9629:1;9626:13;9607:258;;;9693:13;;23503:37;;7060:4;7051:14;;;;43152;;;;9654:1;9647:9;9607:258;;;9611:14;;;26070:171;;;;:::o;26248:370::-;26425:2;26439:47;;;42463:12;;26410:18;;;43667:19;;;26248:370;;26425:2;41870:14;;;;43707;;;;26248:370;10324:260;10349:6;10346:1;10343:13;10324:260;;;10410:13;;23503:37;;43152:14;;;;7051;;;;10371:1;10364:9;10324:260;;26625:210;44621:13;;44614:21;10679:34;;26746:2;26731:18;;26717:118::o;27099:310::-;;27246:2;;27267:17;27260:47;11031:5;42463:12;43679:6;27246:2;27235:9;27231:18;43667:19;-1:-1;45591:101;45605:6;45602:1;45599:13;45591:101;;;45672:11;;;;;45666:18;45653:11;;;43707:14;45653:11;45646:39;45620:10;;45591:101;;;45707:6;45704:1;45701:13;45698:2;;;-1:-1;43707:14;45763:6;27235:9;45754:16;;45747:27;45698:2;-1:-1;45879:7;45863:14;-1:-1;;45859:28;11189:39;;;;43707:14;11189:39;;27217:192;-1:-1;;;27217:192::o;27416:416::-;27616:2;27630:47;;;11465:2;27601:18;;;43667:19;11501:34;43707:14;;;11481:55;-1:-1;;;11556:12;;;11549:30;11598:12;;;27587:245::o;27839:416::-;28039:2;28053:47;;;11849:2;28024:18;;;43667:19;-1:-1;;;43707:14;;;11865:36;11920:12;;;28010:245::o;28262:416::-;28462:2;28476:47;;;12171:2;28447:18;;;43667:19;12207:34;43707:14;;;12187:55;-1:-1;;;12262:12;;;12255:38;12312:12;;;28433:245::o;28685:416::-;28885:2;28899:47;;;12563:2;28870:18;;;43667:19;12599:34;43707:14;;;12579:55;-1:-1;;;12654:12;;;12647:36;12702:12;;;28856:245::o;29108:416::-;29308:2;29322:47;;;12953:2;29293:18;;;43667:19;-1:-1;;;43707:14;;;12969:37;13025:12;;;29279:245::o;29531:416::-;29731:2;29745:47;;;13276:2;29716:18;;;43667:19;13312:29;43707:14;;;13292:50;13361:12;;;29702:245::o;29954:416::-;30154:2;30168:47;;;13612:2;30139:18;;;43667:19;-1:-1;;;43707:14;;;13628:42;13689:12;;;30125:245::o;30377:416::-;30577:2;30591:47;;;13940:2;30562:18;;;43667:19;13976:31;43707:14;;;13956:52;14027:12;;;30548:245::o;30800:416::-;31000:2;31014:47;;;14278:2;30985:18;;;43667:19;-1:-1;;;43707:14;;;14294:45;14358:12;;;30971:245::o;31223:416::-;31423:2;31437:47;;;14609:2;31408:18;;;43667:19;14645:30;43707:14;;;14625:51;14695:12;;;31394:245::o;31646:416::-;31846:2;31860:47;;;14946:2;31831:18;;;43667:19;14982:34;43707:14;;;14962:55;-1:-1;;;15037:12;;;15030:30;15079:12;;;31817:245::o;32069:416::-;32269:2;32283:47;;;15330:2;32254:18;;;43667:19;15366:29;43707:14;;;15346:50;15415:12;;;32240:245::o;32492:416::-;32692:2;32706:47;;;15666:2;32677:18;;;43667:19;15702:33;43707:14;;;15682:54;15755:12;;;32663:245::o;32915:416::-;33115:2;33129:47;;;16006:2;33100:18;;;43667:19;16042:32;43707:14;;;16022:53;16094:12;;;33086:245::o;33338:416::-;33538:2;33552:47;;;16345:2;33523:18;;;43667:19;-1:-1;;;43707:14;;;16361:44;16424:12;;;33509:245::o;33761:416::-;33961:2;33975:47;;;16675:2;33946:18;;;43667:19;16711:34;43707:14;;;16691:55;-1:-1;;;16766:12;;;16759:40;16818:12;;;33932:245::o;34184:416::-;34384:2;34398:47;;;17069:2;34369:18;;;43667:19;17105:34;43707:14;;;17085:55;17174:25;17160:12;;;17153:47;17219:12;;;34355:245::o;34607:416::-;34807:2;34821:47;;;34792:18;;;43667:19;17506:34;43707:14;;;17486:55;17560:12;;;34778:245::o;35030:416::-;35230:2;35244:47;;;17811:2;35215:18;;;43667:19;17847:34;43707:14;;;17827:55;-1:-1;;;17902:12;;;17895:30;17944:12;;;35201:245::o;35453:416::-;35653:2;35667:47;;;18195:2;35638:18;;;43667:19;18231:34;43707:14;;;18211:55;-1:-1;;;18286:12;;;18279:25;18323:12;;;35624:245::o;35876:416::-;36076:2;36090:47;;;18574:2;36061:18;;;43667:19;18610:34;43707:14;;;18590:55;-1:-1;;;18665:12;;;18658:38;18715:12;;;36047:245::o;36299:416::-;36499:2;36513:47;;;18966:2;36484:18;;;43667:19;-1:-1;;;43707:14;;;18982:37;19038:12;;;36470:245::o;36722:416::-;36922:2;36936:47;;;19289:2;36907:18;;;43667:19;-1:-1;;;43707:14;;;19305:43;19367:12;;;36893:245::o;37145:416::-;37345:2;37359:47;;;19618:2;37330:18;;;43667:19;19654:34;43707:14;;;19634:55;-1:-1;;;19709:12;;;19702:31;19752:12;;;37316:245::o;37568:416::-;37768:2;37782:47;;;20003:2;37753:18;;;43667:19;20039:28;43707:14;;;20019:49;20087:12;;;37739:245::o;37991:416::-;38191:2;38205:47;;;20338:2;38176:18;;;43667:19;20374:32;43707:14;;;20354:53;20426:12;;;38162:245::o;38414:416::-;38614:2;38628:47;;;38599:18;;;43667:19;20713:34;43707:14;;;20693:55;20767:12;;;38585:245::o;38837:416::-;39037:2;39051:47;;;21018:2;39022:18;;;43667:19;21054:34;43707:14;;;21034:55;-1:-1;;;21109:12;;;21102:40;21161:12;;;39008:245::o;39260:416::-;39460:2;39474:47;;;21412:2;39445:18;;;43667:19;21448:34;43707:14;;;21428:55;21517:28;21503:12;;;21496:50;21565:12;;;39431:245::o;39683:416::-;39883:2;39897:47;;;21816:2;39868:18;;;43667:19;21852:34;43707:14;;;21832:55;-1:-1;;;21907:12;;;21900:37;21956:12;;;39854:245::o;40106:416::-;40306:2;40320:47;;;22207:2;40291:18;;;43667:19;22243:33;43707:14;;;22223:54;22296:12;;;40277:245::o;40529:416::-;40729:2;40743:47;;;22547:2;40714:18;;;43667:19;22583:34;43707:14;;;22563:55;-1:-1;;;22638:12;;;22631:38;22688:12;;;40700:245::o;40952:222::-;23503:37;;;41079:2;41064:18;;41050:124::o;46024:111::-;46105:5;44621:13;44614:21;46083:5;46080:32;46070:2;;46126:1;;46116:12

Swarm Source

ipfs://71f9d7de36bb6be53dc576498f0cdba64e39e59f2f31b3d93ba12cb1af148cc4

Block Transaction Gas Used Reward
view all blocks sequenced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.