Contract 0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb 3

Contract Overview

Balance:
0 CRO

CRO Value:
$0.00

Token:
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x4d6d4a05d27ede3512af074640291a385f20e4c85fb938748e35b5e8d5d4392cHarvest59354822022-12-09 9:32:263 hrs 38 mins ago0x9f554f90560247d9afcdfa626b8353f2d89719f1 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO1.014795628128 4,963.418004589
0xd8e987522d53143c573184f3b8bea514af12fb6818bdb32a71183034001c6548Harvest59281662022-12-08 22:01:1515 hrs 9 mins ago0x46ef395e9159da55ea7cb992b23987271765bf26 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.9203037130650
0x70e81d76be7d286766728f60e3fe6cfe64f1919a42a030adf90915dc365a8caaHarvest59281382022-12-08 21:58:3615 hrs 12 mins ago0x46ef395e9159da55ea7cb992b23987271765bf26 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.9203039578840
0x9cf4ca446dcd9f612cafbbff0a96c0202402911fab07830ffb65be9af5735396Harvest59279412022-12-08 21:39:5915 hrs 30 mins ago0x1be53a742e4571d0de2454697e142868a818f6ce IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.9203056872790
0x4dd2e534a4947894e7188d83bf6bb1e61f7943295f4b40a95d61c912fdfd1f35Harvest59274632022-12-08 20:54:4916 hrs 15 mins ago0x46ef395e9159da55ea7cb992b23987271765bf26 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.9203098399010
0x779febe911c61ff345e19767d4c064fd047a1664dbfa71f571689fe9337c5941Harvest59261402022-12-08 18:49:3118 hrs 21 mins ago0x75a31b45a046899e18e885ed1bb783bf8c693f7c IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.7494979056260
0x3ad1ac36297dda2eb6d1249e7409e820bef3c5e9882912d583bf47a66a2433f6Harvest59261042022-12-08 18:46:0518 hrs 24 mins ago0x450b66d90da714ece6d50ec001dae18e25230ea7 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.920605548109 4,860.924066918
0xf2738eba4b3f2efa57d746ebde07f0e4fa41588fa2d9b06e97bec9156e425f3eHarvest59261032022-12-08 18:45:5918 hrs 24 mins ago0x450b66d90da714ece6d50ec001dae18e25230ea7 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.920605556719 4,860.924112382
0x7afccb8525e797eed7fd1e71dec4007c4f23e07b49e13f217568d553c8aac53eWithdraw59260742022-12-08 18:43:1518 hrs 27 mins ago0x9a220be1e48306220d52fcb2d3b254bb31205d02 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.980740312428 4,860.925418458
0xfde3d9e21f411e0fd50465d30d9e4be6a4edadf5b7eb16d4e656dbe9d9964a5cWithdraw59260552022-12-08 18:41:2818 hrs 29 mins ago0x9a220be1e48306220d52fcb2d3b254bb31205d02 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.980740483784 4,860.926267764
0x48ed4c7cc23a3c8b5957cd59fdec465c5199cd13c4127dfcd1ce82470e78a38aWithdraw59258642022-12-08 18:23:2118 hrs 47 mins ago0x9a220be1e48306220d52fcb2d3b254bb31205d02 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO1.053772924928 4,860.934962581
0x884b193ff42c7acbe72c64fab96bd67b5a6c350786858667c6cdf78c5792cd0aHarvest59199112022-12-08 9:00:491 day 4 hrs ago0x34fd51d8a633ba934d44fd4a55d6d4ef959c8ad4 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.920659169372 4,861.207194568
0xbc88596c3caeb5ddf74aef6c4c2066e643d64eb972b1695c764cb681e2857666Harvest59043322022-12-07 8:32:542 days 4 hrs ago0xc4f75bd440ff4f77a14d97f5ca41ee4e2e262754 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.920512517110
0x9a8052973017e58719116e3bb1f7e548ccdafca55e863db8e4cb4056962868a8Harvest59043122022-12-07 8:31:012 days 4 hrs ago0xc4f75bd440ff4f77a14d97f5ca41ee4e2e262754 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.9205126838790
0x1db5882d4d9bfbb62ce8489ff0231c49483bd07cdb53ca0d5ad3d4bcb109b89bWithdraw59009292022-12-07 3:11:472 days 9 hrs ago0x62336578e89db2a0bacd2690ddcc919cf03a6641 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.9806727870290
0xca70792fa02c44320d8dea45e728eb3a2288773d96882b675bf9836c06ac185dHarvest59000512022-12-07 1:48:582 days 11 hrs ago0xbef6d27a9c166b252e544e07a7bfee9a4f34a95f IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.9937803679730
0x5db7184cc04a36bd70ae6269acfbd8c2b5d2f3d6a547049e7bf3660db5319d4fWithdraw58941432022-12-06 16:30:362 days 20 hrs ago0x9287ad53963a6a004ed46ddc2ba3d99c99b9fda1 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO1.053915693388 4,862.401006645
0x36b7409a0eadc177960441490517fe3f1a6c5efd44d950260d2ad4f9f42c477fHarvest58901012022-12-06 10:09:383 days 3 hrs ago0x03bca9b303a7508953d78be56f6af05dac46bcfd IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.92092064532 4,862.587823581
0xf586981a4a8fe4e4f44d54683e10f2a82fa74953a8cba456f365e60f58fdcc08Harvest58901002022-12-06 10:09:323 days 3 hrs ago0x03bca9b303a7508953d78be56f6af05dac46bcfd IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.920920654439 4,862.587871731
0xee63ad2a665de1b681fea2d4fc523219cc16526c005fd41f3c9bb180f48987abHarvest58900992022-12-06 10:09:273 days 3 hrs ago0x03bca9b303a7508953d78be56f6af05dac46bcfd IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.920920663407 4,862.587919084
0xe78c5026f34921eb820471e71ed19ad5a4c21b9df59a153f0fac7e735c98059dHarvest58900922022-12-06 10:08:473 days 3 hrs ago0x03bca9b303a7508953d78be56f6af05dac46bcfd IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.920920726155 4,862.588250402
0x43a3ad71d45db16b20f194e19c56c6b144bdabc09f9fc8850dc59ee25d2b9195Harvest58900912022-12-06 10:08:413 days 3 hrs ago0x03bca9b303a7508953d78be56f6af05dac46bcfd IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.993859559498 4,862.588297308
0xbff97ca6e33e764f9c97b716b26c76b3bac1718b06f104ba4c0c6686b645686cHarvest58881662022-12-06 7:07:363 days 6 hrs ago0xbface808553f3b544d43b46cd8165d44a4c1c231 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.9935714267130
0x6cf2ae98959fb761226603677a20e5a2332852b2b2828369edbec9e6f54df983Harvest58846732022-12-06 1:39:113 days 11 hrs ago0xbce55b4bf4dd2b14de8b5d6558c04e24b8337956 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.92128953216 4,862.840949883
0x7ccef7dd25a49547eeb66b0a64e2eb694cb9ad8109b5476c4d2612e092826eebHarvest58846722022-12-06 1:39:053 days 11 hrs ago0xbce55b4bf4dd2b14de8b5d6558c04e24b8337956 IN  0x1ae8a7c582c3f9f9117d5bc2863f2ed16cbd29cb0 CRO0.920968593342 4,862.840995741
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BigBang

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at cronoscan.com on 2022-05-31
*/

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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



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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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




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

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

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

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

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

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

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

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


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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

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

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

        _;

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



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

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}


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

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

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

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

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

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

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

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


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

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

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




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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

        return true;
    }

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

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

        return true;
    }

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

        _beforeTokenTransfer(sender, recipient, amount);

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

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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


/**
       _____ _             __     _______                           
      / ___/(_)___  ____ _/ /__  / ____(_)___  ____ _____  ________ 
      \__ \/ / __ \/ __ `/ / _ \/ /_  / / __ \/ __ `/ __ \/ ___/ _ \
     ___/ / / / / / /_/ / /  __/ __/ / / / / / /_/ / / / / /__/  __/
    /____/_/_/ /_/\__, /_/\___/_/   /_/_/ /_/\__,_/_/ /_/\___/\___/ 
                 /____/                                             
*/


/**
 * Single Finance token with Governance.
 */
