ETH Price: $3,344.40 (-1.05%)

Token

Supreme Kong 2 (SPK2)
 

Overview

Max Total Supply

10,000 SPK2

Holders

647

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
solidsnake81.eth
Balance
1 SPK2
0x1C63231661B8b5e1F0356b172F66d9aD2eb4852d
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Supreme dominance, undeniable in the jungle.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
SupremeKongGen2

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-12-01
*/

// SPDX-License-Identifier: GPL-3.0
// File: @openzeppelin/contracts/security/ReentrancyGuard.sol


// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

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

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

        _;

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

// File: @openzeppelin/contracts/utils/structs/EnumerableSet.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 *  Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.
 *  See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 *  In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastValue;
                // Update the index for the moved value
                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        return _values(set._inner);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

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


// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

// File: @openzeppelin/contracts/utils/cryptography/ECDSA.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;


/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

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


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

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

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;


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

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

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

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

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

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

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


// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @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
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 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
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: @openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/utils/ERC721Holder.sol)

pragma solidity ^0.8.0;


/**
 * @dev Implementation of the {IERC721Receiver} interface.
 *
 * Accepts all token transfers.
 * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}.
 */
contract ERC721Holder is IERC721Receiver {
    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     *
     * Always returns `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address,
        address,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }
}

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts/interfaces/IERC2981.sol


// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.0;


/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}

// File: @openzeppelin/contracts/utils/introspection/ERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// File: @openzeppelin/contracts/token/common/ERC2981.sol


// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)

pragma solidity ^0.8.0;



/**
 * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
 *
 * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
 * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
 *
 * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
 * fee is specified in basis points by default.
 *
 * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
 * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
 * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
 *
 * _Available since v4.5._
 */
abstract contract ERC2981 is IERC2981, ERC165 {
    struct RoyaltyInfo {
        address receiver;
        uint96 royaltyFraction;
    }

    RoyaltyInfo private _defaultRoyaltyInfo;
    mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @inheritdoc IERC2981
     */
    function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) {
        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];

        if (royalty.receiver == address(0)) {
            royalty = _defaultRoyaltyInfo;
        }

        uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();

        return (royalty.receiver, royaltyAmount);
    }

    /**
     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
     * override.
     */
    function _feeDenominator() internal pure virtual returns (uint96) {
        return 10000;
    }

    /**
     * @dev Sets the royalty information that all ids in this contract will default to.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: invalid receiver");

        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Removes default royalty information.
     */
    function _deleteDefaultRoyalty() internal virtual {
        delete _defaultRoyaltyInfo;
    }

    /**
     * @dev Sets the royalty information for a specific token id, overriding the global default.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setTokenRoyalty(
        uint256 tokenId,
        address receiver,
        uint96 feeNumerator
    ) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: Invalid parameters");

        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Resets royalty information for the token id back to the global default.
     */
    function _resetTokenRoyalty(uint256 tokenId) internal virtual {
        delete _tokenRoyaltyInfo[tokenId];
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol


// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

// File: contracts/genericstaking.sol



pragma solidity ^0.8.11;





contract Staking is ERC721Holder, Ownable {

    using EnumerableSet for EnumerableSet.UintSet;

    struct Staker {
        //uint256[] tokenIds; // array of token ids
        EnumerableSet.UintSet tokenIds; //set of token ids
        uint256 amount;
    }

    struct StakedNft {
        uint256 timestamp;
        uint256 stakedTime;
        uint256 lockedTime;
    }

    struct Collection {
        IERC721 NFT;
        uint256 lockTime;
        mapping(address => Staker) Stakers;
        mapping(uint256 => StakedNft) StakedNfts;
        mapping(uint256 => address) StakerAddresses;
    }

    Collection[] nftPools;

    constructor() {
    }

    event Stake(address indexed owner, uint256 id, uint256 time);
    event Unstake(address indexed owner, uint256 id, uint256 time);

    function stakeNFT(uint256 _tokenId, uint256 _poolId) public {
        Collection storage pool = nftPools[_poolId];
        require(pool.NFT.balanceOf(msg.sender) >= 1, "you dont have enough nfts");
        require(
            pool.NFT.ownerOf(_tokenId) == msg.sender,
            "you don't own this nft!"
        );
        pool.Stakers[msg.sender].amount += 1;
        //pool.Stakers[msg.sender].tokenIds.push(_tokenId);
        pool.Stakers[msg.sender].tokenIds.add(_tokenId);
        pool.StakedNfts[_tokenId].lockedTime = block.timestamp + pool.lockTime;
        pool.StakedNfts[_tokenId].timestamp = block.timestamp;
        pool.StakedNfts[_tokenId].stakedTime = block.timestamp;
        pool.StakerAddresses[_tokenId] = msg.sender;
        pool.NFT.safeTransferFrom(msg.sender, address(this), _tokenId);
        emit Stake (msg.sender, _tokenId, block.timestamp);
    }

    function batchStakeNFT(uint256[] memory _tokenIds, uint256 _poolId) public {
        Collection storage pool = nftPools[_poolId];
        require(pool.NFT.balanceOf(msg.sender) >= 1, "you dont have enough nfts");
        
        for (uint i = 0; i < _tokenIds.length; i++) {
            require(
                pool.NFT.ownerOf(_tokenIds[i]) == msg.sender,
                "you don't own this nft!"
            );
            pool.Stakers[msg.sender].amount += 1;
            //pool.Stakers[msg.sender].tokenIds.push(_tokenIds[i]);
            pool.Stakers[msg.sender].tokenIds.add(_tokenIds[i]);
            pool.StakedNfts[_tokenIds[i]].lockedTime = block.timestamp + pool.lockTime;
            pool.StakedNfts[_tokenIds[i]].timestamp = block.timestamp;
            pool.StakedNfts[_tokenIds[i]].stakedTime = block.timestamp;
            pool.StakerAddresses[_tokenIds[i]] = msg.sender;
            pool.NFT.safeTransferFrom(msg.sender, address(this), _tokenIds[i]);
            emit Stake (msg.sender, _tokenIds[i], block.timestamp);
        }
    }

    function unstakeNFT(uint256 _tokenId, uint256 _poolId) public {
        Collection storage pool = nftPools[_poolId];
        require(block.timestamp >= pool.StakedNfts[_tokenId].lockedTime, "your nft is locked for withdrawal");
        require(
            pool.Stakers[msg.sender].amount > 0,
            "you have no nfts staked"
        );
        require(pool.StakerAddresses[_tokenId] == msg.sender, "you don't own this token!");
        pool.Stakers[msg.sender].amount -= 1;
        pool.StakerAddresses[_tokenId] = address(0);

        Staker storage u = pool.Stakers[msg.sender];
        u.tokenIds.remove(_tokenId);

        pool.NFT.safeTransferFrom(address(this), msg.sender, _tokenId);

        emit Unstake(msg.sender, _tokenId, block.timestamp);
    }

    function batchUnstakeNFT(uint256[] memory _tokenIds, uint256 _poolId) public {
        Collection storage pool = nftPools[_poolId];
        require(
            pool.Stakers[msg.sender].amount > 0,
            "you have no nfts staked"
        );

        for (uint i = 0; i < _tokenIds.length; i++) {
            if(pool.StakerAddresses[_tokenIds[i]] == msg.sender && block.timestamp >= pool.StakedNfts[_tokenIds[i]].lockedTime) {
                pool.Stakers[msg.sender].amount -= 1;
                pool.StakerAddresses[_tokenIds[i]] = address(0);

                Staker storage u = pool.Stakers[msg.sender];
                u.tokenIds.remove(_tokenIds[i]);

                pool.NFT.safeTransferFrom(address(this), msg.sender, _tokenIds[i]);

                emit Unstake(msg.sender, _tokenIds[i], block.timestamp);
            }
        }
    }

    function claimRewards(uint256 _tokenId, uint256 _poolId) public {
        Collection storage pool = nftPools[_poolId];
        require(
            pool.Stakers[msg.sender].amount > 0,
            "you have no nfts staked"
        );
        require(pool.StakerAddresses[_tokenId] == msg.sender, "you don't own this token!");
        pool.StakedNfts[_tokenId].timestamp = block.timestamp;        
    }

    function addPool(address _nftAddress, uint256 _lockTime) external onlyOwner {
        Collection storage newCollection = nftPools.push();
        newCollection.NFT = IERC721(_nftAddress);
        newCollection.lockTime = _lockTime;
    }

    function stakedNftInfo(uint256 _tokenId, uint256 _poolId) external view returns(uint256, uint256, uint256) {
        Collection storage pool = nftPools[_poolId];
        StakedNft memory stakeInfo = pool.StakedNfts[_tokenId];
        
        return (stakeInfo.timestamp, stakeInfo.lockedTime, stakeInfo.stakedTime);
    }

    function stakedNfts(address _owner, uint256 _poolId) external view returns(uint256[] memory) {
        Collection storage pool = nftPools[_poolId];
        uint256[] memory tempArr = new uint256[](pool.Stakers[_owner].tokenIds.length());
        // Delegate to internal OpenZeppelin function
        for(uint i = 0; i < pool.Stakers[_owner].tokenIds.length(); i++){
            tempArr[i] = pool.Stakers[_owner].tokenIds.at(i);
        }
        return tempArr;
    }

}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol


// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

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


// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;








/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: address zero is not a valid owner");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: invalid token ID");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not token owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
        _safeTransfer(from, to, tokenId, data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);

        _afterTokenTransfer(owner, address(0), tokenId);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits an {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` 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 tokenId
    ) 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.
     * - `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 tokenId
    ) internal virtual {}
}

// File: contracts/erc721a.sol


pragma solidity ^0.8.11;




/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata and Enumerable extension. Built to optimize for lower gas during batch mints.
 *
 * Assumes serials are sequentially minted starting at 0 (e.g. 0, 1, 2, 3..).
 *
 * Does not support burning tokens to address(0).
 *
 * Assumes that an owner cannot have more than the 2**128 - 1 (max value of uint128) of supply
 */
contract ERC721A is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
    using Address for address;
    using Strings for uint256;

    struct TokenOwnership {
        address addr;
        uint64 startTimestamp;
    }

    struct AddressData {
        uint128 balance;
        uint128 numberMinted;
    }

    uint256 internal currentIndex;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned. See ownershipOf implementation for details.
    mapping(uint256 => TokenOwnership) internal _ownerships;

    // Mapping owner address to address data
    mapping(address => AddressData) private _addressData;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view override returns (uint256) {
        require(index < totalSupply(), "ERC721A: global index out of bounds");
        return index;
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     * This read function is O(totalSupply). If calling from a separate contract, be sure to test gas first.
     * It may also degrade with extremely large collection sizes (e.g >> 10000), test for your use case.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
        require(index < balanceOf(owner), "ERC721A: owner index out of bounds");
        uint256 numMintedSoFar = totalSupply();
        uint256 tokenIdsIdx;
        address currOwnershipAddr;

        // Counter overflow is impossible as the loop breaks when uint256 i is equal to another uint256 numMintedSoFar.
        unchecked {
            for (uint256 i; i < numMintedSoFar; i++) {
                TokenOwnership memory ownership = _ownerships[i];
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    if (tokenIdsIdx == index) {
                        return i;
                    }
                    tokenIdsIdx++;
                }
            }
        }

        revert("ERC721A: unable to get token of owner by index");
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            interfaceId == type(IERC721Enumerable).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view override returns (uint256) {
        require(owner != address(0), "ERC721A: balance query for the zero address");
        return uint256(_addressData[owner].balance);
    }

    function _numberMinted(address owner) internal view returns (uint256) {
        require(owner != address(0), "ERC721A: number minted query for the zero address");
        return uint256(_addressData[owner].numberMinted);
    }

    /**
     * Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around in the collection over time.
     */
    function ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) {
        require(_exists(tokenId), "ERC721A: owner query for nonexistent token");

        unchecked {
            for (uint256 curr = tokenId; curr >= 0; curr--) {
                TokenOwnership memory ownership = _ownerships[curr];
                if (ownership.addr != address(0)) {
                    return ownership;
                }
            }
        }

        revert("ERC721A: unable to determine the owner of token");
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view override returns (address) {
        return ownershipOf(tokenId).addr;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory baseURI = _baseURI();
        return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overriden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public override {
        address owner = ERC721A.ownerOf(tokenId);
        require(to != owner, "ERC721A: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721A: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId, owner);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view override returns (address) {
        require(_exists(tokenId), "ERC721A: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public override {
        require(operator != _msgSender(), "ERC721A: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public override {
        _transfer(from, to, tokenId);
        require(
            _checkOnERC721Received(from, to, tokenId, _data),
            "ERC721A: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        return tokenId < currentIndex;
    }

    function _safeMint(address to, uint256 quantity) internal {
        _safeMint(to, quantity, "");
    }

    /**
     * @dev Safely mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal {
        _mint(to, quantity, _data, true);
    }

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event.
     */
    function _mint(
        address to,
        uint256 quantity,
        bytes memory _data,
        bool safe
    ) internal {
        uint256 startTokenId = currentIndex;
        require(to != address(0), "ERC721A: mint to the zero address");
        require(quantity != 0, "ERC721A: quantity must be greater than 0");

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are incredibly unrealistic.
        // balance or numberMinted overflow if current value of either + quantity > 3.4e38 (2**128) - 1
        // updatedIndex overflows if currentIndex + quantity > 1.56e77 (2**256) - 1
        unchecked {
            _addressData[to].balance += uint128(quantity);
            _addressData[to].numberMinted += uint128(quantity);

            _ownerships[startTokenId].addr = to;
            _ownerships[startTokenId].startTimestamp = uint64(block.timestamp);

            uint256 updatedIndex = startTokenId;

            for (uint256 i; i < quantity; i++) {
                emit Transfer(address(0), to, updatedIndex);
                if (safe) {
                    require(
                        _checkOnERC721Received(address(0), to, updatedIndex, _data),
                        "ERC721A: transfer to non ERC721Receiver implementer"
                    );
                }

                updatedIndex++;
            }

            currentIndex = updatedIndex;
        }

        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) private {
        TokenOwnership memory prevOwnership = ownershipOf(tokenId);

        bool isApprovedOrOwner = (_msgSender() == prevOwnership.addr ||
            getApproved(tokenId) == _msgSender() ||
            isApprovedForAll(prevOwnership.addr, _msgSender()));

        require(isApprovedOrOwner, "ERC721A: transfer caller is not owner nor approved");

        require(prevOwnership.addr == from, "ERC721A: transfer from incorrect owner");
        require(to != address(0), "ERC721A: transfer to the zero address");

        _beforeTokenTransfers(from, to, tokenId, 1);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId, prevOwnership.addr);

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256.
        unchecked {
            _addressData[from].balance -= 1;
            _addressData[to].balance += 1;

            _ownerships[tokenId].addr = to;
            _ownerships[tokenId].startTimestamp = uint64(block.timestamp);

            // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            if (_ownerships[nextTokenId].addr == address(0)) {
                if (_exists(nextTokenId)) {
                    _ownerships[nextTokenId].addr = prevOwnership.addr;
                    _ownerships[nextTokenId].startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

        emit Transfer(from, to, tokenId);
        _afterTokenTransfers(from, to, tokenId, 1);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(
        address to,
        uint256 tokenId,
        address owner
    ) private {
        _tokenApprovals[tokenId] = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver(to).onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721A: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token ids are about to be transferred. This includes minting.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token ids have been transferred. This includes
     * minting.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}
}
// File: contracts/supremekong2.sol

pragma solidity ^0.8.11;











contract SupremeKongGen2 is ERC721A, ERC2981, ERC721Holder, Ownable, ReentrancyGuard {

    using EnumerableSet for EnumerableSet.UintSet;

    struct Staker {
        EnumerableSet.UintSet tokenIds; // set of token ids
        uint256 amount;
    }

    struct StakedNft {
        uint256 stakedTime;
        uint256 lockedTime;
    }

    uint256 lockTime;
    mapping(address => Staker) Stakers;
    mapping(uint256 => StakedNft) StakedNfts;
    mapping(uint256 => address) StakerAddresses;

    using ECDSA for bytes32;

    address private      systemAddress;
    address private      stakeAddress;
    address private      kongAddress;
    address private      bananaAddress;
    address private      mutantAddress;
    string public        hiddenURI;
    string public        baseURI;
    uint public          price = 0.099 ether;
    uint public          stakePrice = 0.08 ether;
    uint public          nextOwnerToExplicitlySet;
    uint public          maxSupply = 10000;
    uint public          teamSupply = 1000;
    uint public          mutantSupply = 300;
    uint public          whitelistSupply = 700;
    uint public          freemintSupply = 1800;
    uint public          publicLimit = 5;
    bool public          mintEnabled;
    bool public          revealed;

    mapping(address => uint256) publicMinted;

    mapping(uint256 => bool) public _redeemedKongIds;
    mapping(uint256 => bool) public _redeemedBananaIds;
    mapping(uint256 => bool) public _redeemedMutantBananaIds;

    mapping(string => bool) public _usedNonces;
    mapping(uint256 => bool) public _paidMutantBananaIds;

    constructor(address _kongAddress, address _bananaAddress, address _mutantAddress, address _stakeAddress, address _systemAddress, address payable royaltiesReceiver, uint256 _lockTime) ERC721A("Supreme Kong 2", "SPK2") {
        kongAddress = _kongAddress;
        bananaAddress = _bananaAddress;
        mutantAddress = _mutantAddress;
        stakeAddress = _stakeAddress;
        systemAddress = _systemAddress;
        lockTime = _lockTime;

        setRoyaltyInfo(royaltiesReceiver, 750);
    }

    function freeMint(address to) external {
        uint mintAmount = 0;
        require(mintEnabled, "Mint disabled");

        uint256[] memory stakedKong = Staking(stakeAddress).stakedNfts(msg.sender, 0);
        uint256[] memory stakedBanana = Staking(stakeAddress).stakedNfts(msg.sender, 1);
        uint256[] memory stakedMutant = Staking(stakeAddress).stakedNfts(msg.sender, 2);

        require(IERC721(kongAddress).balanceOf(msg.sender) > 0 || stakedKong.length > 0, "Must have more than 1 Supreme Kong to free mint");
        require(IERC721(bananaAddress).balanceOf(msg.sender) > 0 || IERC721(mutantAddress).balanceOf(msg.sender) > 0 || stakedBanana.length > 0 || stakedMutant.length > 0, "Must have more than 1 Banana to free mint");
        
        uint256[] memory tempArrKong = new uint256[](IERC721(kongAddress).balanceOf(msg.sender)+stakedKong.length);
        uint256[] memory tempArrBanana = new uint256[](IERC721(bananaAddress).balanceOf(msg.sender)+stakedBanana.length);
        uint256[] memory tempArrMutant = new uint256[](IERC721(mutantAddress).balanceOf(msg.sender)+stakedMutant.length);

        uint index = IERC721(kongAddress).balanceOf(msg.sender);
        for (uint i = 0; i < IERC721(kongAddress).balanceOf(msg.sender); i++) {
            uint256 tokenId = IERC721Enumerable(kongAddress).tokenOfOwnerByIndex(msg.sender, i);
            tempArrKong[i] = tokenId;
        }
        for (uint i = 0; i < stakedKong.length; i++) {
            tempArrKong[index] = stakedKong[i];
            index++;
        }

        index = IERC721(bananaAddress).balanceOf(msg.sender);
        for (uint i = 0; i < IERC721(bananaAddress).balanceOf(msg.sender); i++) {
            uint256 tokenId = IERC721Enumerable(bananaAddress).tokenOfOwnerByIndex(msg.sender, i);
            tempArrBanana[i] = tokenId;
        }
        for (uint i = 0; i < stakedBanana.length; i++) {
            tempArrBanana[index] = stakedBanana[i];
            index++;
        }

        index = IERC721(mutantAddress).balanceOf(msg.sender);
        for (uint i = 0; i < IERC721(mutantAddress).balanceOf(msg.sender); i++) {
            uint256 tokenId = IERC721Enumerable(mutantAddress).tokenOfOwnerByIndex(msg.sender, i);
            tempArrMutant[i] = tokenId;
        }
        for (uint i = 0; i < stakedMutant.length; i++) {
            tempArrMutant[index] = stakedMutant[i];
            index++;
        }

        for (uint i = 0; i < tempArrKong.length; i++) {
            uint256 kongId = tempArrKong[i];
            for (uint j = 0; j < tempArrBanana.length; j++) {
                uint256 bananaId = tempArrBanana[j];
                if (!_redeemedKongIds[kongId] && !_redeemedBananaIds[bananaId]) {
                    _redeemedBananaIds[bananaId] = true;
                    _redeemedKongIds[kongId] = true;
                    mintAmount++;
                }
            }
            for (uint j = 0; j < tempArrMutant.length; j++) {
                uint256 mutantId = tempArrMutant[j];
                if (!_redeemedKongIds[kongId] && !_redeemedMutantBananaIds[mutantId]) {
                    _redeemedMutantBananaIds[mutantId] = true;
                    _redeemedKongIds[kongId] = true;
                    mintAmount++;
                }
            }
        }

        require(mintAmount > 0, "You don't have available kong and banana pair");
        uint startTokenId = currentIndex;
        _safeMint(address(this), mintAmount);

        for(uint i = 0; i < mintAmount; i++) {
            Stakers[to].amount += 1;
            Stakers[to].tokenIds.add(startTokenId);
            StakedNfts[startTokenId].lockedTime = block.timestamp + lockTime;
            StakedNfts[startTokenId].stakedTime = block.timestamp;
            StakerAddresses[startTokenId] = to;
            startTokenId++;
        }
    }

    function teamMint(address to, uint256 numberOfTokens) external onlyOwner {
        require(mintEnabled, "Mint disabled");
        require(totalSupply() + numberOfTokens < maxSupply + 1, "We're sold out!");

        _safeMint(to, numberOfTokens);
    }

    function publicMint(address to, uint256 numberOfTokens) external payable {
        uint cost = price;
        require(mintEnabled, "Mint disabled");
        require(totalSupply() + numberOfTokens < (maxSupply - teamSupply - mutantSupply - whitelistSupply - freemintSupply) + 1, "We're sold out!");
        require(publicMinted[msg.sender] + numberOfTokens <= publicLimit, "Too many per wallet");
        require(msg.value >= numberOfTokens * cost, "Ether is not enough");
        publicMinted[msg.sender] += numberOfTokens;
        _safeMint(to, numberOfTokens);
    }

    function publicMintAndStake(address to, uint256 numberOfTokens) external payable {
        uint cost = stakePrice;
        require(mintEnabled, "Mint disabled");
        require(totalSupply() + numberOfTokens < (maxSupply - teamSupply - mutantSupply - whitelistSupply - freemintSupply) + 1, "We're sold out!");
        require(publicMinted[msg.sender] + numberOfTokens <= publicLimit, "Too many per wallet");
        require(msg.value >= numberOfTokens * cost, "Ether is not enough");
        
        uint startTokenId = currentIndex;
        _safeMint(address(this), numberOfTokens);
        
        for(uint i = 0; i < numberOfTokens; i++) {
            Stakers[to].amount += 1;
            Stakers[to].tokenIds.add(startTokenId);
            StakedNfts[startTokenId].lockedTime = block.timestamp + lockTime;
            StakedNfts[startTokenId].stakedTime = block.timestamp;
            StakerAddresses[startTokenId] = to;
            startTokenId++;
        }
    }

    function mutantMint(address to, uint256 numberOfTokens) external payable {
        uint cost = price;
        uint mintAmount = 0;
        uint amount = numberOfTokens;
        require(mintEnabled, "Mint disabled");

        uint256[] memory stakedMutant = Staking(stakeAddress).stakedNfts(msg.sender, 2);
        require(IERC721(mutantAddress).balanceOf(msg.sender) > 0 || stakedMutant.length > 0, "Must have more than 1 Mutant Banana");
        
        uint mutantBananaOwned = IERC721(mutantAddress).balanceOf(msg.sender);
        for (uint i = 0; i < mutantBananaOwned; i++) {
            uint256 tokenId = IERC721Enumerable(mutantAddress).tokenOfOwnerByIndex(msg.sender, i);
            if (!_paidMutantBananaIds[tokenId] && amount > 0) { 
                _paidMutantBananaIds[tokenId] = true;
                mintAmount++;
                amount--;
            }
        }
        for (uint i = 0; i < stakedMutant.length; i++) {
            uint256 tokenId = stakedMutant[i];
            if (!_paidMutantBananaIds[tokenId] && amount > 0) { 
                _paidMutantBananaIds[tokenId] = true;
                mintAmount++;
                amount--;
            }
        }

        require(totalSupply() + mintAmount < (maxSupply - teamSupply - whitelistSupply) + 1, "We're sold out!");
        require(msg.value >= mintAmount * cost, "Ether is not enough");
        require(mintAmount > 0, "You have used all your mutants");
        _safeMint(to, mintAmount);
    }

    function mutantMintAndStake(address to, uint256 numberOfTokens) external payable {
        uint cost = stakePrice;
        uint mintAmount = 0;
        uint amount = numberOfTokens;
        require(mintEnabled, "Mint disabled");

        uint256[] memory stakedMutant = Staking(stakeAddress).stakedNfts(msg.sender, 2);
        require(IERC721(mutantAddress).balanceOf(msg.sender) > 0 || stakedMutant.length > 0, "Must have more than 1 Mutant Banana");
        
        uint mutantBananaOwned = IERC721(mutantAddress).balanceOf(msg.sender);
        for (uint i = 0; i < mutantBananaOwned; i++) {
            uint256 tokenId = IERC721Enumerable(mutantAddress).tokenOfOwnerByIndex(msg.sender, i);
            if (!_paidMutantBananaIds[tokenId] && amount > 0) { 
                _paidMutantBananaIds[tokenId] = true;
                mintAmount++;
                amount--;
            }
        }
        for (uint i = 0; i < stakedMutant.length; i++) {
            uint256 tokenId = stakedMutant[i];
            if (!_paidMutantBananaIds[tokenId] && amount > 0) { 
                _paidMutantBananaIds[tokenId] = true;
                mintAmount++;
                amount--;
            }
        }

        require(totalSupply() + mintAmount < (maxSupply - teamSupply - whitelistSupply) + 1, "We're sold out!");
        require(msg.value >= mintAmount * cost, "Ether is not enough");
        require(mintAmount > 0, "You have used all your mutants");

        uint startTokenId = currentIndex;
        _safeMint(address(this), mintAmount);

        for(uint i = 0; i < mintAmount; i++) {
            Stakers[to].amount += 1;
            Stakers[to].tokenIds.add(startTokenId);
            StakedNfts[startTokenId].lockedTime = block.timestamp + lockTime;
            StakedNfts[startTokenId].stakedTime = block.timestamp;
            StakerAddresses[startTokenId] = to;
            startTokenId++;
        }
    }

    function whitelistMint(address to, uint256 numberOfTokens, string memory nonce, bytes32 hash, bytes memory signature) external payable {
        uint cost = price;
        require(mintEnabled, "Mint disabled");
        require(publicMinted[msg.sender] + numberOfTokens <= publicLimit, "Too many per wallet");
        require(totalSupply() + numberOfTokens < (maxSupply - teamSupply - mutantSupply ) + 1, "We're sold out!");
        require(msg.value >= numberOfTokens * cost, "Ether is not enough");

        // signature verification
        require(matchSigner(hash, signature), "Please mint through website");
        require(!_usedNonces[nonce], "Hash reused");
        require(hashTransaction(msg.sender, 1, nonce) == hash, "Hash failed"); 

        publicMinted[msg.sender] += numberOfTokens;
        _usedNonces[nonce] = true;
        _safeMint(to, numberOfTokens);
    }

    function whitelistMintAndStake(address to, uint256 numberOfTokens, string memory nonce, bytes32 hash, bytes memory signature) external payable {
        uint cost = stakePrice;
        require(mintEnabled, "Mint disabled");
        require(publicMinted[msg.sender] + numberOfTokens <= publicLimit, "Too many per wallet");
        require(totalSupply() + numberOfTokens < (maxSupply - teamSupply - mutantSupply ) + 1, "We're sold out!");
        require(msg.value >= numberOfTokens * cost, "Ether is not enough");

        // signature verification
        require(matchSigner(hash, signature), "Please mint through website");
        require(!_usedNonces[nonce], "Hash reused");
        require(hashTransaction(msg.sender, 1, nonce) == hash, "Hash failed"); 

        publicMinted[msg.sender] += numberOfTokens;
        _usedNonces[nonce] = true;

        uint startTokenId = currentIndex;
        _safeMint(address(this), numberOfTokens);

        for(uint i = 0; i < numberOfTokens; i++) {
            Stakers[to].amount += 1;
            Stakers[to].tokenIds.add(startTokenId);
            StakedNfts[startTokenId].lockedTime = block.timestamp + lockTime;
            StakedNfts[startTokenId].stakedTime = block.timestamp;
            StakerAddresses[startTokenId] = to;
            startTokenId++;
        }
    }

    function stakeNFT(uint256 _tokenId) public {
        require(IERC721(address(this)).balanceOf(msg.sender) >= 1, "you dont have enough nfts");
        require(
            IERC721(address(this)).ownerOf(_tokenId) == msg.sender,
            "you don't own this nft!"
        );
        Stakers[msg.sender].amount += 1;
        Stakers[msg.sender].tokenIds.add(_tokenId);
        StakedNfts[_tokenId].lockedTime = block.timestamp + lockTime;
        StakedNfts[_tokenId].stakedTime = block.timestamp;
        StakerAddresses[_tokenId] = msg.sender;
        IERC721(address(this)).transferFrom(msg.sender, address(this), _tokenId);
    }

    function batchStakeNFT(uint256[] memory _tokenIds) public {
        require(IERC721(address(this)).balanceOf(msg.sender) >= 1, "you dont have enough nfts");
        
        for (uint i = 0; i < _tokenIds.length; i++) {
            require(
                IERC721(address(this)).ownerOf(_tokenIds[i]) == msg.sender,
                "you don't own this nft!"
            );
            Stakers[msg.sender].amount += 1;
            Stakers[msg.sender].tokenIds.add(_tokenIds[i]);
            StakedNfts[_tokenIds[i]].lockedTime = block.timestamp + lockTime;
            StakedNfts[_tokenIds[i]].stakedTime = block.timestamp;
            StakerAddresses[_tokenIds[i]] = msg.sender;
            IERC721(address(this)).transferFrom(msg.sender, address(this), _tokenIds[i]);
        }
    }

    function unstakeNFT(uint256 _tokenId) public {
        require(block.timestamp >= StakedNfts[_tokenId].lockedTime, "your nft is locked for withdrawal");
        require(
            Stakers[msg.sender].amount > 0,
            "you have no nfts staked"
        );
        require(StakerAddresses[_tokenId] == msg.sender, "you don't own this token!");
        Stakers[msg.sender].amount -= 1;
        StakerAddresses[_tokenId] = address(0);

        Staker storage u = Stakers[msg.sender];
        u.tokenIds.remove(_tokenId);

        IERC721(address(this)).transferFrom(address(this), msg.sender, _tokenId);
    }

    function batchUnstakeNFT() public {
        require(
            Stakers[msg.sender].amount > 0,
            "you have no nfts staked"
        );
        uint tokenAmount = Stakers[msg.sender].tokenIds.length();

        for(uint i = 0; i < tokenAmount; i++) {
            uint tokenId = Stakers[msg.sender].tokenIds.at(0);
            if(StakerAddresses[tokenId] == msg.sender && block.timestamp >= StakedNfts[tokenId].lockedTime) {
                Stakers[msg.sender].amount -= 1;
                StakerAddresses[tokenId] = address(0);

                Staker storage u = Stakers[msg.sender];
                u.tokenIds.remove(tokenId);

                IERC721(address(this)).transferFrom(address(this), msg.sender, tokenId);

            }
        }
    }

    function toggleMinting() external onlyOwner {
        mintEnabled = !mintEnabled;
    }

    function toggleRevealed() external onlyOwner {
        revealed = !revealed;
    }

    function setMutantSupply(uint256 _amount) external onlyOwner {
        mutantSupply = _amount;
    }

    function setWhitelistSupply(uint256 _amount) external onlyOwner {
        whitelistSupply = _amount;
    }

    function setFreemintSupply(uint256 _amount) external onlyOwner {
        freemintSupply = _amount;
    }

    function setHiddenURI(string calldata hiddenURI_) external onlyOwner {
        hiddenURI = hiddenURI_;
    }

    function setBaseURI(string calldata baseURI_) external onlyOwner {
        baseURI = baseURI_;
    }

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        require(_exists(tokenId), "Kong does not exist");

        if (revealed) {
            return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, Strings.toString(tokenId))) : "";
        }

        return hiddenURI;
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return baseURI;
    }

    function withdraw() external onlyOwner nonReentrant {
        (bool success, ) = msg.sender.call{value: address(this).balance}("");
        require(success, "transfer failed");
    }

    function setOwnersExplicit(uint256 quantity) external onlyOwner nonReentrant {
        _setOwnersExplicit(quantity);
    }

    function getOwnershipData(uint256 tokenId) external view returns (TokenOwnership memory) {
        return ownershipOf(tokenId);
    }

    function stakedNfts(address _owner) external view returns(uint256[] memory) {
        uint256[] memory tempArr = new uint256[](Stakers[_owner].tokenIds.length());
        for(uint i = 0; i < Stakers[_owner].tokenIds.length(); i++) {
            tempArr[i] = Stakers[_owner].tokenIds.at(i);
        }
        return tempArr;
    }

    function matchSigner(bytes32 hash, bytes memory signature) public view returns (bool) {
        return systemAddress == hash.toEthSignedMessageHash().recover(signature);
    }

    function hashTransaction(
    address sender,
    uint256 amount,
    string memory nonce
    ) public view returns (bytes32) {
    
        bytes32 hash = keccak256(
        abi.encodePacked(sender, amount, nonce, address(this))
        );

        return hash;
    }

    // IERC2981

    function setRoyaltyInfo(address payable receiver, uint96 numerator) public onlyOwner {
        _setDefaultRoyalty(receiver, numerator);
    }
    //
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721A, ERC2981) returns (bool) {
    return ERC721A.supportsInterface(interfaceId) || ERC2981.supportsInterface(interfaceId);
    }

    /**
     * @dev Explicitly set `owners` to eliminate loops in future calls of ownerOf().
     */
    function _setOwnersExplicit(uint256 quantity) internal {
        require(quantity != 0, "quantity must be nonzero");
        require(currentIndex != 0, "no tokens minted yet");
        uint256 _nextOwnerToExplicitlySet = nextOwnerToExplicitlySet;
        require(_nextOwnerToExplicitlySet < currentIndex, "all ownerships have been set");

        // Index underflow is impossible.
        // Counter or index overflow is incredibly unrealistic.
        unchecked {
            uint256 endIndex = _nextOwnerToExplicitlySet + quantity - 1;

            // Set the end index to be the last token index
            if (endIndex + 1 > currentIndex) {
                endIndex = currentIndex - 1;
            }

            for (uint256 i = _nextOwnerToExplicitlySet; i <= endIndex; i++) {
                if (_ownerships[i].addr == address(0)) {
                    TokenOwnership memory ownership = ownershipOf(i);
                    _ownerships[i].addr = ownership.addr;
                    _ownerships[i].startTimestamp = ownership.startTimestamp;
                }
            }

            nextOwnerToExplicitlySet = endIndex + 1;
        }
    }

}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_kongAddress","type":"address"},{"internalType":"address","name":"_bananaAddress","type":"address"},{"internalType":"address","name":"_mutantAddress","type":"address"},{"internalType":"address","name":"_stakeAddress","type":"address"},{"internalType":"address","name":"_systemAddress","type":"address"},{"internalType":"address payable","name":"royaltiesReceiver","type":"address"},{"internalType":"uint256","name":"_lockTime","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","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":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_paidMutantBananaIds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_redeemedBananaIds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_redeemedKongIds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_redeemedMutantBananaIds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"_usedNonces","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"batchStakeNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"batchUnstakeNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"freeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"freemintSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getOwnershipData","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"}],"internalType":"struct ERC721A.TokenOwnership","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"nonce","type":"string"}],"name":"hashTransaction","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hiddenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"matchSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"mutantMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"mutantMintAndStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mutantSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextOwnerToExplicitlySet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"publicMintAndStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setFreemintSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"hiddenURI_","type":"string"}],"name":"setHiddenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMutantSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"setOwnersExplicit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"uint96","name":"numerator","type":"uint96"}],"name":"setRoyaltyInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setWhitelistSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"stakeNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"stakedNfts","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"teamMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"teamSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleRevealed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"unstakeNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"numberOfTokens","type":"uint256"},{"internalType":"string","name":"nonce","type":"string"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"whitelistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"numberOfTokens","type":"uint256"},{"internalType":"string","name":"nonce","type":"string"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"whitelistMintAndStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"whitelistSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405267015fb7f9b8c3800060165567011c37937e0800006017556127106019556103e8601a5561012c601b556102bc601c55610708601d556005601e553480156200004c57600080fd5b50604051620064d4380380620064d48339810160408190526200006f9162000357565b6040518060400160405280600e81526020016d29bab83932b6b29025b7b733901960911b8152506040518060400160405280600481526020016329a8259960e11b8152508160019081620000c491906200049b565b506002620000d382826200049b565b505050620000f0620000ea6200016b60201b60201c565b6200016f565b6001600a55601180546001600160a01b03199081166001600160a01b038a811691909117909255601280548216898416179055601380548216888416179055601080548216878416179055600f8054909116918516919091179055600b8190556200015e826102ee620001c1565b5050505050505062000567565b3390565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b620001cb620001db565b620001d782826200023d565b5050565b6009546001600160a01b031633146200023b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b565b6127106001600160601b0382161115620002ad5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b606482015260840162000232565b6001600160a01b038216620003055760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c696420726563656976657200000000000000604482015260640162000232565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600755565b6001600160a01b03811681146200035457600080fd5b50565b600080600080600080600060e0888a0312156200037357600080fd5b875162000380816200033e565b602089015190975062000393816200033e565b6040890151909650620003a6816200033e565b6060890151909550620003b9816200033e565b6080890151909450620003cc816200033e565b60a0890151909350620003df816200033e565b8092505060c0880151905092959891949750929550565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200042157607f821691505b6020821081036200044257634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200049657600081815260208120601f850160051c81016020861015620004715750805b601f850160051c820191505b8181101562000492578281556001016200047d565b5050505b505050565b81516001600160401b03811115620004b757620004b7620003f6565b620004cf81620004c884546200040c565b8462000448565b602080601f831160018114620005075760008415620004ee5750858301515b600019600386901b1c1916600185901b17855562000492565b600085815260208120601f198616915b82811015620005385788860151825594840194600190910190840162000517565b5085821015620005575787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b615f5d80620005776000396000f3fe6080604052600436106103ce5760003560e01c80636954f3e5116101fd578063a6ba55c711610118578063d1239730116100ab578063dd8d74d81161007a578063dd8d74d814610b47578063e985e9c514610b67578063ebe6e6f214610bb0578063f2fde38b14610bc3578063fa07ce1d14610be357600080fd5b8063d123973014610aee578063d5abeb0114610b08578063d7224ba014610b1e578063dbde06aa14610b3457600080fd5b8063bbaac02f116100e7578063bbaac02f14610a7b578063c1dfa0bb14610a9b578063c87b56dd14610abb578063ce6df2b914610adb57600080fd5b8063a6ba55c7146109ea578063ac2b697314610a25578063add5a4fa14610a3b578063b88d4fde14610a5b57600080fd5b80638da5cb5b11610190578063a035b1fe1161015f578063a035b1fe14610971578063a071bf1314610987578063a22cb465146109b4578063a4331d2d146109d457600080fd5b80638da5cb5b146108db5780639231ab2a146108f957806395d89b4114610946578063a023cf691461095b57600080fd5b8063715018a6116101cc578063715018a6146108875780637a6f5c681461089c5780637d55094d146108b15780638cc54e7f146108c657600080fd5b80636954f3e5146108125780636c0360eb146108325780636eb604e01461084757806370a082311461086757600080fd5b80632d20fb60116102ed57806352171660116102805780636218186d1161024f5780636218186d146107ac5780636352211e146107bf5780636763e114146107df57806367717e2a146107f257600080fd5b8063521716601461074457806355a63bf41461075757806355f804b3146107775780635bc020bc1461079757600080fd5b806342842e0e116102bc57806342842e0e146106b55780634d0854eb146106d55780634f6ccce714610705578063518302271461072557600080fd5b80632d20fb601461064a5780632f745c591461066a57806333e614131461068a5780633ccfd60b146106a057600080fd5b8063177ab6c71161036557806323b872dd1161033457806323b872dd146105c6578063295871c3146105e65780632a55205a146106065780632cfac6ec1461063457600080fd5b8063177ab6c71461053157806318160ddd1461056157806318890b991461057657806318c2c7be146105a657600080fd5b8063095ea7b3116103a1578063095ea7b3146104845780630c56f187146104a457806311783b4f146104c8578063150b7a02146104f857600080fd5b806301ffc9a7146103d357806302fa7c471461040857806306fdde031461042a578063081812fc1461044c575b600080fd5b3480156103df57600080fd5b506103f36103ee36600461537e565b610c03565b60405190151581526020015b60405180910390f35b34801561041457600080fd5b506104286104233660046153b0565b610c23565b005b34801561043657600080fd5b5061043f610c39565b6040516103ff9190615445565b34801561045857600080fd5b5061046c610467366004615458565b610ccb565b6040516001600160a01b0390911681526020016103ff565b34801561049057600080fd5b5061042861049f366004615471565b610d5b565b3480156104b057600080fd5b506104ba601d5481565b6040519081526020016103ff565b3480156104d457600080fd5b506103f36104e3366004615458565b60226020526000908152604090205460ff1681565b34801561050457600080fd5b50610518610513366004615552565b610e72565b6040516001600160e01b031990911681526020016103ff565b34801561053d57600080fd5b506103f361054c366004615458565b60256020526000908152604090205460ff1681565b34801561056d57600080fd5b506000546104ba565b34801561058257600080fd5b506103f3610591366004615458565b60216020526000908152604090205460ff1681565b3480156105b257600080fd5b506104286105c1366004615458565b610e83565b3480156105d257600080fd5b506104286105e13660046155bd565b610e90565b3480156105f257600080fd5b50610428610601366004615458565b610e9b565b34801561061257600080fd5b506106266106213660046155fe565b610ea8565b6040516103ff929190615620565b34801561064057600080fd5b506104ba601a5481565b34801561065657600080fd5b50610428610665366004615458565b610f56565b34801561067657600080fd5b506104ba610685366004615471565b610fc6565b34801561069657600080fd5b506104ba601c5481565b3480156106ac57600080fd5b50610428611120565b3480156106c157600080fd5b506104286106d03660046155bd565b611209565b3480156106e157600080fd5b506103f36106f0366004615458565b60236020526000908152604090205460ff1681565b34801561071157600080fd5b506104ba610720366004615458565b611224565b34801561073157600080fd5b50601f546103f390610100900460ff1681565b610428610752366004615471565b611286565b34801561076357600080fd5b50610428610772366004615458565b61145d565b34801561078357600080fd5b50610428610792366004615639565b61146a565b3480156107a357600080fd5b5061042861147f565b6104286107ba3660046156aa565b6114a4565b3480156107cb57600080fd5b5061046c6107da366004615458565b6116eb565b6104286107ed366004615471565b6116fd565b3480156107fe57600080fd5b506104ba61080d366004615733565b611be7565b34801561081e57600080fd5b5061042861082d3660046157ae565b611c22565b34801561083e57600080fd5b5061043f611f71565b34801561085357600080fd5b50610428610862366004615458565b611fff565b34801561087357600080fd5b506104ba610882366004615843565b612236565b34801561089357600080fd5b506104286122c7565b3480156108a857600080fd5b506104286122db565b3480156108bd57600080fd5b5061042861247b565b3480156108d257600080fd5b5061043f612497565b3480156108e757600080fd5b506009546001600160a01b031661046c565b34801561090557600080fd5b50610919610914366004615458565b6124a4565b6040805182516001600160a01b031681526020928301516001600160401b031692810192909252016103ff565b34801561095257600080fd5b5061043f6124c1565b34801561096757600080fd5b506104ba60175481565b34801561097d57600080fd5b506104ba60165481565b34801561099357600080fd5b506109a76109a2366004615843565b6124d0565b6040516103ff9190615860565b3480156109c057600080fd5b506104286109cf3660046158a4565b6125bb565b3480156109e057600080fd5b506104ba601e5481565b3480156109f657600080fd5b506103f3610a053660046158d7565b805160208183018101805160248252928201919093012091525460ff1681565b348015610a3157600080fd5b506104ba601b5481565b348015610a4757600080fd5b50610428610a56366004615471565b61267f565b348015610a6757600080fd5b50610428610a76366004615552565b6126f2565b348015610a8757600080fd5b50610428610a96366004615639565b61272b565b348015610aa757600080fd5b50610428610ab6366004615458565b612740565b348015610ac757600080fd5b5061043f610ad6366004615458565b61291b565b610428610ae9366004615471565b612a68565b348015610afa57600080fd5b50601f546103f39060ff1681565b348015610b1457600080fd5b506104ba60195481565b348015610b2a57600080fd5b506104ba60185481565b610428610b423660046156aa565b612b92565b348015610b5357600080fd5b506103f3610b6236600461590b565b612ea5565b348015610b7357600080fd5b506103f3610b82366004615951565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b610428610bbe366004615471565b612f20565b348015610bcf57600080fd5b50610428610bde366004615843565b61333e565b348015610bef57600080fd5b50610428610bfe366004615843565b6133b7565b6000610c0e82614293565b80610c1d5750610c1d826142fe565b92915050565b610c2b614323565b610c35828261437d565b5050565b606060018054610c489061597f565b80601f0160208091040260200160405190810160405280929190818152602001828054610c749061597f565b8015610cc15780601f10610c9657610100808354040283529160200191610cc1565b820191906000526020600020905b815481529060010190602001808311610ca457829003601f168201915b5050505050905090565b6000610cd8826000541190565b610d3f5760405162461bcd60e51b815260206004820152602d60248201527f455243373231413a20617070726f76656420717565727920666f72206e6f6e6560448201526c3c34b9ba32b73a103a37b5b2b760991b60648201526084015b60405180910390fd5b506000908152600560205260409020546001600160a01b031690565b6000610d66826116eb565b9050806001600160a01b0316836001600160a01b031603610dd45760405162461bcd60e51b815260206004820152602260248201527f455243373231413a20617070726f76616c20746f2063757272656e74206f776e60448201526132b960f11b6064820152608401610d36565b336001600160a01b0382161480610df05750610df08133610b82565b610e625760405162461bcd60e51b815260206004820152603960248201527f455243373231413a20617070726f76652063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f76656420666f7220616c6c000000000000006064820152608401610d36565b610e6d83838361447a565b505050565b630a85bd0160e11b5b949350505050565b610e8b614323565b601b55565b610e6d8383836144d6565b610ea3614323565b601d55565b60008281526008602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092528291610f1d5750604080518082019091526007546001600160a01b0381168252600160a01b90046001600160601b031660208201525b602081015160009061271090610f3c906001600160601b0316876159cf565b610f4691906159fc565b91519350909150505b9250929050565b610f5e614323565b6002600a5403610fb05760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d36565b6002600a55610fbe816147b6565b506001600a55565b6000610fd183612236565b821061102a5760405162461bcd60e51b815260206004820152602260248201527f455243373231413a206f776e657220696e646578206f7574206f6620626f756e604482015261647360f01b6064820152608401610d36565b600080549080805b838110156110c0576000818152600360209081526040918290208251808401909352546001600160a01b038116808452600160a01b9091046001600160401b0316918301919091521561108457805192505b876001600160a01b0316836001600160a01b0316036110b7578684036110b057509350610c1d92505050565b6001909301925b50600101611032565b5060405162461bcd60e51b815260206004820152602e60248201527f455243373231413a20756e61626c6520746f2067657420746f6b656e206f662060448201526d0deeedccae440c4f240d2dcc8caf60931b6064820152608401610d36565b611128614323565b6002600a540361117a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d36565b6002600a55604051600090339047908381818185875af1925050503d80600081146111c1576040519150601f19603f3d011682016040523d82523d6000602084013e6111c6565b606091505b5050905080610fbe5760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b6044820152606401610d36565b610e6d838383604051806020016040528060008152506126f2565b6000805482106112825760405162461bcd60e51b815260206004820152602360248201527f455243373231413a20676c6f62616c20696e646578206f7574206f6620626f756044820152626e647360e81b6064820152608401610d36565b5090565b601754601f5460ff166112ab5760405162461bcd60e51b8152600401610d3690615a10565b601d54601c54601b54601a546019546112c49190615a37565b6112ce9190615a37565b6112d89190615a37565b6112e29190615a37565b6112ed906001615a4a565b826112f760005490565b6113019190615a4a565b1061131e5760405162461bcd60e51b8152600401610d3690615a5d565b601e5433600090815260208052604090205461133b908490615a4a565b11156113595760405162461bcd60e51b8152600401610d3690615a86565b61136381836159cf565b3410156113825760405162461bcd60e51b8152600401610d3690615ab3565b60005461138f308461494a565b60005b83811015611456576001600160a01b0385166000908152600c602052604081206002018054600192906113c6908490615a4a565b90915550506001600160a01b0385166000908152600c602052604090206113ed9083614964565b50600b546113fb9042615a4a565b6000838152600d60209081526040808320600181019490945542909355600e90522080546001600160a01b0319166001600160a01b0387161790558161144081615ae0565b925050808061144e90615ae0565b915050611392565b5050505050565b611465614323565b601c55565b611472614323565b6015610e6d828483615b3f565b611487614323565b601f805461ff001981166101009182900460ff1615909102179055565b601654601f5460ff166114c95760405162461bcd60e51b8152600401610d3690615a10565b601e543360009081526020805260409020546114e6908790615a4a565b11156115045760405162461bcd60e51b8152600401610d3690615a86565b601b54601a546019546115179190615a37565b6115219190615a37565b61152c906001615a4a565b8561153660005490565b6115409190615a4a565b1061155d5760405162461bcd60e51b8152600401610d3690615a5d565b61156781866159cf565b3410156115865760405162461bcd60e51b8152600401610d3690615ab3565b6115908383612ea5565b6115dc5760405162461bcd60e51b815260206004820152601b60248201527f506c65617365206d696e74207468726f756768207765627369746500000000006044820152606401610d36565b6024846040516115ec9190615bfe565b9081526040519081900360200190205460ff161561163a5760405162461bcd60e51b815260206004820152600b60248201526a12185cda081c995d5cd95960aa1b6044820152606401610d36565b8261164733600187611be7565b146116825760405162461bcd60e51b815260206004820152600b60248201526a12185cda0819985a5b195960aa1b6044820152606401610d36565b336000908152602080526040812080548792906116a0908490615a4a565b9250508190555060016024856040516116b99190615bfe565b908152604051908190036020019020805491151560ff199092169190911790556116e3868661494a565b505050505050565b60006116f682614977565b5192915050565b601754601f54600090839060ff166117275760405162461bcd60e51b8152600401610d3690615a10565b6010546040516394b6e75160e01b81526000916001600160a01b0316906394b6e7519061175b903390600290600401615620565b600060405180830381865afa158015611778573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117a09190810190615c1a565b6013546040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156117ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118129190615c9f565b118061181f575060008151115b61183b5760405162461bcd60e51b8152600401610d3690615cb8565b6013546040516370a0823160e01b81523360048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190615c9f565b905060005b8181101561199857601354604051632f745c5960e01b81526000916001600160a01b031690632f745c59906118e89033908690600401615620565b602060405180830381865afa158015611905573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119299190615c9f565b60008181526025602052604090205490915060ff1615801561194b5750600085115b15611985576000818152602560205260409020805460ff191660011790558561197381615ae0565b965050848061198190615cfb565b9550505b508061199081615ae0565b9150506118ad565b5060005b8251811015611a355760008382815181106119b9576119b9615d12565b6020908102919091018101516000818152602590925260409091205490915060ff161580156119e85750600085115b15611a22576000818152602560205260409020805460ff1916600117905585611a1081615ae0565b9650508480611a1e90615cfb565b9550505b5080611a2d81615ae0565b91505061199c565b50601c54601a54601954611a499190615a37565b611a539190615a37565b611a5e906001615a4a565b84611a6860005490565b611a729190615a4a565b10611a8f5760405162461bcd60e51b8152600401610d3690615a5d565b611a9985856159cf565b341015611ab85760405162461bcd60e51b8152600401610d3690615ab3565b60008411611b085760405162461bcd60e51b815260206004820152601e60248201527f596f752068617665207573656420616c6c20796f7572206d7574616e747300006044820152606401610d36565b600054611b15308661494a565b60005b85811015611bdc576001600160a01b0389166000908152600c60205260408120600201805460019290611b4c908490615a4a565b90915550506001600160a01b0389166000908152600c60205260409020611b739083614964565b50600b54611b819042615a4a565b6000838152600d60209081526040808320600181019490945542909355600e90522080546001600160a01b0319166001600160a01b038b1617905581611bc681615ae0565b9250508080611bd490615ae0565b915050611b18565b505050505050505050565b60008084848430604051602001611c019493929190615d28565b60408051808303601f19018152919052805160209091012095945050505050565b6040516370a0823160e01b815233600482015260019030906370a0823190602401602060405180830381865afa158015611c60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c849190615c9f565b1015611cce5760405162461bcd60e51b8152602060048201526019602482015278796f7520646f6e74206861766520656e6f756768206e66747360381b6044820152606401610d36565b60005b8151811015610c3557336001600160a01b0316306001600160a01b0316636352211e848481518110611d0557611d05615d12565b60200260200101516040518263ffffffff1660e01b8152600401611d2b91815260200190565b602060405180830381865afa158015611d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6c9190615d72565b6001600160a01b031614611dbc5760405162461bcd60e51b8152602060048201526017602482015276796f7520646f6e2774206f776e2074686973206e66742160481b6044820152606401610d36565b336000908152600c60205260408120600201805460019290611ddf908490615a4a565b92505081905550611e1d828281518110611dfb57611dfb615d12565b602090810291909101810151336000908152600c909252604090912090614964565b50600b54611e2b9042615a4a565b600d6000848481518110611e4157611e41615d12565b602002602001015181526020019081526020016000206001018190555042600d6000848481518110611e7557611e75615d12565b602002602001015181526020019081526020016000206000018190555033600e6000848481518110611ea957611ea9615d12565b6020026020010151815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550306001600160a01b03166323b872dd3330858581518110611f0657611f06615d12565b60200260200101516040518463ffffffff1660e01b8152600401611f2c93929190615d8f565b600060405180830381600087803b158015611f4657600080fd5b505af1158015611f5a573d6000803e3d6000fd5b505050508080611f6990615ae0565b915050611cd1565b60158054611f7e9061597f565b80601f0160208091040260200160405190810160405280929190818152602001828054611faa9061597f565b8015611ff75780601f10611fcc57610100808354040283529160200191611ff7565b820191906000526020600020905b815481529060010190602001808311611fda57829003601f168201915b505050505081565b6040516370a0823160e01b815233600482015260019030906370a0823190602401602060405180830381865afa15801561203d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120619190615c9f565b10156120ab5760405162461bcd60e51b8152602060048201526019602482015278796f7520646f6e74206861766520656e6f756768206e66747360381b6044820152606401610d36565b6040516331a9108f60e11b81526004810182905233903090636352211e90602401602060405180830381865afa1580156120e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061210d9190615d72565b6001600160a01b03161461215d5760405162461bcd60e51b8152602060048201526017602482015276796f7520646f6e2774206f776e2074686973206e66742160481b6044820152606401610d36565b336000908152600c60205260408120600201805460019290612180908490615a4a565b9091555050336000908152600c6020526040902061219e9082614964565b50600b546121ac9042615a4a565b6000828152600d60209081526040808320600181019490945542909355600e905281902080546001600160a01b0319163390811790915590516323b872dd60e01b815230916323b872dd91612208919084908690600401615d8f565b600060405180830381600087803b15801561222257600080fd5b505af1158015611456573d6000803e3d6000fd5b60006001600160a01b0382166122a25760405162461bcd60e51b815260206004820152602b60248201527f455243373231413a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b6064820152608401610d36565b506001600160a01b03166000908152600460205260409020546001600160801b031690565b6122cf614323565b6122d96000614a4d565b565b336000908152600c60205260409020600201546123345760405162461bcd60e51b81526020600482015260176024820152761e5bdd481a185d99481b9bc81b999d1cc81cdd185ad959604a1b6044820152606401610d36565b336000908152600c6020526040812061234c90614a9f565b905060005b81811015610c3557336000908152600c602052604081206123729082614aa9565b6000818152600e60205260409020549091506001600160a01b0316331480156123ac57506000818152600d60205260409020600101544210155b1561246857336000908152600c602052604081206002018054600192906123d4908490615a37565b90915550506000818152600e6020908152604080832080546001600160a01b0319169055338352600c909152902061240c8183614ab5565b506040516323b872dd60e01b815230906323b872dd9061243490839033908790600401615d8f565b600060405180830381600087803b15801561244e57600080fd5b505af1158015612462573d6000803e3d6000fd5b50505050505b508061247381615ae0565b915050612351565b612483614323565b601f805460ff19811660ff90911615179055565b60148054611f7e9061597f565b6040805180820190915260008082526020820152610c1d82614977565b606060028054610c489061597f565b6001600160a01b0381166000908152600c60205260408120606091906124f590614a9f565b6001600160401b0381111561250c5761250c61549d565b604051908082528060200260200182016040528015612535578160200160208202803683370190505b50905060005b6001600160a01b0384166000908152600c6020526040902061255c90614a9f565b8110156125b4576001600160a01b0384166000908152600c602052604090206125859082614aa9565b82828151811061259757612597615d12565b6020908102919091010152806125ac81615ae0565b91505061253b565b5092915050565b336001600160a01b038316036126135760405162461bcd60e51b815260206004820152601a60248201527f455243373231413a20617070726f766520746f2063616c6c65720000000000006044820152606401610d36565b3360008181526006602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b612687614323565b601f5460ff166126a95760405162461bcd60e51b8152600401610d3690615a10565b6019546126b7906001615a4a565b816126c160005490565b6126cb9190615a4a565b106126e85760405162461bcd60e51b8152600401610d3690615a5d565b610c35828261494a565b6126fd8484846144d6565b61270984848484614ac1565b6127255760405162461bcd60e51b8152600401610d3690615db3565b50505050565b612733614323565b6014610e6d828483615b3f565b6000818152600d60205260409020600101544210156127ab5760405162461bcd60e51b815260206004820152602160248201527f796f7572206e6674206973206c6f636b656420666f72207769746864726177616044820152601b60fa1b6064820152608401610d36565b336000908152600c60205260409020600201546128045760405162461bcd60e51b81526020600482015260176024820152761e5bdd481a185d99481b9bc81b999d1cc81cdd185ad959604a1b6044820152606401610d36565b6000818152600e60205260409020546001600160a01b0316331461286a5760405162461bcd60e51b815260206004820152601960248201527f796f7520646f6e2774206f776e207468697320746f6b656e21000000000000006044820152606401610d36565b336000908152600c6020526040812060020180546001929061288d908490615a37565b90915550506000818152600e6020908152604080832080546001600160a01b0319169055338352600c90915290206128c58183614ab5565b506040516323b872dd60e01b815230906323b872dd906128ed90839033908790600401615d8f565b600060405180830381600087803b15801561290757600080fd5b505af11580156116e3573d6000803e3d6000fd5b6060612928826000541190565b61296a5760405162461bcd60e51b815260206004820152601360248201527212dbdb99c8191bd95cc81b9bdd08195e1a5cdd606a1b6044820152606401610d36565b601f54610100900460ff16156129d657601580546129879061597f565b90506000036129a55760405180602001604052806000815250610c1d565b60156129b083614bbf565b6040516020016129c1929190615e06565b60405160208183030381529060405292915050565b601480546129e39061597f565b80601f0160208091040260200160405190810160405280929190818152602001828054612a0f9061597f565b8015612a5c5780601f10612a3157610100808354040283529160200191612a5c565b820191906000526020600020905b815481529060010190602001808311612a3f57829003601f168201915b50505050509050919050565b601654601f5460ff16612a8d5760405162461bcd60e51b8152600401610d3690615a10565b601d54601c54601b54601a54601954612aa69190615a37565b612ab09190615a37565b612aba9190615a37565b612ac49190615a37565b612acf906001615a4a565b82612ad960005490565b612ae39190615a4a565b10612b005760405162461bcd60e51b8152600401610d3690615a5d565b601e54336000908152602080526040902054612b1d908490615a4a565b1115612b3b5760405162461bcd60e51b8152600401610d3690615a86565b612b4581836159cf565b341015612b645760405162461bcd60e51b8152600401610d3690615ab3565b33600090815260208052604081208054849290612b82908490615a4a565b90915550610e6d9050838361494a565b601754601f5460ff16612bb75760405162461bcd60e51b8152600401610d3690615a10565b601e54336000908152602080526040902054612bd4908790615a4a565b1115612bf25760405162461bcd60e51b8152600401610d3690615a86565b601b54601a54601954612c059190615a37565b612c0f9190615a37565b612c1a906001615a4a565b85612c2460005490565b612c2e9190615a4a565b10612c4b5760405162461bcd60e51b8152600401610d3690615a5d565b612c5581866159cf565b341015612c745760405162461bcd60e51b8152600401610d3690615ab3565b612c7e8383612ea5565b612cca5760405162461bcd60e51b815260206004820152601b60248201527f506c65617365206d696e74207468726f756768207765627369746500000000006044820152606401610d36565b602484604051612cda9190615bfe565b9081526040519081900360200190205460ff1615612d285760405162461bcd60e51b815260206004820152600b60248201526a12185cda081c995d5cd95960aa1b6044820152606401610d36565b82612d3533600187611be7565b14612d705760405162461bcd60e51b815260206004820152600b60248201526a12185cda0819985a5b195960aa1b6044820152606401610d36565b33600090815260208052604081208054879290612d8e908490615a4a565b925050819055506001602485604051612da79190615bfe565b908152604051908190036020019020805491151560ff19909216919091179055600054612dd4308761494a565b60005b86811015612e9b576001600160a01b0388166000908152600c60205260408120600201805460019290612e0b908490615a4a565b90915550506001600160a01b0388166000908152600c60205260409020612e329083614964565b50600b54612e409042615a4a565b6000838152600d60209081526040808320600181019490945542909355600e90522080546001600160a01b0319166001600160a01b038a1617905581612e8581615ae0565b9250508080612e9390615ae0565b915050612dd7565b5050505050505050565b6000612f0882612f02856040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b90614cbf565b600f546001600160a01b039182169116149392505050565b601654601f54600090839060ff16612f4a5760405162461bcd60e51b8152600401610d3690615a10565b6010546040516394b6e75160e01b81526000916001600160a01b0316906394b6e75190612f7e903390600290600401615620565b600060405180830381865afa158015612f9b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612fc39190810190615c1a565b6013546040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613011573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130359190615c9f565b1180613042575060008151115b61305e5760405162461bcd60e51b8152600401610d3690615cb8565b6013546040516370a0823160e01b81523360048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156130a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130cb9190615c9f565b905060005b818110156131bb57601354604051632f745c5960e01b81526000916001600160a01b031690632f745c599061310b9033908690600401615620565b602060405180830381865afa158015613128573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061314c9190615c9f565b60008181526025602052604090205490915060ff1615801561316e5750600085115b156131a8576000818152602560205260409020805460ff191660011790558561319681615ae0565b96505084806131a490615cfb565b9550505b50806131b381615ae0565b9150506130d0565b5060005b82518110156132585760008382815181106131dc576131dc615d12565b6020908102919091018101516000818152602590925260409091205490915060ff1615801561320b5750600085115b15613245576000818152602560205260409020805460ff191660011790558561323381615ae0565b965050848061324190615cfb565b9550505b508061325081615ae0565b9150506131bf565b50601c54601a5460195461326c9190615a37565b6132769190615a37565b613281906001615a4a565b8461328b60005490565b6132959190615a4a565b106132b25760405162461bcd60e51b8152600401610d3690615a5d565b6132bc85856159cf565b3410156132db5760405162461bcd60e51b8152600401610d3690615ab3565b6000841161332b5760405162461bcd60e51b815260206004820152601e60248201527f596f752068617665207573656420616c6c20796f7572206d7574616e747300006044820152606401610d36565b613335878561494a565b50505050505050565b613346614323565b6001600160a01b0381166133ab5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d36565b6133b481614a4d565b50565b601f5460009060ff166133dc5760405162461bcd60e51b8152600401610d3690615a10565b6010546040516394b6e75160e01b81526000916001600160a01b0316906394b6e7519061340f9033908590600401615620565b600060405180830381865afa15801561342c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526134549190810190615c1a565b6010546040516394b6e75160e01b81529192506000916001600160a01b03909116906394b6e7519061348d903390600190600401615620565b600060405180830381865afa1580156134aa573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526134d29190810190615c1a565b6010546040516394b6e75160e01b81529192506000916001600160a01b03909116906394b6e7519061350b903390600290600401615620565b600060405180830381865afa158015613528573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526135509190810190615c1a565b6011546040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561359e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c29190615c9f565b11806135cf575060008351115b6136335760405162461bcd60e51b815260206004820152602f60248201527f4d7573742068617665206d6f7265207468616e20312053757072656d65204b6f60448201526e1b99c81d1bc8199c9959481b5a5b9d608a1b6064820152608401610d36565b6012546040516370a0823160e01b81523360048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561367c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a09190615c9f565b118061371657506013546040516370a0823160e01b81523360048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156136f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137149190615c9f565b115b80613722575060008251115b8061372e575060008151115b61378c5760405162461bcd60e51b815260206004820152602960248201527f4d7573742068617665206d6f7265207468616e20312042616e616e6120746f20604482015268199c9959481b5a5b9d60ba1b6064820152608401610d36565b82516011546040516370a0823160e01b8152336004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa1580156137d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137fc9190615c9f565b6138069190615a4a565b6001600160401b0381111561381d5761381d61549d565b604051908082528060200260200182016040528015613846578160200160208202803683370190505b5083516012546040516370a0823160e01b81523360048201529293506000926001600160a01b03909116906370a0823190602401602060405180830381865afa158015613897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138bb9190615c9f565b6138c59190615a4a565b6001600160401b038111156138dc576138dc61549d565b604051908082528060200260200182016040528015613905578160200160208202803683370190505b5083516013546040516370a0823160e01b81523360048201529293506000926001600160a01b03909116906370a0823190602401602060405180830381865afa158015613956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061397a9190615c9f565b6139849190615a4a565b6001600160401b0381111561399b5761399b61549d565b6040519080825280602002602001820160405280156139c4578160200160208202803683370190505b506011546040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613a13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a379190615c9f565b905060005b6011546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613a84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aa89190615c9f565b811015613b5657601154604051632f745c5960e01b81526000916001600160a01b031690632f745c5990613ae29033908690600401615620565b602060405180830381865afa158015613aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b239190615c9f565b905080868381518110613b3857613b38615d12565b60209081029190910101525080613b4e81615ae0565b915050613a3c565b5060005b8751811015613bba57878181518110613b7557613b75615d12565b6020026020010151858381518110613b8f57613b8f615d12565b602090810291909101015281613ba481615ae0565b9250508080613bb290615ae0565b915050613b5a565b506012546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c279190615c9f565b905060005b6012546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c989190615c9f565b811015613d4657601254604051632f745c5960e01b81526000916001600160a01b031690632f745c5990613cd29033908690600401615620565b602060405180830381865afa158015613cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d139190615c9f565b905080858381518110613d2857613d28615d12565b60209081029190910101525080613d3e81615ae0565b915050613c2c565b5060005b8651811015613daa57868181518110613d6557613d65615d12565b6020026020010151848381518110613d7f57613d7f615d12565b602090810291909101015281613d9481615ae0565b9250508080613da290615ae0565b915050613d4a565b506013546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613df3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e179190615c9f565b905060005b6013546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e889190615c9f565b811015613f3657601354604051632f745c5960e01b81526000916001600160a01b031690632f745c5990613ec29033908690600401615620565b602060405180830381865afa158015613edf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f039190615c9f565b905080848381518110613f1857613f18615d12565b60209081029190910101525080613f2e81615ae0565b915050613e1c565b5060005b8551811015613f9a57858181518110613f5557613f55615d12565b6020026020010151838381518110613f6f57613f6f615d12565b602090810291909101015281613f8481615ae0565b9250508080613f9290615ae0565b915050613f3a565b5060005b845181101561414b576000858281518110613fbb57613fbb615d12565b6020026020010151905060005b855181101561407d576000868281518110613fe557613fe5615d12565b6020908102919091018101516000858152602190925260409091205490915060ff16158015614023575060008181526022602052604090205460ff16155b1561406a5760008181526022602090815260408083208054600160ff19918216811790925587855260219093529220805490911690911790558b61406681615ae0565b9c50505b508061407581615ae0565b915050613fc8565b5060005b845181101561413657600085828151811061409e5761409e615d12565b6020908102919091018101516000858152602190925260409091205490915060ff161580156140dc575060008181526023602052604090205460ff16155b156141235760008181526023602090815260408083208054600160ff19918216811790925587855260219093529220805490911690911790558b61411f81615ae0565b9c50505b508061412e81615ae0565b915050614081565b5050808061414390615ae0565b915050613f9e565b50600088116141b25760405162461bcd60e51b815260206004820152602d60248201527f596f7520646f6e2774206861766520617661696c61626c65206b6f6e6720616e60448201526c32103130b730b730903830b4b960991b6064820152608401610d36565b6000546141bf308a61494a565b60005b89811015614286576001600160a01b038b166000908152600c602052604081206002018054600192906141f6908490615a4a565b90915550506001600160a01b038b166000908152600c6020526040902061421d9083614964565b50600b5461422b9042615a4a565b6000838152600d60209081526040808320600181019490945542909355600e90522080546001600160a01b0319166001600160a01b038d161790558161427081615ae0565b925050808061427e90615ae0565b9150506141c2565b5050505050505050505050565b60006001600160e01b031982166380ac58cd60e01b14806142c457506001600160e01b03198216635b5e139f60e01b145b806142df57506001600160e01b0319821663780e9d6360e01b145b80610c1d57506301ffc9a760e01b6001600160e01b0319831614610c1d565b60006001600160e01b0319821663152a902d60e11b1480610c1d5750610c1d82614293565b6009546001600160a01b031633146122d95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d36565b6127106001600160601b03821611156143eb5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610d36565b6001600160a01b0382166144415760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610d36565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600755565b60008281526005602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60006144e182614977565b80519091506000906001600160a01b0316336001600160a01b0316148061451857503361450d84610ccb565b6001600160a01b0316145b8061452a5750815161452a9033610b82565b9050806145945760405162461bcd60e51b815260206004820152603260248201527f455243373231413a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b6064820152608401610d36565b846001600160a01b031682600001516001600160a01b0316146146085760405162461bcd60e51b815260206004820152602660248201527f455243373231413a207472616e736665722066726f6d20696e636f72726563746044820152651037bbb732b960d11b6064820152608401610d36565b6001600160a01b03841661466c5760405162461bcd60e51b815260206004820152602560248201527f455243373231413a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b6064820152608401610d36565b61467c600084846000015161447a565b6001600160a01b03858116600090815260046020908152604080832080546001600160801b03198082166001600160801b03928316600019018316179092558986168086528386208054938416938316600190810190931693909317909255888552600390935281842080546001600160e01b031916909117600160a01b426001600160401b03160217905590860180835291205490911661476f57614723816000541190565b1561476f57825160008281526003602090815260409091208054918601516001600160401b0316600160a01b026001600160e01b03199092166001600160a01b03909316929092171790555b5082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611456565b806000036148065760405162461bcd60e51b815260206004820152601860248201527f7175616e74697479206d757374206265206e6f6e7a65726f00000000000000006044820152606401610d36565b60005460000361484f5760405162461bcd60e51b81526020600482015260146024820152731b9bc81d1bdad95b9cc81b5a5b9d1959081e595d60621b6044820152606401610d36565b60185460005481106148a35760405162461bcd60e51b815260206004820152601c60248201527f616c6c206f776e657273686970732068617665206265656e20736574000000006044820152606401610d36565b60005482820160001981019110156148be5750600054600019015b815b81811161493f576000818152600360205260409020546001600160a01b03166149375760006148ee82614977565b80516000848152600360209081526040909120805491909301516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b0390921691909117179055505b6001016148c0565b506001016018555050565b610c35828260405180602001604052806000815250614ce3565b60006149708383614cf0565b9392505050565b6040805180820190915260008082526020820152614996826000541190565b6149f55760405162461bcd60e51b815260206004820152602a60248201527f455243373231413a206f776e657220717565727920666f72206e6f6e657869736044820152693a32b73a103a37b5b2b760b11b6064820152608401610d36565b815b6000818152600360209081526040918290208251808401909352546001600160a01b038116808452600160a01b9091046001600160401b03169183019190915215614a43579392505050565b50600019016149f7565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000610c1d825490565b60006149708383614d3f565b60006149708383614d69565b60006001600160a01b0384163b15614bb757604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290614b05903390899088908890600401615e8d565b6020604051808303816000875af1925050508015614b40575060408051601f3d908101601f19168201909252614b3d91810190615eca565b60015b614b9d573d808015614b6e576040519150601f19603f3d011682016040523d82523d6000602084013e614b73565b606091505b508051600003614b955760405162461bcd60e51b8152600401610d3690615db3565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610e7b565b506001610e7b565b606081600003614be65750506040805180820190915260018152600360fc1b602082015290565b8160005b8115614c105780614bfa81615ae0565b9150614c099050600a836159fc565b9150614bea565b6000816001600160401b03811115614c2a57614c2a61549d565b6040519080825280601f01601f191660200182016040528015614c54576020820181803683370190505b5090505b8415610e7b57614c69600183615a37565b9150614c76600a86615ee7565b614c81906030615a4a565b60f81b818381518110614c9657614c96615d12565b60200101906001600160f81b031916908160001a905350614cb8600a866159fc565b9450614c58565b6000806000614cce8585614e5c565b91509150614cdb81614ec7565b509392505050565b610e6d838383600161507d565b6000818152600183016020526040812054614d3757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610c1d565b506000610c1d565b6000826000018281548110614d5657614d56615d12565b9060005260206000200154905092915050565b60008181526001830160205260408120548015614e52576000614d8d600183615a37565b8554909150600090614da190600190615a37565b9050818114614e06576000866000018281548110614dc157614dc1615d12565b9060005260206000200154905080876000018481548110614de457614de4615d12565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614e1757614e17615efb565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610c1d565b6000915050610c1d565b6000808251604103614e925760208301516040840151606085015160001a614e8687828585615242565b94509450505050610f4f565b8251604003614ebb5760208301516040840151614eb086838361532f565b935093505050610f4f565b50600090506002610f4f565b6000816004811115614edb57614edb615f11565b03614ee35750565b6001816004811115614ef757614ef7615f11565b03614f445760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610d36565b6002816004811115614f5857614f58615f11565b03614fa55760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610d36565b6003816004811115614fb957614fb9615f11565b036150115760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610d36565b600481600481111561502557615025615f11565b036133b45760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610d36565b6000546001600160a01b0385166150e05760405162461bcd60e51b815260206004820152602160248201527f455243373231413a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610d36565b836000036151415760405162461bcd60e51b815260206004820152602860248201527f455243373231413a207175616e74697479206d75737420626520677265617465604482015267072207468616e20360c41b6064820152608401610d36565b6001600160a01b03851660008181526004602090815260408083208054600160801b6001600160801b031982166001600160801b039283168c01831690811782900483168c01909216021790558483526003909152812080546001600160e01b031916909217600160a01b426001600160401b0316021790915581905b858110156152395760405182906001600160a01b038916906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4831561522d576152116000888488614ac1565b61522d5760405162461bcd60e51b8152600401610d3690615db3565b600191820191016151be565b50600055611456565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156152795750600090506003615326565b8460ff16601b1415801561529157508460ff16601c14155b156152a25750600090506004615326565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156152f6573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661531f57600060019250925050615326565b9150600090505b94509492505050565b6000806001600160ff1b0383168161534c60ff86901c601b615a4a565b905061535a87828885615242565b935093505050935093915050565b6001600160e01b0319811681146133b457600080fd5b60006020828403121561539057600080fd5b813561497081615368565b6001600160a01b03811681146133b457600080fd5b600080604083850312156153c357600080fd5b82356153ce8161539b565b915060208301356001600160601b03811681146153ea57600080fd5b809150509250929050565b60005b838110156154105781810151838201526020016153f8565b50506000910152565b600081518084526154318160208601602086016153f5565b601f01601f19169290920160200192915050565b6020815260006149706020830184615419565b60006020828403121561546a57600080fd5b5035919050565b6000806040838503121561548457600080fd5b823561548f8161539b565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156154db576154db61549d565b604052919050565b600082601f8301126154f457600080fd5b81356001600160401b0381111561550d5761550d61549d565b615520601f8201601f19166020016154b3565b81815284602083860101111561553557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561556857600080fd5b84356155738161539b565b935060208501356155838161539b565b92506040850135915060608501356001600160401b038111156155a557600080fd5b6155b1878288016154e3565b91505092959194509250565b6000806000606084860312156155d257600080fd5b83356155dd8161539b565b925060208401356155ed8161539b565b929592945050506040919091013590565b6000806040838503121561561157600080fd5b50508035926020909101359150565b6001600160a01b03929092168252602082015260400190565b6000806020838503121561564c57600080fd5b82356001600160401b038082111561566357600080fd5b818501915085601f83011261567757600080fd5b81358181111561568657600080fd5b86602082850101111561569857600080fd5b60209290920196919550909350505050565b600080600080600060a086880312156156c257600080fd5b85356156cd8161539b565b94506020860135935060408601356001600160401b03808211156156f057600080fd5b6156fc89838a016154e3565b945060608801359350608088013591508082111561571957600080fd5b50615726888289016154e3565b9150509295509295909350565b60008060006060848603121561574857600080fd5b83356157538161539b565b92506020840135915060408401356001600160401b0381111561577557600080fd5b615781868287016154e3565b9150509250925092565b60006001600160401b038211156157a4576157a461549d565b5060051b60200190565b600060208083850312156157c157600080fd5b82356001600160401b038111156157d757600080fd5b8301601f810185136157e857600080fd5b80356157fb6157f68261578b565b6154b3565b81815260059190911b8201830190838101908783111561581a57600080fd5b928401925b828410156158385783358252928401929084019061581f565b979650505050505050565b60006020828403121561585557600080fd5b81356149708161539b565b6020808252825182820181905260009190848201906040850190845b818110156158985783518352928401929184019160010161587c565b50909695505050505050565b600080604083850312156158b757600080fd5b82356158c28161539b565b9150602083013580151581146153ea57600080fd5b6000602082840312156158e957600080fd5b81356001600160401b038111156158ff57600080fd5b610e7b848285016154e3565b6000806040838503121561591e57600080fd5b8235915060208301356001600160401b0381111561593b57600080fd5b615947858286016154e3565b9150509250929050565b6000806040838503121561596457600080fd5b823561596f8161539b565b915060208301356153ea8161539b565b600181811c9082168061599357607f821691505b6020821081036159b357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610c1d57610c1d6159b9565b634e487b7160e01b600052601260045260246000fd5b600082615a0b57615a0b6159e6565b500490565b6020808252600d908201526c135a5b9d08191a5cd8589b1959609a1b604082015260600190565b81810381811115610c1d57610c1d6159b9565b80820180821115610c1d57610c1d6159b9565b6020808252600f908201526e576527726520736f6c64206f75742160881b604082015260600190565b602080825260139082015272151bdbc81b585b9e481c195c881dd85b1b195d606a1b604082015260600190565b60208082526013908201527208ae8d0cae440d2e640dcdee840cadcdeeaced606b1b604082015260600190565b600060018201615af257615af26159b9565b5060010190565b601f821115610e6d57600081815260208120601f850160051c81016020861015615b205750805b601f850160051c820191505b818110156116e357828155600101615b2c565b6001600160401b03831115615b5657615b5661549d565b615b6a83615b64835461597f565b83615af9565b6000601f841160018114615b9e5760008515615b865750838201355b600019600387901b1c1916600186901b178355611456565b600083815260209020601f19861690835b82811015615bcf5786850135825560209485019460019092019101615baf565b5086821015615bec5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008251615c108184602087016153f5565b9190910192915050565b60006020808385031215615c2d57600080fd5b82516001600160401b03811115615c4357600080fd5b8301601f81018513615c5457600080fd5b8051615c626157f68261578b565b81815260059190911b82018301908381019087831115615c8157600080fd5b928401925b8284101561583857835182529284019290840190615c86565b600060208284031215615cb157600080fd5b5051919050565b60208082526023908201527f4d7573742068617665206d6f7265207468616e2031204d7574616e742042616e604082015262616e6160e81b606082015260800190565b600081615d0a57615d0a6159b9565b506000190190565b634e487b7160e01b600052603260045260246000fd5b60006001600160601b0319808760601b1683528560148401528451615d548160348601602089016153f5565b60609490941b16919092016034810191909152604801949350505050565b600060208284031215615d8457600080fd5b81516149708161539b565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208082526033908201527f455243373231413a207472616e7366657220746f206e6f6e204552433732315260408201527232b1b2b4bb32b91034b6b83632b6b2b73a32b960691b606082015260800190565b6000808454615e148161597f565b60018281168015615e2c5760018114615e4157615e70565b60ff1984168752821515830287019450615e70565b8860005260208060002060005b85811015615e675781548a820152908401908201615e4e565b50505082870194505b505050508351615e848183602088016153f5565b01949350505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615ec090830184615419565b9695505050505050565b600060208284031215615edc57600080fd5b815161497081615368565b600082615ef657615ef66159e6565b500690565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052602160045260246000fdfea2646970667358221220059a0e01d0094b9b990e2e5b9b4383a884f97b638ef07bb8e95fb5c5de76253164736f6c6343000811003300000000000000000000000012787526c03d626aac88e6edc4d0fb930d86c631000000000000000000000000f59afe732b2793d541780fd02945228db1fad8ed0000000000000000000000008ace1ec951bc29b98440d1bbca64e6010c9e9e1700000000000000000000000070c7af7a78b5453e4a09376eb2b506ce4e4140e5000000000000000000000000f41f1c3d48bb18b0624a38cadc63f3134a65c23e000000000000000000000000fe67cfa5d71a88f6353036966655d6e65e15bf400000000000000000000000000000000000000000000000000000000000093a80

Deployed Bytecode

0x6080604052600436106103ce5760003560e01c80636954f3e5116101fd578063a6ba55c711610118578063d1239730116100ab578063dd8d74d81161007a578063dd8d74d814610b47578063e985e9c514610b67578063ebe6e6f214610bb0578063f2fde38b14610bc3578063fa07ce1d14610be357600080fd5b8063d123973014610aee578063d5abeb0114610b08578063d7224ba014610b1e578063dbde06aa14610b3457600080fd5b8063bbaac02f116100e7578063bbaac02f14610a7b578063c1dfa0bb14610a9b578063c87b56dd14610abb578063ce6df2b914610adb57600080fd5b8063a6ba55c7146109ea578063ac2b697314610a25578063add5a4fa14610a3b578063b88d4fde14610a5b57600080fd5b80638da5cb5b11610190578063a035b1fe1161015f578063a035b1fe14610971578063a071bf1314610987578063a22cb465146109b4578063a4331d2d146109d457600080fd5b80638da5cb5b146108db5780639231ab2a146108f957806395d89b4114610946578063a023cf691461095b57600080fd5b8063715018a6116101cc578063715018a6146108875780637a6f5c681461089c5780637d55094d146108b15780638cc54e7f146108c657600080fd5b80636954f3e5146108125780636c0360eb146108325780636eb604e01461084757806370a082311461086757600080fd5b80632d20fb60116102ed57806352171660116102805780636218186d1161024f5780636218186d146107ac5780636352211e146107bf5780636763e114146107df57806367717e2a146107f257600080fd5b8063521716601461074457806355a63bf41461075757806355f804b3146107775780635bc020bc1461079757600080fd5b806342842e0e116102bc57806342842e0e146106b55780634d0854eb146106d55780634f6ccce714610705578063518302271461072557600080fd5b80632d20fb601461064a5780632f745c591461066a57806333e614131461068a5780633ccfd60b146106a057600080fd5b8063177ab6c71161036557806323b872dd1161033457806323b872dd146105c6578063295871c3146105e65780632a55205a146106065780632cfac6ec1461063457600080fd5b8063177ab6c71461053157806318160ddd1461056157806318890b991461057657806318c2c7be146105a657600080fd5b8063095ea7b3116103a1578063095ea7b3146104845780630c56f187146104a457806311783b4f146104c8578063150b7a02146104f857600080fd5b806301ffc9a7146103d357806302fa7c471461040857806306fdde031461042a578063081812fc1461044c575b600080fd5b3480156103df57600080fd5b506103f36103ee36600461537e565b610c03565b60405190151581526020015b60405180910390f35b34801561041457600080fd5b506104286104233660046153b0565b610c23565b005b34801561043657600080fd5b5061043f610c39565b6040516103ff9190615445565b34801561045857600080fd5b5061046c610467366004615458565b610ccb565b6040516001600160a01b0390911681526020016103ff565b34801561049057600080fd5b5061042861049f366004615471565b610d5b565b3480156104b057600080fd5b506104ba601d5481565b6040519081526020016103ff565b3480156104d457600080fd5b506103f36104e3366004615458565b60226020526000908152604090205460ff1681565b34801561050457600080fd5b50610518610513366004615552565b610e72565b6040516001600160e01b031990911681526020016103ff565b34801561053d57600080fd5b506103f361054c366004615458565b60256020526000908152604090205460ff1681565b34801561056d57600080fd5b506000546104ba565b34801561058257600080fd5b506103f3610591366004615458565b60216020526000908152604090205460ff1681565b3480156105b257600080fd5b506104286105c1366004615458565b610e83565b3480156105d257600080fd5b506104286105e13660046155bd565b610e90565b3480156105f257600080fd5b50610428610601366004615458565b610e9b565b34801561061257600080fd5b506106266106213660046155fe565b610ea8565b6040516103ff929190615620565b34801561064057600080fd5b506104ba601a5481565b34801561065657600080fd5b50610428610665366004615458565b610f56565b34801561067657600080fd5b506104ba610685366004615471565b610fc6565b34801561069657600080fd5b506104ba601c5481565b3480156106ac57600080fd5b50610428611120565b3480156106c157600080fd5b506104286106d03660046155bd565b611209565b3480156106e157600080fd5b506103f36106f0366004615458565b60236020526000908152604090205460ff1681565b34801561071157600080fd5b506104ba610720366004615458565b611224565b34801561073157600080fd5b50601f546103f390610100900460ff1681565b610428610752366004615471565b611286565b34801561076357600080fd5b50610428610772366004615458565b61145d565b34801561078357600080fd5b50610428610792366004615639565b61146a565b3480156107a357600080fd5b5061042861147f565b6104286107ba3660046156aa565b6114a4565b3480156107cb57600080fd5b5061046c6107da366004615458565b6116eb565b6104286107ed366004615471565b6116fd565b3480156107fe57600080fd5b506104ba61080d366004615733565b611be7565b34801561081e57600080fd5b5061042861082d3660046157ae565b611c22565b34801561083e57600080fd5b5061043f611f71565b34801561085357600080fd5b50610428610862366004615458565b611fff565b34801561087357600080fd5b506104ba610882366004615843565b612236565b34801561089357600080fd5b506104286122c7565b3480156108a857600080fd5b506104286122db565b3480156108bd57600080fd5b5061042861247b565b3480156108d257600080fd5b5061043f612497565b3480156108e757600080fd5b506009546001600160a01b031661046c565b34801561090557600080fd5b50610919610914366004615458565b6124a4565b6040805182516001600160a01b031681526020928301516001600160401b031692810192909252016103ff565b34801561095257600080fd5b5061043f6124c1565b34801561096757600080fd5b506104ba60175481565b34801561097d57600080fd5b506104ba60165481565b34801561099357600080fd5b506109a76109a2366004615843565b6124d0565b6040516103ff9190615860565b3480156109c057600080fd5b506104286109cf3660046158a4565b6125bb565b3480156109e057600080fd5b506104ba601e5481565b3480156109f657600080fd5b506103f3610a053660046158d7565b805160208183018101805160248252928201919093012091525460ff1681565b348015610a3157600080fd5b506104ba601b5481565b348015610a4757600080fd5b50610428610a56366004615471565b61267f565b348015610a6757600080fd5b50610428610a76366004615552565b6126f2565b348015610a8757600080fd5b50610428610a96366004615639565b61272b565b348015610aa757600080fd5b50610428610ab6366004615458565b612740565b348015610ac757600080fd5b5061043f610ad6366004615458565b61291b565b610428610ae9366004615471565b612a68565b348015610afa57600080fd5b50601f546103f39060ff1681565b348015610b1457600080fd5b506104ba60195481565b348015610b2a57600080fd5b506104ba60185481565b610428610b423660046156aa565b612b92565b348015610b5357600080fd5b506103f3610b6236600461590b565b612ea5565b348015610b7357600080fd5b506103f3610b82366004615951565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b610428610bbe366004615471565b612f20565b348015610bcf57600080fd5b50610428610bde366004615843565b61333e565b348015610bef57600080fd5b50610428610bfe366004615843565b6133b7565b6000610c0e82614293565b80610c1d5750610c1d826142fe565b92915050565b610c2b614323565b610c35828261437d565b5050565b606060018054610c489061597f565b80601f0160208091040260200160405190810160405280929190818152602001828054610c749061597f565b8015610cc15780601f10610c9657610100808354040283529160200191610cc1565b820191906000526020600020905b815481529060010190602001808311610ca457829003601f168201915b5050505050905090565b6000610cd8826000541190565b610d3f5760405162461bcd60e51b815260206004820152602d60248201527f455243373231413a20617070726f76656420717565727920666f72206e6f6e6560448201526c3c34b9ba32b73a103a37b5b2b760991b60648201526084015b60405180910390fd5b506000908152600560205260409020546001600160a01b031690565b6000610d66826116eb565b9050806001600160a01b0316836001600160a01b031603610dd45760405162461bcd60e51b815260206004820152602260248201527f455243373231413a20617070726f76616c20746f2063757272656e74206f776e60448201526132b960f11b6064820152608401610d36565b336001600160a01b0382161480610df05750610df08133610b82565b610e625760405162461bcd60e51b815260206004820152603960248201527f455243373231413a20617070726f76652063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f76656420666f7220616c6c000000000000006064820152608401610d36565b610e6d83838361447a565b505050565b630a85bd0160e11b5b949350505050565b610e8b614323565b601b55565b610e6d8383836144d6565b610ea3614323565b601d55565b60008281526008602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092528291610f1d5750604080518082019091526007546001600160a01b0381168252600160a01b90046001600160601b031660208201525b602081015160009061271090610f3c906001600160601b0316876159cf565b610f4691906159fc565b91519350909150505b9250929050565b610f5e614323565b6002600a5403610fb05760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d36565b6002600a55610fbe816147b6565b506001600a55565b6000610fd183612236565b821061102a5760405162461bcd60e51b815260206004820152602260248201527f455243373231413a206f776e657220696e646578206f7574206f6620626f756e604482015261647360f01b6064820152608401610d36565b600080549080805b838110156110c0576000818152600360209081526040918290208251808401909352546001600160a01b038116808452600160a01b9091046001600160401b0316918301919091521561108457805192505b876001600160a01b0316836001600160a01b0316036110b7578684036110b057509350610c1d92505050565b6001909301925b50600101611032565b5060405162461bcd60e51b815260206004820152602e60248201527f455243373231413a20756e61626c6520746f2067657420746f6b656e206f662060448201526d0deeedccae440c4f240d2dcc8caf60931b6064820152608401610d36565b611128614323565b6002600a540361117a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d36565b6002600a55604051600090339047908381818185875af1925050503d80600081146111c1576040519150601f19603f3d011682016040523d82523d6000602084013e6111c6565b606091505b5050905080610fbe5760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b6044820152606401610d36565b610e6d838383604051806020016040528060008152506126f2565b6000805482106112825760405162461bcd60e51b815260206004820152602360248201527f455243373231413a20676c6f62616c20696e646578206f7574206f6620626f756044820152626e647360e81b6064820152608401610d36565b5090565b601754601f5460ff166112ab5760405162461bcd60e51b8152600401610d3690615a10565b601d54601c54601b54601a546019546112c49190615a37565b6112ce9190615a37565b6112d89190615a37565b6112e29190615a37565b6112ed906001615a4a565b826112f760005490565b6113019190615a4a565b1061131e5760405162461bcd60e51b8152600401610d3690615a5d565b601e5433600090815260208052604090205461133b908490615a4a565b11156113595760405162461bcd60e51b8152600401610d3690615a86565b61136381836159cf565b3410156113825760405162461bcd60e51b8152600401610d3690615ab3565b60005461138f308461494a565b60005b83811015611456576001600160a01b0385166000908152600c602052604081206002018054600192906113c6908490615a4a565b90915550506001600160a01b0385166000908152600c602052604090206113ed9083614964565b50600b546113fb9042615a4a565b6000838152600d60209081526040808320600181019490945542909355600e90522080546001600160a01b0319166001600160a01b0387161790558161144081615ae0565b925050808061144e90615ae0565b915050611392565b5050505050565b611465614323565b601c55565b611472614323565b6015610e6d828483615b3f565b611487614323565b601f805461ff001981166101009182900460ff1615909102179055565b601654601f5460ff166114c95760405162461bcd60e51b8152600401610d3690615a10565b601e543360009081526020805260409020546114e6908790615a4a565b11156115045760405162461bcd60e51b8152600401610d3690615a86565b601b54601a546019546115179190615a37565b6115219190615a37565b61152c906001615a4a565b8561153660005490565b6115409190615a4a565b1061155d5760405162461bcd60e51b8152600401610d3690615a5d565b61156781866159cf565b3410156115865760405162461bcd60e51b8152600401610d3690615ab3565b6115908383612ea5565b6115dc5760405162461bcd60e51b815260206004820152601b60248201527f506c65617365206d696e74207468726f756768207765627369746500000000006044820152606401610d36565b6024846040516115ec9190615bfe565b9081526040519081900360200190205460ff161561163a5760405162461bcd60e51b815260206004820152600b60248201526a12185cda081c995d5cd95960aa1b6044820152606401610d36565b8261164733600187611be7565b146116825760405162461bcd60e51b815260206004820152600b60248201526a12185cda0819985a5b195960aa1b6044820152606401610d36565b336000908152602080526040812080548792906116a0908490615a4a565b9250508190555060016024856040516116b99190615bfe565b908152604051908190036020019020805491151560ff199092169190911790556116e3868661494a565b505050505050565b60006116f682614977565b5192915050565b601754601f54600090839060ff166117275760405162461bcd60e51b8152600401610d3690615a10565b6010546040516394b6e75160e01b81526000916001600160a01b0316906394b6e7519061175b903390600290600401615620565b600060405180830381865afa158015611778573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117a09190810190615c1a565b6013546040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156117ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118129190615c9f565b118061181f575060008151115b61183b5760405162461bcd60e51b8152600401610d3690615cb8565b6013546040516370a0823160e01b81523360048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190615c9f565b905060005b8181101561199857601354604051632f745c5960e01b81526000916001600160a01b031690632f745c59906118e89033908690600401615620565b602060405180830381865afa158015611905573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119299190615c9f565b60008181526025602052604090205490915060ff1615801561194b5750600085115b15611985576000818152602560205260409020805460ff191660011790558561197381615ae0565b965050848061198190615cfb565b9550505b508061199081615ae0565b9150506118ad565b5060005b8251811015611a355760008382815181106119b9576119b9615d12565b6020908102919091018101516000818152602590925260409091205490915060ff161580156119e85750600085115b15611a22576000818152602560205260409020805460ff1916600117905585611a1081615ae0565b9650508480611a1e90615cfb565b9550505b5080611a2d81615ae0565b91505061199c565b50601c54601a54601954611a499190615a37565b611a539190615a37565b611a5e906001615a4a565b84611a6860005490565b611a729190615a4a565b10611a8f5760405162461bcd60e51b8152600401610d3690615a5d565b611a9985856159cf565b341015611ab85760405162461bcd60e51b8152600401610d3690615ab3565b60008411611b085760405162461bcd60e51b815260206004820152601e60248201527f596f752068617665207573656420616c6c20796f7572206d7574616e747300006044820152606401610d36565b600054611b15308661494a565b60005b85811015611bdc576001600160a01b0389166000908152600c60205260408120600201805460019290611b4c908490615a4a565b90915550506001600160a01b0389166000908152600c60205260409020611b739083614964565b50600b54611b819042615a4a565b6000838152600d60209081526040808320600181019490945542909355600e90522080546001600160a01b0319166001600160a01b038b1617905581611bc681615ae0565b9250508080611bd490615ae0565b915050611b18565b505050505050505050565b60008084848430604051602001611c019493929190615d28565b60408051808303601f19018152919052805160209091012095945050505050565b6040516370a0823160e01b815233600482015260019030906370a0823190602401602060405180830381865afa158015611c60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c849190615c9f565b1015611cce5760405162461bcd60e51b8152602060048201526019602482015278796f7520646f6e74206861766520656e6f756768206e66747360381b6044820152606401610d36565b60005b8151811015610c3557336001600160a01b0316306001600160a01b0316636352211e848481518110611d0557611d05615d12565b60200260200101516040518263ffffffff1660e01b8152600401611d2b91815260200190565b602060405180830381865afa158015611d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6c9190615d72565b6001600160a01b031614611dbc5760405162461bcd60e51b8152602060048201526017602482015276796f7520646f6e2774206f776e2074686973206e66742160481b6044820152606401610d36565b336000908152600c60205260408120600201805460019290611ddf908490615a4a565b92505081905550611e1d828281518110611dfb57611dfb615d12565b602090810291909101810151336000908152600c909252604090912090614964565b50600b54611e2b9042615a4a565b600d6000848481518110611e4157611e41615d12565b602002602001015181526020019081526020016000206001018190555042600d6000848481518110611e7557611e75615d12565b602002602001015181526020019081526020016000206000018190555033600e6000848481518110611ea957611ea9615d12565b6020026020010151815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550306001600160a01b03166323b872dd3330858581518110611f0657611f06615d12565b60200260200101516040518463ffffffff1660e01b8152600401611f2c93929190615d8f565b600060405180830381600087803b158015611f4657600080fd5b505af1158015611f5a573d6000803e3d6000fd5b505050508080611f6990615ae0565b915050611cd1565b60158054611f7e9061597f565b80601f0160208091040260200160405190810160405280929190818152602001828054611faa9061597f565b8015611ff75780601f10611fcc57610100808354040283529160200191611ff7565b820191906000526020600020905b815481529060010190602001808311611fda57829003601f168201915b505050505081565b6040516370a0823160e01b815233600482015260019030906370a0823190602401602060405180830381865afa15801561203d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120619190615c9f565b10156120ab5760405162461bcd60e51b8152602060048201526019602482015278796f7520646f6e74206861766520656e6f756768206e66747360381b6044820152606401610d36565b6040516331a9108f60e11b81526004810182905233903090636352211e90602401602060405180830381865afa1580156120e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061210d9190615d72565b6001600160a01b03161461215d5760405162461bcd60e51b8152602060048201526017602482015276796f7520646f6e2774206f776e2074686973206e66742160481b6044820152606401610d36565b336000908152600c60205260408120600201805460019290612180908490615a4a565b9091555050336000908152600c6020526040902061219e9082614964565b50600b546121ac9042615a4a565b6000828152600d60209081526040808320600181019490945542909355600e905281902080546001600160a01b0319163390811790915590516323b872dd60e01b815230916323b872dd91612208919084908690600401615d8f565b600060405180830381600087803b15801561222257600080fd5b505af1158015611456573d6000803e3d6000fd5b60006001600160a01b0382166122a25760405162461bcd60e51b815260206004820152602b60248201527f455243373231413a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b6064820152608401610d36565b506001600160a01b03166000908152600460205260409020546001600160801b031690565b6122cf614323565b6122d96000614a4d565b565b336000908152600c60205260409020600201546123345760405162461bcd60e51b81526020600482015260176024820152761e5bdd481a185d99481b9bc81b999d1cc81cdd185ad959604a1b6044820152606401610d36565b336000908152600c6020526040812061234c90614a9f565b905060005b81811015610c3557336000908152600c602052604081206123729082614aa9565b6000818152600e60205260409020549091506001600160a01b0316331480156123ac57506000818152600d60205260409020600101544210155b1561246857336000908152600c602052604081206002018054600192906123d4908490615a37565b90915550506000818152600e6020908152604080832080546001600160a01b0319169055338352600c909152902061240c8183614ab5565b506040516323b872dd60e01b815230906323b872dd9061243490839033908790600401615d8f565b600060405180830381600087803b15801561244e57600080fd5b505af1158015612462573d6000803e3d6000fd5b50505050505b508061247381615ae0565b915050612351565b612483614323565b601f805460ff19811660ff90911615179055565b60148054611f7e9061597f565b6040805180820190915260008082526020820152610c1d82614977565b606060028054610c489061597f565b6001600160a01b0381166000908152600c60205260408120606091906124f590614a9f565b6001600160401b0381111561250c5761250c61549d565b604051908082528060200260200182016040528015612535578160200160208202803683370190505b50905060005b6001600160a01b0384166000908152600c6020526040902061255c90614a9f565b8110156125b4576001600160a01b0384166000908152600c602052604090206125859082614aa9565b82828151811061259757612597615d12565b6020908102919091010152806125ac81615ae0565b91505061253b565b5092915050565b336001600160a01b038316036126135760405162461bcd60e51b815260206004820152601a60248201527f455243373231413a20617070726f766520746f2063616c6c65720000000000006044820152606401610d36565b3360008181526006602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b612687614323565b601f5460ff166126a95760405162461bcd60e51b8152600401610d3690615a10565b6019546126b7906001615a4a565b816126c160005490565b6126cb9190615a4a565b106126e85760405162461bcd60e51b8152600401610d3690615a5d565b610c35828261494a565b6126fd8484846144d6565b61270984848484614ac1565b6127255760405162461bcd60e51b8152600401610d3690615db3565b50505050565b612733614323565b6014610e6d828483615b3f565b6000818152600d60205260409020600101544210156127ab5760405162461bcd60e51b815260206004820152602160248201527f796f7572206e6674206973206c6f636b656420666f72207769746864726177616044820152601b60fa1b6064820152608401610d36565b336000908152600c60205260409020600201546128045760405162461bcd60e51b81526020600482015260176024820152761e5bdd481a185d99481b9bc81b999d1cc81cdd185ad959604a1b6044820152606401610d36565b6000818152600e60205260409020546001600160a01b0316331461286a5760405162461bcd60e51b815260206004820152601960248201527f796f7520646f6e2774206f776e207468697320746f6b656e21000000000000006044820152606401610d36565b336000908152600c6020526040812060020180546001929061288d908490615a37565b90915550506000818152600e6020908152604080832080546001600160a01b0319169055338352600c90915290206128c58183614ab5565b506040516323b872dd60e01b815230906323b872dd906128ed90839033908790600401615d8f565b600060405180830381600087803b15801561290757600080fd5b505af11580156116e3573d6000803e3d6000fd5b6060612928826000541190565b61296a5760405162461bcd60e51b815260206004820152601360248201527212dbdb99c8191bd95cc81b9bdd08195e1a5cdd606a1b6044820152606401610d36565b601f54610100900460ff16156129d657601580546129879061597f565b90506000036129a55760405180602001604052806000815250610c1d565b60156129b083614bbf565b6040516020016129c1929190615e06565b60405160208183030381529060405292915050565b601480546129e39061597f565b80601f0160208091040260200160405190810160405280929190818152602001828054612a0f9061597f565b8015612a5c5780601f10612a3157610100808354040283529160200191612a5c565b820191906000526020600020905b815481529060010190602001808311612a3f57829003601f168201915b50505050509050919050565b601654601f5460ff16612a8d5760405162461bcd60e51b8152600401610d3690615a10565b601d54601c54601b54601a54601954612aa69190615a37565b612ab09190615a37565b612aba9190615a37565b612ac49190615a37565b612acf906001615a4a565b82612ad960005490565b612ae39190615a4a565b10612b005760405162461bcd60e51b8152600401610d3690615a5d565b601e54336000908152602080526040902054612b1d908490615a4a565b1115612b3b5760405162461bcd60e51b8152600401610d3690615a86565b612b4581836159cf565b341015612b645760405162461bcd60e51b8152600401610d3690615ab3565b33600090815260208052604081208054849290612b82908490615a4a565b90915550610e6d9050838361494a565b601754601f5460ff16612bb75760405162461bcd60e51b8152600401610d3690615a10565b601e54336000908152602080526040902054612bd4908790615a4a565b1115612bf25760405162461bcd60e51b8152600401610d3690615a86565b601b54601a54601954612c059190615a37565b612c0f9190615a37565b612c1a906001615a4a565b85612c2460005490565b612c2e9190615a4a565b10612c4b5760405162461bcd60e51b8152600401610d3690615a5d565b612c5581866159cf565b341015612c745760405162461bcd60e51b8152600401610d3690615ab3565b612c7e8383612ea5565b612cca5760405162461bcd60e51b815260206004820152601b60248201527f506c65617365206d696e74207468726f756768207765627369746500000000006044820152606401610d36565b602484604051612cda9190615bfe565b9081526040519081900360200190205460ff1615612d285760405162461bcd60e51b815260206004820152600b60248201526a12185cda081c995d5cd95960aa1b6044820152606401610d36565b82612d3533600187611be7565b14612d705760405162461bcd60e51b815260206004820152600b60248201526a12185cda0819985a5b195960aa1b6044820152606401610d36565b33600090815260208052604081208054879290612d8e908490615a4a565b925050819055506001602485604051612da79190615bfe565b908152604051908190036020019020805491151560ff19909216919091179055600054612dd4308761494a565b60005b86811015612e9b576001600160a01b0388166000908152600c60205260408120600201805460019290612e0b908490615a4a565b90915550506001600160a01b0388166000908152600c60205260409020612e329083614964565b50600b54612e409042615a4a565b6000838152600d60209081526040808320600181019490945542909355600e90522080546001600160a01b0319166001600160a01b038a1617905581612e8581615ae0565b9250508080612e9390615ae0565b915050612dd7565b5050505050505050565b6000612f0882612f02856040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b90614cbf565b600f546001600160a01b039182169116149392505050565b601654601f54600090839060ff16612f4a5760405162461bcd60e51b8152600401610d3690615a10565b6010546040516394b6e75160e01b81526000916001600160a01b0316906394b6e75190612f7e903390600290600401615620565b600060405180830381865afa158015612f9b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612fc39190810190615c1a565b6013546040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613011573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130359190615c9f565b1180613042575060008151115b61305e5760405162461bcd60e51b8152600401610d3690615cb8565b6013546040516370a0823160e01b81523360048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156130a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130cb9190615c9f565b905060005b818110156131bb57601354604051632f745c5960e01b81526000916001600160a01b031690632f745c599061310b9033908690600401615620565b602060405180830381865afa158015613128573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061314c9190615c9f565b60008181526025602052604090205490915060ff1615801561316e5750600085115b156131a8576000818152602560205260409020805460ff191660011790558561319681615ae0565b96505084806131a490615cfb565b9550505b50806131b381615ae0565b9150506130d0565b5060005b82518110156132585760008382815181106131dc576131dc615d12565b6020908102919091018101516000818152602590925260409091205490915060ff1615801561320b5750600085115b15613245576000818152602560205260409020805460ff191660011790558561323381615ae0565b965050848061324190615cfb565b9550505b508061325081615ae0565b9150506131bf565b50601c54601a5460195461326c9190615a37565b6132769190615a37565b613281906001615a4a565b8461328b60005490565b6132959190615a4a565b106132b25760405162461bcd60e51b8152600401610d3690615a5d565b6132bc85856159cf565b3410156132db5760405162461bcd60e51b8152600401610d3690615ab3565b6000841161332b5760405162461bcd60e51b815260206004820152601e60248201527f596f752068617665207573656420616c6c20796f7572206d7574616e747300006044820152606401610d36565b613335878561494a565b50505050505050565b613346614323565b6001600160a01b0381166133ab5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d36565b6133b481614a4d565b50565b601f5460009060ff166133dc5760405162461bcd60e51b8152600401610d3690615a10565b6010546040516394b6e75160e01b81526000916001600160a01b0316906394b6e7519061340f9033908590600401615620565b600060405180830381865afa15801561342c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526134549190810190615c1a565b6010546040516394b6e75160e01b81529192506000916001600160a01b03909116906394b6e7519061348d903390600190600401615620565b600060405180830381865afa1580156134aa573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526134d29190810190615c1a565b6010546040516394b6e75160e01b81529192506000916001600160a01b03909116906394b6e7519061350b903390600290600401615620565b600060405180830381865afa158015613528573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526135509190810190615c1a565b6011546040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561359e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c29190615c9f565b11806135cf575060008351115b6136335760405162461bcd60e51b815260206004820152602f60248201527f4d7573742068617665206d6f7265207468616e20312053757072656d65204b6f60448201526e1b99c81d1bc8199c9959481b5a5b9d608a1b6064820152608401610d36565b6012546040516370a0823160e01b81523360048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561367c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a09190615c9f565b118061371657506013546040516370a0823160e01b81523360048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156136f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137149190615c9f565b115b80613722575060008251115b8061372e575060008151115b61378c5760405162461bcd60e51b815260206004820152602960248201527f4d7573742068617665206d6f7265207468616e20312042616e616e6120746f20604482015268199c9959481b5a5b9d60ba1b6064820152608401610d36565b82516011546040516370a0823160e01b8152336004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa1580156137d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137fc9190615c9f565b6138069190615a4a565b6001600160401b0381111561381d5761381d61549d565b604051908082528060200260200182016040528015613846578160200160208202803683370190505b5083516012546040516370a0823160e01b81523360048201529293506000926001600160a01b03909116906370a0823190602401602060405180830381865afa158015613897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138bb9190615c9f565b6138c59190615a4a565b6001600160401b038111156138dc576138dc61549d565b604051908082528060200260200182016040528015613905578160200160208202803683370190505b5083516013546040516370a0823160e01b81523360048201529293506000926001600160a01b03909116906370a0823190602401602060405180830381865afa158015613956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061397a9190615c9f565b6139849190615a4a565b6001600160401b0381111561399b5761399b61549d565b6040519080825280602002602001820160405280156139c4578160200160208202803683370190505b506011546040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613a13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a379190615c9f565b905060005b6011546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613a84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aa89190615c9f565b811015613b5657601154604051632f745c5960e01b81526000916001600160a01b031690632f745c5990613ae29033908690600401615620565b602060405180830381865afa158015613aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b239190615c9f565b905080868381518110613b3857613b38615d12565b60209081029190910101525080613b4e81615ae0565b915050613a3c565b5060005b8751811015613bba57878181518110613b7557613b75615d12565b6020026020010151858381518110613b8f57613b8f615d12565b602090810291909101015281613ba481615ae0565b9250508080613bb290615ae0565b915050613b5a565b506012546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c279190615c9f565b905060005b6012546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c989190615c9f565b811015613d4657601254604051632f745c5960e01b81526000916001600160a01b031690632f745c5990613cd29033908690600401615620565b602060405180830381865afa158015613cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d139190615c9f565b905080858381518110613d2857613d28615d12565b60209081029190910101525080613d3e81615ae0565b915050613c2c565b5060005b8651811015613daa57868181518110613d6557613d65615d12565b6020026020010151848381518110613d7f57613d7f615d12565b602090810291909101015281613d9481615ae0565b9250508080613da290615ae0565b915050613d4a565b506013546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613df3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e179190615c9f565b905060005b6013546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015613e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e889190615c9f565b811015613f3657601354604051632f745c5960e01b81526000916001600160a01b031690632f745c5990613ec29033908690600401615620565b602060405180830381865afa158015613edf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f039190615c9f565b905080848381518110613f1857613f18615d12565b60209081029190910101525080613f2e81615ae0565b915050613e1c565b5060005b8551811015613f9a57858181518110613f5557613f55615d12565b6020026020010151838381518110613f6f57613f6f615d12565b602090810291909101015281613f8481615ae0565b9250508080613f9290615ae0565b915050613f3a565b5060005b845181101561414b576000858281518110613fbb57613fbb615d12565b6020026020010151905060005b855181101561407d576000868281518110613fe557613fe5615d12565b6020908102919091018101516000858152602190925260409091205490915060ff16158015614023575060008181526022602052604090205460ff16155b1561406a5760008181526022602090815260408083208054600160ff19918216811790925587855260219093529220805490911690911790558b61406681615ae0565b9c50505b508061407581615ae0565b915050613fc8565b5060005b845181101561413657600085828151811061409e5761409e615d12565b6020908102919091018101516000858152602190925260409091205490915060ff161580156140dc575060008181526023602052604090205460ff16155b156141235760008181526023602090815260408083208054600160ff19918216811790925587855260219093529220805490911690911790558b61411f81615ae0565b9c50505b508061412e81615ae0565b915050614081565b5050808061414390615ae0565b915050613f9e565b50600088116141b25760405162461bcd60e51b815260206004820152602d60248201527f596f7520646f6e2774206861766520617661696c61626c65206b6f6e6720616e60448201526c32103130b730b730903830b4b960991b6064820152608401610d36565b6000546141bf308a61494a565b60005b89811015614286576001600160a01b038b166000908152600c602052604081206002018054600192906141f6908490615a4a565b90915550506001600160a01b038b166000908152600c6020526040902061421d9083614964565b50600b5461422b9042615a4a565b6000838152600d60209081526040808320600181019490945542909355600e90522080546001600160a01b0319166001600160a01b038d161790558161427081615ae0565b925050808061427e90615ae0565b9150506141c2565b5050505050505050505050565b60006001600160e01b031982166380ac58cd60e01b14806142c457506001600160e01b03198216635b5e139f60e01b145b806142df57506001600160e01b0319821663780e9d6360e01b145b80610c1d57506301ffc9a760e01b6001600160e01b0319831614610c1d565b60006001600160e01b0319821663152a902d60e11b1480610c1d5750610c1d82614293565b6009546001600160a01b031633146122d95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d36565b6127106001600160601b03821611156143eb5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610d36565b6001600160a01b0382166144415760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610d36565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600755565b60008281526005602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60006144e182614977565b80519091506000906001600160a01b0316336001600160a01b0316148061451857503361450d84610ccb565b6001600160a01b0316145b8061452a5750815161452a9033610b82565b9050806145945760405162461bcd60e51b815260206004820152603260248201527f455243373231413a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b6064820152608401610d36565b846001600160a01b031682600001516001600160a01b0316146146085760405162461bcd60e51b815260206004820152602660248201527f455243373231413a207472616e736665722066726f6d20696e636f72726563746044820152651037bbb732b960d11b6064820152608401610d36565b6001600160a01b03841661466c5760405162461bcd60e51b815260206004820152602560248201527f455243373231413a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b6064820152608401610d36565b61467c600084846000015161447a565b6001600160a01b03858116600090815260046020908152604080832080546001600160801b03198082166001600160801b03928316600019018316179092558986168086528386208054938416938316600190810190931693909317909255888552600390935281842080546001600160e01b031916909117600160a01b426001600160401b03160217905590860180835291205490911661476f57614723816000541190565b1561476f57825160008281526003602090815260409091208054918601516001600160401b0316600160a01b026001600160e01b03199092166001600160a01b03909316929092171790555b5082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611456565b806000036148065760405162461bcd60e51b815260206004820152601860248201527f7175616e74697479206d757374206265206e6f6e7a65726f00000000000000006044820152606401610d36565b60005460000361484f5760405162461bcd60e51b81526020600482015260146024820152731b9bc81d1bdad95b9cc81b5a5b9d1959081e595d60621b6044820152606401610d36565b60185460005481106148a35760405162461bcd60e51b815260206004820152601c60248201527f616c6c206f776e657273686970732068617665206265656e20736574000000006044820152606401610d36565b60005482820160001981019110156148be5750600054600019015b815b81811161493f576000818152600360205260409020546001600160a01b03166149375760006148ee82614977565b80516000848152600360209081526040909120805491909301516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b0390921691909117179055505b6001016148c0565b506001016018555050565b610c35828260405180602001604052806000815250614ce3565b60006149708383614cf0565b9392505050565b6040805180820190915260008082526020820152614996826000541190565b6149f55760405162461bcd60e51b815260206004820152602a60248201527f455243373231413a206f776e657220717565727920666f72206e6f6e657869736044820152693a32b73a103a37b5b2b760b11b6064820152608401610d36565b815b6000818152600360209081526040918290208251808401909352546001600160a01b038116808452600160a01b9091046001600160401b03169183019190915215614a43579392505050565b50600019016149f7565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000610c1d825490565b60006149708383614d3f565b60006149708383614d69565b60006001600160a01b0384163b15614bb757604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290614b05903390899088908890600401615e8d565b6020604051808303816000875af1925050508015614b40575060408051601f3d908101601f19168201909252614b3d91810190615eca565b60015b614b9d573d808015614b6e576040519150601f19603f3d011682016040523d82523d6000602084013e614b73565b606091505b508051600003614b955760405162461bcd60e51b8152600401610d3690615db3565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610e7b565b506001610e7b565b606081600003614be65750506040805180820190915260018152600360fc1b602082015290565b8160005b8115614c105780614bfa81615ae0565b9150614c099050600a836159fc565b9150614bea565b6000816001600160401b03811115614c2a57614c2a61549d565b6040519080825280601f01601f191660200182016040528015614c54576020820181803683370190505b5090505b8415610e7b57614c69600183615a37565b9150614c76600a86615ee7565b614c81906030615a4a565b60f81b818381518110614c9657614c96615d12565b60200101906001600160f81b031916908160001a905350614cb8600a866159fc565b9450614c58565b6000806000614cce8585614e5c565b91509150614cdb81614ec7565b509392505050565b610e6d838383600161507d565b6000818152600183016020526040812054614d3757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610c1d565b506000610c1d565b6000826000018281548110614d5657614d56615d12565b9060005260206000200154905092915050565b60008181526001830160205260408120548015614e52576000614d8d600183615a37565b8554909150600090614da190600190615a37565b9050818114614e06576000866000018281548110614dc157614dc1615d12565b9060005260206000200154905080876000018481548110614de457614de4615d12565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614e1757614e17615efb565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610c1d565b6000915050610c1d565b6000808251604103614e925760208301516040840151606085015160001a614e8687828585615242565b94509450505050610f4f565b8251604003614ebb5760208301516040840151614eb086838361532f565b935093505050610f4f565b50600090506002610f4f565b6000816004811115614edb57614edb615f11565b03614ee35750565b6001816004811115614ef757614ef7615f11565b03614f445760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610d36565b6002816004811115614f5857614f58615f11565b03614fa55760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610d36565b6003816004811115614fb957614fb9615f11565b036150115760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610d36565b600481600481111561502557615025615f11565b036133b45760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610d36565b6000546001600160a01b0385166150e05760405162461bcd60e51b815260206004820152602160248201527f455243373231413a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610d36565b836000036151415760405162461bcd60e51b815260206004820152602860248201527f455243373231413a207175616e74697479206d75737420626520677265617465604482015267072207468616e20360c41b6064820152608401610d36565b6001600160a01b03851660008181526004602090815260408083208054600160801b6001600160801b031982166001600160801b039283168c01831690811782900483168c01909216021790558483526003909152812080546001600160e01b031916909217600160a01b426001600160401b0316021790915581905b858110156152395760405182906001600160a01b038916906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4831561522d576152116000888488614ac1565b61522d5760405162461bcd60e51b8152600401610d3690615db3565b600191820191016151be565b50600055611456565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156152795750600090506003615326565b8460ff16601b1415801561529157508460ff16601c14155b156152a25750600090506004615326565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156152f6573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661531f57600060019250925050615326565b9150600090505b94509492505050565b6000806001600160ff1b0383168161534c60ff86901c601b615a4a565b905061535a87828885615242565b935093505050935093915050565b6001600160e01b0319811681146133b457600080fd5b60006020828403121561539057600080fd5b813561497081615368565b6001600160a01b03811681146133b457600080fd5b600080604083850312156153c357600080fd5b82356153ce8161539b565b915060208301356001600160601b03811681146153ea57600080fd5b809150509250929050565b60005b838110156154105781810151838201526020016153f8565b50506000910152565b600081518084526154318160208601602086016153f5565b601f01601f19169290920160200192915050565b6020815260006149706020830184615419565b60006020828403121561546a57600080fd5b5035919050565b6000806040838503121561548457600080fd5b823561548f8161539b565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156154db576154db61549d565b604052919050565b600082601f8301126154f457600080fd5b81356001600160401b0381111561550d5761550d61549d565b615520601f8201601f19166020016154b3565b81815284602083860101111561553557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561556857600080fd5b84356155738161539b565b935060208501356155838161539b565b92506040850135915060608501356001600160401b038111156155a557600080fd5b6155b1878288016154e3565b91505092959194509250565b6000806000606084860312156155d257600080fd5b83356155dd8161539b565b925060208401356155ed8161539b565b929592945050506040919091013590565b6000806040838503121561561157600080fd5b50508035926020909101359150565b6001600160a01b03929092168252602082015260400190565b6000806020838503121561564c57600080fd5b82356001600160401b038082111561566357600080fd5b818501915085601f83011261567757600080fd5b81358181111561568657600080fd5b86602082850101111561569857600080fd5b60209290920196919550909350505050565b600080600080600060a086880312156156c257600080fd5b85356156cd8161539b565b94506020860135935060408601356001600160401b03808211156156f057600080fd5b6156fc89838a016154e3565b945060608801359350608088013591508082111561571957600080fd5b50615726888289016154e3565b9150509295509295909350565b60008060006060848603121561574857600080fd5b83356157538161539b565b92506020840135915060408401356001600160401b0381111561577557600080fd5b615781868287016154e3565b9150509250925092565b60006001600160401b038211156157a4576157a461549d565b5060051b60200190565b600060208083850312156157c157600080fd5b82356001600160401b038111156157d757600080fd5b8301601f810185136157e857600080fd5b80356157fb6157f68261578b565b6154b3565b81815260059190911b8201830190838101908783111561581a57600080fd5b928401925b828410156158385783358252928401929084019061581f565b979650505050505050565b60006020828403121561585557600080fd5b81356149708161539b565b6020808252825182820181905260009190848201906040850190845b818110156158985783518352928401929184019160010161587c565b50909695505050505050565b600080604083850312156158b757600080fd5b82356158c28161539b565b9150602083013580151581146153ea57600080fd5b6000602082840312156158e957600080fd5b81356001600160401b038111156158ff57600080fd5b610e7b848285016154e3565b6000806040838503121561591e57600080fd5b8235915060208301356001600160401b0381111561593b57600080fd5b615947858286016154e3565b9150509250929050565b6000806040838503121561596457600080fd5b823561596f8161539b565b915060208301356153ea8161539b565b600181811c9082168061599357607f821691505b6020821081036159b357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610c1d57610c1d6159b9565b634e487b7160e01b600052601260045260246000fd5b600082615a0b57615a0b6159e6565b500490565b6020808252600d908201526c135a5b9d08191a5cd8589b1959609a1b604082015260600190565b81810381811115610c1d57610c1d6159b9565b80820180821115610c1d57610c1d6159b9565b6020808252600f908201526e576527726520736f6c64206f75742160881b604082015260600190565b602080825260139082015272151bdbc81b585b9e481c195c881dd85b1b195d606a1b604082015260600190565b60208082526013908201527208ae8d0cae440d2e640dcdee840cadcdeeaced606b1b604082015260600190565b600060018201615af257615af26159b9565b5060010190565b601f821115610e6d57600081815260208120601f850160051c81016020861015615b205750805b601f850160051c820191505b818110156116e357828155600101615b2c565b6001600160401b03831115615b5657615b5661549d565b615b6a83615b64835461597f565b83615af9565b6000601f841160018114615b9e5760008515615b865750838201355b600019600387901b1c1916600186901b178355611456565b600083815260209020601f19861690835b82811015615bcf5786850135825560209485019460019092019101615baf565b5086821015615bec5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008251615c108184602087016153f5565b9190910192915050565b60006020808385031215615c2d57600080fd5b82516001600160401b03811115615c4357600080fd5b8301601f81018513615c5457600080fd5b8051615c626157f68261578b565b81815260059190911b82018301908381019087831115615c8157600080fd5b928401925b8284101561583857835182529284019290840190615c86565b600060208284031215615cb157600080fd5b5051919050565b60208082526023908201527f4d7573742068617665206d6f7265207468616e2031204d7574616e742042616e604082015262616e6160e81b606082015260800190565b600081615d0a57615d0a6159b9565b506000190190565b634e487b7160e01b600052603260045260246000fd5b60006001600160601b0319808760601b1683528560148401528451615d548160348601602089016153f5565b60609490941b16919092016034810191909152604801949350505050565b600060208284031215615d8457600080fd5b81516149708161539b565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60208082526033908201527f455243373231413a207472616e7366657220746f206e6f6e204552433732315260408201527232b1b2b4bb32b91034b6b83632b6b2b73a32b960691b606082015260800190565b6000808454615e148161597f565b60018281168015615e2c5760018114615e4157615e70565b60ff1984168752821515830287019450615e70565b8860005260208060002060005b85811015615e675781548a820152908401908201615e4e565b50505082870194505b505050508351615e848183602088016153f5565b01949350505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615ec090830184615419565b9695505050505050565b600060208284031215615edc57600080fd5b815161497081615368565b600082615ef657615ef66159e6565b500690565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052602160045260246000fdfea2646970667358221220059a0e01d0094b9b990e2e5b9b4383a884f97b638ef07bb8e95fb5c5de76253164736f6c63430008110033

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

00000000000000000000000012787526c03d626aac88e6edc4d0fb930d86c631000000000000000000000000f59afe732b2793d541780fd02945228db1fad8ed0000000000000000000000008ace1ec951bc29b98440d1bbca64e6010c9e9e1700000000000000000000000070c7af7a78b5453e4a09376eb2b506ce4e4140e5000000000000000000000000f41f1c3d48bb18b0624a38cadc63f3134a65c23e000000000000000000000000fe67cfa5d71a88f6353036966655d6e65e15bf400000000000000000000000000000000000000000000000000000000000093a80

-----Decoded View---------------
Arg [0] : _kongAddress (address): 0x12787526c03d626AAc88E6EDc4d0Fb930d86C631
Arg [1] : _bananaAddress (address): 0xF59aFe732B2793d541780fd02945228db1fAd8ed
Arg [2] : _mutantAddress (address): 0x8ACe1Ec951Bc29b98440d1bbCa64E6010c9E9E17
Arg [3] : _stakeAddress (address): 0x70C7af7a78B5453E4A09376eB2b506CE4E4140E5
Arg [4] : _systemAddress (address): 0xF41F1C3D48BB18b0624a38CAdc63F3134a65c23e
Arg [5] : royaltiesReceiver (address): 0xFE67CfA5D71a88f6353036966655D6E65E15Bf40
Arg [6] : _lockTime (uint256): 604800

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 00000000000000000000000012787526c03d626aac88e6edc4d0fb930d86c631
Arg [1] : 000000000000000000000000f59afe732b2793d541780fd02945228db1fad8ed
Arg [2] : 0000000000000000000000008ace1ec951bc29b98440d1bbca64e6010c9e9e17
Arg [3] : 00000000000000000000000070c7af7a78b5453e4a09376eb2b506ce4e4140e5
Arg [4] : 000000000000000000000000f41f1c3d48bb18b0624a38cadc63f3134a65c23e
Arg [5] : 000000000000000000000000fe67cfa5d71a88f6353036966655d6e65e15bf40
Arg [6] : 0000000000000000000000000000000000000000000000000000000000093a80


Deployed Bytecode Sourcemap

93180:20710:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112388:211;;;;;;;;;;-1:-1:-1;112388:211:0;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;112388:211:0;;;;;;;;112231:143;;;;;;;;;;-1:-1:-1;112231:143:0;;;;;:::i;:::-;;:::i;:::-;;81841:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;83403:214::-;;;;;;;;;;-1:-1:-1;83403:214:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;2297:32:1;;;2279:51;;2267:2;2252:18;83403:214:0;2133:203:1;82924:413:0;;;;;;;;;;-1:-1:-1;82924:413:0;;;;;:::i;:::-;;:::i;94339:42::-;;;;;;;;;;;;;;;;;;;2815:25:1;;;2803:2;2788:18;94339:42:0;2669:177:1;94612:50:0;;;;;;;;;;-1:-1:-1;94612:50:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;41826:207;;;;;;;;;;-1:-1:-1;41826:207:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;;4646:33:1;;;4628:52;;4616:2;4601:18;41826:207:0;4484:202:1;94783:52:0;;;;;;;;;;-1:-1:-1;94783:52:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;78212:100;;;;;;;;;;-1:-1:-1;78265:7:0;78292:12;78212:100;;94557:48;;;;;;;;;;-1:-1:-1;94557:48:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;109907:102;;;;;;;;;;-1:-1:-1;109907:102:0;;;;;:::i;:::-;;:::i;84279:170::-;;;;;;;;;;-1:-1:-1;84279:170:0;;;;;:::i;:::-;;:::i;110133:106::-;;;;;;;;;;-1:-1:-1;110133:106:0;;;;;:::i;:::-;;:::i;46540:442::-;;;;;;;;;;-1:-1:-1;46540:442:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;94199:38::-;;;;;;;;;;;;;;;;111122:124;;;;;;;;;;-1:-1:-1;111122:124:0;;;;;:::i;:::-;;:::i;78876:1007::-;;;;;;;;;;-1:-1:-1;78876:1007:0;;;;;:::i;:::-;;:::i;94290:42::-;;;;;;;;;;;;;;;;110929:185;;;;;;;;;;;;;:::i;84520:::-;;;;;;;;;;-1:-1:-1;84520:185:0;;;;;:::i;:::-;;:::i;94669:56::-;;;;;;;;;;-1:-1:-1;94669:56:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;78389:187;;;;;;;;;;-1:-1:-1;78389:187:0;;;;;:::i;:::-;;:::i;94470:29::-;;;;;;;;;;-1:-1:-1;94470:29:0;;;;;;;;;;;100110:989;;;;;;:::i;:::-;;:::i;110017:108::-;;;;;;;;;;-1:-1:-1;110017:108:0;;;;;:::i;:::-;;:::i;110365:102::-;;;;;;;;;;-1:-1:-1;110365:102:0;;;;;:::i;:::-;;:::i;109815:84::-;;;;;;;;;;;;;:::i;104583:893::-;;;;;;:::i;:::-;;:::i;81650:124::-;;;;;;;;;;-1:-1:-1;81650:124:0;;;;;:::i;:::-;;:::i;102622:1953::-;;;;;;:::i;:::-;;:::i;111925:279::-;;;;;;;;;;-1:-1:-1;111925:279:0;;;;;:::i;:::-;;:::i;107488:800::-;;;;;;;;;;-1:-1:-1;107488:800:0;;;;;:::i;:::-;;:::i;93969:28::-;;;;;;;;;;;;;:::i;106835:645::-;;;;;;;;;;-1:-1:-1;106835:645:0;;;;;:::i;:::-;;:::i;80391:221::-;;;;;;;;;;-1:-1:-1;80391:221:0;;;;;:::i;:::-;;:::i;30788:103::-;;;;;;;;;;;;;:::i;108931:779::-;;;;;;;;;;;;;:::i;109718:89::-;;;;;;;;;;;;;:::i;93932:30::-;;;;;;;;;;;;;:::i;30140:87::-;;;;;;;;;;-1:-1:-1;30213:6:0;;-1:-1:-1;;;;;30213:6:0;30140:87;;111254:135;;;;;;;;;;-1:-1:-1;111254:135:0;;;;;:::i;:::-;;:::i;:::-;;;;9418:13:1;;-1:-1:-1;;;;;9414:39:1;9396:58;;9514:4;9502:17;;;9496:24;-1:-1:-1;;;;;9492:49:1;9470:20;;;9463:79;;;;9369:18;111254:135:0;9186:362:1;82010:104:0;;;;;;;;;;;;;:::i;94051:44::-;;;;;;;;;;;;;;;;94004:40;;;;;;;;;;;;;;;;111397:335;;;;;;;;;;-1:-1:-1;111397:335:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;83689:288::-;;;;;;;;;;-1:-1:-1;83689:288:0;;;;;:::i;:::-;;:::i;94388:36::-;;;;;;;;;;;;;;;;94734:42;;;;;;;;;;-1:-1:-1;94734:42:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94244:39;;;;;;;;;;;;;;;;99262:256;;;;;;;;;;-1:-1:-1;99262:256:0;;;;;:::i;:::-;;:::i;84776:355::-;;;;;;;;;;-1:-1:-1;84776:355:0;;;;;:::i;:::-;;:::i;110247:110::-;;;;;;;;;;-1:-1:-1;110247:110:0;;;;;:::i;:::-;;:::i;108296:627::-;;;;;;;;;;-1:-1:-1;108296:627:0;;;;;:::i;:::-;;:::i;110475:330::-;;;;;;;;;;-1:-1:-1;110475:330:0;;;;;:::i;:::-;;:::i;99526:576::-;;;;;;:::i;:::-;;:::i;94431:32::-;;;;;;;;;;-1:-1:-1;94431:32:0;;;;;;;;94154:38;;;;;;;;;;;;;;;;94102:45;;;;;;;;;;;;;;;;105484:1343;;;;;;:::i;:::-;;:::i;111740:177::-;;;;;;;;;;-1:-1:-1;111740:177:0;;;;;:::i;:::-;;:::i;84048:164::-;;;;;;;;;;-1:-1:-1;84048:164:0;;;;;:::i;:::-;-1:-1:-1;;;;;84169:25:0;;;84145:4;84169:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;84048:164;101107:1507;;;;;;:::i;:::-;;:::i;31046:201::-;;;;;;;;;;-1:-1:-1;31046:201:0;;;;;:::i;:::-;;:::i;95358:3896::-;;;;;;;;;;-1:-1:-1;95358:3896:0;;;;;:::i;:::-;;:::i;112388:211::-;112491:4;112511:38;112537:11;112511:25;:38::i;:::-;:80;;;;112553:38;112579:11;112553:25;:38::i;:::-;112504:87;112388:211;-1:-1:-1;;112388:211:0:o;112231:143::-;30026:13;:11;:13::i;:::-;112327:39:::1;112346:8;112356:9;112327:18;:39::i;:::-;112231:143:::0;;:::o;81841:100::-;81895:13;81928:5;81921:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81841:100;:::o;83403:214::-;83471:7;83499:16;83507:7;85443:4;85477:12;-1:-1:-1;85467:22:0;85386:111;83499:16;83491:74;;;;-1:-1:-1;;;83491:74:0;;12334:2:1;83491:74:0;;;12316:21:1;12373:2;12353:18;;;12346:30;12412:34;12392:18;;;12385:62;-1:-1:-1;;;12463:18:1;;;12456:43;12516:19;;83491:74:0;;;;;;;;;-1:-1:-1;83585:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;83585:24:0;;83403:214::o;82924:413::-;82997:13;83013:24;83029:7;83013:15;:24::i;:::-;82997:40;;83062:5;-1:-1:-1;;;;;83056:11:0;:2;-1:-1:-1;;;;;83056:11:0;;83048:58;;;;-1:-1:-1;;;83048:58:0;;12748:2:1;83048:58:0;;;12730:21:1;12787:2;12767:18;;;12760:30;12826:34;12806:18;;;12799:62;-1:-1:-1;;;12877:18:1;;;12870:32;12919:19;;83048:58:0;12546:398:1;83048:58:0;28771:10;-1:-1:-1;;;;;83141:21:0;;;;:62;;-1:-1:-1;83166:37:0;83183:5;28771:10;84048:164;:::i;83166:37::-;83119:169;;;;-1:-1:-1;;;83119:169:0;;13151:2:1;83119:169:0;;;13133:21:1;13190:2;13170:18;;;13163:30;13229:34;13209:18;;;13202:62;13300:27;13280:18;;;13273:55;13345:19;;83119:169:0;12949:421:1;83119:169:0;83301:28;83310:2;83314:7;83323:5;83301:8;:28::i;:::-;82986:351;82924:413;;:::o;41826:207::-;-1:-1:-1;;;41826:207:0;;;;;;;:::o;109907:102::-;30026:13;:11;:13::i;:::-;109979:12:::1;:22:::0;109907:102::o;84279:170::-;84413:28;84423:4;84429:2;84433:7;84413:9;:28::i;110133:106::-;30026:13;:11;:13::i;:::-;110207:14:::1;:24:::0;110133:106::o;46540:442::-;46637:7;46695:27;;;:17;:27;;;;;;;;46666:56;;;;;;;;;-1:-1:-1;;;;;46666:56:0;;;;;-1:-1:-1;;;46666:56:0;;;-1:-1:-1;;;;;46666:56:0;;;;;;;;46637:7;;46735:92;;-1:-1:-1;46786:29:0;;;;;;;;;46796:19;46786:29;-1:-1:-1;;;;;46786:29:0;;;;-1:-1:-1;;;46786:29:0;;-1:-1:-1;;;;;46786:29:0;;;;;46735:92;46877:23;;;;46839:21;;47348:5;;46864:36;;-1:-1:-1;;;;;46864:36:0;:10;:36;:::i;:::-;46863:58;;;;:::i;:::-;46942:16;;;-1:-1:-1;46839:82:0;;-1:-1:-1;;46540:442:0;;;;;;:::o;111122:124::-;30026:13;:11;:13::i;:::-;1849:1:::1;2447:7;;:19:::0;2439:63:::1;;;::::0;-1:-1:-1;;;2439:63:0;;14139:2:1;2439:63:0::1;::::0;::::1;14121:21:1::0;14178:2;14158:18;;;14151:30;14217:33;14197:18;;;14190:61;14268:18;;2439:63:0::1;13937:355:1::0;2439:63:0::1;1849:1;2580:7;:18:::0;111210:28:::2;111229:8:::0;111210:18:::2;:28::i;:::-;-1:-1:-1::0;1805:1:0::1;2759:7;:22:::0;111122:124::o;78876:1007::-;78965:7;79001:16;79011:5;79001:9;:16::i;:::-;78993:5;:24;78985:71;;;;-1:-1:-1;;;78985:71:0;;14499:2:1;78985:71:0;;;14481:21:1;14538:2;14518:18;;;14511:30;14577:34;14557:18;;;14550:62;-1:-1:-1;;;14628:18:1;;;14621:32;14670:19;;78985:71:0;14297:398:1;78985:71:0;79067:22;78292:12;;;79067:22;;79330:466;79350:14;79346:1;:18;79330:466;;;79390:31;79424:14;;;:11;:14;;;;;;;;;79390:48;;;;;;;;;-1:-1:-1;;;;;79390:48:0;;;;;-1:-1:-1;;;79390:48:0;;;-1:-1:-1;;;;;79390:48:0;;;;;;;;79461:28;79457:111;;79534:14;;;-1:-1:-1;79457:111:0;79611:5;-1:-1:-1;;;;;79590:26:0;:17;-1:-1:-1;;;;;79590:26:0;;79586:195;;79660:5;79645:11;:20;79641:85;;-1:-1:-1;79701:1:0;-1:-1:-1;79694:8:0;;-1:-1:-1;;;79694:8:0;79641:85;79748:13;;;;;79586:195;-1:-1:-1;79366:3:0;;79330:466;;;-1:-1:-1;79819:56:0;;-1:-1:-1;;;79819:56:0;;14902:2:1;79819:56:0;;;14884:21:1;14941:2;14921:18;;;14914:30;14980:34;14960:18;;;14953:62;-1:-1:-1;;;15031:18:1;;;15024:44;15085:19;;79819:56:0;14700:410:1;110929:185:0;30026:13;:11;:13::i;:::-;1849:1:::1;2447:7;;:19:::0;2439:63:::1;;;::::0;-1:-1:-1;;;2439:63:0;;14139:2:1;2439:63:0::1;::::0;::::1;14121:21:1::0;14178:2;14158:18;;;14151:30;14217:33;14197:18;;;14190:61;14268:18;;2439:63:0::1;13937:355:1::0;2439:63:0::1;1849:1;2580:7;:18:::0;111011:49:::2;::::0;110993:12:::2;::::0;111011:10:::2;::::0;111034:21:::2;::::0;110993:12;111011:49;110993:12;111011:49;111034:21;111011:10;:49:::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110992:68;;;111079:7;111071:35;;;::::0;-1:-1:-1;;;111071:35:0;;15527:2:1;111071:35:0::2;::::0;::::2;15509:21:1::0;15566:2;15546:18;;;15539:30;-1:-1:-1;;;15585:18:1;;;15578:45;15640:18;;111071:35:0::2;15325:339:1::0;84520:185:0;84658:39;84675:4;84681:2;84685:7;84658:39;;;;;;;;;;;;:16;:39::i;78389:187::-;78456:7;78292:12;;78484:5;:21;78476:69;;;;-1:-1:-1;;;78476:69:0;;15871:2:1;78476:69:0;;;15853:21:1;15910:2;15890:18;;;15883:30;15949:34;15929:18;;;15922:62;-1:-1:-1;;;16000:18:1;;;15993:33;16043:19;;78476:69:0;15669:399:1;78476:69:0;-1:-1:-1;78563:5:0;78389:187::o;100110:989::-;100214:10;;100243:11;;;;100235:37;;;;-1:-1:-1;;;100235:37:0;;;;;;;:::i;:::-;100383:14;;100365:15;;100350:12;;100337:10;;100325:9;;:22;;;;:::i;:::-;:37;;;;:::i;:::-;:55;;;;:::i;:::-;:72;;;;:::i;:::-;100324:78;;100401:1;100324:78;:::i;:::-;100307:14;100291:13;78265:7;78292:12;;78212:100;100291:13;:30;;;;:::i;:::-;:111;100283:139;;;;-1:-1:-1;;;100283:139:0;;;;;;;:::i;:::-;100486:11;;100454:10;100441:24;;;;:12;:24;;;;;;:41;;100468:14;;100441:41;:::i;:::-;:56;;100433:88;;;;-1:-1:-1;;;100433:88:0;;;;;;;:::i;:::-;100553:21;100570:4;100553:14;:21;:::i;:::-;100540:9;:34;;100532:66;;;;-1:-1:-1;;;100532:66:0;;;;;;;:::i;:::-;100619:17;100639:12;100662:40;100680:4;100687:14;100662:9;:40::i;:::-;100727:6;100723:369;100743:14;100739:1;:18;100723:369;;;-1:-1:-1;;;;;100779:11:0;;;;;;:7;:11;;;;;:18;;:23;;100801:1;;100779:11;:23;;100801:1;;100779:23;:::i;:::-;;;;-1:-1:-1;;;;;;;100817:11:0;;;;;;:7;:11;;;;;:38;;100842:12;100817:24;:38::i;:::-;-1:-1:-1;100926:8:0;;100908:26;;:15;:26;:::i;:::-;100870:24;;;;:10;:24;;;;;;;;:35;;;:64;;;;100987:15;100949:53;;;101017:15;:29;;;:34;;-1:-1:-1;;;;;;101017:34:0;-1:-1:-1;;;;;101017:34:0;;;;;100870:24;101066:14;100870:24;101066:14;:::i;:::-;;;;100759:3;;;;;:::i;:::-;;;;100723:369;;;;100191:908;;100110:989;;:::o;110017:108::-;30026:13;:11;:13::i;:::-;110092:15:::1;:25:::0;110017:108::o;110365:102::-;30026:13;:11;:13::i;:::-;110441:7:::1;:18;110451:8:::0;;110441:7;:18:::1;:::i;109815:84::-:0;30026:13;:11;:13::i;:::-;109883:8:::1;::::0;;-1:-1:-1;;109871:20:0;::::1;109883:8;::::0;;;::::1;;;109882:9;109871:20:::0;;::::1;;::::0;;109815:84::o;104583:893::-;104741:5;;104765:11;;;;104757:37;;;;-1:-1:-1;;;104757:37:0;;;;;;;:::i;:::-;104858:11;;104826:10;104813:24;;;;:12;:24;;;;;;:41;;104840:14;;104813:41;:::i;:::-;:56;;104805:88;;;;-1:-1:-1;;;104805:88:0;;;;;;;:::i;:::-;104971:12;;104958:10;;104946:9;;:22;;;;:::i;:::-;:37;;;;:::i;:::-;104945:44;;104988:1;104945:44;:::i;:::-;104928:14;104912:13;78265:7;78292:12;;78212:100;104912:13;:30;;;;:::i;:::-;:77;104904:105;;;;-1:-1:-1;;;104904:105:0;;;;;;;:::i;:::-;105041:21;105058:4;105041:14;:21;:::i;:::-;105028:9;:34;;105020:66;;;;-1:-1:-1;;;105020:66:0;;;;;;;:::i;:::-;105142:28;105154:4;105160:9;105142:11;:28::i;:::-;105134:68;;;;-1:-1:-1;;;105134:68:0;;20118:2:1;105134:68:0;;;20100:21:1;20157:2;20137:18;;;20130:30;20196:29;20176:18;;;20169:57;20243:18;;105134:68:0;19916:351:1;105134:68:0;105222:11;105234:5;105222:18;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;105221:19;105213:43;;;;-1:-1:-1;;;105213:43:0;;20768:2:1;105213:43:0;;;20750:21:1;20807:2;20787:18;;;20780:30;-1:-1:-1;;;20826:18:1;;;20819:41;20877:18;;105213:43:0;20566:335:1;105213:43:0;105316:4;105275:37;105291:10;105303:1;105306:5;105275:15;:37::i;:::-;:45;105267:69;;;;-1:-1:-1;;;105267:69:0;;21108:2:1;105267:69:0;;;21090:21:1;21147:2;21127:18;;;21120:30;-1:-1:-1;;;21166:18:1;;;21159:41;21217:18;;105267:69:0;20906:335:1;105267:69:0;105363:10;105350:24;;;;:12;:24;;;;;:42;;105378:14;;105350:24;:42;;105378:14;;105350:42;:::i;:::-;;;;;;;;105424:4;105403:11;105415:5;105403:18;;;;;;:::i;:::-;;;;;;;;;;;;;;:25;;;;;-1:-1:-1;;105403:25:0;;;;;;;;;105439:29;105449:2;105453:14;105439:9;:29::i;:::-;104718:758;104583:893;;;;;:::o;81650:124::-;81714:7;81741:20;81753:7;81741:11;:20::i;:::-;:25;;81650:124;-1:-1:-1;;81650:124:0:o;102622:1953::-;102726:10;;102824:11;;102714:9;;102791:14;;102824:11;;102816:37;;;;-1:-1:-1;;;102816:37:0;;;;;;;:::i;:::-;102906:12;;102898:47;;-1:-1:-1;;;102898:47:0;;102866:29;;-1:-1:-1;;;;;102906:12:0;;102898:32;;:47;;102931:10;;102943:1;;102898:47;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;102898:47:0;;;;;;;;;;;;:::i;:::-;102972:13;;102964:44;;-1:-1:-1;;;102964:44:0;;102997:10;102964:44;;;2279:51:1;102866:79:0;;-1:-1:-1;103011:1:0;;-1:-1:-1;;;;;102972:13:0;;;;102964:32;;2252:18:1;;102964:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:48;:75;;;;103038:1;103016:12;:19;:23;102964:75;102956:123;;;;-1:-1:-1;;;102956:123:0;;;;;;;:::i;:::-;103133:13;;103125:44;;-1:-1:-1;;;103125:44:0;;103158:10;103125:44;;;2279:51:1;103100:22:0;;-1:-1:-1;;;;;103133:13:0;;103125:32;;2252:18:1;;103125:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103100:69;;103185:6;103180:351;103201:17;103197:1;:21;103180:351;;;103276:13;;103258:67;;-1:-1:-1;;;103258:67:0;;103240:15;;-1:-1:-1;;;;;103276:13:0;;103258:52;;:67;;103311:10;;103323:1;;103258:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103345:29;;;;:20;:29;;;;;;103240:85;;-1:-1:-1;103345:29:0;;103344:30;:44;;;;;103387:1;103378:6;:10;103344:44;103340:180;;;103410:29;;;;:20;:29;;;;;:36;;-1:-1:-1;;103410:36:0;103442:4;103410:36;;;103465:12;;;;:::i;:::-;;;;103496:8;;;;;:::i;:::-;;;;103340:180;-1:-1:-1;103220:3:0;;;;:::i;:::-;;;;103180:351;;;;103546:6;103541:301;103562:12;:19;103558:1;:23;103541:301;;;103603:15;103621:12;103634:1;103621:15;;;;;;;;:::i;:::-;;;;;;;;;;;;103656:29;;;;:20;:29;;;;;;;;103621:15;;-1:-1:-1;103656:29:0;;103655:30;:44;;;;;103698:1;103689:6;:10;103655:44;103651:180;;;103721:29;;;;:20;:29;;;;;:36;;-1:-1:-1;;103721:36:0;103753:4;103721:36;;;103776:12;;;;:::i;:::-;;;;103807:8;;;;;:::i;:::-;;;;103651:180;-1:-1:-1;103583:3:0;;;;:::i;:::-;;;;103541:301;;;;103917:15;;103904:10;;103892:9;;:22;;;;:::i;:::-;:40;;;;:::i;:::-;103891:46;;103936:1;103891:46;:::i;:::-;103878:10;103862:13;78265:7;78292:12;;78212:100;103862:13;:26;;;;:::i;:::-;:75;103854:103;;;;-1:-1:-1;;;103854:103:0;;;;;;;:::i;:::-;103989:17;104002:4;103989:10;:17;:::i;:::-;103976:9;:30;;103968:62;;;;-1:-1:-1;;;103968:62:0;;;;;;;:::i;:::-;104062:1;104049:10;:14;104041:57;;;;-1:-1:-1;;;104041:57:0;;23487:2:1;104041:57:0;;;23469:21:1;23526:2;23506:18;;;23499:30;23565:32;23545:18;;;23538:60;23615:18;;104041:57:0;23285:354:1;104041:57:0;104111:17;104131:12;104154:36;104172:4;104179:10;104154:9;:36::i;:::-;104207:6;104203:365;104223:10;104219:1;:14;104203:365;;;-1:-1:-1;;;;;104255:11:0;;;;;;:7;:11;;;;;:18;;:23;;104277:1;;104255:11;:23;;104277:1;;104255:23;:::i;:::-;;;;-1:-1:-1;;;;;;;104293:11:0;;;;;;:7;:11;;;;;:38;;104318:12;104293:24;:38::i;:::-;-1:-1:-1;104402:8:0;;104384:26;;:15;:26;:::i;:::-;104346:24;;;;:10;:24;;;;;;;;:35;;;:64;;;;104463:15;104425:53;;;104493:15;:29;;;:34;;-1:-1:-1;;;;;;104493:34:0;-1:-1:-1;;;;;104493:34:0;;;;;104346:24;104542:14;104346:24;104542:14;:::i;:::-;;;;104235:3;;;;;:::i;:::-;;;;104203:365;;;;102703:1872;;;;;;102622:1953;;:::o;111925:279::-;112046:7;112072:12;112124:6;112132;112140:5;112155:4;112107:54;;;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;112107:54:0;;;;;;112087:85;;112107:54;112087:85;;;;;111925:279;-1:-1:-1;;;;;111925:279:0:o;107488:800::-;107565:44;;-1:-1:-1;;;107565:44:0;;107598:10;107565:44;;;2279:51:1;107613:1:0;;107581:4;;107565:32;;2252:18:1;;107565:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:49;;107557:87;;;;-1:-1:-1;;;107557:87:0;;24450:2:1;107557:87:0;;;24432:21:1;24489:2;24469:18;;;24462:30;-1:-1:-1;;;24508:18:1;;;24501:55;24573:18;;107557:87:0;24248:349:1;107557:87:0;107670:6;107665:616;107686:9;:16;107682:1;:20;107665:616;;;107798:10;-1:-1:-1;;;;;107750:58:0;107766:4;-1:-1:-1;;;;;107750:30:0;;107781:9;107791:1;107781:12;;;;;;;;:::i;:::-;;;;;;;107750:44;;;;;;;;;;;;;2815:25:1;;2803:2;2788:18;;2669:177;107750:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;107750:58:0;;107724:143;;;;-1:-1:-1;;;107724:143:0;;25068:2:1;107724:143:0;;;25050:21:1;25107:2;25087:18;;;25080:30;-1:-1:-1;;;25126:18:1;;;25119:53;25189:18;;107724:143:0;24866:347:1;107724:143:0;107890:10;107882:19;;;;:7;:19;;;;;:26;;:31;;107912:1;;107882:19;:31;;107912:1;;107882:31;:::i;:::-;;;;;;;;107928:46;107961:9;107971:1;107961:12;;;;;;;;:::i;:::-;;;;;;;;;;;;107936:10;107928:19;;;;:7;:19;;;;;;;;:32;:46::i;:::-;-1:-1:-1;108045:8:0;;108027:26;;:15;:26;:::i;:::-;107989:10;:24;108000:9;108010:1;108000:12;;;;;;;;:::i;:::-;;;;;;;107989:24;;;;;;;;;;;:35;;:64;;;;108106:15;108068:10;:24;108079:9;108089:1;108079:12;;;;;;;;:::i;:::-;;;;;;;108068:24;;;;;;;;;;;:35;;:53;;;;108168:10;108136:15;:29;108152:9;108162:1;108152:12;;;;;;;;:::i;:::-;;;;;;;108136:29;;;;;;;;;;;;:42;;;;;-1:-1:-1;;;;;108136:42:0;;;;;-1:-1:-1;;;;;108136:42:0;;;;;;108209:4;-1:-1:-1;;;;;108193:35:0;;108229:10;108249:4;108256:9;108266:1;108256:12;;;;;;;;:::i;:::-;;;;;;;108193:76;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107704:3;;;;;:::i;:::-;;;;107665:616;;93969:28;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;106835:645::-;106897:44;;-1:-1:-1;;;106897:44:0;;106930:10;106897:44;;;2279:51:1;106945:1:0;;106913:4;;106897:32;;2252:18:1;;106897:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:49;;106889:87;;;;-1:-1:-1;;;106889:87:0;;24450:2:1;106889:87:0;;;24432:21:1;24489:2;24469:18;;;24462:30;-1:-1:-1;;;24508:18:1;;;24501:55;24573:18;;106889:87:0;24248:349:1;106889:87:0;107009:40;;-1:-1:-1;;;107009:40:0;;;;;2815:25:1;;;107053:10:0;;107025:4;;107009:30;;2788:18:1;;107009:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;107009:54:0;;106987:127;;;;-1:-1:-1;;;106987:127:0;;25068:2:1;106987:127:0;;;25050:21:1;25107:2;25087:18;;;25080:30;-1:-1:-1;;;25126:18:1;;;25119:53;25189:18;;106987:127:0;24866:347:1;106987:127:0;107133:10;107125:19;;;;:7;:19;;;;;:26;;:31;;107155:1;;107125:19;:31;;107155:1;;107125:31;:::i;:::-;;;;-1:-1:-1;;107175:10:0;107167:19;;;;:7;:19;;;;;:42;;107200:8;107167:32;:42::i;:::-;-1:-1:-1;107272:8:0;;107254:26;;:15;:26;:::i;:::-;107220:20;;;;:10;:20;;;;;;;;:31;;;:60;;;;107325:15;107291:49;;;107351:15;:25;;;;;:38;;-1:-1:-1;;;;;;107351:38:0;107379:10;107351:38;;;;;;107400:72;;-1:-1:-1;;;107400:72:0;;107416:4;;107400:35;;:72;;107379:10;107416:4;;107231:8;;107400:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80391:221;80455:7;-1:-1:-1;;;;;80483:19:0;;80475:75;;;;-1:-1:-1;;;80475:75:0;;25800:2:1;80475:75:0;;;25782:21:1;25839:2;25819:18;;;25812:30;25878:34;25858:18;;;25851:62;-1:-1:-1;;;25929:18:1;;;25922:41;25980:19;;80475:75:0;25598:407:1;80475:75:0;-1:-1:-1;;;;;;80576:19:0;;;;;:12;:19;;;;;:27;-1:-1:-1;;;;;80576:27:0;;80391:221::o;30788:103::-;30026:13;:11;:13::i;:::-;30853:30:::1;30880:1;30853:18;:30::i;:::-;30788:103::o:0;108931:779::-;109006:10;109027:1;108998:19;;;:7;:19;;;;;:26;;;108976:103;;;;-1:-1:-1;;;108976:103:0;;26212:2:1;108976:103:0;;;26194:21:1;26251:2;26231:18;;;26224:30;-1:-1:-1;;;26270:18:1;;;26263:53;26333:18;;108976:103:0;26010:347:1;108976:103:0;109117:10;109090:16;109109:19;;;:7;:19;;;;;:37;;:35;:37::i;:::-;109090:56;;109163:6;109159:544;109179:11;109175:1;:15;109159:544;;;109235:10;109212:12;109227:19;;;:7;:19;;;;;:34;;109212:12;109227:31;:34::i;:::-;109279:24;;;;:15;:24;;;;;;109212:49;;-1:-1:-1;;;;;;109279:24:0;109307:10;109279:38;:91;;;;-1:-1:-1;109340:19:0;;;;:10;:19;;;;;:30;;;109321:15;:49;;109279:91;109276:416;;;109399:10;109391:19;;;;:7;:19;;;;;:26;;:31;;109421:1;;109391:19;:31;;109421:1;;109391:31;:::i;:::-;;;;-1:-1:-1;;109476:1:0;109441:24;;;:15;:24;;;;;;;;:37;;-1:-1:-1;;;;;;109441:37:0;;;109526:10;109518:19;;:7;:19;;;;;109556:26;109518:19;109457:7;109556:17;:26::i;:::-;-1:-1:-1;109603:71:0;;-1:-1:-1;;;109603:71:0;;109619:4;;109603:35;;:71;;109619:4;;109654:10;;109666:7;;109603:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109372:320;109276:416;-1:-1:-1;109192:3:0;;;;:::i;:::-;;;;109159:544;;109718:89;30026:13;:11;:13::i;:::-;109788:11:::1;::::0;;-1:-1:-1;;109773:26:0;::::1;109788:11;::::0;;::::1;109787:12;109773:26;::::0;;109718:89::o;93932:30::-;;;;;;;:::i;111254:135::-;-1:-1:-1;;;;;;;;;;;;;;;;;111361:20:0;111373:7;111361:11;:20::i;82010:104::-;82066:13;82099:7;82092:14;;;;;:::i;111397:335::-;-1:-1:-1;;;;;111525:15:0;;111484:24;111525:15;;;:7;:15;;;;;111455:16;;111484:24;111525:33;;:31;:33::i;:::-;-1:-1:-1;;;;;111511:48:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;111511:48:0;;111484:75;;111574:6;111570:130;-1:-1:-1;;;;;111590:15:0;;;;;;:7;:15;;;;;:33;;:31;:33::i;:::-;111586:1;:37;111570:130;;;-1:-1:-1;;;;;111658:15:0;;;;;;:7;:15;;;;;:30;;111686:1;111658:27;:30::i;:::-;111645:7;111653:1;111645:10;;;;;;;;:::i;:::-;;;;;;;;;;:43;111625:3;;;;:::i;:::-;;;;111570:130;;;-1:-1:-1;111717:7:0;111397:335;-1:-1:-1;;111397:335:0:o;83689:288::-;28771:10;-1:-1:-1;;;;;83784:24:0;;;83776:63;;;;-1:-1:-1;;;83776:63:0;;26564:2:1;83776:63:0;;;26546:21:1;26603:2;26583:18;;;26576:30;26642:28;26622:18;;;26615:56;26688:18;;83776:63:0;26362:350:1;83776:63:0;28771:10;83852:32;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;83852:42:0;;;;;;;;;;;;:53;;-1:-1:-1;;83852:53:0;;;;;;;;;;83921:48;;540:41:1;;;83852:42:0;;28771:10;83921:48;;513:18:1;83921:48:0;;;;;;;83689:288;;:::o;99262:256::-;30026:13;:11;:13::i;:::-;99354:11:::1;::::0;::::1;;99346:37;;;;-1:-1:-1::0;;;99346:37:0::1;;;;;;;:::i;:::-;99435:9;::::0;:13:::1;::::0;99447:1:::1;99435:13;:::i;:::-;99418:14;99402:13;78265:7:::0;78292:12;;78212:100;99402:13:::1;:30;;;;:::i;:::-;:46;99394:74;;;;-1:-1:-1::0;;;99394:74:0::1;;;;;;;:::i;:::-;99481:29;99491:2;99495:14;99481:9;:29::i;84776:355::-:0;84935:28;84945:4;84951:2;84955:7;84935:9;:28::i;:::-;84996:48;85019:4;85025:2;85029:7;85038:5;84996:22;:48::i;:::-;84974:149;;;;-1:-1:-1;;;84974:149:0;;;;;;;:::i;:::-;84776:355;;;;:::o;110247:110::-;30026:13;:11;:13::i;:::-;110327:9:::1;:22;110339:10:::0;;110327:9;:22:::1;:::i;108296:627::-:0;108379:20;;;;:10;:20;;;;;:31;;;108360:15;:50;;108352:96;;;;-1:-1:-1;;;108352:96:0;;27339:2:1;108352:96:0;;;27321:21:1;27378:2;27358:18;;;27351:30;27417:34;27397:18;;;27390:62;-1:-1:-1;;;27468:18:1;;;27461:31;27509:19;;108352:96:0;27137:397:1;108352:96:0;108489:10;108510:1;108481:19;;;:7;:19;;;;;:26;;;108459:103;;;;-1:-1:-1;;;108459:103:0;;26212:2:1;108459:103:0;;;26194:21:1;26251:2;26231:18;;;26224:30;-1:-1:-1;;;26270:18:1;;;26263:53;26333:18;;108459:103:0;26010:347:1;108459:103:0;108581:25;;;;:15;:25;;;;;;-1:-1:-1;;;;;108581:25:0;108610:10;108581:39;108573:77;;;;-1:-1:-1;;;108573:77:0;;27741:2:1;108573:77:0;;;27723:21:1;27780:2;27760:18;;;27753:30;27819:27;27799:18;;;27792:55;27864:18;;108573:77:0;27539:349:1;108573:77:0;108669:10;108661:19;;;;:7;:19;;;;;:26;;:31;;108691:1;;108661:19;:31;;108691:1;;108661:31;:::i;:::-;;;;-1:-1:-1;;108739:1:0;108703:25;;;:15;:25;;;;;;;;:38;;-1:-1:-1;;;;;;108703:38:0;;;108781:10;108773:19;;:7;:19;;;;;108803:27;108773:19;108719:8;108803:17;:27::i;:::-;-1:-1:-1;108843:72:0;;-1:-1:-1;;;108843:72:0;;108859:4;;108843:35;;:72;;108859:4;;108894:10;;108906:8;;108843:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110475:330;110540:13;110574:16;110582:7;85443:4;85477:12;-1:-1:-1;85467:22:0;85386:111;110574:16;110566:48;;;;-1:-1:-1;;;110566:48:0;;28095:2:1;110566:48:0;;;28077:21:1;28134:2;28114:18;;;28107:30;-1:-1:-1;;;28153:18:1;;;28146:49;28212:18;;110566:48:0;27893:343:1;110566:48:0;110631:8;;;;;;;110627:142;;;110669:7;110663:21;;;;;:::i;:::-;;;110688:1;110663:26;:94;;;;;;;;;;;;;;;;;110716:7;110725:25;110742:7;110725:16;:25::i;:::-;110699:52;;;;;;;;;:::i;:::-;;;;;;;;;;;;;110656:101;110475:330;-1:-1:-1;;110475:330:0:o;110627:142::-;110788:9;110781:16;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110475:330;;;:::o;99526:576::-;99622:5;;99646:11;;;;99638:37;;;;-1:-1:-1;;;99638:37:0;;;;;;;:::i;:::-;99786:14;;99768:15;;99753:12;;99740:10;;99728:9;;:22;;;;:::i;:::-;:37;;;;:::i;:::-;:55;;;;:::i;:::-;:72;;;;:::i;:::-;99727:78;;99804:1;99727:78;:::i;:::-;99710:14;99694:13;78265:7;78292:12;;78212:100;99694:13;:30;;;;:::i;:::-;:111;99686:139;;;;-1:-1:-1;;;99686:139:0;;;;;;;:::i;:::-;99889:11;;99857:10;99844:24;;;;:12;:24;;;;;;:41;;99871:14;;99844:41;:::i;:::-;:56;;99836:88;;;;-1:-1:-1;;;99836:88:0;;;;;;;:::i;:::-;99956:21;99973:4;99956:14;:21;:::i;:::-;99943:9;:34;;99935:66;;;;-1:-1:-1;;;99935:66:0;;;;;;;:::i;:::-;100025:10;100012:24;;;;:12;:24;;;;;:42;;100040:14;;100012:24;:42;;100040:14;;100012:42;:::i;:::-;;;;-1:-1:-1;100065:29:0;;-1:-1:-1;100075:2:0;100079:14;100065:9;:29::i;105484:1343::-;105650:10;;105679:11;;;;105671:37;;;;-1:-1:-1;;;105671:37:0;;;;;;;:::i;:::-;105772:11;;105740:10;105727:24;;;;:12;:24;;;;;;:41;;105754:14;;105727:41;:::i;:::-;:56;;105719:88;;;;-1:-1:-1;;;105719:88:0;;;;;;;:::i;:::-;105885:12;;105872:10;;105860:9;;:22;;;;:::i;:::-;:37;;;;:::i;:::-;105859:44;;105902:1;105859:44;:::i;:::-;105842:14;105826:13;78265:7;78292:12;;78212:100;105826:13;:30;;;;:::i;:::-;:77;105818:105;;;;-1:-1:-1;;;105818:105:0;;;;;;;:::i;:::-;105955:21;105972:4;105955:14;:21;:::i;:::-;105942:9;:34;;105934:66;;;;-1:-1:-1;;;105934:66:0;;;;;;;:::i;:::-;106056:28;106068:4;106074:9;106056:11;:28::i;:::-;106048:68;;;;-1:-1:-1;;;106048:68:0;;20118:2:1;106048:68:0;;;20100:21:1;20157:2;20137:18;;;20130:30;20196:29;20176:18;;;20169:57;20243:18;;106048:68:0;19916:351:1;106048:68:0;106136:11;106148:5;106136:18;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;106135:19;106127:43;;;;-1:-1:-1;;;106127:43:0;;20768:2:1;106127:43:0;;;20750:21:1;20807:2;20787:18;;;20780:30;-1:-1:-1;;;20826:18:1;;;20819:41;20877:18;;106127:43:0;20566:335:1;106127:43:0;106230:4;106189:37;106205:10;106217:1;106220:5;106189:15;:37::i;:::-;:45;106181:69;;;;-1:-1:-1;;;106181:69:0;;21108:2:1;106181:69:0;;;21090:21:1;21147:2;21127:18;;;21120:30;-1:-1:-1;;;21166:18:1;;;21159:41;21217:18;;106181:69:0;20906:335:1;106181:69:0;106277:10;106264:24;;;;:12;:24;;;;;:42;;106292:14;;106264:24;:42;;106292:14;;106264:42;:::i;:::-;;;;;;;;106338:4;106317:11;106329:5;106317:18;;;;;;:::i;:::-;;;;;;;;;;;;;;:25;;;;;-1:-1:-1;;106317:25:0;;;;;;;;;:18;106375:12;106398:40;106416:4;106423:14;106398:9;:40::i;:::-;106455:6;106451:369;106471:14;106467:1;:18;106451:369;;;-1:-1:-1;;;;;106507:11:0;;;;;;:7;:11;;;;;:18;;:23;;106529:1;;106507:11;:23;;106529:1;;106507:23;:::i;:::-;;;;-1:-1:-1;;;;;;;106545:11:0;;;;;;:7;:11;;;;;:38;;106570:12;106545:24;:38::i;:::-;-1:-1:-1;106654:8:0;;106636:26;;:15;:26;:::i;:::-;106598:24;;;;:10;:24;;;;;;;;:35;;;:64;;;;106715:15;106677:53;;;106745:15;:29;;;:34;;-1:-1:-1;;;;;;106745:34:0;-1:-1:-1;;;;;106745:34:0;;;;;106598:24;106794:14;106598:24;106794:14;:::i;:::-;;;;106487:3;;;;;:::i;:::-;;;;106451:369;;;;105627:1200;;105484:1343;;;;;:::o;111740:177::-;111820:4;111861:48;111899:9;111861:29;:4;26899:58;;36838:66:1;26899:58:0;;;36826:79:1;36921:12;;;36914:28;;;26766:7:0;;36958:12:1;;26899:58:0;;;;;;;;;;;;26889:69;;;;;;26882:76;;26697:269;;;;111861:29;:37;;:48::i;:::-;111844:13;;-1:-1:-1;;;;;111844:65:0;;;:13;;:65;;111740:177;-1:-1:-1;;;111740:177:0:o;101107:1507::-;101203:5;;101296:11;;101191:9;;101263:14;;101296:11;;101288:37;;;;-1:-1:-1;;;101288:37:0;;;;;;;:::i;:::-;101378:12;;101370:47;;-1:-1:-1;;;101370:47:0;;101338:29;;-1:-1:-1;;;;;101378:12:0;;101370:32;;:47;;101403:10;;101415:1;;101370:47;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;101370:47:0;;;;;;;;;;;;:::i;:::-;101444:13;;101436:44;;-1:-1:-1;;;101436:44:0;;101469:10;101436:44;;;2279:51:1;101338:79:0;;-1:-1:-1;101483:1:0;;-1:-1:-1;;;;;101444:13:0;;;;101436:32;;2252:18:1;;101436:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:48;:75;;;;101510:1;101488:12;:19;:23;101436:75;101428:123;;;;-1:-1:-1;;;101428:123:0;;;;;;;:::i;:::-;101605:13;;101597:44;;-1:-1:-1;;;101597:44:0;;101630:10;101597:44;;;2279:51:1;101572:22:0;;-1:-1:-1;;;;;101605:13:0;;101597:32;;2252:18:1;;101597:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101572:69;;101657:6;101652:351;101673:17;101669:1;:21;101652:351;;;101748:13;;101730:67;;-1:-1:-1;;;101730:67:0;;101712:15;;-1:-1:-1;;;;;101748:13:0;;101730:52;;:67;;101783:10;;101795:1;;101730:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101817:29;;;;:20;:29;;;;;;101712:85;;-1:-1:-1;101817:29:0;;101816:30;:44;;;;;101859:1;101850:6;:10;101816:44;101812:180;;;101882:29;;;;:20;:29;;;;;:36;;-1:-1:-1;;101882:36:0;101914:4;101882:36;;;101937:12;;;;:::i;:::-;;;;101968:8;;;;;:::i;:::-;;;;101812:180;-1:-1:-1;101692:3:0;;;;:::i;:::-;;;;101652:351;;;;102018:6;102013:301;102034:12;:19;102030:1;:23;102013:301;;;102075:15;102093:12;102106:1;102093:15;;;;;;;;:::i;:::-;;;;;;;;;;;;102128:29;;;;:20;:29;;;;;;;;102093:15;;-1:-1:-1;102128:29:0;;102127:30;:44;;;;;102170:1;102161:6;:10;102127:44;102123:180;;;102193:29;;;;:20;:29;;;;;:36;;-1:-1:-1;;102193:36:0;102225:4;102193:36;;;102248:12;;;;:::i;:::-;;;;102279:8;;;;;:::i;:::-;;;;102123:180;-1:-1:-1;102055:3:0;;;;:::i;:::-;;;;102013:301;;;;102389:15;;102376:10;;102364:9;;:22;;;;:::i;:::-;:40;;;;:::i;:::-;102363:46;;102408:1;102363:46;:::i;:::-;102350:10;102334:13;78265:7;78292:12;;78212:100;102334:13;:26;;;;:::i;:::-;:75;102326:103;;;;-1:-1:-1;;;102326:103:0;;;;;;;:::i;:::-;102461:17;102474:4;102461:10;:17;:::i;:::-;102448:9;:30;;102440:62;;;;-1:-1:-1;;;102440:62:0;;;;;;;:::i;:::-;102534:1;102521:10;:14;102513:57;;;;-1:-1:-1;;;102513:57:0;;23487:2:1;102513:57:0;;;23469:21:1;23526:2;23506:18;;;23499:30;23565:32;23545:18;;;23538:60;23615:18;;102513:57:0;23285:354:1;102513:57:0;102581:25;102591:2;102595:10;102581:9;:25::i;:::-;101180:1434;;;;;101107:1507;;:::o;31046:201::-;30026:13;:11;:13::i;:::-;-1:-1:-1;;;;;31135:22:0;::::1;31127:73;;;::::0;-1:-1:-1;;;31127:73:0;;29468:2:1;31127:73:0::1;::::0;::::1;29450:21:1::0;29507:2;29487:18;;;29480:30;29546:34;29526:18;;;29519:62;-1:-1:-1;;;29597:18:1;;;29590:36;29643:19;;31127:73:0::1;29266:402:1::0;31127:73:0::1;31211:28;31230:8;31211:18;:28::i;:::-;31046:201:::0;:::o;95358:3896::-;95446:11;;95408:15;;95446:11;;95438:37;;;;-1:-1:-1;;;95438:37:0;;;;;;;:::i;:::-;95526:12;;95518:47;;-1:-1:-1;;;95518:47:0;;95488:27;;-1:-1:-1;;;;;95526:12:0;;95518:32;;:47;;95551:10;;95488:27;;95518:47;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;95518:47:0;;;;;;;;;;;;:::i;:::-;95616:12;;95608:47;;-1:-1:-1;;;95608:47:0;;95488:77;;-1:-1:-1;95576:29:0;;-1:-1:-1;;;;;95616:12:0;;;;95608:32;;:47;;95641:10;;95616:12;;95608:47;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;95608:47:0;;;;;;;;;;;;:::i;:::-;95706:12;;95698:47;;-1:-1:-1;;;95698:47:0;;95576:79;;-1:-1:-1;95666:29:0;;-1:-1:-1;;;;;95706:12:0;;;;95698:32;;:47;;95731:10;;95743:1;;95698:47;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;95698:47:0;;;;;;;;;;;;:::i;:::-;95774:11;;95766:42;;-1:-1:-1;;;95766:42:0;;95797:10;95766:42;;;2279:51:1;95666:79:0;;-1:-1:-1;95811:1:0;;-1:-1:-1;;;;;95774:11:0;;;;95766:30;;2252:18:1;;95766:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:46;:71;;;;95836:1;95816:10;:17;:21;95766:71;95758:131;;;;-1:-1:-1;;;95758:131:0;;30449:2:1;95758:131:0;;;30431:21:1;30488:2;30468:18;;;30461:30;30527:34;30507:18;;;30500:62;-1:-1:-1;;;30578:18:1;;;30571:45;30633:19;;95758:131:0;30247:411:1;95758:131:0;95916:13;;95908:44;;-1:-1:-1;;;95908:44:0;;95941:10;95908:44;;;2279:51:1;95955:1:0;;-1:-1:-1;;;;;95916:13:0;;95908:32;;2252:18:1;;95908:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:48;:100;;;-1:-1:-1;95968:13:0;;95960:44;;-1:-1:-1;;;95960:44:0;;95993:10;95960:44;;;2279:51:1;96007:1:0;;-1:-1:-1;;;;;95968:13:0;;95960:32;;2252:18:1;;95960:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:48;95908:100;:127;;;;96034:1;96012:12;:19;:23;95908:127;:154;;;;96061:1;96039:12;:19;:23;95908:154;95900:208;;;;-1:-1:-1;;;95900:208:0;;30865:2:1;95900:208:0;;;30847:21:1;30904:2;30884:18;;;30877:30;30943:34;30923:18;;;30916:62;-1:-1:-1;;;30994:18:1;;;30987:39;31043:19;;95900:208:0;30663:405:1;95900:208:0;96217:17;;96182:11;;96174:42;;-1:-1:-1;;;96174:42:0;;96205:10;96174:42;;;2279:51:1;96129:28:0;;96217:17;-1:-1:-1;;;;;96182:11:0;;96174:30;;2252:18:1;;96174:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:60;;;;:::i;:::-;-1:-1:-1;;;;;96160:75:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;96160:75:0;-1:-1:-1;96338:19:0;;96301:13;;96293:44;;-1:-1:-1;;;96293:44:0;;96326:10;96293:44;;;2279:51:1;96129:106:0;;-1:-1:-1;96246:30:0;;-1:-1:-1;;;;;96301:13:0;;;;96293:32;;2252:18:1;;96293:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:64;;;;:::i;:::-;-1:-1:-1;;;;;96279:79:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;96279:79:0;-1:-1:-1;96461:19:0;;96424:13;;96416:44;;-1:-1:-1;;;96416:44:0;;96449:10;96416:44;;;2279:51:1;96246:112:0;;-1:-1:-1;96369:30:0;;-1:-1:-1;;;;;96424:13:0;;;;96416:32;;2252:18:1;;96416:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:64;;;;:::i;:::-;-1:-1:-1;;;;;96402:79:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;96402:79:0;-1:-1:-1;96515:11:0;;96507:42;;-1:-1:-1;;;96507:42:0;;96538:10;96507:42;;;2279:51:1;96369:112:0;;-1:-1:-1;96494:10:0;;-1:-1:-1;;;;;96515:11:0;;;;96507:30;;2252:18:1;;96507:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96494:55;;96565:6;96560:219;96589:11;;96581:42;;-1:-1:-1;;;96581:42:0;;96612:10;96581:42;;;2279:51:1;-1:-1:-1;;;;;96589:11:0;;;;96581:30;;2252:18:1;;96581:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96577:1;:46;96560:219;;;96681:11;;96663:65;;-1:-1:-1;;;96663:65:0;;96645:15;;-1:-1:-1;;;;;96681:11:0;;96663:50;;:65;;96714:10;;96726:1;;96663:65;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96645:83;;96760:7;96743:11;96755:1;96743:14;;;;;;;;:::i;:::-;;;;;;;;;;:24;-1:-1:-1;96625:3:0;;;;:::i;:::-;;;;96560:219;;;;96794:6;96789:128;96810:10;:17;96806:1;:21;96789:128;;;96870:10;96881:1;96870:13;;;;;;;;:::i;:::-;;;;;;;96849:11;96861:5;96849:18;;;;;;;;:::i;:::-;;;;;;;;;;:34;96898:7;;;;:::i;:::-;;;;96829:3;;;;;:::i;:::-;;;;96789:128;;;-1:-1:-1;96945:13:0;;96937:44;;-1:-1:-1;;;96937:44:0;;96970:10;96937:44;;;2279:51:1;-1:-1:-1;;;;;96945:13:0;;;;96937:32;;2252:18:1;;96937:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96929:52;;96997:6;96992:225;97021:13;;97013:44;;-1:-1:-1;;;97013:44:0;;97046:10;97013:44;;;2279:51:1;-1:-1:-1;;;;;97021:13:0;;;;97013:32;;2252:18:1;;97013:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97009:1;:48;96992:225;;;97115:13;;97097:67;;-1:-1:-1;;;97097:67:0;;97079:15;;-1:-1:-1;;;;;97115:13:0;;97097:52;;:67;;97150:10;;97162:1;;97097:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97079:85;;97198:7;97179:13;97193:1;97179:16;;;;;;;;:::i;:::-;;;;;;;;;;:26;-1:-1:-1;97059:3:0;;;;:::i;:::-;;;;96992:225;;;;97232:6;97227:134;97248:12;:19;97244:1;:23;97227:134;;;97312:12;97325:1;97312:15;;;;;;;;:::i;:::-;;;;;;;97289:13;97303:5;97289:20;;;;;;;;:::i;:::-;;;;;;;;;;:38;97342:7;;;;:::i;:::-;;;;97269:3;;;;;:::i;:::-;;;;97227:134;;;-1:-1:-1;97389:13:0;;97381:44;;-1:-1:-1;;;97381:44:0;;97414:10;97381:44;;;2279:51:1;-1:-1:-1;;;;;97389:13:0;;;;97381:32;;2252:18:1;;97381:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97373:52;;97441:6;97436:225;97465:13;;97457:44;;-1:-1:-1;;;97457:44:0;;97490:10;97457:44;;;2279:51:1;-1:-1:-1;;;;;97465:13:0;;;;97457:32;;2252:18:1;;97457:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97453:1;:48;97436:225;;;97559:13;;97541:67;;-1:-1:-1;;;97541:67:0;;97523:15;;-1:-1:-1;;;;;97559:13:0;;97541:52;;:67;;97594:10;;97606:1;;97541:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97523:85;;97642:7;97623:13;97637:1;97623:16;;;;;;;;:::i;:::-;;;;;;;;;;:26;-1:-1:-1;97503:3:0;;;;:::i;:::-;;;;97436:225;;;;97676:6;97671:134;97692:12;:19;97688:1;:23;97671:134;;;97756:12;97769:1;97756:15;;;;;;;;:::i;:::-;;;;;;;97733:13;97747:5;97733:20;;;;;;;;:::i;:::-;;;;;;;;;;:38;97786:7;;;;:::i;:::-;;;;97713:3;;;;;:::i;:::-;;;;97671:134;;;;97822:6;97817:878;97838:11;:18;97834:1;:22;97817:878;;;97878:14;97895:11;97907:1;97895:14;;;;;;;;:::i;:::-;;;;;;;97878:31;;97929:6;97924:367;97945:13;:20;97941:1;:24;97924:367;;;97991:16;98010:13;98024:1;98010:16;;;;;;;;:::i;:::-;;;;;;;;;;;;98050:24;;;;:16;:24;;;;;;;;98010:16;;-1:-1:-1;98050:24:0;;98049:25;:58;;;;-1:-1:-1;98079:28:0;;;;:18;:28;;;;;;;;98078:29;98049:58;98045:231;;;98132:28;;;;:18;:28;;;;;;;;:35;;98163:4;-1:-1:-1;;98132:35:0;;;;;;;;98190:24;;;:16;:24;;;;;:31;;;;;;;;;;98244:12;;;;:::i;:::-;;;;98045:231;-1:-1:-1;97967:3:0;;;;:::i;:::-;;;;97924:367;;;;98310:6;98305:379;98326:13;:20;98322:1;:24;98305:379;;;98372:16;98391:13;98405:1;98391:16;;;;;;;;:::i;:::-;;;;;;;;;;;;98431:24;;;;:16;:24;;;;;;;;98391:16;;-1:-1:-1;98431:24:0;;98430:25;:64;;;;-1:-1:-1;98460:34:0;;;;:24;:34;;;;;;;;98459:35;98430:64;98426:243;;;98519:34;;;;:24;:34;;;;;;;;:41;;98556:4;-1:-1:-1;;98519:41:0;;;;;;;;98583:24;;;:16;:24;;;;;:31;;;;;;;;;;98637:12;;;;:::i;:::-;;;;98426:243;-1:-1:-1;98348:3:0;;;;:::i;:::-;;;;98305:379;;;;97863:832;97858:3;;;;;:::i;:::-;;;;97817:878;;;;98728:1;98715:10;:14;98707:72;;;;-1:-1:-1;;;98707:72:0;;31275:2:1;98707:72:0;;;31257:21:1;31314:2;31294:18;;;31287:30;31353:34;31333:18;;;31326:62;-1:-1:-1;;;31404:18:1;;;31397:43;31457:19;;98707:72:0;31073:409:1;98707:72:0;98790:17;98810:12;98833:36;98851:4;98858:10;98833:9;:36::i;:::-;98886:6;98882:365;98902:10;98898:1;:14;98882:365;;;-1:-1:-1;;;;;98934:11:0;;;;;;:7;:11;;;;;:18;;:23;;98956:1;;98934:11;:23;;98956:1;;98934:23;:::i;:::-;;;;-1:-1:-1;;;;;;;98972:11:0;;;;;;:7;:11;;;;;:38;;98997:12;98972:24;:38::i;:::-;-1:-1:-1;99081:8:0;;99063:26;;:15;:26;:::i;:::-;99025:24;;;;:10;:24;;;;;;;;:35;;;:64;;;;99142:15;99104:53;;;99172:15;:29;;;:34;;-1:-1:-1;;;;;;99172:34:0;-1:-1:-1;;;;;99172:34:0;;;;;99025:24;99221:14;99025:24;99221:14;:::i;:::-;;;;98914:3;;;;;:::i;:::-;;;;98882:365;;;;95397:3857;;;;;;;;;95358:3896;:::o;79955:372::-;80057:4;-1:-1:-1;;;;;;80094:40:0;;-1:-1:-1;;;80094:40:0;;:105;;-1:-1:-1;;;;;;;80151:48:0;;-1:-1:-1;;;80151:48:0;80094:105;:172;;;-1:-1:-1;;;;;;;80216:50:0;;-1:-1:-1;;;80216:50:0;80094:172;:225;;;-1:-1:-1;;;;;;;;;;44829:40:0;;;80283:36;44720:157;46270:215;46372:4;-1:-1:-1;;;;;;46396:41:0;;-1:-1:-1;;;46396:41:0;;:81;;;46441:36;46465:11;46441:23;:36::i;30305:132::-;30213:6;;-1:-1:-1;;;;;30213:6:0;28771:10;30369:23;30361:68;;;;-1:-1:-1;;;30361:68:0;;31689:2:1;30361:68:0;;;31671:21:1;;;31708:18;;;31701:30;31767:34;31747:18;;;31740:62;31819:18;;30361:68:0;31487:356:1;47632:332:0;47348:5;-1:-1:-1;;;;;47735:33:0;;;;47727:88;;;;-1:-1:-1;;;47727:88:0;;32050:2:1;47727:88:0;;;32032:21:1;32089:2;32069:18;;;32062:30;32128:34;32108:18;;;32101:62;-1:-1:-1;;;32179:18:1;;;32172:40;32229:19;;47727:88:0;31848:406:1;47727:88:0;-1:-1:-1;;;;;47834:22:0;;47826:60;;;;-1:-1:-1;;;47826:60:0;;32461:2:1;47826:60:0;;;32443:21:1;32500:2;32480:18;;;32473:30;32539:27;32519:18;;;32512:55;32584:18;;47826:60:0;32259:349:1;47826:60:0;47921:35;;;;;;;;;-1:-1:-1;;;;;47921:35:0;;;;;;-1:-1:-1;;;;;47921:35:0;;;;;;;;;;-1:-1:-1;;;47899:57:0;;;;:19;:57;47632:332::o;90306:196::-;90421:24;;;;:15;:24;;;;;;:29;;-1:-1:-1;;;;;;90421:29:0;-1:-1:-1;;;;;90421:29:0;;;;;;;;;90466:28;;90421:24;;90466:28;;;;;;;90306:196;;;:::o;88186:2002::-;88301:35;88339:20;88351:7;88339:11;:20::i;:::-;88414:18;;88301:58;;-1:-1:-1;88372:22:0;;-1:-1:-1;;;;;88398:34:0;28771:10;-1:-1:-1;;;;;88398:34:0;;:87;;;-1:-1:-1;28771:10:0;88449:20;88461:7;88449:11;:20::i;:::-;-1:-1:-1;;;;;88449:36:0;;88398:87;:154;;;-1:-1:-1;88519:18:0;;88502:50;;28771:10;84048:164;:::i;88502:50::-;88372:181;;88574:17;88566:80;;;;-1:-1:-1;;;88566:80:0;;32815:2:1;88566:80:0;;;32797:21:1;32854:2;32834:18;;;32827:30;32893:34;32873:18;;;32866:62;-1:-1:-1;;;32944:18:1;;;32937:48;33002:19;;88566:80:0;32613:414:1;88566:80:0;88689:4;-1:-1:-1;;;;;88667:26:0;:13;:18;;;-1:-1:-1;;;;;88667:26:0;;88659:77;;;;-1:-1:-1;;;88659:77:0;;33234:2:1;88659:77:0;;;33216:21:1;33273:2;33253:18;;;33246:30;33312:34;33292:18;;;33285:62;-1:-1:-1;;;33363:18:1;;;33356:36;33409:19;;88659:77:0;33032:402:1;88659:77:0;-1:-1:-1;;;;;88755:16:0;;88747:66;;;;-1:-1:-1;;;88747:66:0;;33641:2:1;88747:66:0;;;33623:21:1;33680:2;33660:18;;;33653:30;33719:34;33699:18;;;33692:62;-1:-1:-1;;;33770:18:1;;;33763:35;33815:19;;88747:66:0;33439:401:1;88747:66:0;88934:49;88951:1;88955:7;88964:13;:18;;;88934:8;:49::i;:::-;-1:-1:-1;;;;;89279:18:0;;;;;;;:12;:18;;;;;;;;:31;;-1:-1:-1;;;;;;89279:31:0;;;-1:-1:-1;;;;;89279:31:0;;;-1:-1:-1;;89279:31:0;;;;;;;89325:16;;;;;;;;;:29;;;;;;;;-1:-1:-1;89325:29:0;;;;;;;;;;;;;89371:20;;;:11;:20;;;;;;:30;;-1:-1:-1;;;;;;89416:61:0;;;;-1:-1:-1;;;89461:15:0;-1:-1:-1;;;;;89416:61:0;;;;;89751:11;;;89781:24;;;;;:29;89751:11;;89781:29;89777:295;;89849:20;89857:11;85443:4;85477:12;-1:-1:-1;85467:22:0;85386:111;89849:20;89845:212;;;89926:18;;;89894:24;;;:11;:24;;;;;;;;:50;;90009:28;;;;-1:-1:-1;;;;;89967:70:0;-1:-1:-1;;;89967:70:0;-1:-1:-1;;;;;;89967:70:0;;;-1:-1:-1;;;;;89894:50:0;;;89967:70;;;;;;;89845:212;89254:829;90119:7;90115:2;-1:-1:-1;;;;;90100:27:0;90109:4;-1:-1:-1;;;;;90100:27:0;;;;;;;;;;;90138:42;84776:355;112711:1174;112785:8;112797:1;112785:13;112777:50;;;;-1:-1:-1;;;112777:50:0;;34047:2:1;112777:50:0;;;34029:21:1;34086:2;34066:18;;;34059:30;34125:26;34105:18;;;34098:54;34169:18;;112777:50:0;33845:348:1;112777:50:0;112846:12;;112862:1;112846:17;112838:50;;;;-1:-1:-1;;;112838:50:0;;34400:2:1;112838:50:0;;;34382:21:1;34439:2;34419:18;;;34412:30;-1:-1:-1;;;34458:18:1;;;34451:50;34518:18;;112838:50:0;34198:344:1;112838:50:0;112935:24;;112899:33;113006:12;112978:40;;112970:81;;;;-1:-1:-1;;;112970:81:0;;34749:2:1;112970:81:0;;;34731:21:1;34788:2;34768:18;;;34761:30;34827;34807:18;;;34800:58;34875:18;;112970:81:0;34547:352:1;112970:81:0;113197:16;113353:12;113216:36;;;-1:-1:-1;;113216:40:0;;;-1:-1:-1;113334:95:0;;;-1:-1:-1;113397:12:0;;-1:-1:-1;;113397:16:0;113334:95;113462:25;113445:366;113494:8;113489:1;:13;113445:366;;113563:1;113532:14;;;:11;:14;;;;;:19;-1:-1:-1;;;;;113532:19:0;113528:268;;113590:31;113624:14;113636:1;113624:11;:14::i;:::-;113683;;;113661;;;:11;:14;;;;;;;;:36;;113752:24;;;;;-1:-1:-1;;;;;113720:56:0;-1:-1:-1;;;113720:56:0;-1:-1:-1;;;;;;113720:56:0;;;-1:-1:-1;;;;;113661:36:0;;;113720:56;;;;;;;-1:-1:-1;113528:268:0;113504:3;;113445:366;;;-1:-1:-1;113865:1:0;113854:12;113827:24;:39;-1:-1:-1;;112711:1174:0:o;85505:104::-;85574:27;85584:2;85588:8;85574:27;;;;;;;;;;;;:9;:27::i;13654:131::-;13721:4;13745:32;13750:3;13770:5;13745:4;:32::i;:::-;13738:39;13654:131;-1:-1:-1;;;13654:131:0:o;81051:537::-;-1:-1:-1;;;;;;;;;;;;;;;;;81154:16:0;81162:7;85443:4;85477:12;-1:-1:-1;85467:22:0;85386:111;81154:16;81146:71;;;;-1:-1:-1;;;81146:71:0;;35106:2:1;81146:71:0;;;35088:21:1;35145:2;35125:18;;;35118:30;35184:34;35164:18;;;35157:62;-1:-1:-1;;;35235:18:1;;;35228:40;35285:19;;81146:71:0;34904:406:1;81146:71:0;81275:7;81255:245;81322:31;81356:17;;;:11;:17;;;;;;;;;81322:51;;;;;;;;;-1:-1:-1;;;;;81322:51:0;;;;;-1:-1:-1;;;81322:51:0;;;-1:-1:-1;;;;;81322:51:0;;;;;;;;81396:28;81392:93;;81456:9;81051:537;-1:-1:-1;;;81051:537:0:o;81392:93::-;-1:-1:-1;;;81295:6:0;81255:245;;31407:191;31500:6;;;-1:-1:-1;;;;;31517:17:0;;;-1:-1:-1;;;;;;31517:17:0;;;;;;;31550:40;;31500:6;;;31517:17;31500:6;;31550:40;;31481:16;;31550:40;31470:128;31407:191;:::o;14416:114::-;14476:7;14503:19;14511:3;7401:18;;7318:109;14884:137;14955:7;14990:22;14994:3;15006:5;14990:3;:22::i;13961:137::-;14031:4;14055:35;14063:3;14083:5;14055:7;:35::i;91067:804::-;91222:4;-1:-1:-1;;;;;91243:13:0;;33133:19;:23;91239:625;;91279:72;;-1:-1:-1;;;91279:72:0;;-1:-1:-1;;;;;91279:36:0;;;;;:72;;28771:10;;91330:4;;91336:7;;91345:5;;91279:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;91279:72:0;;;;;;;;-1:-1:-1;;91279:72:0;;;;;;;;;;;;:::i;:::-;;;91275:534;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91525:6;:13;91542:1;91525:18;91521:273;;91568:61;;-1:-1:-1;;;91568:61:0;;;;;;;:::i;91521:273::-;91744:6;91738:13;91729:6;91725:2;91721:15;91714:38;91275:534;-1:-1:-1;;;;;;91402:55:0;-1:-1:-1;;;91402:55:0;;-1:-1:-1;91395:62:0;;91239:625;-1:-1:-1;91848:4:0;91841:11;;16315:723;16371:13;16592:5;16601:1;16592:10;16588:53;;-1:-1:-1;;16619:10:0;;;;;;;;;;;;-1:-1:-1;;;16619:10:0;;;;;16315:723::o;16588:53::-;16666:5;16651:12;16707:78;16714:9;;16707:78;;16740:8;;;;:::i;:::-;;-1:-1:-1;16763:10:0;;-1:-1:-1;16771:2:0;16763:10;;:::i;:::-;;;16707:78;;;16795:19;16827:6;-1:-1:-1;;;;;16817:17:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16817:17:0;;16795:39;;16845:154;16852:10;;16845:154;;16879:11;16889:1;16879:11;;:::i;:::-;;-1:-1:-1;16948:10:0;16956:2;16948:5;:10;:::i;:::-;16935:24;;:2;:24;:::i;:::-;16922:39;;16905:6;16912;16905:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;16905:56:0;;;;;;;;-1:-1:-1;16976:11:0;16985:2;16976:11;;:::i;:::-;;;16845:154;;22895:231;22973:7;22994:17;23013:18;23035:27;23046:4;23052:9;23035:10;:27::i;:::-;22993:69;;;;23073:18;23085:5;23073:11;:18::i;:::-;-1:-1:-1;23109:9:0;22895:231;-1:-1:-1;;;22895:231:0:o;85972:163::-;86095:32;86101:2;86105:8;86115:5;86122:4;86095:5;:32::i;5007:414::-;5070:4;7200:19;;;:12;;;:19;;;;;;5087:327;;-1:-1:-1;5130:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;5313:18;;5291:19;;;:12;;;:19;;;;;;:40;;;;5346:11;;5087:327;-1:-1:-1;5397:5:0;5390:12;;7781:120;7848:7;7875:3;:11;;7887:5;7875:18;;;;;;;;:::i;:::-;;;;;;;;;7868:25;;7781:120;;;;:::o;5597:1420::-;5663:4;5802:19;;;:12;;;:19;;;;;;5838:15;;5834:1176;;6213:21;6237:14;6250:1;6237:10;:14;:::i;:::-;6286:18;;6213:38;;-1:-1:-1;6266:17:0;;6286:22;;6307:1;;6286:22;:::i;:::-;6266:42;;6342:13;6329:9;:26;6325:405;;6376:17;6396:3;:11;;6408:9;6396:22;;;;;;;;:::i;:::-;;;;;;;;;6376:42;;6550:9;6521:3;:11;;6533:13;6521:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;6635:23;;;:12;;;:23;;;;;:36;;;6325:405;6811:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;6906:3;:12;;:19;6919:5;6906:19;;;;;;;;;;;6899:26;;;6949:4;6942:11;;;;;;;5834:1176;6993:5;6986:12;;;;;20689:1404;20770:7;20779:12;21004:9;:16;21024:2;21004:22;21000:1086;;21348:4;21333:20;;21327:27;21398:4;21383:20;;21377:27;21456:4;21441:20;;21435:27;21043:9;21427:36;21499:25;21510:4;21427:36;21327:27;21377;21499:10;:25::i;:::-;21492:32;;;;;;;;;21000:1086;21546:9;:16;21566:2;21546:22;21542:544;;21869:4;21854:20;;21848:27;21920:4;21905:20;;21899:27;21962:23;21973:4;21848:27;21899;21962:10;:23::i;:::-;21955:30;;;;;;;;21542:544;-1:-1:-1;22034:1:0;;-1:-1:-1;22038:35:0;22018:56;;18960:643;19038:20;19029:5;:29;;;;;;;;:::i;:::-;;19025:571;;18960:643;:::o;19025:571::-;19136:29;19127:5;:38;;;;;;;;:::i;:::-;;19123:473;;19182:34;;-1:-1:-1;;;19182:34:0;;37447:2:1;19182:34:0;;;37429:21:1;37486:2;37466:18;;;37459:30;37525:26;37505:18;;;37498:54;37569:18;;19182:34:0;37245:348:1;19123:473:0;19247:35;19238:5;:44;;;;;;;;:::i;:::-;;19234:362;;19299:41;;-1:-1:-1;;;19299:41:0;;37800:2:1;19299:41:0;;;37782:21:1;37839:2;37819:18;;;37812:30;37878:33;37858:18;;;37851:61;37929:18;;19299:41:0;37598:355:1;19234:362:0;19371:30;19362:5;:39;;;;;;;;:::i;:::-;;19358:238;;19418:44;;-1:-1:-1;;;19418:44:0;;38160:2:1;19418:44:0;;;38142:21:1;38199:2;38179:18;;;38172:30;38238:34;38218:18;;;38211:62;-1:-1:-1;;;38289:18:1;;;38282:32;38331:19;;19418:44:0;37958:398:1;19358:238:0;19493:30;19484:5;:39;;;;;;;;:::i;:::-;;19480:116;;19540:44;;-1:-1:-1;;;19540:44:0;;38563:2:1;19540:44:0;;;38545:21:1;38602:2;38582:18;;;38575:30;38641:34;38621:18;;;38614:62;-1:-1:-1;;;38692:18:1;;;38685:32;38734:19;;19540:44:0;38361:398:1;86394:1538:0;86533:20;86556:12;-1:-1:-1;;;;;86587:16:0;;86579:62;;;;-1:-1:-1;;;86579:62:0;;38966:2:1;86579:62:0;;;38948:21:1;39005:2;38985:18;;;38978:30;39044:34;39024:18;;;39017:62;-1:-1:-1;;;39095:18:1;;;39088:31;39136:19;;86579:62:0;38764:397:1;86579:62:0;86660:8;86672:1;86660:13;86652:66;;;;-1:-1:-1;;;86652:66:0;;39368:2:1;86652:66:0;;;39350:21:1;39407:2;39387:18;;;39380:30;39446:34;39426:18;;;39419:62;-1:-1:-1;;;39497:18:1;;;39490:38;39545:19;;86652:66:0;39166:404:1;86652:66:0;-1:-1:-1;;;;;87070:16:0;;;;;;:12;:16;;;;;;;;:45;;-1:-1:-1;;;;;;;;;87070:45:0;;-1:-1:-1;;;;;87070:45:0;;;;;;;;;;87130:50;;;;;;;;;;;;;;87197:25;;;:11;:25;;;;;:35;;-1:-1:-1;;;;;;87247:66:0;;;;-1:-1:-1;;;87297:15:0;-1:-1:-1;;;;;87247:66:0;;;;;;87197:25;;87382:415;87402:8;87398:1;:12;87382:415;;;87441:38;;87466:12;;-1:-1:-1;;;;;87441:38:0;;;87458:1;;87441:38;;87458:1;;87441:38;87502:4;87498:249;;;87565:59;87596:1;87600:2;87604:12;87618:5;87565:22;:59::i;:::-;87531:196;;;;-1:-1:-1;;;87531:196:0;;;;;;;:::i;:::-;87767:14;;;;;87412:3;87382:415;;;-1:-1:-1;87813:12:0;:27;87864:60;84776:355;24347:1632;24478:7;;25412:66;25399:79;;25395:163;;;-1:-1:-1;25511:1:0;;-1:-1:-1;25515:30:0;25495:51;;25395:163;25572:1;:7;;25577:2;25572:7;;:18;;;;;25583:1;:7;;25588:2;25583:7;;25572:18;25568:102;;;-1:-1:-1;25623:1:0;;-1:-1:-1;25627:30:0;25607:51;;25568:102;25784:24;;;25767:14;25784:24;;;;;;;;;39802:25:1;;;39875:4;39863:17;;39843:18;;;39836:45;;;;39897:18;;;39890:34;;;39940:18;;;39933:34;;;25784:24:0;;39774:19:1;;25784:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;25784:24:0;;-1:-1:-1;;25784:24:0;;;-1:-1:-1;;;;;;;25823:20:0;;25819:103;;25876:1;25880:29;25860:50;;;;;;;25819:103;25942:6;-1:-1:-1;25950:20:0;;-1:-1:-1;24347:1632:0;;;;;;;;:::o;23389:344::-;23503:7;;-1:-1:-1;;;;;23549:80:0;;23503:7;23656:25;23672:3;23657:18;;;23679:2;23656:25;:::i;:::-;23640:42;;23700:25;23711:4;23717:1;23720;23723;23700:10;:25::i;:::-;23693:32;;;;;;23389:344;;;;;;:::o;14:131:1:-;-1:-1:-1;;;;;;88:32:1;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;592:139::-;-1:-1:-1;;;;;675:31:1;;665:42;;655:70;;721:1;718;711:12;736:451;811:6;819;872:2;860:9;851:7;847:23;843:32;840:52;;;888:1;885;878:12;840:52;927:9;914:23;946:39;979:5;946:39;:::i;:::-;1004:5;-1:-1:-1;1061:2:1;1046:18;;1033:32;-1:-1:-1;;;;;1096:40:1;;1084:53;;1074:81;;1151:1;1148;1141:12;1074:81;1174:7;1164:17;;;736:451;;;;;:::o;1192:250::-;1277:1;1287:113;1301:6;1298:1;1295:13;1287:113;;;1377:11;;;1371:18;1358:11;;;1351:39;1323:2;1316:10;1287:113;;;-1:-1:-1;;1434:1:1;1416:16;;1409:27;1192:250::o;1447:271::-;1489:3;1527:5;1521:12;1554:6;1549:3;1542:19;1570:76;1639:6;1632:4;1627:3;1623:14;1616:4;1609:5;1605:16;1570:76;:::i;:::-;1700:2;1679:15;-1:-1:-1;;1675:29:1;1666:39;;;;1707:4;1662:50;;1447:271;-1:-1:-1;;1447:271:1:o;1723:220::-;1872:2;1861:9;1854:21;1835:4;1892:45;1933:2;1922:9;1918:18;1910:6;1892:45;:::i;1948:180::-;2007:6;2060:2;2048:9;2039:7;2035:23;2031:32;2028:52;;;2076:1;2073;2066:12;2028:52;-1:-1:-1;2099:23:1;;1948:180;-1:-1:-1;1948:180:1:o;2341:323::-;2409:6;2417;2470:2;2458:9;2449:7;2445:23;2441:32;2438:52;;;2486:1;2483;2476:12;2438:52;2525:9;2512:23;2544:39;2577:5;2544:39;:::i;:::-;2602:5;2654:2;2639:18;;;;2626:32;;-1:-1:-1;;;2341:323:1:o;2851:127::-;2912:10;2907:3;2903:20;2900:1;2893:31;2943:4;2940:1;2933:15;2967:4;2964:1;2957:15;2983:275;3054:2;3048:9;3119:2;3100:13;;-1:-1:-1;;3096:27:1;3084:40;;-1:-1:-1;;;;;3139:34:1;;3175:22;;;3136:62;3133:88;;;3201:18;;:::i;:::-;3237:2;3230:22;2983:275;;-1:-1:-1;2983:275:1:o;3263:530::-;3305:5;3358:3;3351:4;3343:6;3339:17;3335:27;3325:55;;3376:1;3373;3366:12;3325:55;3412:6;3399:20;-1:-1:-1;;;;;3434:2:1;3431:26;3428:52;;;3460:18;;:::i;:::-;3504:55;3547:2;3528:13;;-1:-1:-1;;3524:27:1;3553:4;3520:38;3504:55;:::i;:::-;3584:2;3575:7;3568:19;3630:3;3623:4;3618:2;3610:6;3606:15;3602:26;3599:35;3596:55;;;3647:1;3644;3637:12;3596:55;3712:2;3705:4;3697:6;3693:17;3686:4;3677:7;3673:18;3660:55;3760:1;3735:16;;;3753:4;3731:27;3724:38;;;;3739:7;3263:530;-1:-1:-1;;;3263:530:1:o;3798:681::-;3893:6;3901;3909;3917;3970:3;3958:9;3949:7;3945:23;3941:33;3938:53;;;3987:1;3984;3977:12;3938:53;4026:9;4013:23;4045:39;4078:5;4045:39;:::i;:::-;4103:5;-1:-1:-1;4160:2:1;4145:18;;4132:32;4173:41;4132:32;4173:41;:::i;:::-;4233:7;-1:-1:-1;4287:2:1;4272:18;;4259:32;;-1:-1:-1;4342:2:1;4327:18;;4314:32;-1:-1:-1;;;;;4358:30:1;;4355:50;;;4401:1;4398;4391:12;4355:50;4424:49;4465:7;4456:6;4445:9;4441:22;4424:49;:::i;:::-;4414:59;;;3798:681;;;;;;;:::o;4691:472::-;4768:6;4776;4784;4837:2;4825:9;4816:7;4812:23;4808:32;4805:52;;;4853:1;4850;4843:12;4805:52;4892:9;4879:23;4911:39;4944:5;4911:39;:::i;:::-;4969:5;-1:-1:-1;5026:2:1;5011:18;;4998:32;5039:41;4998:32;5039:41;:::i;:::-;4691:472;;5099:7;;-1:-1:-1;;;5153:2:1;5138:18;;;;5125:32;;4691:472::o;5168:248::-;5236:6;5244;5297:2;5285:9;5276:7;5272:23;5268:32;5265:52;;;5313:1;5310;5303:12;5265:52;-1:-1:-1;;5336:23:1;;;5406:2;5391:18;;;5378:32;;-1:-1:-1;5168:248:1:o;5421:274::-;-1:-1:-1;;;;;5613:32:1;;;;5595:51;;5677:2;5662:18;;5655:34;5583:2;5568:18;;5421:274::o;5700:592::-;5771:6;5779;5832:2;5820:9;5811:7;5807:23;5803:32;5800:52;;;5848:1;5845;5838:12;5800:52;5888:9;5875:23;-1:-1:-1;;;;;5958:2:1;5950:6;5947:14;5944:34;;;5974:1;5971;5964:12;5944:34;6012:6;6001:9;5997:22;5987:32;;6057:7;6050:4;6046:2;6042:13;6038:27;6028:55;;6079:1;6076;6069:12;6028:55;6119:2;6106:16;6145:2;6137:6;6134:14;6131:34;;;6161:1;6158;6151:12;6131:34;6206:7;6201:2;6192:6;6188:2;6184:15;6180:24;6177:37;6174:57;;;6227:1;6224;6217:12;6174:57;6258:2;6250:11;;;;;6280:6;;-1:-1:-1;5700:592:1;;-1:-1:-1;;;;5700:592:1:o;6297:821::-;6411:6;6419;6427;6435;6443;6496:3;6484:9;6475:7;6471:23;6467:33;6464:53;;;6513:1;6510;6503:12;6464:53;6552:9;6539:23;6571:39;6604:5;6571:39;:::i;:::-;6629:5;-1:-1:-1;6681:2:1;6666:18;;6653:32;;-1:-1:-1;6736:2:1;6721:18;;6708:32;-1:-1:-1;;;;;6789:14:1;;;6786:34;;;6816:1;6813;6806:12;6786:34;6839:49;6880:7;6871:6;6860:9;6856:22;6839:49;:::i;:::-;6829:59;;6935:2;6924:9;6920:18;6907:32;6897:42;;6992:3;6981:9;6977:19;6964:33;6948:49;;7022:2;7012:8;7009:16;7006:36;;;7038:1;7035;7028:12;7006:36;;7061:51;7104:7;7093:8;7082:9;7078:24;7061:51;:::i;:::-;7051:61;;;6297:821;;;;;;;;:::o;7123:532::-;7210:6;7218;7226;7279:2;7267:9;7258:7;7254:23;7250:32;7247:52;;;7295:1;7292;7285:12;7247:52;7334:9;7321:23;7353:39;7386:5;7353:39;:::i;:::-;7411:5;-1:-1:-1;7463:2:1;7448:18;;7435:32;;-1:-1:-1;7518:2:1;7503:18;;7490:32;-1:-1:-1;;;;;7534:30:1;;7531:50;;;7577:1;7574;7567:12;7531:50;7600:49;7641:7;7632:6;7621:9;7617:22;7600:49;:::i;:::-;7590:59;;;7123:532;;;;;:::o;7842:183::-;7902:4;-1:-1:-1;;;;;7927:6:1;7924:30;7921:56;;;7957:18;;:::i;:::-;-1:-1:-1;8002:1:1;7998:14;8014:4;7994:25;;7842:183::o;8030:891::-;8114:6;8145:2;8188;8176:9;8167:7;8163:23;8159:32;8156:52;;;8204:1;8201;8194:12;8156:52;8244:9;8231:23;-1:-1:-1;;;;;8269:6:1;8266:30;8263:50;;;8309:1;8306;8299:12;8263:50;8332:22;;8385:4;8377:13;;8373:27;-1:-1:-1;8363:55:1;;8414:1;8411;8404:12;8363:55;8450:2;8437:16;8473:60;8489:43;8529:2;8489:43;:::i;:::-;8473:60;:::i;:::-;8567:15;;;8649:1;8645:10;;;;8637:19;;8633:28;;;8598:12;;;;8673:19;;;8670:39;;;8705:1;8702;8695:12;8670:39;8729:11;;;;8749:142;8765:6;8760:3;8757:15;8749:142;;;8831:17;;8819:30;;8782:12;;;;8869;;;;8749:142;;;8910:5;8030:891;-1:-1:-1;;;;;;;8030:891:1:o;8926:255::-;8985:6;9038:2;9026:9;9017:7;9013:23;9009:32;9006:52;;;9054:1;9051;9044:12;9006:52;9093:9;9080:23;9112:39;9145:5;9112:39;:::i;9553:632::-;9724:2;9776:21;;;9846:13;;9749:18;;;9868:22;;;9695:4;;9724:2;9947:15;;;;9921:2;9906:18;;;9695:4;9990:169;10004:6;10001:1;9998:13;9990:169;;;10065:13;;10053:26;;10134:15;;;;10099:12;;;;10026:1;10019:9;9990:169;;;-1:-1:-1;10176:3:1;;9553:632;-1:-1:-1;;;;;;9553:632:1:o;10190:424::-;10255:6;10263;10316:2;10304:9;10295:7;10291:23;10287:32;10284:52;;;10332:1;10329;10322:12;10284:52;10371:9;10358:23;10390:39;10423:5;10390:39;:::i;:::-;10448:5;-1:-1:-1;10505:2:1;10490:18;;10477:32;10547:15;;10540:23;10528:36;;10518:64;;10578:1;10575;10568:12;10619:321;10688:6;10741:2;10729:9;10720:7;10716:23;10712:32;10709:52;;;10757:1;10754;10747:12;10709:52;10797:9;10784:23;-1:-1:-1;;;;;10822:6:1;10819:30;10816:50;;;10862:1;10859;10852:12;10816:50;10885:49;10926:7;10917:6;10906:9;10902:22;10885:49;:::i;10945:388::-;11022:6;11030;11083:2;11071:9;11062:7;11058:23;11054:32;11051:52;;;11099:1;11096;11089:12;11051:52;11135:9;11122:23;11112:33;;11196:2;11185:9;11181:18;11168:32;-1:-1:-1;;;;;11215:6:1;11212:30;11209:50;;;11255:1;11252;11245:12;11209:50;11278:49;11319:7;11310:6;11299:9;11295:22;11278:49;:::i;:::-;11268:59;;;10945:388;;;;;:::o;11338:404::-;11406:6;11414;11467:2;11455:9;11446:7;11442:23;11438:32;11435:52;;;11483:1;11480;11473:12;11435:52;11522:9;11509:23;11541:39;11574:5;11541:39;:::i;:::-;11599:5;-1:-1:-1;11656:2:1;11641:18;;11628:32;11669:41;11628:32;11669:41;:::i;11747:380::-;11826:1;11822:12;;;;11869;;;11890:61;;11944:4;11936:6;11932:17;11922:27;;11890:61;11997:2;11989:6;11986:14;11966:18;11963:38;11960:161;;12043:10;12038:3;12034:20;12031:1;12024:31;12078:4;12075:1;12068:15;12106:4;12103:1;12096:15;11960:161;;11747:380;;;:::o;13375:127::-;13436:10;13431:3;13427:20;13424:1;13417:31;13467:4;13464:1;13457:15;13491:4;13488:1;13481:15;13507:168;13580:9;;;13611;;13628:15;;;13622:22;;13608:37;13598:71;;13649:18;;:::i;13680:127::-;13741:10;13736:3;13732:20;13729:1;13722:31;13772:4;13769:1;13762:15;13796:4;13793:1;13786:15;13812:120;13852:1;13878;13868:35;;13883:18;;:::i;:::-;-1:-1:-1;13917:9:1;;13812:120::o;16073:337::-;16275:2;16257:21;;;16314:2;16294:18;;;16287:30;-1:-1:-1;;;16348:2:1;16333:18;;16326:43;16401:2;16386:18;;16073:337::o;16415:128::-;16482:9;;;16503:11;;;16500:37;;;16517:18;;:::i;16548:125::-;16613:9;;;16634:10;;;16631:36;;;16647:18;;:::i;16678:339::-;16880:2;16862:21;;;16919:2;16899:18;;;16892:30;-1:-1:-1;;;16953:2:1;16938:18;;16931:45;17008:2;16993:18;;16678:339::o;17022:343::-;17224:2;17206:21;;;17263:2;17243:18;;;17236:30;-1:-1:-1;;;17297:2:1;17282:18;;17275:49;17356:2;17341:18;;17022:343::o;17370:::-;17572:2;17554:21;;;17611:2;17591:18;;;17584:30;-1:-1:-1;;;17645:2:1;17630:18;;17623:49;17704:2;17689:18;;17370:343::o;17718:135::-;17757:3;17778:17;;;17775:43;;17798:18;;:::i;:::-;-1:-1:-1;17845:1:1;17834:13;;17718:135::o;17984:545::-;18086:2;18081:3;18078:11;18075:448;;;18122:1;18147:5;18143:2;18136:17;18192:4;18188:2;18178:19;18262:2;18250:10;18246:19;18243:1;18239:27;18233:4;18229:38;18298:4;18286:10;18283:20;18280:47;;;-1:-1:-1;18321:4:1;18280:47;18376:2;18371:3;18367:12;18364:1;18360:20;18354:4;18350:31;18340:41;;18431:82;18449:2;18442:5;18439:13;18431:82;;;18494:17;;;18475:1;18464:13;18431:82;;18705:1206;-1:-1:-1;;;;;18824:3:1;18821:27;18818:53;;;18851:18;;:::i;:::-;18880:94;18970:3;18930:38;18962:4;18956:11;18930:38;:::i;:::-;18924:4;18880:94;:::i;:::-;19000:1;19025:2;19020:3;19017:11;19042:1;19037:616;;;;19697:1;19714:3;19711:93;;;-1:-1:-1;19770:19:1;;;19757:33;19711:93;-1:-1:-1;;18662:1:1;18658:11;;;18654:24;18650:29;18640:40;18686:1;18682:11;;;18637:57;19817:78;;19010:895;;19037:616;17931:1;17924:14;;;17968:4;17955:18;;-1:-1:-1;;19073:17:1;;;19174:9;19196:229;19210:7;19207:1;19204:14;19196:229;;;19299:19;;;19286:33;19271:49;;19406:4;19391:20;;;;19359:1;19347:14;;;;19226:12;19196:229;;;19200:3;19453;19444:7;19441:16;19438:159;;;19577:1;19573:6;19567:3;19561;19558:1;19554:11;19550:21;19546:34;19542:39;19529:9;19524:3;19520:19;19507:33;19503:79;19495:6;19488:95;19438:159;;;19640:1;19634:3;19631:1;19627:11;19623:19;19617:4;19610:33;19010:895;;18705:1206;;;:::o;20272:289::-;20403:3;20441:6;20435:13;20457:66;20516:6;20511:3;20504:4;20496:6;20492:17;20457:66;:::i;:::-;20539:16;;;;;20272:289;-1:-1:-1;;20272:289:1:o;21533:881::-;21628:6;21659:2;21702;21690:9;21681:7;21677:23;21673:32;21670:52;;;21718:1;21715;21708:12;21670:52;21751:9;21745:16;-1:-1:-1;;;;;21776:6:1;21773:30;21770:50;;;21816:1;21813;21806:12;21770:50;21839:22;;21892:4;21884:13;;21880:27;-1:-1:-1;21870:55:1;;21921:1;21918;21911:12;21870:55;21950:2;21944:9;21973:60;21989:43;22029:2;21989:43;:::i;21973:60::-;22067:15;;;22149:1;22145:10;;;;22137:19;;22133:28;;;22098:12;;;;22173:19;;;22170:39;;;22205:1;22202;22195:12;22170:39;22229:11;;;;22249:135;22265:6;22260:3;22257:15;22249:135;;;22331:10;;22319:23;;22282:12;;;;22362;;;;22249:135;;22419:184;22489:6;22542:2;22530:9;22521:7;22517:23;22513:32;22510:52;;;22558:1;22555;22548:12;22510:52;-1:-1:-1;22581:16:1;;22419:184;-1:-1:-1;22419:184:1:o;22608:399::-;22810:2;22792:21;;;22849:2;22829:18;;;22822:30;22888:34;22883:2;22868:18;;22861:62;-1:-1:-1;;;22954:2:1;22939:18;;22932:33;22997:3;22982:19;;22608:399::o;23012:136::-;23051:3;23079:5;23069:39;;23088:18;;:::i;:::-;-1:-1:-1;;;23124:18:1;;23012:136::o;23153:127::-;23214:10;23209:3;23205:20;23202:1;23195:31;23245:4;23242:1;23235:15;23269:4;23266:1;23259:15;23644:599;23859:3;-1:-1:-1;;;;;23887:31:1;23960:2;23951:6;23947:2;23943:15;23939:24;23934:3;23927:37;23994:6;23989:2;23984:3;23980:12;23973:28;24030:6;24024:13;24046:75;24114:6;24109:2;24104:3;24100:12;24093:4;24085:6;24081:17;24046:75;:::i;:::-;24193:2;24189:15;;;;24185:24;24140:16;;;;24180:2;24172:11;;24165:45;;;;24234:2;24226:11;;;-1:-1:-1;;;;23644:599:1:o;24602:259::-;24672:6;24725:2;24713:9;24704:7;24700:23;24696:32;24693:52;;;24741:1;24738;24731:12;24693:52;24773:9;24767:16;24792:39;24825:5;24792:39;:::i;25218:375::-;-1:-1:-1;;;;;25476:15:1;;;25458:34;;25528:15;;;;25523:2;25508:18;;25501:43;25575:2;25560:18;;25553:34;;;;25408:2;25393:18;;25218:375::o;26717:415::-;26919:2;26901:21;;;26958:2;26938:18;;;26931:30;26997:34;26992:2;26977:18;;26970:62;-1:-1:-1;;;27063:2:1;27048:18;;27041:49;27122:3;27107:19;;26717:415::o;28241:1020::-;28417:3;28446:1;28479:6;28473:13;28509:36;28535:9;28509:36;:::i;:::-;28564:1;28581:18;;;28608:133;;;;28755:1;28750:356;;;;28574:532;;28608:133;-1:-1:-1;;28641:24:1;;28629:37;;28714:14;;28707:22;28695:35;;28686:45;;;-1:-1:-1;28608:133:1;;28750:356;28781:6;28778:1;28771:17;28811:4;28856:2;28853:1;28843:16;28881:1;28895:165;28909:6;28906:1;28903:13;28895:165;;;28987:14;;28974:11;;;28967:35;29030:16;;;;28924:10;;28895:165;;;28899:3;;;29089:6;29084:3;29080:16;29073:23;;28574:532;;;;;29137:6;29131:13;29153:68;29212:8;29207:3;29200:4;29192:6;29188:17;29153:68;:::i;:::-;29237:18;;28241:1020;-1:-1:-1;;;;28241:1020:1:o;35731:489::-;-1:-1:-1;;;;;36000:15:1;;;35982:34;;36052:15;;36047:2;36032:18;;36025:43;36099:2;36084:18;;36077:34;;;36147:3;36142:2;36127:18;;36120:31;;;35925:4;;36168:46;;36194:19;;36186:6;36168:46;:::i;:::-;36160:54;35731:489;-1:-1:-1;;;;;;35731:489:1:o;36225:249::-;36294:6;36347:2;36335:9;36326:7;36322:23;36318:32;36315:52;;;36363:1;36360;36353:12;36315:52;36395:9;36389:16;36414:30;36438:5;36414:30;:::i;36479:112::-;36511:1;36537;36527:35;;36542:18;;:::i;:::-;-1:-1:-1;36576:9:1;;36479:112::o;36981:127::-;37042:10;37037:3;37033:20;37030:1;37023:31;37073:4;37070:1;37063:15;37097:4;37094:1;37087:15;37113:127;37174:10;37169:3;37165:20;37162:1;37155:31;37205:4;37202:1;37195:15;37229:4;37226:1;37219:15

Swarm Source

ipfs://059a0e01d0094b9b990e2e5b9b4383a884f97b638ef07bb8e95fb5c5de762531
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.