contract SingleToken is ERC20("SINGLE Token", "SINGLE"), Ownable {
  using SafeMath for uint256;

  uint256 private constant CAP = 1000_000_000e18;

  uint256 public constant INVESTOR_MINT_CAP = 137_000_000e18;
  uint256 public constant LIQUIDITY_MINT_CAP = 20_000_000e18;

  uint256 public startMiningTimestamp;
  // uint256 public startReleaseTimestamp;
  uint256 public launchPeriodEndTimestamp;
  uint256 public nextAdjustTimestamp;

  uint256 public INITIAL_SUPPLY_PER_BLOCK;
  uint256 public SUPPLY_PER_BLOCK;
  uint256 public constant LAUNCH_PERIOD_ADJUST_WINDOW = 365 days / 12;
  uint256 public constant SUPPLY_HALVING_WINDOW = 365 days / 2;

  uint256 public constant ECOSYSTEM_TGE_RELEASE = 11_150_000e18;
  uint256 public constant ECOSYSTEM_VESTING_AMT = 211_850_000e18;
  uint256 public constant ECOSYSTEM_VESTING_PERIOD = 365 days *2; // 24 months

  uint256 public constant TEAM_TGE_RELEASE = 2_200_000e18;
  uint256 public constant TEAM_VESTING_AMT = 217_800_000e18;
  uint256 public constant TEAM_VESTING_PERIOD = 365 days *2; // 24 months

  uint256 public investorMinted = 0;
  uint256 public liquidityMinted = 0;
  uint256 public teamMinted = 0;
  uint256 public ecosystemMinted = 0;

  
  event SupplyAdjusted(uint256 supplyPerBlock, uint256 nextAdjustTs);


  constructor(
    uint256 initialSupplyPerBlock,
    uint256 _startMiningTimestamp
  ) {

    if(_startMiningTimestamp == 0){
      _startMiningTimestamp = block.timestamp;
    }

    require(block.timestamp <= _startMiningTimestamp, "cannot set past block number");

    startMiningTimestamp = _startMiningTimestamp;
    
    launchPeriodEndTimestamp = startMiningTimestamp.add(SUPPLY_HALVING_WINDOW);

    // available for first adjustment after mining started
    nextAdjustTimestamp = startMiningTimestamp;

    INITIAL_SUPPLY_PER_BLOCK = initialSupplyPerBlock;
    SUPPLY_PER_BLOCK = 0;

  }

  function cap() public pure returns (uint256) {
    return CAP;
  }



  
  function mint(address _to, uint256 _amount) public onlyOwner {
    require(totalSupply().add(_amount) <= cap(), "cap exceeded");
    _mint(_to, _amount);
    _moveDelegates(address(0), _delegates[_to], _amount);
  }

  function mintForLiquidity(address _to, uint256 _amount) public onlyOwner {
    require(liquidityMinted.add(_amount) <= LIQUIDITY_MINT_CAP, "mint limit exceeded");
    liquidityMinted = liquidityMinted.add(_amount);
    mint(_to, _amount);
  }

  function mintForInvestor(address _to, uint256 _amount) public onlyOwner {
    require(investorMinted.add(_amount) <= INVESTOR_MINT_CAP, "mint limit exceeded");
    investorMinted = investorMinted.add(_amount);
    mint(_to, _amount);
  }


  function mintForEcosystem(address _to, uint256 _amount) public onlyOwner {
    require(ecosystemMinted.add(_amount) <= ECOSYSTEM_VESTING_AMT.add(ECOSYSTEM_TGE_RELEASE), "mint limit exceeded");
    require(_amount <= pendingEcosystemTokens(), "available limit exceeded");
    ecosystemMinted = ecosystemMinted.add(_amount);
    mint(_to, _amount);
  }

  function mintForTeam(address _to, uint256 _amount) public onlyOwner {
    require(teamMinted.add(_amount) <= TEAM_VESTING_AMT.add(TEAM_TGE_RELEASE), "mint limit exceeded");
    require(_amount <= pendingTeamTokens(), "available limit exceeded");
    teamMinted = teamMinted.add(_amount);
    mint(_to, _amount);
  }


  function burn(address _account, uint256 _amount) external onlyOwner {
    _burn(_account, _amount);
    _moveDelegates(_delegates[_account], address(0), _amount);
  }

  function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
    require(recipient != address(this), "ERC20: transfer to the token contract");

    _transfer(_msgSender(), recipient, amount);
    _moveDelegates(_delegates[_msgSender()], _delegates[recipient], amount);
    return true;
  }

  function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
    require(recipient != address(this), "ERC20: transfer to the token contract");

    _transfer(sender, recipient, amount);
    _approve(sender, _msgSender(), allowance(sender, _msgSender()).sub(amount, "ERC20: transfer amount exceeds allowance"));
    _moveDelegates(_delegates[sender], _delegates[recipient], amount);
    return true;
  }


  function pendingEcosystemTokens() public view returns (uint256)
  {
    if(block.timestamp < startMiningTimestamp){
      return 0;
    }

    uint256 singlePerSec = ECOSYSTEM_VESTING_AMT.div(ECOSYSTEM_VESTING_PERIOD);

    uint256 timePast = uint256(block.timestamp).sub(startMiningTimestamp);

    if(timePast >= ECOSYSTEM_VESTING_PERIOD){
      return ECOSYSTEM_VESTING_AMT.add(ECOSYSTEM_TGE_RELEASE).sub(ecosystemMinted);
    }

    return timePast.mul(singlePerSec).add(ECOSYSTEM_TGE_RELEASE).sub(ecosystemMinted);
  }


  function pendingTeamTokens() public view returns (uint256)
  {
    if(block.timestamp < startMiningTimestamp){
      return 0;
    }

    uint256 singlePerSec = TEAM_VESTING_AMT.div(TEAM_VESTING_PERIOD);

    uint256 timePast = uint256(block.timestamp).sub(startMiningTimestamp);

    if(timePast >= TEAM_VESTING_PERIOD){
      return TEAM_VESTING_AMT.add(TEAM_TGE_RELEASE).sub(teamMinted);
    }

    return timePast.mul(singlePerSec).add(TEAM_TGE_RELEASE).sub(teamMinted);
  }


  /**
   * Perform adjust on token supply once invoked
   */
  function supplyAdjust() public onlyOwner
  {

    require(block.timestamp >= nextAdjustTimestamp, "SingleToken: not yet");


    if(block.timestamp < launchPeriodEndTimestamp)
    {
      launchPeriodSupplyAdjust();
    }else
    {

      // first halving
      if( (block.timestamp - launchPeriodEndTimestamp) < SUPPLY_HALVING_WINDOW ){
        SUPPLY_PER_BLOCK = INITIAL_SUPPLY_PER_BLOCK.div(2);
      }else{
        // halving
        SUPPLY_PER_BLOCK = SUPPLY_PER_BLOCK.div(2);
      }

      nextAdjustTimestamp = nextAdjustTimestamp.add(SUPPLY_HALVING_WINDOW);

      emit SupplyAdjusted(SUPPLY_PER_BLOCK, nextAdjustTimestamp);

    }

  }


  function launchPeriodSupplyAdjust() internal{

    uint256 N = 6 - (launchPeriodEndTimestamp - block.timestamp).mul(100).div(LAUNCH_PERIOD_ADJUST_WINDOW).div(100);

    // multiplier = ( 32 + p(3.5-N) ) / 32
    // p = 5
    uint256 multiplier = uint256(3200).add(1750).sub(N.mul(500)).mul(1e12).div(3200);

    SUPPLY_PER_BLOCK = INITIAL_SUPPLY_PER_BLOCK.mul(multiplier).div(1e12);

    // advance the next adjust time
    nextAdjustTimestamp = nextAdjustTimestamp.add(LAUNCH_PERIOD_ADJUST_WINDOW);

    emit SupplyAdjusted(SUPPLY_PER_BLOCK, nextAdjustTimestamp);

  }



  // Copied and modified from YAM code:
  // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol
  // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol
  // Which is copied and modified from COMPOUND:
  // https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol

  /// @notice A record of each accounts delegate
  mapping (address => address) internal _delegates;

  /// @notice A checkpoint for marking number of votes from a given block
  struct Checkpoint {
    uint32 fromBlock;
    uint256 votes;
  }

  /// @notice A record of votes checkpoints for each account, by index
  mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;

  /// @notice The number of checkpoints for each account
  mapping (address => uint32) public numCheckpoints;

  /// @notice The EIP-712 typehash for the contract's domain
  bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");

  /// @notice The EIP-712 typehash for the delegation struct used by the contract
  bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");

  /// @notice A record of states for signing / validating signatures
  mapping (address => uint) public nonces;

  /// @notice An event thats emitted when an account changes its delegate
  event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

  /// @notice An event thats emitted when a delegate account's vote balance changes
  event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);

  /**
    * @notice Delegate votes from `msg.sender` to `delegatee`
    * @param delegator The address to get delegatee for
    */
  function delegates(address delegator)
      external
      view
      returns (address)
  {
      return _delegates[delegator];
  }

  /**
  * @notice Delegate votes from `msg.sender` to `delegatee`
  * @param delegatee The address to delegate votes to
  */
  function delegate(address delegatee) external {
    return _delegate(msg.sender, delegatee);
  }

  /**
    * @notice Delegates votes from signatory to `delegatee`
    * @param delegatee The address to delegate votes to
    * @param nonce The contract state required to match the signature
    * @param expiry The time at which to expire the signature
    * @param v The recovery byte of the signature
    * @param r Half of the ECDSA signature pair
    * @param s Half of the ECDSA signature pair
    */
  function delegateBySig(
    address delegatee,
    uint256 nonce,
    uint256 expiry,
    uint8 v,
    bytes32 r,
    bytes32 s
  )
      external
  {
      bytes32 domainSeparator = keccak256(
          abi.encode(
              DOMAIN_TYPEHASH,
              keccak256(bytes(name())),
              // getChainId(),
              block.chainid,
              address(this)
          )
      );

      bytes32 structHash = keccak256(
          abi.encode(
              DELEGATION_TYPEHASH,
              delegatee,
              nonce,
              expiry
          )
      );

      bytes32 digest = keccak256(
          abi.encodePacked(
              "\x19\x01",
              domainSeparator,
              structHash
          )
      );

      address signatory = ecrecover(digest, v, r, s);
      require(signatory != address(0), "SINGLE::delegateBySig: invalid signature");
      require(nonce == nonces[signatory]++, "SINGLE::delegateBySig: invalid nonce");
      require(block.timestamp <= expiry, "SINGLE::delegateBySig: signature expired");
      return _delegate(signatory, delegatee);
  }

  /**
    * @notice Gets the current votes balance for `account`
    * @param account The address to get votes balance
    * @return The number of current votes for `account`
    */
  function getCurrentVotes(address account)
      external
      view
      returns (uint256)
  {
      uint32 nCheckpoints = numCheckpoints[account];
      return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
  }

  /**
    * @notice Determine the prior number of votes for an account as of a block number
    * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
    * @param account The address of the account to check
    * @param blockNumber The block number to get the vote balance at
    * @return The number of votes the account had as of the given block
    */
  function getPriorVotes(address account, uint blockNumber)
      external
      view
      returns (uint256)
  {
    require(blockNumber < block.number, "SINGLE::getPriorVotes: not yet determined");

    uint32 nCheckpoints = numCheckpoints[account];
    if (nCheckpoints == 0) {
        return 0;
    }

    // First check most recent balance
    if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
        return checkpoints[account][nCheckpoints - 1].votes;
    }

    // Next check implicit zero balance
    if (checkpoints[account][0].fromBlock > blockNumber) {
        return 0;
    }

    uint32 lower = 0;
    uint32 upper = nCheckpoints - 1;
    while (upper > lower) {
        uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
        Checkpoint memory cp = checkpoints[account][center];
        if (cp.fromBlock == blockNumber) {
            return cp.votes;
        } else if (cp.fromBlock < blockNumber) {
            lower = center;
        } else {
            upper = center - 1;
        }
    }
    return checkpoints[account][lower].votes;
  }

  function _delegate(address delegator, address delegatee)
      internal
  {
    address currentDelegate = _delegates[delegator];
    uint256 delegatorBalance = balanceOf(delegator); // balance of underlying YAMs (not scaled);
    _delegates[delegator] = delegatee;

    emit DelegateChanged(delegator, currentDelegate, delegatee);

    _moveDelegates(currentDelegate, delegatee, delegatorBalance);
  }

  function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
    if (srcRep != dstRep && amount > 0) {
      if (srcRep != address(0)) {
        // decrease old representative
        uint32 srcRepNum = numCheckpoints[srcRep];
        uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
        uint256 srcRepNew = srcRepOld.sub(amount);
        _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
      }

      if (dstRep != address(0)) {
        // increase new representative
        uint32 dstRepNum = numCheckpoints[dstRep];
        uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
        uint256 dstRepNew = dstRepOld.add(amount);
        _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
      }
    }
  }

  function _writeCheckpoint(
    address delegatee,
    uint32 nCheckpoints,
    uint256 oldVotes,
    uint256 newVotes
  ) internal
  {
    uint32 blockNumber = safe32(block.number, "SINGLE::_writeCheckpoint: block number exceeds 32 bits");

    if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
        checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
    } else {
        checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
        numCheckpoints[delegatee] = nCheckpoints + 1;
    }

    emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
  }

  function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
    require(n < 2**32, errorMessage);
    return uint32(n);
  }


}



interface IAccountant {
  function withdrawToProtocol(address token, uint256 amount, uint256 singleAmtMin) external returns(uint256 protocolAmount);

  function withdrawToBurn(address token,uint256 amount, uint256 singleAmtMin) external returns(uint256 burnAmount);
  
  function deposit(address token, uint16 treasuryBps, uint16 protocolBps, uint256 totalAmount) external;
}



interface ILocker {
    function lock(address _user, uint256 _amount, uint256 pid) external;
    function pendingTokens(uint256 pid, address user) external returns (uint256);
    function release(uint256 pid, address user) external;
}



pragma experimental ABIEncoderV2;


/**
 * Distribute SINGLE by staking ERC20 based tokens
 */
contract BigBang is Ownable, ReentrancyGuard {
  using SafeMath for uint256;
  using SafeERC20 for IERC20;

  // Info of each user.
  struct UserInfo {
    uint256 amount; // How many Staking tokens the user has provided.
    uint256 rewardDebt; // Reward debt. See explanation below.
    address fundedBy; // Funded by who?
  }

  // Info of each pool.
  struct PoolInfo {
    uint256 allocPoint; // How many allocation points assigned to this pool. SINGLEs to distribute per block.
    uint256 lastRewardBlock; // Last block number that SINGLEs distribution occurs.
    uint256 accRewardPerShare; // Accumulated SINGLEs per share, times 1e12. See below.
  }

  // The reward token
  SingleToken public single;
  // Dev address.
  address public devaddr;
  // SINGLE tokens created per block.
  uint256 public singlePerBlock;


  /// @notice The SINGLE ERC-20 contract.
  IERC20 public SINGLE;

  /// @notice Info of each pool.
  PoolInfo[] public poolInfo;
  /// @notice Address of the ERC-20 for each Pool.
  IERC20[] public stakeTokens;
  /// @notice Address of each `ILockers` contract.
  ILocker public locker;
  IAccountant public accountant;
  

  /// @notice Info of each user that stakes tokens.
  mapping (uint256 => mapping (address => UserInfo)) public userInfo;
  /// @dev Total allocation points. Must be the sum of all allocation points in all pools.
  uint256 public totalAllocPoint;

  uint256 private constant ACC_SINGLE_PRECISION = 1e12;

  // always the first vault to be deployed
  uint8 public constant IBSINGLE_POOL_ID = 1;
  mapping (address => bool ) public whitelistedFunders;

  // Bonus single during bonus period.
  uint256 public bonusSinglePerBlock;
  // Block number when bonus SINGLE period ends.
  uint256 public bonusEndBlock;
  // Block number when bonus SINGLE period starts.
  uint256 public bonusStartBlock;


  event Deposit(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);
  event Withdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);
  event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);
  event Harvest(address indexed user, uint256 indexed pid, uint256 amount);
  event LogPoolAddition(uint256 indexed pid, uint256 allocPoint, IERC20 indexed lpToken);
  event LogSetPool(uint256 indexed pid, uint256 allocPoint);
  event LogUpdatePool(uint256 indexed pid, uint256 lastRewardBlock, uint256 lpSupply, uint256 accRewardPerShare);
  event RewardProtocol(uint256 rewardTotal, uint256 extraPerShare);
  event SetBonus( uint256 extraRewardPerBlock, uint256 bonusStartBlock, uint256 bonusEndBlock);
  event LogUpdatePoolBonus(uint256 indexed pid, uint256 lastRewardBlock, uint256 lpSupply, uint256 accRewardPerShare);
  event BuyBack(uint256 accRewardPerShare);
  event LogInit();
  

  constructor(
    SingleToken _single,
    address _devaddr
  ) {
    totalAllocPoint = 0;
    single = _single;
    SINGLE = IERC20(address(_single));
    devaddr = _devaddr;
    singlePerBlock = single.SUPPLY_PER_BLOCK();

    emit LogInit();
  }


  // Update dev address by the previous dev.
  function setDev(address _devaddr) public {
    require(msg.sender == devaddr, "dev: not owner?");
    devaddr = _devaddr;
  }


  // control the mining rate of reward tokens
  // only can invoked at the time of supply halving
  function updateSinglePerBlock() external onlyOwner {
    single.supplyAdjust();
    singlePerBlock = single.SUPPLY_PER_BLOCK();
  }


  /// @notice Returns the number of pools.
  function poolLength() public view returns (uint256) {
    return poolInfo.length;
  }

  function manualBurn(uint256 _amount) external {
    require (msg.sender == address(accountant), "accountant only"); 
    IERC20(SINGLE).safeTransferFrom(msg.sender, address(this), _amount);
    single.burn(address(this), _amount);
  }

  function mintForLiquidity(address _to, uint256 _amount) public onlyOwner {
    single.mintForLiquidity(_to, _amount);
  }

  function mintForEcosystem(address _to, uint256 _amount) public onlyOwner {
    single.mintForEcosystem(_to, _amount);
  }

  function mintForTeam(address _to, uint256 _amount) public onlyOwner {
    single.mintForTeam(_to, _amount);
  }
  

  /**
   * Mint SINGLE tokens and lock for a period of time
   * @param pid Locker pool id
   */
  function mintForInvestor(uint256 pid, address _for, uint256 _amount) public onlyOwner {
    // mint SINGLE from the investor pool
    single.mintForInvestor(address(this), _amount);
    require(address(locker) != address(0), "!locker");
    SINGLE.safeApprove(address(locker),_amount);
    // locker handle the lock and vesting
    locker.lock(_for, _amount, pid);
  }


  /// @notice Returns if stakeToken is duplicated
  function isDuplicatedPool(IERC20 _stakeToken) public view returns (bool) {
    uint256 length = poolInfo.length;
    for(uint256 _pid = 0; _pid < length; _pid++) {
      if(stakeTokens[_pid] == _stakeToken) return true;
    }
    return false;
  }

  function setLocker (address _locker) external onlyOwner {
    require(address(locker) == address(0),"once only");
    locker = ILocker (_locker);
  }


  /// @notice Add a new lp to the pool. Can only be called by the owner.
  
  /// @param allocPoint AP of the new pool
  /// @param _stakeToken address of the LP token
  function addPool(
      uint256 allocPoint, 
      IERC20 _stakeToken, 
      uint256 _startBlock,
      bool _withUpdate
  ) external onlyOwner {
    
    require(!isDuplicatedPool(_stakeToken), "BigBang::addPool:: stakeToken dup");
    
    if (_withUpdate) {
      updateAllPools();
    }
    
    uint256 lastRewardBlock = block.number > _startBlock ? block.number : _startBlock;
    totalAllocPoint = totalAllocPoint.add(allocPoint);

    stakeTokens.push(_stakeToken);
    
    poolInfo.push(PoolInfo({
      allocPoint: allocPoint,
      lastRewardBlock: lastRewardBlock,
      accRewardPerShare: 0
    }));

    emit LogPoolAddition(stakeTokens.length.sub(1), allocPoint, _stakeToken);
  }


  /// @notice Update the given pool's SINGLE allocation point. Can only be called by the owner.
  
  /// @param _pid The index of the pool. See `poolInfo`.
  /// @param _allocPoint new AP of the pool
  function setPool(
    uint256 _pid, 
    uint256 _allocPoint,
    bool _withUpdate
  ) external onlyOwner {
    if(_withUpdate) {
      updateAllPools();
    }
    
    totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);
    poolInfo[_pid].allocPoint = _allocPoint;
    
    emit LogSetPool(_pid, _allocPoint);
  }

  /// @notice Update reward variables for all pools. Be careful of gas spending!
  function updateAllPools() public {
    uint256 len = poolLength();
    for (uint256 i = 0; i < len; ++i) {
      updatePool(i);
    }
  }

  function setBonus(
    uint256 _extraRewardPerBlock,
    uint256 _numberOfBlocks
    // bool _withUpdate
    // uint256 _bonusLockUpBps
  ) external onlyOwner {
    require(_numberOfBlocks > 0, "setBonus: bad bonusEndBlock");
    require(_extraRewardPerBlock > 0, "setBonus: bad extraReward");
    require(bonusEndBlock < block.number, "setBonus: bonus round not ended");
    
    // if(_withUpdate) {
    //   updateAllPools();
    // }

    bonusSinglePerBlock = _extraRewardPerBlock;
    bonusStartBlock = block.number;
    bonusEndBlock = block.number.add(_numberOfBlocks);
    SINGLE.safeTransferFrom(msg.sender, address(this), bonusSinglePerBlock.mul(_numberOfBlocks));
    
    emit SetBonus(_extraRewardPerBlock, bonusStartBlock, bonusEndBlock);
  }


  /// @notice Update reward variables of the given pool.
  /// @param pid The index of the pool. See `poolInfo`.
  function updatePool(uint256 pid) public {
    PoolInfo storage pool = poolInfo[pid];
    if (block.number <= pool.lastRewardBlock) {
      return;
    }
    uint256 stakeTokenSupply = stakeTokens[pid].balanceOf(address(this));
    if (stakeTokenSupply == 0) {
      pool.lastRewardBlock = block.number;
      return;
    }
    uint256 lastRewardBlock = pool.lastRewardBlock;
    uint256 multiplier = block.number.sub(lastRewardBlock);
    pool.lastRewardBlock = block.number;
    
    
    
    // uint256 multiplier = blocks;
    uint256 singleReward = totalAllocPoint > 0? multiplier.mul(singlePerBlock).mul(pool.allocPoint).div(totalAllocPoint) : 0;
    
    // prevent minting rewards if the reserve is depleted
    if( single.totalSupply().add(singleReward).add(singleReward.div(10)) < single.cap() ){
      pool.accRewardPerShare = pool.accRewardPerShare.add( singleReward.mul(ACC_SINGLE_PRECISION).div(stakeTokenSupply) );
      // pool.lastRewardBlock = block.number;
      single.mint(devaddr, singleReward.div(10));
      single.mint(address(this), singleReward);
      
      emit LogUpdatePool(pid, pool.lastRewardBlock, stakeTokenSupply, pool.accRewardPerShare);
    }

    //if bonus tokens are rewarded.
    uint256 bonusReward;
    uint256 bonusEndRange = bonusEndBlock > block.number? block.number : bonusEndBlock;
    uint256 bonusStartRange = lastRewardBlock > bonusStartBlock? lastRewardBlock : bonusStartBlock;
    if (bonusEndRange > bonusStartRange){
      bonusReward = totalAllocPoint > 0? (bonusEndRange.sub(bonusStartRange)).mul(bonusSinglePerBlock).mul(pool.allocPoint).div(totalAllocPoint): 0;
    }

    if (bonusReward > 0) {
      pool.accRewardPerShare = pool.accRewardPerShare.add( bonusReward.mul(ACC_SINGLE_PRECISION).div(stakeTokenSupply) );
      emit LogUpdatePoolBonus(pid, pool.lastRewardBlock, stakeTokenSupply, pool.accRewardPerShare);
    }
      

  }



  /**
      ██     ██  ██████  ██████  ██   ██ 
      ██     ██ ██    ██ ██   ██ ██  ██  
      ██  █  ██ ██    ██ ██████  █████   
      ██ ███ ██ ██    ██ ██   ██ ██  ██  
      ███ ███   ██████  ██   ██ ██   ██ 
  */


  /// @notice Deposit tokens for SINGLE allocation.
  /// @param _for The address that will get yield
  /// @param pid The index of the pool. See `poolInfo`.
  /// @param amount to deposit.
  function deposit(address _for, uint256 pid, uint256 amount) external nonReentrant {
    if(!whitelistedFunders[msg.sender]){
      require(_for == msg.sender, "EOA cannot deposit for others");
    } 
    _deposit(_for, pid, amount);
    
  }

  

  function _deposit(address _for, uint256 pid, uint amount) internal {
    PoolInfo storage pool = poolInfo[pid];
    UserInfo storage user = userInfo[pid][_for];
    if (user.fundedBy != address(0)) require(user.fundedBy == msg.sender, "bad sof");
    require(address(stakeTokens[pid]) != address(0), "deposit: not accept deposit");
    updatePool(pid);
    if (user.amount > 0) _harvest(_for, pid);
    if (user.fundedBy == address(0)) user.fundedBy = msg.sender;
    stakeTokens[pid].safeTransferFrom(address(msg.sender), address(this), amount);
    user.amount = user.amount.add(amount);
    user.rewardDebt = user.amount.mul(pool.accRewardPerShare).div(ACC_SINGLE_PRECISION);

    emit Deposit(msg.sender, pid, amount, _for);
  }

  
  /// @notice Withdraw tokens from the distribution pool
  /// @param _for Receiver of yield
  /// @param pid The index of the pool. See `poolInfo`.
  /// @param amount of lp tokens to withdraw.
  function withdraw(address _for, uint256 pid, uint256 amount) external nonReentrant {

    PoolInfo storage pool = poolInfo[pid];
    UserInfo storage user = userInfo[pid][_for];
    require(user.fundedBy == msg.sender, "only funder");
    require(user.amount >= amount, "withdraw: not good");
    updatePool(pid);
    _harvest(_for, pid);
    user.amount = user.amount.sub(amount);
    user.rewardDebt = user.amount.mul(pool.accRewardPerShare).div(1e12);
    if (user.amount == 0) user.fundedBy = address(0);
    
    stakeTokens[pid].safeTransfer(address(msg.sender), amount);

    emit Withdraw(msg.sender, pid, user.amount, _for);
  }


  // Harvest SINGLEs earn from the pool.
  function harvest(uint256 _pid) external nonReentrant {
    // console.log("harvesting", block.number);
    PoolInfo storage pool = poolInfo[_pid];
    UserInfo storage user = userInfo[_pid][msg.sender];
    updatePool(_pid);
    _harvest(msg.sender, _pid);
    user.rewardDebt = user.amount.mul(pool.accRewardPerShare).div(ACC_SINGLE_PRECISION);
  }


  /// @notice Harvest proceeds for transaction sender to `to`.
  /// @param pid The index of the pool. See `poolInfo`.
  /// @param to Receiver of SINGLE rewards.
  function _harvest(address to, uint256 pid) internal {
    PoolInfo storage pool = poolInfo[pid];
    UserInfo storage user = userInfo[pid][to];

    if(user.amount > 0){
      uint256 pending = user.amount.mul(pool.accRewardPerShare).div(ACC_SINGLE_PRECISION).sub(user.rewardDebt);
      require(pending <= single.balanceOf(address(this)), "wtf not enough SINGLE");
      SINGLE.safeTransfer(to, pending);

      emit Harvest(to, pid, pending);
    }
  }


  /// @notice Withdraw without caring about rewards. EMERGENCY ONLY.
  /// @param pid The index of the pool. See `poolInfo`.
  /// @param to Receiver of the staking tokens.
  function emergencyWithdraw(uint256 pid, address to) external nonReentrant {
    UserInfo storage user = userInfo[pid][msg.sender];
    require(user.fundedBy == msg.sender, "BigBang::emergencyWithdraw:: only funder");
    uint256 amount = user.amount;
    user.amount = 0;
    user.rewardDebt = 0;
    user.fundedBy = address(0);
    // Note: transfer can fail or succeed if `amount` is zero.
    stakeTokens[pid].safeTransfer(to, amount);
    emit EmergencyWithdraw(msg.sender, pid, amount, to);
  }



  /// @notice View function to see pending SINGLEs on frontend.
  /// @param _pid The index of the pool. See `poolInfo`.
  /// @param _user address of user
  function pendingSingle(uint256 _pid, address _user) external view returns (uint256) {
    PoolInfo storage pool = poolInfo[_pid];
    UserInfo storage user = userInfo[_pid][_user];
    uint256 accRewardPerShare = pool.accRewardPerShare;
    uint256 stakeTokenSupply = stakeTokens[_pid].balanceOf(address(this));
    if (block.number > pool.lastRewardBlock && stakeTokenSupply != 0) {
      // uint256 blocks = block.number.sub(pool.lastRewardBlock);
      uint256 multiplier = block.number.sub(pool.lastRewardBlock);
      uint256 singleReward = totalAllocPoint > 0? multiplier.mul(singlePerBlock).mul(pool.allocPoint).div(totalAllocPoint) : 0;
    //   accRewardPerShare = accRewardPerShare.add(singleReward.mul(ACC_SINGLE_PRECISION).div(stakeTokenSupply));
      uint256 bonusReward;
      if (block.number <= bonusEndBlock) {
        bonusReward = totalAllocPoint > 0? multiplier.mul(bonusSinglePerBlock).mul(pool.allocPoint).div(totalAllocPoint): 0;
      }else if(block.number > bonusEndBlock && pool.lastRewardBlock < bonusEndBlock) {
        bonusReward = totalAllocPoint > 0? bonusEndBlock.sub(pool.lastRewardBlock).mul(bonusSinglePerBlock).mul(pool.allocPoint).div(totalAllocPoint) : 0;
      }
    
      accRewardPerShare = accRewardPerShare.add((singleReward.add(bonusReward)).mul(ACC_SINGLE_PRECISION).div(stakeTokenSupply));
    }
    
    return user.amount.mul(accRewardPerShare).div(ACC_SINGLE_PRECISION).sub(user.rewardDebt);
  }


  function setAccountant (address payable _accountant) external onlyOwner {
    accountant = IAccountant(_accountant);
  }

  function setWhitelistedFunders(address[] calldata funders, bool status) external onlyOwner {
    for (uint256 i = 0; i <  funders.length; i++) {
      whitelistedFunders[funders[i]] = status;
    }
  }

  function rewardProtocol(address token, uint256 amount, uint256 returnAmtMin) external {
    require( msg.sender == devaddr, "not dev");
    require(IERC20(stakeTokens[IBSINGLE_POOL_ID]).balanceOf(address(this)) > 0,"no staking amount" );
    
    // perform buyback and compute the total SINGLE
    uint256 back = accountant.withdrawToProtocol(token, amount, returnAmtMin);

    // burn portion of the SINGLE
    // uint256 burn = back.mul(accountant.burnBps()).div(10000);
    // back = back.sub(burn);
    // single.burn(address(this), burn);
    require(IERC20(SINGLE).balanceOf(address(this)) >= back, "wtf? not enough single");
    uint256 extraPerShare = back.mul(ACC_SINGLE_PRECISION).div(IERC20(stakeTokens[IBSINGLE_POOL_ID]).balanceOf(address(this)));
    // deposit into protocol profit
    poolInfo[IBSINGLE_POOL_ID].accRewardPerShare = poolInfo[IBSINGLE_POOL_ID].accRewardPerShare
      .add(extraPerShare);

    emit RewardProtocol(back, extraPerShare);
  }

  function buyBackAndBurn(address token, uint256 amount,  uint256 returnAmtMin) external {
    require( msg.sender == devaddr, "not dev");
    
    single.burn(address(this), accountant.withdrawToBurn(token, amount, returnAmtMin));
    
  }

}

Contract ABI

[{"inputs":[{"internalType":"contract SingleToken","name":"_single","type":"address"},{"internalType":"address","name":"_devaddr","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"accRewardPerShare","type":"uint256"}],"name":"BuyBack","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Harvest","type":"event"},{"anonymous":false,"inputs":[],"name":"LogInit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allocPoint","type":"uint256"},{"indexed":true,"internalType":"contract IERC20","name":"lpToken","type":"address"}],"name":"LogPoolAddition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allocPoint","type":"uint256"}],"name":"LogSetPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"accRewardPerShare","type":"uint256"}],"name":"LogUpdatePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"accRewardPerShare","type":"uint256"}],"name":"LogUpdatePoolBonus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rewardTotal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"extraPerShare","type":"uint256"}],"name":"RewardProtocol","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"extraRewardPerBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bonusStartBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bonusEndBlock","type":"uint256"}],"name":"SetBonus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"IBSINGLE_POOL_ID","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SINGLE","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accountant","outputs":[{"internalType":"contract IAccountant","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"contract IERC20","name":"_stakeToken","type":"address"},{"internalType":"uint256","name":"_startBlock","type":"uint256"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"addPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bonusEndBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonusSinglePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonusStartBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"returnAmtMin","type":"uint256"}],"name":"buyBackAndBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_for","type":"address"},{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"devaddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_stakeToken","type":"address"}],"name":"isDuplicatedPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"locker","outputs":[{"internalType":"contract ILocker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"manualBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintForEcosystem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"address","name":"_for","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintForInvestor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintForLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintForTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingSingle","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"internalType":"uint256","name":"accRewardPerShare","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"returnAmtMin","type":"uint256"}],"name":"rewardProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_accountant","type":"address"}],"name":"setAccountant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_extraRewardPerBlock","type":"uint256"},{"internalType":"uint256","name":"_numberOfBlocks","type":"uint256"}],"name":"setBonus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_devaddr","type":"address"}],"name":"setDev","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_locker","type":"address"}],"name":"setLocker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"setPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"funders","type":"address[]"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setWhitelistedFunders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"single","outputs":[{"internalType":"contract SingleToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"singlePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakeTokens","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAllocPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateAllPools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateSinglePerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"address","name":"fundedBy","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistedFunders","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_for","type":"address"},{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b506040516200321938038062003219833981016040819052620000349162000176565b6200003f3362000126565b600180556000600b55600280546001600160a01b038085166001600160a01b0319928316811790935560058054831684179055600380549185169190921617905560408051636687fb5360e01b81529051636687fb5391600480820192602092909190829003018186803b158015620000b757600080fd5b505afa158015620000cc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000f29190620001b4565b6004556040517f98a9bd3b7a617581fc53b1e2992534e0e0cb5091c9d44aa1a7fc978f706caa8390600090a15050620001e6565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000806040838503121562000189578182fd5b82516200019681620001cd565b6020840151909250620001a981620001cd565b809150509250929050565b600060208284031215620001c6578081fd5b5051919050565b6001600160a01b0381168114620001e357600080fd5b50565b61302380620001f66000396000f3fe608060405234801561001057600080fd5b506004361061025e5760003560e01c8063670746a711610146578063b9ec7d74116100c3578063d743b81b11610087578063d743b81b14610567578063d7b96d4e1461057a578063ddc632621461058d578063de3e828e146105a0578063e46d2ee0146105b3578063f2fde38b146105cd57600080fd5b8063b9ec7d7414610513578063c5d8ca381461051b578063c937d7e51461052e578063d477f05f14610541578063d49e77cd1461055457600080fd5b80638da5cb5b1161010a5780638da5cb5b1461046c57806393f1a40b1461047d578063a921aa9d146104e4578063b03df69d146104ed578063b5c5f6721461050057600080fd5b8063670746a714610422578063715018a6146104355780637547c7a31461043d5780637c179aa31461045057806386b8faa51461046357600080fd5b80632c27e40e116101df5780634878e97f116101a35780634878e97f146103c557806348ea7127146103d857806349c10824146103eb5780634fb3ccc5146103f357806351eb05a6146104065780635ad473801461041957600080fd5b80632c27e40e146103465780632f940c701461035957806335c02cb71461036c57806335e3f5db1461037f57806346ca6bea146103b257600080fd5b8063171060ec11610226578063171060ec146102fb57806317caf6f11461030e57806319e6af1c146103175780631aed65531461032a57806323b635851461033357600080fd5b8063037c99b014610263578063081e3eda146102785780630efe6a8b1461028f57806314c1af35146102a25780631526fe27146102cd575b600080fd5b610276610271366004612ddd565b6105e0565b005b6006545b6040519081526020015b60405180910390f35b61027661029d366004612c2d565b61078e565b6005546102b5906001600160a01b031681565b6040516001600160a01b039091168152602001610286565b6102e06102db366004612cfe565b610839565b60408051938452602084019290925290820152606001610286565b610276610309366004612be6565b61086c565b61027c600b5481565b610276610325366004612c02565b6108fd565b61027c600e5481565b610276610341366004612cfe565b61098f565b610276610354366004612c02565b610a5a565b610276610367366004612d2e565b610ab6565b61027661037a366004612c2d565b610c22565b6103a261038d366004612be6565b600c6020526000908152604090205460ff1681565b6040519015158152602001610286565b6102766103c0366004612dfe565b610d55565b6102766103d3366004612d94565b610e51565b6102766103e6366004612be6565b61103c565b610276611088565b6009546102b5906001600160a01b031681565b610276610414366004612cfe565b6111a5565b61027c600d5481565b610276610430366004612c2d565b611654565b610276611a62565b6102b561044b366004612cfe565b611a98565b61027661045e366004612d5d565b611ac2565b61027c60045481565b6000546001600160a01b03166102b5565b6104c061048b366004612d2e565b600a6020908152600092835260408084209091529082529020805460018201546002909201549091906001600160a01b031683565b6040805193845260208401929092526001600160a01b031690820152606001610286565b61027c600f5481565b6103a26104fb366004612be6565b611bf3565b61027661050e366004612c2d565b611c6f565b610276611e46565b61027c610529366004612d2e565b611e7b565b61027661053c366004612c61565b6120ef565b61027661054f366004612be6565b61219e565b6003546102b5906001600160a01b031681565b610276610575366004612c02565b61220c565b6008546102b5906001600160a01b031681565b61027661059b366004612cfe565b612268565b6002546102b5906001600160a01b031681565b6105bb600181565b60405160ff9091168152602001610286565b6102766105db366004612be6565b612318565b6000546001600160a01b031633146106135760405162461bcd60e51b815260040161060a90612e93565b60405180910390fd5b600081116106635760405162461bcd60e51b815260206004820152601b60248201527f736574426f6e75733a2062616420626f6e7573456e64426c6f636b0000000000604482015260640161060a565b600082116106b35760405162461bcd60e51b815260206004820152601960248201527f736574426f6e75733a2062616420657874726152657761726400000000000000604482015260640161060a565b43600e54106107045760405162461bcd60e51b815260206004820152601f60248201527f736574426f6e75733a20626f6e757320726f756e64206e6f7420656e64656400604482015260640161060a565b600d82905543600f81905561071990826123b3565b600e55600d54610745903390309061073190856123c6565b6005546001600160a01b03169291906123d2565b600f54600e546040805185815260208101939093528201527fc792ade3e5d9b37fc2fd56ab64f9565275ad09c1b491d55839dadc83cb7090569060600160405180910390a15050565b600260015414156107b15760405162461bcd60e51b815260040161060a90612ec8565b6002600155336000908152600c602052604090205460ff16610825576001600160a01b03831633146108255760405162461bcd60e51b815260206004820152601d60248201527f454f412063616e6e6f74206465706f73697420666f72206f7468657273000000604482015260640161060a565b61083083838361243d565b50506001805550565b6006818154811061084957600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000546001600160a01b031633146108965760405162461bcd60e51b815260040161060a90612e93565b6008546001600160a01b0316156108db5760405162461bcd60e51b81526020600482015260096024820152686f6e6365206f6e6c7960b81b604482015260640161060a565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146109275760405162461bcd60e51b815260040161060a90612e93565b600254604051630679abc760e21b81526001600160a01b03909116906319e6af1c906109599085908590600401612e47565b600060405180830381600087803b15801561097357600080fd5b505af1158015610987573d6000803e3d6000fd5b505050505050565b6009546001600160a01b031633146109db5760405162461bcd60e51b815260206004820152600f60248201526e6163636f756e74616e74206f6e6c7960881b604482015260640161060a565b6005546109f3906001600160a01b03163330846123d2565b600254604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac90610a259030908590600401612e47565b600060405180830381600087803b158015610a3f57600080fd5b505af1158015610a53573d6000803e3d6000fd5b5050505050565b6000546001600160a01b03163314610a845760405162461bcd60e51b815260040161060a90612e93565b600254604051631613f20760e11b81526001600160a01b0390911690632c27e40e906109599085908590600401612e47565b60026001541415610ad95760405162461bcd60e51b815260040161060a90612ec8565b600260018190556000838152600a60209081526040808320338085529252909120918201546001600160a01b031614610b655760405162461bcd60e51b815260206004820152602860248201527f42696742616e673a3a656d657267656e637957697468647261773a3a206f6e6c6044820152673c90333ab73232b960c11b606482015260840161060a565b8054600080835560018301556002820180546001600160a01b031916905560078054610bca91859184919088908110610bae57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0316919061266e565b826001600160a01b031684336001600160a01b03167f2cac5e20e1541d836381527a43f651851e302817b71dc8e810284e69210c1c6b84604051610c1091815260200190565b60405180910390a45050600180555050565b6003546001600160a01b03163314610c665760405162461bcd60e51b81526020600482015260076024820152663737ba103232bb60c91b604482015260640161060a565b60025460095460405163eb15cb9b60e01b81526001600160a01b038681166004830152602482018690526044820185905292831692639dc29fac92309291169063eb15cb9b90606401602060405180830381600087803b158015610cc957600080fd5b505af1158015610cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d019190612d16565b6040518363ffffffff1660e01b8152600401610d1e929190612e47565b600060405180830381600087803b158015610d3857600080fd5b505af1158015610d4c573d6000803e3d6000fd5b50505050505050565b6000546001600160a01b03163314610d7f5760405162461bcd60e51b815260040161060a90612e93565b8015610d8d57610d8d611e46565b610dd582610dcf60068681548110610db557634e487b7160e01b600052603260045260246000fd5b6000918252602090912060039091020154600b5490612692565b906123b3565b600b819055508160068481548110610dfd57634e487b7160e01b600052603260045260246000fd5b906000526020600020906003020160000181905550827f942cc7e17a17c164bd977f32ab8c54265d5b9d481e4e352bf874f1e568874e7c83604051610e4491815260200190565b60405180910390a2505050565b6000546001600160a01b03163314610e7b5760405162461bcd60e51b815260040161060a90612e93565b610e8483611bf3565b15610edb5760405162461bcd60e51b815260206004820152602160248201527f42696742616e673a3a616464506f6f6c3a3a207374616b65546f6b656e2064756044820152600760fc1b606482015260840161060a565b8015610ee957610ee9611e46565b6000824311610ef85782610efa565b435b600b54909150610f0a90866123b3565b600b5560078054600180820183557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68890910180546001600160a01b0319166001600160a01b03881690811790915560408051606081018252898152602081018681526000928201838152600680548088018255945291517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f600390940293840155517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40830155517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d4190910155915461100191612692565b6040518781527f4710feb78e3bce8d2e3ca2989a8eb2f8bcd32a6a55b4535942c180fc4d2e2952906020015b60405180910390a35050505050565b6000546001600160a01b031633146110665760405162461bcd60e51b815260040161060a90612e93565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146110b25760405162461bcd60e51b815260040161060a90612e93565b600260009054906101000a90046001600160a01b03166001600160a01b031663dc04b8e16040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561110257600080fd5b505af1158015611116573d6000803e3d6000fd5b50505050600260009054906101000a90046001600160a01b03166001600160a01b0316636687fb536040518163ffffffff1660e01b815260040160206040518083038186803b15801561116857600080fd5b505afa15801561117c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a09190612d16565b600455565b6000600682815481106111c857634e487b7160e01b600052603260045260246000fd5b90600052602060002090600302019050806001015443116111e7575050565b60006007838154811061120a57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561125657600080fd5b505afa15801561126a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128e9190612d16565b9050806112a057504360019091015550565b600182015460006112b14383612692565b436001860155600b549091506000906112cb5760006112fa565b6112fa600b546112f487600001546112ee600454876123c690919063ffffffff16565b906123c6565b9061269e565b9050600260009054906101000a90046001600160a01b03166001600160a01b031663355274ea6040518163ffffffff1660e01b815260040160206040518083038186803b15801561134a57600080fd5b505afa15801561135e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113829190612d16565b61141a61139083600a61269e565b610dcf84600260009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e257600080fd5b505afa1580156113f6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcf9190612d16565b101561156a57611441611436856112f48464e8d4a510006123c6565b6002870154906123b3565b600280870191909155546003546001600160a01b03918216916340c10f19911661146c84600a61269e565b6040518363ffffffff1660e01b8152600401611489929190612e47565b600060405180830381600087803b1580156114a357600080fd5b505af11580156114b7573d6000803e3d6000fd5b50506002546040516340c10f1960e01b81526001600160a01b0390911692506340c10f1991506114ed9030908590600401612e47565b600060405180830381600087803b15801561150757600080fd5b505af115801561151b573d6000803e3d6000fd5b5050506001860154600287015460408051928352602083018890528201528791507fcb7325664a4a3b7c7223eefc492a97ca4fdf94d46884621e5a8fae5a04b2b9d29060600160405180910390a25b60008043600e541161157e57600e54611580565b435b90506000600f54861161159557600f54611597565b855b9050808211156115d2576000600b54116115b25760006115cf565b600b548854600d546115cf92916112f4916112ee90818888612692565b92505b8215611649576115f96115ee886112f48664e8d4a510006123c6565b60028a0154906123b3565b60028901819055600189015460408051918252602082018a905281019190915289907f18abc8dd3aed2549a71ea38dd4f33f27965b83d5faa27e9f8c57ea793f26bfa09060600160405180910390a25b505050505050505050565b6003546001600160a01b031633146116985760405162461bcd60e51b81526020600482015260076024820152663737ba103232bb60c91b604482015260640161060a565b60006007600160ff16815481106116bf57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561170b57600080fd5b505afa15801561171f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117439190612d16565b116117845760405162461bcd60e51b81526020600482015260116024820152701b9bc81cdd185ada5b99c8185b5bdd5b9d607a1b604482015260640161060a565b60095460405163319ad32360e21b81526001600160a01b0385811660048301526024820185905260448201849052600092169063c66b4c8c90606401602060405180830381600087803b1580156117da57600080fd5b505af11580156117ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118129190612d16565b6005546040516370a0823160e01b815230600482015291925082916001600160a01b03909116906370a082319060240160206040518083038186803b15801561185a57600080fd5b505afa15801561186e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118929190612d16565b10156118d95760405162461bcd60e51b81526020600482015260166024820152757774663f206e6f7420656e6f7567682073696e676c6560501b604482015260640161060a565b60006119966007600160ff168154811061190357634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561194f57600080fd5b505afa158015611963573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119879190612d16565b6112f48464e8d4a510006123c6565b90506119e1816006600160ff16815481106119c157634e487b7160e01b600052603260045260246000fd5b9060005260206000209060030201600201546123b390919063ffffffff16565b600680546001908110611a0457634e487b7160e01b600052603260045260246000fd5b9060005260206000209060030201600201819055507f5049043f22094ec08370ec6e3e282dd2a2322376430a73f8c8b0e6a7110ab1958282604051611a53929190918252602082015260400190565b60405180910390a15050505050565b6000546001600160a01b03163314611a8c5760405162461bcd60e51b815260040161060a90612e93565b611a9660006126aa565b565b60078181548110611aa857600080fd5b6000918252602090912001546001600160a01b0316905081565b6000546001600160a01b03163314611aec5760405162461bcd60e51b815260040161060a90612e93565b600254604051631efd988560e31b81526001600160a01b039091169063f7ecc42890611b1e9030908590600401612e47565b600060405180830381600087803b158015611b3857600080fd5b505af1158015611b4c573d6000803e3d6000fd5b50506008546001600160a01b031615159150611b9690505760405162461bcd60e51b815260206004820152600760248201526610b637b1b5b2b960c91b604482015260640161060a565b600854600554611bb3916001600160a01b039182169116836126fa565b60085460405163e2ab691d60e01b81526001600160a01b03848116600483015260248201849052604482018690529091169063e2ab691d90606401610d1e565b600654600090815b81811015611c6557836001600160a01b031660078281548110611c2e57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b03161415611c53575060019392505050565b80611c5d81612f99565b915050611bfb565b5060009392505050565b60026001541415611c925760405162461bcd60e51b815260040161060a90612ec8565b6002600181905550600060068381548110611cbd57634e487b7160e01b600052603260045260246000fd5b60009182526020808320868452600a825260408085206001600160a01b03808b1687529352909320600281015460039093029093019350163314611d315760405162461bcd60e51b815260206004820152600b60248201526a37b7363c90333ab73232b960a91b604482015260640161060a565b8054831115611d775760405162461bcd60e51b81526020600482015260126024820152711dda5d1a191c985dce881b9bdd0819dbdbd960721b604482015260640161060a565b611d80846111a5565b611d8a858561280d565b8054611d969084612692565b8082556002830154611db39164e8d4a51000916112f491906123c6565b60018201558054611dd1576002810180546001600160a01b03191690555b611df7338460078781548110610bae57634e487b7160e01b600052603260045260246000fd5b80546040519081526001600160a01b03861690859033907f8166bf25f8a2b7ed3c85049207da4358d16edbed977d23fa2ee6f0dde3ec21329060200160405180910390a4505060018055505050565b6000611e5160065490565b905060005b81811015611e7757611e67816111a5565b611e7081612f99565b9050611e56565b5050565b60008060068481548110611e9f57634e487b7160e01b600052603260045260246000fd5b60009182526020808320878452600a825260408085206001600160a01b03891686529092529083206003929092020160028101546007805492955092939092909188908110611efe57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015611f4a57600080fd5b505afa158015611f5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f829190612d16565b9050836001015443118015611f9657508015155b156120b6576000611fb485600101544361269290919063ffffffff16565b9050600080600b5411611fc8576000611feb565b611feb600b546112f488600001546112ee600454876123c690919063ffffffff16565b90506000600e544311612033576000600b541161200957600061202c565b61202c600b546112f489600001546112ee600d54886123c690919063ffffffff16565b905061208f565b600e54431180156120495750600e548760010154105b1561208f576000600b541161205f57600061208c565b61208c600b546112f489600001546112ee600d546112ee8d60010154600e5461269290919063ffffffff16565b90505b6120b06120a9856112f464e8d4a510006112ee87876123b3565b86906123b3565b94505050505b6120e483600101546120de64e8d4a510006112f48688600001546123c690919063ffffffff16565b90612692565b979650505050505050565b6000546001600160a01b031633146121195760405162461bcd60e51b815260040161060a90612e93565b60005b828110156121985781600c600086868581811061214957634e487b7160e01b600052603260045260246000fd5b905060200201602081019061215e9190612be6565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558061219081612f99565b91505061211c565b50505050565b6003546001600160a01b031633146121ea5760405162461bcd60e51b815260206004820152600f60248201526e6465763a206e6f74206f776e65723f60881b604482015260640161060a565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146122365760405162461bcd60e51b815260040161060a90612e93565b60025460405163d743b81b60e01b81526001600160a01b039091169063d743b81b906109599085908590600401612e47565b6002600154141561228b5760405162461bcd60e51b815260040161060a90612ec8565b60026001819055506000600682815481106122b657634e487b7160e01b600052603260045260246000fd5b60009182526020808320858452600a825260408085203386529092529220600390910290910191506122e7836111a5565b6122f1338461280d565b6002820154815461230c9164e8d4a51000916112f4916123c6565b60019182015580555050565b6000546001600160a01b031633146123425760405162461bcd60e51b815260040161060a90612e93565b6001600160a01b0381166123a75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161060a565b6123b0816126aa565b50565b60006123bf8284612eff565b9392505050565b60006123bf8284612f37565b6040516001600160a01b03808516602483015283166044820152606481018290526121989085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526129ac565b60006006838154811061246057634e487b7160e01b600052603260045260246000fd5b60009182526020808320868452600a825260408085206001600160a01b03808b168752935290932060028101546003909302909301935016156124e35760028101546001600160a01b031633146124e35760405162461bcd60e51b81526020600482015260076024820152663130b21039b7b360c91b604482015260640161060a565b60006001600160a01b03166007858154811061250f57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b031614156125725760405162461bcd60e51b815260206004820152601b60248201527f6465706f7369743a206e6f7420616363657074206465706f7369740000000000604482015260640161060a565b61257b846111a5565b80541561258c5761258c858561280d565b60028101546001600160a01b03166125b3576002810180546001600160a01b031916331790555b6125f7333085600788815481106125da57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b03169291906123d2565b805461260390846123b3565b80825560028301546126209164e8d4a51000916112f491906123c6565b60018201556040518381526001600160a01b03861690859033907f02d7e648dd130fc184d383e55bb126ac4c9c60e8f94bf05acdf557ba2d540b479060200160405180910390a45050505050565b61268d8363a9059cbb60e01b8484604051602401612406929190612e47565b505050565b60006123bf8284612f56565b60006123bf8284612f17565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8015806127835750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561274957600080fd5b505afa15801561275d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127819190612d16565b155b6127ee5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161060a565b61268d8363095ea7b360e01b8484604051602401612406929190612e47565b60006006828154811061283057634e487b7160e01b600052603260045260246000fd5b60009182526020808320858452600a825260408085206001600160a01b038916865290925292208054600390920290920192501561219857600061289682600101546120de64e8d4a510006112f4876002015487600001546123c690919063ffffffff16565b6002546040516370a0823160e01b81523060048201529192506001600160a01b0316906370a082319060240160206040518083038186803b1580156128da57600080fd5b505afa1580156128ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129129190612d16565b8111156129595760405162461bcd60e51b8152602060048201526015602482015274777466206e6f7420656e6f7567682053494e474c4560581b604482015260640161060a565b600554612970906001600160a01b0316868361266e565b83856001600160a01b03167f71bab65ced2e5750775a0613be067df48ef06cf92a496ebf7663ae06609249548360405161102d91815260200190565b6000612a01826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612a7e9092919063ffffffff16565b80519091501561268d5780806020019051810190612a1f9190612ce2565b61268d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161060a565b6060612a8d8484600085612a95565b949350505050565b606082471015612af65760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161060a565b843b612b445760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161060a565b600080866001600160a01b03168587604051612b609190612e2b565b60006040518083038185875af1925050503d8060008114612b9d576040519150601f19603f3d011682016040523d82523d6000602084013e612ba2565b606091505b50915091506120e482828660608315612bbc5750816123bf565b825115612bcc5782518084602001fd5b8160405162461bcd60e51b815260040161060a9190612e60565b600060208284031215612bf7578081fd5b81356123bf81612fca565b60008060408385031215612c14578081fd5b8235612c1f81612fca565b946020939093013593505050565b600080600060608486031215612c41578081fd5b8335612c4c81612fca565b95602085013595506040909401359392505050565b600080600060408486031215612c75578283fd5b833567ffffffffffffffff80821115612c8c578485fd5b818601915086601f830112612c9f578485fd5b813581811115612cad578586fd5b8760208260051b8501011115612cc1578586fd5b60209283019550935050840135612cd781612fdf565b809150509250925092565b600060208284031215612cf3578081fd5b81516123bf81612fdf565b600060208284031215612d0f578081fd5b5035919050565b600060208284031215612d27578081fd5b5051919050565b60008060408385031215612d40578182fd5b823591506020830135612d5281612fca565b809150509250929050565b600080600060608486031215612d71578283fd5b833592506020840135612d8381612fca565b929592945050506040919091013590565b60008060008060808587031215612da9578081fd5b843593506020850135612dbb81612fca565b9250604085013591506060850135612dd281612fdf565b939692955090935050565b60008060408385031215612def578182fd5b50508035926020909101359150565b600080600060608486031215612e12578283fd5b83359250602084013591506040840135612cd781612fdf565b60008251612e3d818460208701612f6d565b9190910192915050565b6001600160a01b03929092168252602082015260400190565b6020815260008251806020840152612e7f816040850160208701612f6d565b601f01601f19169190910160400192915050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60008219821115612f1257612f12612fb4565b500190565b600082612f3257634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615612f5157612f51612fb4565b500290565b600082821015612f6857612f68612fb4565b500390565b60005b83811015612f88578181015183820152602001612f70565b838111156121985750506000910152565b6000600019821415612fad57612fad612fb4565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03811681146123b057600080fd5b80151581146123b057600080fdfea264697066735822122028fd478196ba8c27f31fada6504c13301af6b9a62505270ab5afea30a0432e3264736f6c634300080400330000000000000000000000000804702a4e749d39a35fde73d1df0b1f1d6b834700000000000000000000000011c078e0d65c840a00bd4bfaa0e3cab5c402d85a

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

0000000000000000000000000804702a4e749d39a35fde73d1df0b1f1d6b834700000000000000000000000011c078e0d65c840a00bd4bfaa0e3cab5c402d85a

-----Decoded View---------------
Arg [0] : _single (address): 0x0804702a4e749d39a35fde73d1df0b1f1d6b8347
Arg [1] : _devaddr (address): 0x11c078e0d65c840a00bd4bfaa0e3cab5c402d85a

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000804702a4e749d39a35fde73d1df0b1f1d6b8347
Arg [1] : 00000000000000000000000011c078e0d65c840a00bd4bfaa0e3cab5c402d85a


Deployed ByteCode Sourcemap

55522:17312:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62541:777;;;;;;:::i;:::-;;:::i;:::-;;59169:87;59235:8;:15;59169:87;;;17456:25:1;;;17444:2;17429:18;59169:87:0;;;;;;;;66005:247;;;;;;:::i;:::-;;:::i;56422:20::-;;;;;-1:-1:-1;;;;;56422:20:0;;;;;;-1:-1:-1;;;;;5381:32:1;;;5363:51;;5351:2;5336:18;56422:20:0;5318:102:1;56483:26:0;;;;;;:::i;:::-;;:::i;:::-;;;;18297:25:1;;;18353:2;18338:18;;18331:34;;;;18381:18;;;18374:34;18285:2;18270:18;56483:26:0;18252:162:1;60681:152:0;;;;;;:::i;:::-;;:::i;56932:30::-;;;;;;59635:123;;;;;;:::i;:::-;;:::i;57307:28::-;;;;;;59262:238;;;;;;:::i;:::-;;:::i;59506:123::-;;;;;;:::i;:::-;;:::i;69099:509::-;;;;;;:::i;:::-;;:::i;72586:243::-;;;;;;:::i;:::-;;:::i;57119:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;6908:14:1;;6901:22;6883:41;;6871:2;6856:18;57119:52:0;6838:92:1;61947:358:0;;;;;;:::i;:::-;;:::i;61013:722::-;;;;;;:::i;:::-;;:::i;71253:122::-;;;;;;:::i;:::-;;:::i;58983:134::-;;;:::i;56676:29::-;;;;;-1:-1:-1;;;;;56676:29:0;;;63441:1939;;;;;;:::i;:::-;;:::i;57218:34::-;;;;;;71592:988;;;;;;:::i;:::-;;:::i;26440:94::-;;;:::i;56566:27::-;;;;;;:::i;:::-;;:::i;59988:375::-;;;;;;:::i;:::-;;:::i;56341:29::-;;;;;;25789:87;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;25789:87;;56769:66;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;56769:66:0;;;;;;;17947:25:1;;;18003:2;17988:18;;17981:34;;;;-1:-1:-1;;;;;18051:32:1;18031:18;;;18024:60;17935:2;17920:18;56769:66:0;17902:188:1;57392:30:0;;;;;;60422:253;;;;;;:::i;:::-;;:::i;67218:652::-;;;;;;:::i;:::-;;:::i;62393:142::-;;;:::i;69777:1468::-;;;;;;:::i;:::-;;:::i;71381:205::-;;;;;;:::i;:::-;;:::i;58747:128::-;;;;;;:::i;:::-;;:::i;56275:22::-;;;;;-1:-1:-1;;;;;56275:22:0;;;59764:113;;;;;;:::i;:::-;;:::i;56650:21::-;;;;;-1:-1:-1;;;;;56650:21:0;;;67920:356;;;;;;:::i;:::-;;:::i;56226:25::-;;;;;-1:-1:-1;;;;;56226:25:0;;;57072:42;;57113:1;57072:42;;;;;18591:4:1;18579:17;;;18561:36;;18549:2;18534:18;57072:42:0;18516:87:1;26689:192:0;;;;;;:::i;:::-;;:::i;62541:777::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;;;;;;;;;62738:1:::1;62720:15;:19;62712:59;;;::::0;-1:-1:-1;;;62712:59:0;;9177:2:1;62712:59:0::1;::::0;::::1;9159:21:1::0;9216:2;9196:18;;;9189:30;9255:29;9235:18;;;9228:57;9302:18;;62712:59:0::1;9149:177:1::0;62712:59:0::1;62809:1;62786:20;:24;62778:62;;;::::0;-1:-1:-1;;;62778:62:0;;10966:2:1;62778:62:0::1;::::0;::::1;10948:21:1::0;11005:2;10985:18;;;10978:30;11044:27;11024:18;;;11017:55;11089:18;;62778:62:0::1;10938:175:1::0;62778:62:0::1;62871:12;62855:13;;:28;62847:72;;;::::0;-1:-1:-1;;;62847:72:0;;11320:2:1;62847:72:0::1;::::0;::::1;11302:21:1::0;11359:2;11339:18;;;11332:30;11398:33;11378:18;;;11371:61;11449:18;;62847:72:0::1;11292:181:1::0;62847:72:0::1;62998:19;:42:::0;;;63065:12:::1;63047:15;:30:::0;;;63100:33:::1;::::0;63117:15;63100:16:::1;:33::i;:::-;63084:13;:49:::0;63191:19:::1;::::0;63140:92:::1;::::0;63164:10:::1;::::0;63184:4:::1;::::0;63191:40:::1;::::0;63215:15;63191:23:::1;:40::i;:::-;63140:6;::::0;-1:-1:-1;;;;;63140:6:0::1;::::0;:92;;:23:::1;:92::i;:::-;63281:15;::::0;63298:13:::1;::::0;63250:62:::1;::::0;;18297:25:1;;;18353:2;18338:18;;18331:34;;;;18381:18;;18374:34;63250:62:0::1;::::0;18285:2:1;18270:18;63250:62:0::1;;;;;;;62541:777:::0;;:::o;66005:247::-;23174:1;23770:7;;:19;;23762:63;;;;-1:-1:-1;;;23762:63:0;;;;;;;:::i;:::-;23174:1;23903:7;:18;66117:10:::1;66098:30;::::0;;;:18:::1;:30;::::0;;;;;::::1;;66094:112;;-1:-1:-1::0;;;;;66146:18:0;::::1;66154:10;66146:18;66138:60;;;::::0;-1:-1:-1;;;66138:60:0;;12391:2:1;66138:60:0::1;::::0;::::1;12373:21:1::0;12430:2;12410:18;;;12403:30;12469:31;12449:18;;;12442:59;12518:18;;66138:60:0::1;12363:179:1::0;66138:60:0::1;66213:27;66222:4;66228:3;66233:6;66213:8;:27::i;:::-;-1:-1:-1::0;;23130:1:0;24082:22;;-1:-1:-1;66005:247:0:o;56483:26::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;56483:26:0;:::o;60681:152::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;60760:6:::1;::::0;-1:-1:-1;;;;;60760:6:0::1;60752:29:::0;60744:50:::1;;;::::0;-1:-1:-1;;;60744:50:0;;13428:2:1;60744:50:0::1;::::0;::::1;13410:21:1::0;13467:1;13447:18;;;13440:29;-1:-1:-1;;;13485:18:1;;;13478:39;13534:18;;60744:50:0::1;13400:158:1::0;60744:50:0::1;60801:6;:26:::0;;-1:-1:-1;;;;;;60801:26:0::1;-1:-1:-1::0;;;;;60801:26:0;;;::::1;::::0;;;::::1;::::0;;60681:152::o;59635:123::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;59715:6:::1;::::0;:37:::1;::::0;-1:-1:-1;;;59715:37:0;;-1:-1:-1;;;;;59715:6:0;;::::1;::::0;:23:::1;::::0;:37:::1;::::0;59739:3;;59744:7;;59715:37:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;59635:123:::0;;:::o;59262:238::-;59346:10;;-1:-1:-1;;;;;59346:10:0;59324;:33;59315:62;;;;-1:-1:-1;;;59315:62:0;;8426:2:1;59315:62:0;;;8408:21:1;8465:2;8445:18;;;8438:30;-1:-1:-1;;;8484:18:1;;;8477:45;8539:18;;59315:62:0;8398:165:1;59315:62:0;59392:6;;59385:67;;-1:-1:-1;;;;;59392:6:0;59417:10;59437:4;59444:7;59385:31;:67::i;:::-;59459:6;;:35;;-1:-1:-1;;;59459:35:0;;-1:-1:-1;;;;;59459:6:0;;;;:11;;:35;;59479:4;;59486:7;;59459:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59262:238;:::o;59506:123::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;59586:6:::1;::::0;:37:::1;::::0;-1:-1:-1;;;59586:37:0;;-1:-1:-1;;;;;59586:6:0;;::::1;::::0;:23:::1;::::0;:37:::1;::::0;59610:3;;59615:7;;59586:37:::1;;;:::i;69099:509::-:0;23174:1;23770:7;;:19;;23762:63;;;;-1:-1:-1;;;23762:63:0;;;;;;;:::i;:::-;23174:1;23903:7;:18;;;69180:21:::1;69204:13:::0;;;:8:::1;:13;::::0;;;;;;;69218:10:::1;69204:25:::0;;;;;;;;69244:13;;::::1;::::0;-1:-1:-1;;;;;69244:13:0::1;:27;69236:80;;;::::0;-1:-1:-1;;;69236:80:0;;17103:2:1;69236:80:0::1;::::0;::::1;17085:21:1::0;17142:2;17122:18;;;17115:30;17181:34;17161:18;;;17154:62;-1:-1:-1;;;17232:18:1;;;17225:38;17280:19;;69236:80:0::1;17075:230:1::0;69236:80:0::1;69340:11:::0;;69323:14:::1;69358:15:::0;;;-1:-1:-1;69380:15:0;::::1;:19:::0;69406:13:::1;::::0;::::1;:26:::0;;-1:-1:-1;;;;;;69406:26:0::1;::::0;;69503:11:::1;:16:::0;;:41:::1;::::0;69533:2;;69340:11;;69503;69515:3;;69503:16;::::1;;;-1:-1:-1::0;;;69503:16:0::1;;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;-1:-1:-1;;;;;69503:16:0::1;::::0;:41;:29:::1;:41::i;:::-;69599:2;-1:-1:-1::0;;;;;69556:46:0::1;69586:3;69574:10;-1:-1:-1::0;;;;;69556:46:0::1;;69591:6;69556:46;;;;17456:25:1::0;;17444:2;17429:18;;17411:76;69556:46:0::1;;;;;;;;-1:-1:-1::0;;23130:1:0;24082:22;;-1:-1:-1;;69099:509:0:o;72586:243::-;72703:7;;-1:-1:-1;;;;;72703:7:0;72689:10;:21;72680:42;;;;-1:-1:-1;;;72680:42:0;;10224:2:1;72680:42:0;;;10206:21:1;10263:1;10243:18;;;10236:29;-1:-1:-1;;;10281:18:1;;;10274:37;10328:18;;72680:42:0;10196:156:1;72680:42:0;72735:6;;72762:10;;:54;;-1:-1:-1;;;72762:54:0;;-1:-1:-1;;;;;6613:32:1;;;72762:54:0;;;6595:51:1;6662:18;;;6655:34;;;6705:18;;;6698:34;;;72735:6:0;;;;:11;;72755:4;;72762:10;;;:25;;6568:18:1;;72762:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72735:82;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72586:243;;;:::o;61947:358::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;62067:11:::1;62064:49;;;62089:16;:14;:16::i;:::-;62143:63;62194:11;62143:46;62163:8;62172:4;62163:14;;;;;;-1:-1:-1::0;;;62163:14:0::1;;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;;::::1;;:25:::0;62143:15:::1;::::0;;:19:::1;:46::i;:::-;:50:::0;::::1;:63::i;:::-;62125:15;:81;;;;62241:11;62213:8;62222:4;62213:14;;;;;;-1:-1:-1::0;;;62213:14:0::1;;;;;;;;;;;;;;;;;;;:25;;:39;;;;62281:4;62270:29;62287:11;62270:29;;;;17456:25:1::0;;17444:2;17429:18;;17411:76;62270:29:0::1;;;;;;;;61947:358:::0;;;:::o;61013:722::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;61185:29:::1;61202:11;61185:16;:29::i;:::-;61184:30;61176:76;;;::::0;-1:-1:-1;;;61176:76:0;;15172:2:1;61176:76:0::1;::::0;::::1;15154:21:1::0;15211:2;15191:18;;;15184:30;15250:34;15230:18;;;15223:62;-1:-1:-1;;;15301:18:1;;;15294:31;15342:19;;61176:76:0::1;15144:223:1::0;61176:76:0::1;61269:11;61265:50;;;61291:16;:14;:16::i;:::-;61327:23;61368:11;61353:12;:26;:55;;61397:11;61353:55;;;61382:12;61353:55;61433:15;::::0;61327:81;;-1:-1:-1;61433:31:0::1;::::0;61453:10;61433:19:::1;:31::i;:::-;61415:15;:49:::0;61473:11:::1;:29:::0;;::::1;::::0;;::::1;::::0;;;;;::::1;::::0;;-1:-1:-1;;;;;;61473:29:0::1;-1:-1:-1::0;;;;;61473:29:0;::::1;::::0;;::::1;::::0;;;61529:118:::1;::::0;;::::1;::::0;::::1;::::0;;;;;61473:29:::1;61529:118:::0;::::1;::::0;;;-1:-1:-1;61529:118:0;;;;;;61515:8:::1;:133:::0;;;;::::1;::::0;;;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;;;;;;;61678:18;;:25:::1;::::0;:22:::1;:25::i;:::-;61662:67;::::0;17456:25:1;;;61662:67:0::1;::::0;17444:2:1;17429:18;61662:67:0::1;;;;;;;;26080:1;61013:722:::0;;;;:::o;71253:122::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;71332:10:::1;:37:::0;;-1:-1:-1;;;;;;71332:37:0::1;-1:-1:-1::0;;;;;71332:37:0;;;::::1;::::0;;;::::1;::::0;;71253:122::o;58983:134::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;59041:6:::1;;;;;;;;;-1:-1:-1::0;;;;;59041:6:0::1;-1:-1:-1::0;;;;;59041:19:0::1;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;59086:6;;;;;;;;;-1:-1:-1::0;;;;;59086:6:0::1;-1:-1:-1::0;;;;;59086:23:0::1;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59069:14;:42:::0;58983:134::o;63441:1939::-;63488:21;63512:8;63521:3;63512:13;;;;;;-1:-1:-1;;;63512:13:0;;;;;;;;;;;;;;;;;;;63488:37;;63552:4;:20;;;63536:12;:36;63532:65;;63583:7;63441:1939;:::o;63532:65::-;63603:24;63630:11;63642:3;63630:16;;;;;;-1:-1:-1;;;63630:16:0;;;;;;;;;;;;;;;;;;;:41;;-1:-1:-1;;;63630:41:0;;63665:4;63630:41;;;5363:51:1;-1:-1:-1;;;;;63630:16:0;;;;:26;;5336:18:1;;63630:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63603:68;-1:-1:-1;63682:21:0;63678:94;;-1:-1:-1;63737:12:0;63714:20;;;;:35;-1:-1:-1;63441:1939:0:o;63678:94::-;63804:20;;;;63778:23;63852:33;:12;63804:20;63852:16;:33::i;:::-;63915:12;63892:20;;;:35;64012:15;;63831:54;;-1:-1:-1;63989:20:0;;64012:97;;64108:1;64012:97;;;64033:72;64089:15;;64033:51;64068:4;:15;;;64033:30;64048:14;;64033:10;:14;;:30;;;;:::i;:::-;:34;;:51::i;:::-;:55;;:72::i;:::-;63989:120;;64252:6;;;;;;;;;-1:-1:-1;;;;;64252:6:0;-1:-1:-1;;;;;64252:10:0;;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64185:64;64228:20;:12;64245:2;64228:16;:20::i;:::-;64185:38;64210:12;64185:6;;;;;;;;;-1:-1:-1;;;;;64185:6:0;-1:-1:-1;;;;;64185:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:64::-;:79;64181:468;;;64300:90;64328:60;64371:16;64328:38;:12;57017:4;64328:16;:38::i;:60::-;64300:22;;;;;:26;:90::i;:::-;64275:22;;;;:115;;;;64446:6;64458:7;;-1:-1:-1;;;;;64446:6:0;;;;:11;;64458:7;64467:20;:12;64484:2;64467:16;:20::i;:::-;64446:42;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;64497:6:0;;:40;;-1:-1:-1;;;64497:40:0;;-1:-1:-1;;;;;64497:6:0;;;;-1:-1:-1;64497:11:0;;-1:-1:-1;64497:40:0;;64517:4;;64524:12;;64497:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;64578:20:0;;;;64618:22;;;;64559:82;;;18297:25:1;;;18353:2;18338:18;;18331:34;;;18381:18;;18374:34;64573:3:0;;-1:-1:-1;64559:82:0;;18285:2:1;18270:18;64559:82:0;;;;;;;64181:468;64694:19;64720:21;64760:12;64744:13;;:28;:58;;64789:13;;64744:58;;;64774:12;64744:58;64720:82;;64809:23;64853:15;;64835;:33;:68;;64888:15;;64835:68;;;64870:15;64835:68;64809:94;;64930:15;64914:13;:31;64910:194;;;64987:1;64969:15;;:19;:127;;65095:1;64969:127;;;65077:15;;65056;;65031:19;;64990:103;;65077:15;64990:82;;:61;;;64991:13;65009:15;64991:17;:34::i;64990:103::-;64955:141;;64910:194;65116:15;;65112:253;;65167:89;65195:59;65237:16;65195:37;:11;57017:4;65195:15;:37::i;:59::-;65167:22;;;;;:26;:89::i;:::-;65142:22;;;:114;;;65294:20;;;;65270:87;;;18297:25:1;;;18353:2;18338:18;;18331:34;;;18381:18;;18374:34;;;;65289:3:0;;65270:87;;18285:2:1;18270:18;65270:87:0;;;;;;;65112:253;63441:1939;;;;;;;;;:::o;71592:988::-;71708:7;;-1:-1:-1;;;;;71708:7:0;71694:10;:21;71685:42;;;;-1:-1:-1;;;71685:42:0;;10224:2:1;71685:42:0;;;10206:21:1;10263:1;10243:18;;;10236:29;-1:-1:-1;;;10281:18:1;;;10274:37;10328:18;;71685:42:0;10196:156:1;71685:42:0;71807:1;71749:11;57113:1;71749:29;;;;;;;;-1:-1:-1;;;71749:29:0;;;;;;;;;;;;;;;;;;;71742:62;;-1:-1:-1;;;71742:62:0;;71798:4;71742:62;;;5363:51:1;-1:-1:-1;;;;;71749:29:0;;;;71742:47;;5336:18:1;;71742:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:66;71734:96;;;;-1:-1:-1;;;71734:96:0;;14826:2:1;71734:96:0;;;14808:21:1;14865:2;14845:18;;;14838:30;-1:-1:-1;;;14884:18:1;;;14877:47;14941:18;;71734:96:0;14798:167:1;71734:96:0;71911:10;;:58;;-1:-1:-1;;;71911:58:0;;-1:-1:-1;;;;;6613:32:1;;;71911:58:0;;;6595:51:1;6662:18;;;6655:34;;;6705:18;;;6698:34;;;71896:12:0;;71911:10;;:29;;6568:18:1;;71911:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72167:6;;72160:39;;-1:-1:-1;;;72160:39:0;;72193:4;72160:39;;;5363:51:1;71896:73:0;;-1:-1:-1;71896:73:0;;-1:-1:-1;;;;;72167:6:0;;;;72160:24;;5336:18:1;;72160:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;72152:82;;;;-1:-1:-1;;;72152:82:0;;9533:2:1;72152:82:0;;;9515:21:1;9572:2;9552:18;;;9545:30;-1:-1:-1;;;9591:18:1;;;9584:52;9653:18;;72152:82:0;9505:172:1;72152:82:0;72241:21;72265:98;72307:11;57113:1;72307:29;;;;;;;;-1:-1:-1;;;72307:29:0;;;;;;;;;;;;;;;;;;;72300:62;;-1:-1:-1;;;72300:62:0;;72356:4;72300:62;;;5363:51:1;-1:-1:-1;;;;;72307:29:0;;;;72300:47;;5336:18:1;;72300:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72265:30;:4;57017;72265:8;:30::i;:98::-;72241:122;;72454:71;72511:13;72454:8;57113:1;72454:26;;;;;;;;-1:-1:-1;;;72454:26:0;;;;;;;;;;;;;;;;;;;:44;;;:56;;:71;;;;:::i;:::-;72407:8;:26;;57113:1;;72407:26;;;;-1:-1:-1;;;72407:26:0;;;;;;;;;;;;;;;;;;;:44;;:118;;;;72539:35;72554:4;72560:13;72539:35;;;;;;17666:25:1;;;17722:2;17707:18;;17700:34;17654:2;17639:18;;17621:119;72539:35:0;;;;;;;;71592:988;;;;;:::o;26440:94::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;26505:21:::1;26523:1;26505:9;:21::i;:::-;26440:94::o:0;56566:27::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;56566:27:0;;-1:-1:-1;56566:27:0;:::o;59988:375::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;60124:6:::1;::::0;:46:::1;::::0;-1:-1:-1;;;60124:46:0;;-1:-1:-1;;;;;60124:6:0;;::::1;::::0;:22:::1;::::0;:46:::1;::::0;60155:4:::1;::::0;60162:7;;60124:46:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;60193:6:0::1;::::0;-1:-1:-1;;;;;60193:6:0::1;60185:29:::0;::::1;::::0;-1:-1:-1;60177:49:0::1;::::0;-1:-1:-1;60177:49:0::1;;::::0;-1:-1:-1;;;60177:49:0;;16768:2:1;60177:49:0::1;::::0;::::1;16750:21:1::0;16807:1;16787:18;;;16780:29;-1:-1:-1;;;16825:18:1;;;16818:37;16872:18;;60177:49:0::1;16740:156:1::0;60177:49:0::1;60260:6;::::0;60233::::1;::::0;:43:::1;::::0;-1:-1:-1;;;;;60233:6:0;;::::1;::::0;60260::::1;60268:7:::0;60233:18:::1;:43::i;:::-;60326:6;::::0;:31:::1;::::0;-1:-1:-1;;;60326:31:0;;-1:-1:-1;;;;;6613:32:1;;;60326:31:0::1;::::0;::::1;6595:51:1::0;6662:18;;;6655:34;;;6705:18;;;6698:34;;;60326:6:0;;::::1;::::0;:11:::1;::::0;6568:18:1;;60326:31:0::1;6550:188:1::0;60422:253:0;60519:8;:15;60489:4;;;60541:110;60570:6;60563:4;:13;60541:110;;;60619:11;-1:-1:-1;;;;;60598:32:0;:11;60610:4;60598:17;;;;;;-1:-1:-1;;;60598:17:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;60598:17:0;:32;60595:48;;;-1:-1:-1;60639:4:0;;60422:253;-1:-1:-1;;;60422:253:0:o;60595:48::-;60578:6;;;;:::i;:::-;;;;60541:110;;;-1:-1:-1;60664:5:0;;60422:253;-1:-1:-1;;;60422:253:0:o;67218:652::-;23174:1;23770:7;;:19;;23762:63;;;;-1:-1:-1;;;23762:63:0;;;;;;;:::i;:::-;23174:1;23903:7;:18;;;;67310:21:::1;67334:8;67343:3;67334:13;;;;;;-1:-1:-1::0;;;67334:13:0::1;;;;;;;;;;::::0;;;::::1;::::0;;;67378;;;:8:::1;:13:::0;;;;;;-1:-1:-1;;;;;67378:19:0;;::::1;::::0;;;;;;;67412:13:::1;::::0;::::1;::::0;67334::::1;::::0;;::::1;::::0;;::::1;::::0;-1:-1:-1;67412:13:0::1;67429:10;67412:27;67404:51;;;::::0;-1:-1:-1;;;67404:51:0;;9884:2:1;67404:51:0::1;::::0;::::1;9866:21:1::0;9923:2;9903:18;;;9896:30;-1:-1:-1;;;9942:18:1;;;9935:41;9993:18;;67404:51:0::1;9856:161:1::0;67404:51:0::1;67470:11:::0;;:21;-1:-1:-1;67470:21:0::1;67462:52;;;::::0;-1:-1:-1;;;67462:52:0;;14123:2:1;67462:52:0::1;::::0;::::1;14105:21:1::0;14162:2;14142:18;;;14135:30;-1:-1:-1;;;14181:18:1;;;14174:48;14239:18;;67462:52:0::1;14095:168:1::0;67462:52:0::1;67521:15;67532:3;67521:10;:15::i;:::-;67543:19;67552:4;67558:3;67543:8;:19::i;:::-;67583:11:::0;;:23:::1;::::0;67599:6;67583:15:::1;:23::i;:::-;67569:37:::0;;;67647:22:::1;::::0;::::1;::::0;67631:49:::1;::::0;67675:4:::1;::::0;67631:39:::1;::::0;67569:37;67631:15:::1;:39::i;:49::-;67613:15;::::0;::::1;:67:::0;67691:11;;67687:48:::1;;67709:13;::::0;::::1;:26:::0;;-1:-1:-1;;;;;;67709:26:0::1;::::0;;67687:48:::1;67748:58;67786:10;67799:6;67748:11;67760:3;67748:16;;;;;;-1:-1:-1::0;;;67748:16:0::1;;;;;;;;:58;67846:11:::0;;67820:44:::1;::::0;17456:25:1;;;-1:-1:-1;;;;;67820:44:0;::::1;::::0;67841:3;;67829:10:::1;::::0;67820:44:::1;::::0;17444:2:1;17429:18;67820:44:0::1;;;;;;;-1:-1:-1::0;;23130:1:0;24082:22;;-1:-1:-1;;;67218:652:0:o;62393:142::-;62433:11;62447:12;59235:8;:15;;59169:87;62447:12;62433:26;;62471:9;62466:64;62490:3;62486:1;:7;62466:64;;;62509:13;62520:1;62509:10;:13::i;:::-;62495:3;;;:::i;:::-;;;62466:64;;;;62393:142;:::o;69777:1468::-;69852:7;69868:21;69892:8;69901:4;69892:14;;;;;;-1:-1:-1;;;69892:14:0;;;;;;;;;;;;;;;;;69937;;;:8;:14;;;;;;-1:-1:-1;;;;;69937:21:0;;;;;;;;;;69892:14;;;;;;69993:22;;;;70049:11;:17;;69892:14;;-1:-1:-1;69937:21:0;;69993:22;;69892:14;;69937;;70049:17;;;;-1:-1:-1;;;70049:17:0;;;;;;;;;;;;;;;;;;;:42;;-1:-1:-1;;;70049:42:0;;70085:4;70049:42;;;5363:51:1;-1:-1:-1;;;;;70049:17:0;;;;:27;;5336:18:1;;70049:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70022:69;;70117:4;:20;;;70102:12;:35;:60;;;;-1:-1:-1;70141:21:0;;;70102:60;70098:1041;;;70240:18;70261:38;70278:4;:20;;;70261:12;:16;;:38;;;;:::i;:::-;70240:59;;70308:20;70349:1;70331:15;;:19;:97;;70427:1;70331:97;;;70352:72;70408:15;;70352:51;70387:4;:15;;;70352:30;70367:14;;70352:10;:14;;:30;;;;:::i;:72::-;70308:120;;70552:19;70600:13;;70584:12;:29;70580:415;;70658:1;70640:15;;:19;:101;;70740:1;70640:101;;;70661:77;70722:15;;70661:56;70701:4;:15;;;70661:35;70676:19;;70661:10;:14;;:35;;;;:::i;:77::-;70626:115;;70580:415;;;70774:13;;70759:12;:28;:68;;;;;70814:13;;70791:4;:20;;;:36;70759:68;70756:239;;;70872:1;70854:15;;:19;:131;;70984:1;70854:131;;;70875:106;70965:15;;70875:85;70944:4;:15;;;70875:64;70919:19;;70875:39;70893:4;:20;;;70875:13;;:17;;:39;;;;:::i;:106::-;70840:145;;70756:239;71029:102;71051:79;71113:16;71051:57;57017:4;71052:29;:12;71069:11;71052:16;:29::i;71051:79::-;71029:17;;:21;:102::i;:::-;71009:122;;70098:1041;;;;71158:81;71223:4;:15;;;71158:60;57017:4;71158:34;71174:17;71158:4;:11;;;:15;;:34;;;;:::i;:60::-;:64;;:81::i;:::-;71151:88;69777:1468;-1:-1:-1;;;;;;;69777:1468:0:o;71381:205::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;71484:9:::1;71479:102;71499:19:::0;;::::1;71479:102;;;71567:6;71534:18;:30;71553:7;;71561:1;71553:10;;;;;-1:-1:-1::0;;;71553:10:0::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;71534:30:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;71534:30:0;:39;;-1:-1:-1;;71534:39:0::1;::::0;::::1;;::::0;;;::::1;::::0;;71520:3;::::1;::::0;::::1;:::i;:::-;;;;71479:102;;;;71381:205:::0;;;:::o;58747:128::-;58817:7;;-1:-1:-1;;;;;58817:7:0;58803:10;:21;58795:49;;;;-1:-1:-1;;;58795:49:0;;13084:2:1;58795:49:0;;;13066:21:1;13123:2;13103:18;;;13096:30;-1:-1:-1;;;13142:18:1;;;13135:45;13197:18;;58795:49:0;13056:165:1;58795:49:0;58851:7;:18;;-1:-1:-1;;;;;;58851:18:0;-1:-1:-1;;;;;58851:18:0;;;;;;;;;;58747:128::o;59764:113::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;59839:6:::1;::::0;:32:::1;::::0;-1:-1:-1;;;59839:32:0;;-1:-1:-1;;;;;59839:6:0;;::::1;::::0;:18:::1;::::0;:32:::1;::::0;59858:3;;59863:7;;59839:32:::1;;;:::i;67920:356::-:0;23174:1;23770:7;;:19;;23762:63;;;;-1:-1:-1;;;23762:63:0;;;;;;;:::i;:::-;23174:1;23903:7;:18;;;;68029:21:::1;68053:8;68062:4;68053:14;;;;;;-1:-1:-1::0;;;68053:14:0::1;;;;;;;;;;::::0;;;::::1;::::0;;;68098;;;:8:::1;:14:::0;;;;;;68113:10:::1;68098:26:::0;;;;;;;68053:14:::1;::::0;;::::1;::::0;;::::1;::::0;-1:-1:-1;68131:16:0::1;68107:4:::0;68131:10:::1;:16::i;:::-;68154:26;68163:10;68175:4;68154:8;:26::i;:::-;68221:22;::::0;::::1;::::0;68205:11;;:65:::1;::::0;57017:4:::1;::::0;68205:39:::1;::::0;:15:::1;:39::i;:65::-;68187:15;::::0;;::::1;:83:::0;24082:22;;-1:-1:-1;;67920:356:0:o;26689:192::-;25835:7;25862:6;-1:-1:-1;;;;;25862:6:0;24743:10;26009:23;26001:68;;;;-1:-1:-1;;;26001:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;26778:22:0;::::1;26770:73;;;::::0;-1:-1:-1;;;26770:73:0;;8770:2:1;26770:73:0::1;::::0;::::1;8752:21:1::0;8809:2;8789:18;;;8782:30;8848:34;8828:18;;;8821:62;-1:-1:-1;;;8899:18:1;;;8892:36;8945:19;;26770:73:0::1;8742:228:1::0;26770:73:0::1;26854:19;26864:8;26854:9;:19::i;:::-;26689:192:::0;:::o;5514:98::-;5572:7;5599:5;5603:1;5599;:5;:::i;:::-;5592:12;5514:98;-1:-1:-1;;;5514:98:0:o;6252:::-;6310:7;6337:5;6341:1;6337;:5;:::i;18444:248::-;18615:68;;-1:-1:-1;;;;;5992:15:1;;;18615:68:0;;;5974:34:1;6044:15;;6024:18;;;6017:43;6076:18;;;6069:34;;;18588:96:0;;18608:5;;-1:-1:-1;;;18638:27:0;5909:18:1;;18615:68:0;;;;-1:-1:-1;;18615:68:0;;;;;;;;;;;;;;-1:-1:-1;;;;;18615:68:0;-1:-1:-1;;;;;;18615:68:0;;;;;;;;;;18588:19;:96::i;66264:745::-;66338:21;66362:8;66371:3;66362:13;;;;;;-1:-1:-1;;;66362:13:0;;;;;;;;;;;;;;;;;66406;;;:8;:13;;;;;;-1:-1:-1;;;;;66406:19:0;;;;;;;;;;66436:13;;;;66362;;;;;;;;-1:-1:-1;66436:13:0;:27;66432:80;;66473:13;;;;-1:-1:-1;;;;;66473:13:0;66490:10;66473:27;66465:47;;;;-1:-1:-1;;;66465:47:0;;12749:2:1;66465:47:0;;;12731:21:1;12788:1;12768:18;;;12761:29;-1:-1:-1;;;12806:18:1;;;12799:37;12853:18;;66465:47:0;12721:156:1;66465:47:0;66564:1;-1:-1:-1;;;;;66527:39:0;66535:11;66547:3;66535:16;;;;;;-1:-1:-1;;;66535:16:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66535:16:0;66527:39;;66519:79;;;;-1:-1:-1;;;66519:79:0;;14470:2:1;66519:79:0;;;14452:21:1;14509:2;14489:18;;;14482:30;14548:29;14528:18;;;14521:57;14595:18;;66519:79:0;14442:177:1;66519:79:0;66605:15;66616:3;66605:10;:15::i;:::-;66631:11;;:15;66627:40;;66648:19;66657:4;66663:3;66648:8;:19::i;:::-;66678:13;;;;-1:-1:-1;;;;;66678:13:0;66674:59;;66707:13;;;:26;;-1:-1:-1;;;;;;66707:26:0;66723:10;66707:26;;;66674:59;66740:77;66782:10;66803:4;66810:6;66740:11;66752:3;66740:16;;;;;;-1:-1:-1;;;66740:16:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66740:16:0;;:77;;:33;:77::i;:::-;66838:11;;:23;;66854:6;66838:15;:23::i;:::-;66824:37;;;66902:22;;;;66886:65;;57017:4;;66886:39;;66824:37;66886:15;:39::i;:65::-;66868:15;;;:83;66965:38;;17456:25:1;;;-1:-1:-1;;;;;66965:38:0;;;66985:3;;66973:10;;66965:38;;17444:2:1;17429:18;66965:38:0;;;;;;;66264:745;;;;;:::o;18225:211::-;18342:86;18362:5;18392:23;;;18417:2;18421:5;18369:58;;;;;;;;;:::i;18342:86::-;18225:211;;;:::o;5895:98::-;5953:7;5980:5;5984:1;5980;:5;:::i;6651:98::-;6709:7;6736:5;6740:1;6736;:5;:::i;26889:173::-;26945:16;26964:6;;-1:-1:-1;;;;;26981:17:0;;;-1:-1:-1;;;;;;26981:17:0;;;;;;27014:40;;26964:6;;;;;;;27014:40;;26945:16;27014:40;26889:173;;:::o;18961:616::-;19325:10;;;19324:62;;-1:-1:-1;19341:39:0;;-1:-1:-1;;;19341:39:0;;19365:4;19341:39;;;5637:34:1;-1:-1:-1;;;;;5707:15:1;;;5687:18;;;5680:43;19341:15:0;;;;;5572:18:1;;19341:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;19324:62;19302:166;;;;-1:-1:-1;;;19302:166:0;;16345:2:1;19302:166:0;;;16327:21:1;16384:2;16364:18;;;16357:30;16423:34;16403:18;;;16396:62;-1:-1:-1;;;16474:18:1;;;16467:52;16536:19;;19302:166:0;16317:244:1;19302:166:0;19479:90;19499:5;19529:22;;;19553:7;19562:5;19506:62;;;;;;;;;:::i;68450:465::-;68509:21;68533:8;68542:3;68533:13;;;;;;-1:-1:-1;;;68533:13:0;;;;;;;;;;;;;;;;;68577;;;:8;:13;;;;;;-1:-1:-1;;;;;68577:17:0;;;;;;;;;68606:11;;68533:13;;;;;;;;-1:-1:-1;68606:15:0;68603:307;;68631:15;68649:86;68719:4;:15;;;68649:65;57017:4;68649:39;68665:4;:22;;;68649:4;:11;;;:15;;:39;;;;:::i;:86::-;68763:6;;:31;;-1:-1:-1;;;68763:31:0;;68788:4;68763:31;;;5363:51:1;68631:104:0;;-1:-1:-1;;;;;;68763:6:0;;:16;;5336:18:1;;68763:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68752:7;:42;;68744:76;;;;-1:-1:-1;;;68744:76:0;;11680:2:1;68744:76:0;;;11662:21:1;11719:2;11699:18;;;11692:30;-1:-1:-1;;;11738:18:1;;;11731:51;11799:18;;68744:76:0;11652:171:1;68744:76:0;68829:6;;:32;;-1:-1:-1;;;;;68829:6:0;68849:2;68853:7;68829:19;:32::i;:::-;68889:3;68885:2;-1:-1:-1;;;;;68877:25:0;;68894:7;68877:25;;;;17456::1;;17444:2;17429:18;;17411:76;20798:716:0;21222:23;21248:69;21276:4;21248:69;;;;;;;;;;;;;;;;;21256:5;-1:-1:-1;;;;;21248:27:0;;;:69;;;;;:::i;:::-;21332:17;;21222:95;;-1:-1:-1;21332:21:0;21328:179;;21429:10;21418:30;;;;;;;;;;;;:::i;:::-;21410:85;;;;-1:-1:-1;;;21410:85:0;;15574:2:1;21410:85:0;;;15556:21:1;15613:2;15593:18;;;15586:30;15652:34;15632:18;;;15625:62;-1:-1:-1;;;15703:18:1;;;15696:40;15753:19;;21410:85:0;15546:232:1;13168:229:0;13305:12;13337:52;13359:6;13367:4;13373:1;13376:12;13337:21;:52::i;:::-;13330:59;13168:229;-1:-1:-1;;;;13168:229:0:o;14288:510::-;14458:12;14516:5;14491:21;:30;;14483:81;;;;-1:-1:-1;;;14483:81:0;;10559:2:1;14483:81:0;;;10541:21:1;10598:2;10578:18;;;10571:30;10637:34;10617:18;;;10610:62;-1:-1:-1;;;10688:18:1;;;10681:36;10734:19;;14483:81:0;10531:228:1;14483:81:0;10685:20;;14575:60;;;;-1:-1:-1;;;14575:60:0;;13765:2:1;14575:60:0;;;13747:21:1;13804:2;13784:18;;;13777:30;13843:31;13823:18;;;13816:59;13892:18;;14575:60:0;13737:179:1;14575:60:0;14649:12;14663:23;14690:6;-1:-1:-1;;;;;14690:11:0;14709:5;14716:4;14690:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14648:73;;;;14739:51;14756:7;14765:10;14777:12;17124;17153:7;17149:530;;;-1:-1:-1;17184:10:0;17177:17;;17149:530;17298:17;;:21;17294:374;;17496:10;17490:17;17557:15;17544:10;17540:2;17536:19;17529:44;17444:148;17639:12;17632:20;;-1:-1:-1;;;17632:20:0;;;;;;;;:::i;14:257:1:-;73:6;126:2;114:9;105:7;101:23;97:32;94:2;;;147:6;139;132:22;94:2;191:9;178:23;210:31;235:5;210:31;:::i;546:325::-;614:6;622;675:2;663:9;654:7;650:23;646:32;643:2;;;696:6;688;681:22;643:2;740:9;727:23;759:31;784:5;759:31;:::i;:::-;809:5;861:2;846:18;;;;833:32;;-1:-1:-1;;;633:238:1:o;876:393::-;953:6;961;969;1022:2;1010:9;1001:7;997:23;993:32;990:2;;;1043:6;1035;1028:22;990:2;1087:9;1074:23;1106:31;1131:5;1106:31;:::i;:::-;1156:5;1208:2;1193:18;;1180:32;;-1:-1:-1;1259:2:1;1244:18;;;1231:32;;980:289;-1:-1:-1;;;980:289:1:o;1274:800::-;1366:6;1374;1382;1435:2;1423:9;1414:7;1410:23;1406:32;1403:2;;;1456:6;1448;1441:22;1403:2;1501:9;1488:23;1530:18;1571:2;1563:6;1560:14;1557:2;;;1592:6;1584;1577:22;1557:2;1635:6;1624:9;1620:22;1610:32;;1680:7;1673:4;1669:2;1665:13;1661:27;1651:2;;1707:6;1699;1692:22;1651:2;1752;1739:16;1778:2;1770:6;1767:14;1764:2;;;1799:6;1791;1784:22;1764:2;1859:7;1852:4;1842:6;1839:1;1835:14;1831:2;1827:23;1823:34;1820:47;1817:2;;;1885:6;1877;1870:22;1817:2;1921:4;1913:13;;;;-1:-1:-1;1945:6:1;-1:-1:-1;;1986:20:1;;1973:34;2016:28;1973:34;2016:28;:::i;:::-;2063:5;2053:15;;;1393:681;;;;;:::o;2079:255::-;2146:6;2199:2;2187:9;2178:7;2174:23;2170:32;2167:2;;;2220:6;2212;2205:22;2167:2;2257:9;2251:16;2276:28;2298:5;2276:28;:::i;2614:190::-;2673:6;2726:2;2714:9;2705:7;2701:23;2697:32;2694:2;;;2747:6;2739;2732:22;2694:2;-1:-1:-1;2775:23:1;;2684:120;-1:-1:-1;2684:120:1:o;2809:194::-;2879:6;2932:2;2920:9;2911:7;2907:23;2903:32;2900:2;;;2953:6;2945;2938:22;2900:2;-1:-1:-1;2981:16:1;;2890:113;-1:-1:-1;2890:113:1:o;3008:325::-;3076:6;3084;3137:2;3125:9;3116:7;3112:23;3108:32;3105:2;;;3158:6;3150;3143:22;3105:2;3199:9;3186:23;3176:33;;3259:2;3248:9;3244:18;3231:32;3272:31;3297:5;3272:31;:::i;:::-;3322:5;3312:15;;;3095:238;;;;;:::o;3338:393::-;3415:6;3423;3431;3484:2;3472:9;3463:7;3459:23;3455:32;3452:2;;;3505:6;3497;3490:22;3452:2;3546:9;3533:23;3523:33;;3606:2;3595:9;3591:18;3578:32;3619:31;3644:5;3619:31;:::i;:::-;3442:289;;3669:5;;-1:-1:-1;;;3721:2:1;3706:18;;;;3693:32;;3442:289::o;3736:542::-;3832:6;3840;3848;3856;3909:3;3897:9;3888:7;3884:23;3880:33;3877:2;;;3931:6;3923;3916:22;3877:2;3972:9;3959:23;3949:33;;4032:2;4021:9;4017:18;4004:32;4045:31;4070:5;4045:31;:::i;:::-;4095:5;-1:-1:-1;4147:2:1;4132:18;;4119:32;;-1:-1:-1;4203:2:1;4188:18;;4175:32;4216:30;4175:32;4216:30;:::i;:::-;3867:411;;;;-1:-1:-1;3867:411:1;;-1:-1:-1;;3867:411:1:o;4283:258::-;4351:6;4359;4412:2;4400:9;4391:7;4387:23;4383:32;4380:2;;;4433:6;4425;4418:22;4380:2;-1:-1:-1;;4461:23:1;;;4531:2;4516:18;;;4503:32;;-1:-1:-1;4370:171:1:o;4546:387::-;4620:6;4628;4636;4689:2;4677:9;4668:7;4664:23;4660:32;4657:2;;;4710:6;4702;4695:22;4657:2;4751:9;4738:23;4728:33;;4808:2;4797:9;4793:18;4780:32;4770:42;;4862:2;4851:9;4847:18;4834:32;4875:28;4897:5;4875:28;:::i;4938:274::-;5067:3;5105:6;5099:13;5121:53;5167:6;5162:3;5155:4;5147:6;5143:17;5121:53;:::i;:::-;5190:16;;;;;5075:137;-1:-1:-1;;5075:137:1:o;6114:274::-;-1:-1:-1;;;;;6306:32:1;;;;6288:51;;6370:2;6355:18;;6348:34;6276:2;6261:18;;6243:145::o;7836:383::-;7985:2;7974:9;7967:21;7948:4;8017:6;8011:13;8060:6;8055:2;8044:9;8040:18;8033:34;8076:66;8135:6;8130:2;8119:9;8115:18;8110:2;8102:6;8098:15;8076:66;:::i;:::-;8203:2;8182:15;-1:-1:-1;;8178:29:1;8163:45;;;;8210:2;8159:54;;7957:262;-1:-1:-1;;7957:262:1:o;11828:356::-;12030:2;12012:21;;;12049:18;;;12042:30;12108:34;12103:2;12088:18;;12081:62;12175:2;12160:18;;12002:182::o;15783:355::-;15985:2;15967:21;;;16024:2;16004:18;;;15997:30;16063:33;16058:2;16043:18;;16036:61;16129:2;16114:18;;15957:181::o;18608:128::-;18648:3;18679:1;18675:6;18672:1;18669:13;18666:2;;;18685:18;;:::i;:::-;-1:-1:-1;18721:9:1;;18656:80::o;18741:217::-;18781:1;18807;18797:2;;-1:-1:-1;;;18832:31:1;;18886:4;18883:1;18876:15;18914:4;18839:1;18904:15;18797:2;-1:-1:-1;18943:9:1;;18787:171::o;18963:168::-;19003:7;19069:1;19065;19061:6;19057:14;19054:1;19051:21;19046:1;19039:9;19032:17;19028:45;19025:2;;;19076:18;;:::i;:::-;-1:-1:-1;19116:9:1;;19015:116::o;19136:125::-;19176:4;19204:1;19201;19198:8;19195:2;;;19209:18;;:::i;:::-;-1:-1:-1;19246:9:1;;19185:76::o;19266:258::-;19338:1;19348:113;19362:6;19359:1;19356:13;19348:113;;;19438:11;;;19432:18;19419:11;;;19412:39;19384:2;19377:10;19348:113;;;19479:6;19476:1;19473:13;19470:2;;;-1:-1:-1;;19514:1:1;19496:16;;19489:27;19319:205::o;19529:135::-;19568:3;-1:-1:-1;;19589:17:1;;19586:2;;;19609:18;;:::i;:::-;-1:-1:-1;19656:1:1;19645:13;;19576:88::o;19669:127::-;19730:10;19725:3;19721:20;19718:1;19711:31;19761:4;19758:1;19751:15;19785:4;19782:1;19775:15;19801:131;-1:-1:-1;;;;;19876:31:1;;19866:42;;19856:2;;19922:1;19919;19912:12;19937:118;20023:5;20016:13;20009:21;20002:5;19999:32;19989:2;;20045:1;20042;20035:12

Swarm Source

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