ETH Price: $3,116.18 (+0.36%)

DarkSoldiers (DS)
 

Overview

TokenID

179

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
DarkSoldiers

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-10-28
*/

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


// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.20;

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The tree and the proofs can be generated using our
 * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 * You will find a quickstart guide in the readme.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the Merkle tree could be reinterpreted as a leaf value.
 * OpenZeppelin's JavaScript library generates Merkle trees that are safe
 * against this attack out of the box.
 */
library MerkleProof {
    /**
     *@dev The multiproof provided is not valid.
     */
    error MerkleProofInvalidMultiproof();

    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Calldata version of {verify}
     */
    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Calldata version of {processProof}
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the Merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        if (leavesLen + proofLen != totalHashes + 1) {
            revert MerkleProofInvalidMultiproof();
        }

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            if (proofPos != proofLen) {
                revert MerkleProofInvalidMultiproof();
            }
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the Merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        if (leavesLen + proofLen != totalHashes + 1) {
            revert MerkleProofInvalidMultiproof();
        }

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            if (proofPos != proofLen) {
                revert MerkleProofInvalidMultiproof();
            }
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Sorts the pair (a, b) and hashes the result.
     */
    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    /**
     * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
     */
    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

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


// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}

// File: @openzeppelin/contracts/security/ReentrancyGuard.sol


// OpenZeppelin Contracts (last updated v4.9.0) (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() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

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

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

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


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

// File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol


// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

// File: @openzeppelin/contracts/utils/math/SignedMath.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

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

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

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

// File: @openzeppelin/contracts/utils/math/Math.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Muldiv operation overflow.
     */
    error MathOverflowedMulDiv();

    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

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

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

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

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

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

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

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

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
     * Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

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


// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)

pragma solidity ^0.8.20;



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

    /**
     * @dev The `value` string doesn't fit in the specified `length`.
     */
    error StringsInsufficientHexLength(uint256 value, uint256 length);

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toStringSigned(int256 value) internal pure returns (string memory) {
        return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        uint256 localValue = value;
        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_DIGITS[localValue & 0xf];
            localValue >>= 4;
        }
        if (localValue != 0) {
            revert StringsInsufficientHexLength(value, length);
        }
        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);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

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


// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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 v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;


/**
 * @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.
 *
 * The initial owner is set to the address provided by the deployer. 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;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling 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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

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

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


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.20;

/**
 * @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/utils/introspection/IERC165.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @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 v5.0.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.20;


/**
 * @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.
 */
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 (last updated v5.0.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;


/**
 * @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);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

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


// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;




/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address account => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 role => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

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

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual returns (bool) {
        return _roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        if (!hasRole(role, account)) {
            _roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        if (hasRole(role, account)) {
            _roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}

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


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;


/**
 * @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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * 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 address zero.
     *
     * 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: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.20;


/**
 * @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 (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.20;


/**
 * @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 v5.0.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.20;








/**
 * @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}.
 */
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    mapping(uint256 tokenId => address) private _owners;

    mapping(address owner => uint256) private _balances;

    mapping(uint256 tokenId => address) private _tokenApprovals;

    mapping(address owner => mapping(address operator => 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 returns (uint256) {
        if (owner == address(0)) {
            revert ERC721InvalidOwner(address(0));
        }
        return _balances[owner];
    }

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

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

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

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

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string.concat(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 {
        _approve(to, tokenId, _msgSender());
    }

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

        return _getApproved(tokenId);
    }

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

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

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(address from, address to, uint256 tokenId) public virtual {
        if (to == address(0)) {
            revert ERC721InvalidReceiver(address(0));
        }
        // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
        // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
        address previousOwner = _update(to, tokenId, _msgSender());
        if (previousOwner != from) {
            revert ERC721IncorrectOwner(from, tokenId, previousOwner);
        }
    }

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

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
        transferFrom(from, to, tokenId);
        _checkOnERC721Received(from, to, tokenId, data);
    }

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     *
     * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
     * core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances
     * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by
     * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    /**
     * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
     */
    function _getApproved(uint256 tokenId) internal view virtual returns (address) {
        return _tokenApprovals[tokenId];
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
     * particular (ignoring whether it is owned by `owner`).
     *
     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
     * assumption.
     */
    function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
        return
            spender != address(0) &&
            (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
    }

    /**
     * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
     * Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets
     * the `spender` for the specific `tokenId`.
     *
     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
     * assumption.
     */
    function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
        if (!_isAuthorized(owner, spender, tokenId)) {
            if (owner == address(0)) {
                revert ERC721NonexistentToken(tokenId);
            } else {
                revert ERC721InsufficientApproval(spender, tokenId);
            }
        }
    }

    /**
     * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
     *
     * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
     * a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
     *
     * WARNING: Increasing an account's balance using this function tends to be paired with an override of the
     * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
     * remain consistent with one another.
     */
    function _increaseBalance(address account, uint128 value) internal virtual {
        unchecked {
            _balances[account] += value;
        }
    }

    /**
     * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
     * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
     *
     * The `auth` argument is optional. If the value passed is non 0, then this function will check that
     * `auth` is either the owner of the token, or approved to operate on the token (by the owner).
     *
     * Emits a {Transfer} event.
     *
     * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
     */
    function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
        address from = _ownerOf(tokenId);

        // Perform (optional) operator check
        if (auth != address(0)) {
            _checkAuthorized(from, auth, tokenId);
        }

        // Execute the update
        if (from != address(0)) {
            // Clear approval. No need to re-authorize or emit the Approval event
            _approve(address(0), tokenId, address(0), false);

            unchecked {
                _balances[from] -= 1;
            }
        }

        if (to != address(0)) {
            unchecked {
                _balances[to] += 1;
            }
        }

        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        return from;
    }

    /**
     * @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 {
        if (to == address(0)) {
            revert ERC721InvalidReceiver(address(0));
        }
        address previousOwner = _update(to, tokenId, address(0));
        if (previousOwner != address(0)) {
            revert ERC721InvalidSender(address(0));
        }
    }

    /**
     * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
     *
     * 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 {
        _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);
        _checkOnERC721Received(address(0), to, tokenId, data);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal {
        address previousOwner = _update(address(0), tokenId, address(0));
        if (previousOwner == address(0)) {
            revert ERC721NonexistentToken(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 {
        if (to == address(0)) {
            revert ERC721InvalidReceiver(address(0));
        }
        address previousOwner = _update(to, tokenId, address(0));
        if (previousOwner == address(0)) {
            revert ERC721NonexistentToken(tokenId);
        } else if (previousOwner != from) {
            revert ERC721IncorrectOwner(from, tokenId, previousOwner);
        }
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
     * are aware of the ERC721 standard 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 like {safeTransferFrom} in the sense that it invokes
     * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `tokenId` token must exist and be owned by `from`.
     * - `to` cannot be the zero address.
     * - `from` cannot be the zero address.
     * - 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) internal {
        _safeTransfer(from, to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
        _transfer(from, to, tokenId);
        _checkOnERC721Received(from, to, tokenId, data);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
     * either the owner of the token, or approved to operate on all tokens held by this owner.
     *
     * Emits an {Approval} event.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address to, uint256 tokenId, address auth) internal {
        _approve(to, tokenId, auth, true);
    }

    /**
     * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
     * emitted in the context of transfers.
     */
    function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
        // Avoid reading the owner unless necessary
        if (emitEvent || auth != address(0)) {
            address owner = _requireOwned(tokenId);

            // We do not use _isAuthorized because single-token approvals should not be able to call approve
            if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
                revert ERC721InvalidApprover(auth);
            }

            if (emitEvent) {
                emit Approval(owner, to, tokenId);
            }
        }

        _tokenApprovals[tokenId] = to;
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Requirements:
     * - operator can't be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
        if (operator == address(0)) {
            revert ERC721InvalidOperator(operator);
        }
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
     * Returns the owner.
     *
     * Overrides to ownership logic should be done to {_ownerOf}.
     */
    function _requireOwned(uint256 tokenId) internal view returns (address) {
        address owner = _ownerOf(tokenId);
        if (owner == address(0)) {
            revert ERC721NonexistentToken(tokenId);
        }
        return owner;
    }

    /**
     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the
     * recipient doesn't accept the token transfer. 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
     */
    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private {
        if (to.code.length > 0) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
                if (retval != IERC721Receiver.onERC721Received.selector) {
                    revert ERC721InvalidReceiver(to);
                }
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert ERC721InvalidReceiver(to);
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        }
    }
}

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


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.20;




/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds enumerability
 * of all the token ids in the contract as well as all token ids owned by each account.
 *
 * CAUTION: `ERC721` extensions that implement custom `balanceOf` logic, such as `ERC721Consecutive`,
 * interfere with enumerability and should not be used together with `ERC721Enumerable`.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens;
    mapping(uint256 tokenId => uint256) private _ownedTokensIndex;

    uint256[] private _allTokens;
    mapping(uint256 tokenId => uint256) private _allTokensIndex;

    /**
     * @dev An `owner`'s token query was out of bounds for `index`.
     *
     * NOTE: The owner being `address(0)` indicates a global out of bounds index.
     */
    error ERC721OutOfBoundsIndex(address owner, uint256 index);

    /**
     * @dev Batch mint is not allowed.
     */
    error ERC721EnumerableForbiddenBatchMint();

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

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
        if (index >= balanceOf(owner)) {
            revert ERC721OutOfBoundsIndex(owner, index);
        }
        return _ownedTokens[owner][index];
    }

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

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual returns (uint256) {
        if (index >= totalSupply()) {
            revert ERC721OutOfBoundsIndex(address(0), index);
        }
        return _allTokens[index];
    }

    /**
     * @dev See {ERC721-_update}.
     */
    function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
        address previousOwner = super._update(to, tokenId, auth);

        if (previousOwner == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (previousOwner != to) {
            _removeTokenFromOwnerEnumeration(previousOwner, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (previousOwner != to) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }

        return previousOwner;
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = balanceOf(to) - 1;
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = balanceOf(from);
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }

    /**
     * See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch
     */
    function _increaseBalance(address account, uint128 amount) internal virtual override {
        if (amount > 0) {
            revert ERC721EnumerableForbiddenBatchMint();
        }
        super._increaseBalance(account, amount);
    }
}

// File: DarkSoldiersNFT-collection-v4.4.sol

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;









contract DarkSoldiers is ERC721Enumerable, Ownable, ReentrancyGuard, AccessControl, IERC2981 {

    bytes32 public wl1MerkleRoot;
    bytes32 public wl2MerkleRoot;
    bytes32 public claimRoot;

    bytes32 public immutable ADMIN_ROLE = keccak256("ADMIN_ROLE");
    uint256 public immutable _maxSupply = 444;
    mapping(uint256 => string) private _uri;
    mapping(uint256 => bool) private _claimed;
    mapping(address => bool) private _wl1Addresses;
    mapping(address => bool) private _wl2Addresses;
    mapping(address => bool) public hasMinted;
    mapping(address => bool) public hasClaimed;


    string private baseExtension = ".json";
    string public baseURI;
    string public _contractURI;
    uint256 public royaltyFee=5;
    address public royaltyRecipient;
    uint256 public mintingCost1 = 0.095 ether; // 95000000000000000
    uint256 public mintingCost2 = 0.099 ether; // 99000000000000000
    uint256 public mintingCost3 = 0.11 ether; // 110000000000000000

    uint256 private lowestUnminted=1;
    uint256 public reserved=0;

    bool public claimLive = false;
    bool public wl1SaleActive = false;
    bool public wl2SaleActive = false;
    bool public publicSaleActive = false;

    event ToggleWl1Sale(bool state);
    event ToggleWl2Sale(bool state);
    event TogglePublicSale(bool state);
    event ClaimLive(bool state);

    event URI(uint256 indexed tokenId);
    event URIAll();
    event ContractURI();

    constructor(
        string memory _name,
        string memory _symbol
    ) ERC721(_name, _symbol) Ownable(msg.sender) {
        _grantRole(ADMIN_ROLE, msg.sender);
        royaltyRecipient = msg.sender;
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Enumerable, IERC165, AccessControl) returns (bool) {
        return super.supportsInterface(interfaceId);
    }
    
    function contractURI() public view returns (string memory) {
        return _contractURI;
    }

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(ownerOf(tokenId) != address(0), "ERC721Metadata: URI query for nonexistent token");

        if (bytes(_uri[tokenId]).length > 0) {
            return _uri[tokenId];
        }

        string memory currentBaseURI = baseURI;
        if (bytes(currentBaseURI).length == 0) {
            return "";
        } else {
            return string(abi.encodePacked(currentBaseURI, Strings.toString(tokenId), baseExtension));
        }
    }

    function royaltyInfo(uint256 /*tokenId*/, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount) {
        uint256 _royaltyAmount = (salePrice * royaltyFee) / 100;
        return (royaltyRecipient, _royaltyAmount);
    }

    function isClaimed(uint256 tokenId) external view returns (bool) {
        return _claimed[tokenId];
    }
    
    function tokensOfOwner(address owner) external view returns (uint256[] memory) {
        uint256 tokenCount = balanceOf(owner);
        if (tokenCount == 0) {
            return new uint256[](0);
        } else {
            uint256[] memory result = new uint256[](tokenCount);
            for (uint256 index = 0; index < tokenCount; index++) {
                result[index] = tokenOfOwnerByIndex(owner, index);
            }
            return result;
        }
    }

    function verifyProof(bytes32[] memory proof, bytes32 root, address account) external pure returns (bool) {
        bytes32 leaf = keccak256(abi.encodePacked(account));
        return MerkleProof.verify(proof, root, leaf);
    }

    function verifyProofClaim(bytes32[] memory proof, bytes32 root, address account, uint256 allocation) external pure returns (bool) {
        bytes32 leaf = keccak256(abi.encodePacked(account, allocation));
        return MerkleProof.verify(proof, root, leaf);
    }

    function calculateLowestUnminted() private{
        while (_claimed[lowestUnminted] && lowestUnminted <= _maxSupply) {
            lowestUnminted++;
        }
    }

    function checkMintingRequirements(bool saleActive, uint256 mintingCost, bool requiresWhitelist, bytes32[] memory proof, bytes32 root) private view {
        require(saleActive, "Sale is not active");
        require(!hasMinted[msg.sender], "You have already minted");
        require(msg.value == mintingCost, "Ether sent is not correct");
        require(totalSupply() + reserved < _maxSupply, "All tokens have been minted");
        if (requiresWhitelist) {
            bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
            bool verified = MerkleProof.verify(proof, root, leaf);
            require(verified, "You are not allowed to mint in this sale");
        }
    }

    function executeMinting() private {
        calculateLowestUnminted();
        uint256 tokenId = lowestUnminted + reserved;

        require(!_claimed[tokenId], "Token is already claimed");
        _claimed[tokenId] = true;
        _safeMint(msg.sender, tokenId);
        hasMinted[msg.sender] = true;
    }

    function wl1PreSaleMint(bytes32[] memory proof) external payable nonReentrant {
        checkMintingRequirements(wl1SaleActive, mintingCost1, true, proof, wl1MerkleRoot);
        executeMinting();
    }

    function wl2PreSaleMint(bytes32[] memory proof) external payable nonReentrant {
        checkMintingRequirements(wl2SaleActive, mintingCost2, true, proof, wl2MerkleRoot);
        executeMinting();
    }

    function publicMint() external payable nonReentrant {
            bytes32 emptyRoot = 0x0000000000000000000000000000000000000000000000000000000000000000;

        checkMintingRequirements(publicSaleActive, mintingCost3, false, new bytes32[](0),emptyRoot);
        executeMinting();
    }

    function claim(bytes32[] memory proof, uint256 allocation) external nonReentrant {
        require(claimLive, "Claiming is not active at the moment");
        require(!hasClaimed[msg.sender], "You have already claimed");
        require(allocation <= reserved, "Not enough reserved tokens");

        bytes32 leaf = keccak256(abi.encodePacked(msg.sender, allocation));
        require(MerkleProof.verify(proof, claimRoot, leaf), "Invalid proof or you're not whitelisted");

        calculateLowestUnminted();
        uint256 tokenId = lowestUnminted;
        uint256 tokensMinted = 0;

        while (tokensMinted < allocation && tokenId <= _maxSupply) {
            if (!_claimed[tokenId]) {
                _claimed[tokenId] = true;
                _safeMint(msg.sender, tokenId);
                tokensMinted++;
                tokenId++;
            }
        }

        reserved -= tokensMinted;
        hasClaimed[msg.sender] = true;
        lowestUnminted = tokenId;
    }

    function burn(uint256 tokenId) external nonReentrant {
        require(
            ownerOf(tokenId) == msg.sender,
            "You are not the owner of this NFT"
        );
        _claimed[tokenId] = false;
        _burn(tokenId);
    }

    //-----------ONLY OWNER----------------
    function setContractURI(string memory newContractURI) external onlyOwner {
        _contractURI = newContractURI;
        emit ContractURI();
    }

    function setTokenURI(uint256 tokenId, string memory newURI) external onlyOwner {
        _uri[tokenId] = string(abi.encodePacked(newURI, baseExtension));
        emit URI(tokenId);
    }


    function setBaseURI(string memory newBaseURI) external onlyOwner {
        baseURI = newBaseURI;
        emit URIAll();
    }

    function setRoyaltyFee(uint256 _fee) external onlyOwner {
        royaltyFee = _fee;
    }

    function setRoyaltyRecipient(address _recipient) external onlyOwner {
        royaltyRecipient = _recipient;
    }

    function setMintingCostWL1(uint256 _mintingCost) external onlyOwner {
    mintingCost1 = _mintingCost;
    }

    function setMintingCostWL2(uint256 _mintingCost) external onlyOwner {
    mintingCost2 = _mintingCost;
    }

    function setMintingCostPublic(uint256 _mintingCost) external onlyOwner {
    mintingCost3 = _mintingCost;
    }

    function setReserved(uint256 _reserved) external onlyOwner {
    reserved = _reserved;
    }

    function ownerClaim(uint256[] memory tokenIds) external onlyOwner nonReentrant{
        for (uint256 i = 0; i < tokenIds.length; i++) {
            uint256 tokenId = tokenIds[i];
            require(tokenId <= _maxSupply, "Invalid tokenId");

            if (!_claimed[tokenId]) {
                _claimed[tokenId] = true;
                _safeMint(msg.sender, tokenId);
            }
        }
    }

    function distribute(address[] memory recipients, uint256[] memory amounts, uint256 add) external onlyOwner nonReentrant {
        require(recipients.length > 0 && recipients.length == amounts.length, "Invalid input");
        uint256 totalTokensRequired = 0;
        for (uint256 i = 0; i < amounts.length; i++) {
            require(!hasClaimed[recipients[i]], "Recipient has already claimed");
            totalTokensRequired += amounts[i];
        }

        uint256 maxTokenId = _maxSupply - totalSupply();
        require(totalTokensRequired <= maxTokenId, "Not enough tokens left");
        require(totalTokensRequired <= (reserved+add), "Not enough reserved tokens");

        calculateLowestUnminted();
        uint256 tokenId = lowestUnminted;
        uint256 tokensDistributed = 0;

        for (uint256 i = 0; i < recipients.length && tokenId <= _maxSupply; i++) {
            uint256 tokensToMintForRecipient = amounts[i];
            
            while (tokensToMintForRecipient > 0 && tokenId <= _maxSupply) {
                if (!_claimed[tokenId]) {
                    _claimed[tokenId] = true;
                    _safeMint(recipients[i], tokenId);
                    tokensDistributed++;
                }
                tokenId++;
                tokensToMintForRecipient--;
            }
            hasClaimed[recipients[i]] = true;
        }
        reserved -= (tokensDistributed-add);
    }

    function setWhitelistMerkleRoots(bytes32 _whitelist1Root, bytes32 _whitelist2Root, bytes32 _claimWhitelistRoot) external onlyOwner {
        wl1MerkleRoot = _whitelist1Root;
        wl2MerkleRoot = _whitelist2Root;
        claimRoot = _claimWhitelistRoot;
    }

    function toggleWl1Sale(bool state) external onlyOwner {
        wl1SaleActive = state;
        emit ToggleWl1Sale(state);    
    }
    function toggleWl2Sale(bool state) external onlyOwner {
        wl2SaleActive = state;
        emit ToggleWl2Sale(state);
    }
    function togglePublicSale(bool _state) external onlyOwner {
        publicSaleActive = _state;
        emit TogglePublicSale(_state);
    }

    function toggleClaimPhase(bool _state) external onlyOwner {
        claimLive = _state;
        emit ClaimLive(_state);
    }

    function withdraw() public onlyOwner nonReentrant {
        uint256 ethBalance = address(this).balance;
        if (ethBalance > 0) {
            payable(owner()).transfer(ethBalance);
        }
    }

    function transferAnyERC20Token(address tokenAddress, address recipient, uint256 amount) external onlyOwner nonReentrant {
    IERC20 token = IERC20(tokenAddress);
    require(token.transfer(recipient, amount), "Transfer failed");
    }

}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ERC721EnumerableForbiddenBatchMint","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ERC721OutOfBoundsIndex","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"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":false,"internalType":"bool","name":"state","type":"bool"}],"name":"ClaimLive","type":"event"},{"anonymous":false,"inputs":[],"name":"ContractURI","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":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"state","type":"bool"}],"name":"TogglePublicSale","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"state","type":"bool"}],"name":"ToggleWl1Sale","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"state","type":"bool"}],"name":"ToggleWl2Sale","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"URI","type":"event"},{"anonymous":false,"inputs":[],"name":"URIAll","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"uint256","name":"allocation","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimLive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256","name":"add","type":"uint256"}],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"uint256","name":"tokenId","type":"uint256"}],"name":"isClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintingCost1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintingCost2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintingCost3","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":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"ownerClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"publicSaleActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserved","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltyFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newContractURI","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintingCost","type":"uint256"}],"name":"setMintingCostPublic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintingCost","type":"uint256"}],"name":"setMintingCostWL1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintingCost","type":"uint256"}],"name":"setMintingCostWL2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reserved","type":"uint256"}],"name":"setReserved","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setRoyaltyFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"}],"name":"setRoyaltyRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"newURI","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_whitelist1Root","type":"bytes32"},{"internalType":"bytes32","name":"_whitelist2Root","type":"bytes32"},{"internalType":"bytes32","name":"_claimWhitelistRoot","type":"bytes32"}],"name":"setWhitelistMerkleRoots","outputs":[],"stateMutability":"nonpayable","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":"bool","name":"_state","type":"bool"}],"name":"toggleClaimPhase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_state","type":"bool"}],"name":"togglePublicSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"state","type":"bool"}],"name":"toggleWl1Sale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"state","type":"bool"}],"name":"toggleWl2Sale","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":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferAnyERC20Token","outputs":[],"stateMutability":"nonpayable","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":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"verifyProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"allocation","type":"uint256"}],"name":"verifyProofClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wl1MerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"wl1PreSaleMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"wl1SaleActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wl2MerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"wl2PreSaleMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"wl2SaleActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756080526101bc60a052610100604052600560c090815264173539b7b760d91b60e052601690620000519082620002ec565b50600560195567015181ff25a98000601b5567015fb7f9b8c38000601c55670186cc6acd4b0000601d556001601e555f601f556020805463ffffffff191690553480156200009d575f80fd5b5060405162003fe538038062003fe5833981016040819052620000c0916200045e565b3382825f620000d08382620002ec565b506001620000df8282620002ec565b5050506001600160a01b0381166200011057604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6200011b816200014b565b506001600b556080516200013090336200019c565b5050601a80546001600160a01b0319163317905550620004c4565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f828152600c602090815260408083206001600160a01b038516845290915281205460ff1662000243575f838152600c602090815260408083206001600160a01b03861684529091529020805460ff19166001179055620001fa3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000246565b505f5b92915050565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200027557607f821691505b6020821081036200029457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115620002e7575f81815260208120601f850160051c81016020861015620002c25750805b601f850160051c820191505b81811015620002e357828155600101620002ce565b5050505b505050565b81516001600160401b038111156200030857620003086200024c565b620003208162000319845462000260565b846200029a565b602080601f83116001811462000356575f84156200033e5750858301515b5f19600386901b1c1916600185901b178555620002e3565b5f85815260208120601f198616915b82811015620003865788860151825594840194600190910190840162000365565b5085821015620003a457878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f82601f830112620003c4575f80fd5b81516001600160401b0380821115620003e157620003e16200024c565b604051601f8301601f19908116603f011681019082821181831017156200040c576200040c6200024c565b8160405283815260209250868385880101111562000428575f80fd5b5f91505b838210156200044b57858201830151818301840152908201906200042c565b5f93810190920192909252949350505050565b5f806040838503121562000470575f80fd5b82516001600160401b038082111562000487575f80fd5b6200049586838701620003b4565b93506020850151915080821115620004ab575f80fd5b50620004ba85828601620003b4565b9150509250929050565b60805160a051613ace620005175f395f81816105c6015281816112990152818161164e01528181611ece01528181611fb501528181612007015281816122ee015261270f01525f6109800152613ace5ff3fe608060405260043610610416575f3560e01c80636352211e11610220578063b88d4fde11610129578063d543667c116100b3578063ea46faf411610078578063ea46faf414610c4f578063f2fde38b14610c6e578063f450838214610c8d578063f72df65114610cac578063fe60d12c14610ccb575f80fd5b8063d543667c14610bd3578063d547741f14610be8578063e8a3d48514610c07578063e9399b4514610c1b578063e985e9c514610c30575f80fd5b8063c0597088116100f9578063c059708814610b4d578063c0e7274014610b6c578063c8491a7e14610b80578063c87b56dd14610b95578063d493b9ac14610bb4575f80fd5b8063b88d4fde14610adb578063b8997a9714610afa578063bc8893b414610b0f578063bd9be19714610b2f575f80fd5b80638462151c116101aa578063938e3d7b1161017a578063938e3d7b14610a4857806395d89b4114610a675780639e34070f14610a7b578063a217fddf14610aa9578063a22cb46514610abc575f80fd5b80638462151c146109c15780638c3cefa3146109ed5780638da5cb5b14610a0c57806391d1485414610a29575f80fd5b8063715018a6116101f0578063715018a61461090e57806373b2e80e1461092257806373f5971b1461095057806375b238fc1461096f578063770c0fb1146109a2575f80fd5b80636352211e1461089d5780636c0360eb146108bc5780636f90ef8d146108d057806370a08231146108ef575f80fd5b80632d6e71b6116103225780633e4086e5116102ac5780634c00de821161027c5780634c00de82146108025780634f6ccce71461082157806355f804b314610840578063576c0ac41461085f5780635a3a36a21461087e575f80fd5b80633e4086e51461078657806341e42f30146107a557806342842e0e146107c457806342966c68146107e3575f80fd5b806336568abe116102f257806336568abe146106f1578063372bc1321461071057806338e21cce146107255780633b439351146107535780633ccfd60b14610772575f80fd5b80632d6e71b61461067b5780632f2ff15d1461069a5780632f745c59146106b957806330922d78146106d8575f80fd5b8063162094c4116103a357806322f4596f1161037357806322f4596f146105b557806323b872dd146105e8578063248a9ca31461060757806326092b83146106355780632a55205a1461063d575f80fd5b8063162094c41461055a578063176a00a81461057957806318160ddd1461058c578063224d9bc3146105a0575f80fd5b80630cff542a116103e95780630cff542a146104c75780630dd2ea84146104da57806313eee0c8146104f957806314bcd5441461051857806314ea35e714610537575f80fd5b806301ffc9a71461041a57806306fdde031461044e578063081812fc1461046f578063095ea7b3146104a6575b5f80fd5b348015610425575f80fd5b506104396104343660046130ff565b610ce0565b60405190151581526020015b60405180910390f35b348015610459575f80fd5b50610462610cf0565b6040516104459190613167565b34801561047a575f80fd5b5061048e610489366004613179565b610d7f565b6040516001600160a01b039091168152602001610445565b3480156104b1575f80fd5b506104c56104c03660046131ab565b610da6565b005b6104c56104d53660046132a1565b610db5565b3480156104e5575f80fd5b506020546104399062010000900460ff1681565b348015610504575f80fd5b506104c5610513366004613179565b610df3565b348015610523575f80fd5b506104c56105323660046132df565b610e00565b348015610542575f80fd5b5061054c600f5481565b604051908152602001610445565b348015610565575f80fd5b506104c561057436600461336c565b610e55565b6104c56105873660046132a1565b610ec5565b348015610597575f80fd5b5060085461054c565b3480156105ab575f80fd5b5061054c601b5481565b3480156105c0575f80fd5b5061054c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105f3575f80fd5b506104c56106023660046133af565b610eee565b348015610612575f80fd5b5061054c610621366004613179565b5f908152600c602052604090206001015490565b6104c5610f7c565b348015610648575f80fd5b5061065c6106573660046133e8565b610fc6565b604080516001600160a01b039093168352602083019190915201610445565b348015610686575f80fd5b506104c5610695366004613179565b610ffa565b3480156106a5575f80fd5b506104c56106b4366004613408565b611007565b3480156106c4575f80fd5b5061054c6106d33660046131ab565b61102b565b3480156106e3575f80fd5b506020546104399060ff1681565b3480156106fc575f80fd5b506104c561070b366004613408565b61108e565b34801561071b575f80fd5b5061054c601c5481565b348015610730575f80fd5b5061043961073f366004613432565b60146020525f908152604090205460ff1681565b34801561075e575f80fd5b506104c561076d36600461344b565b6110c6565b34801561077d575f80fd5b506104c5611357565b348015610791575f80fd5b506104c56107a0366004613179565b6113b1565b3480156107b0575f80fd5b506104c56107bf366004613432565b6113be565b3480156107cf575f80fd5b506104c56107de3660046133af565b6113e8565b3480156107ee575f80fd5b506104c56107fd366004613179565b611402565b34801561080d575f80fd5b50601a5461048e906001600160a01b031681565b34801561082c575f80fd5b5061054c61083b366004613179565b611492565b34801561084b575f80fd5b506104c561085a36600461348c565b6114e7565b34801561086a575f80fd5b506104396108793660046134bd565b611527565b348015610889575f80fd5b506104c5610898366004613179565b611571565b3480156108a8575f80fd5b5061048e6108b7366004613179565b61157e565b3480156108c7575f80fd5b50610462611588565b3480156108db575f80fd5b506104c56108ea3660046132a1565b611614565b3480156108fa575f80fd5b5061054c610909366004613432565b611703565b348015610919575f80fd5b506104c5611748565b34801561092d575f80fd5b5061043961093c366004613432565b60156020525f908152604090205460ff1681565b34801561095b575f80fd5b506104c561096a366004613179565b611759565b34801561097a575f80fd5b5061054c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156109ad575f80fd5b506104c56109bc36600461350f565b611766565b3480156109cc575f80fd5b506109e06109db366004613432565b61177c565b6040516104459190613538565b3480156109f8575f80fd5b506104c5610a073660046132df565b611838565b348015610a17575f80fd5b50600a546001600160a01b031661048e565b348015610a34575f80fd5b50610439610a43366004613408565b61188a565b348015610a53575f80fd5b506104c5610a6236600461348c565b6118b4565b348015610a72575f80fd5b506104626118f4565b348015610a86575f80fd5b50610439610a95366004613179565b5f9081526011602052604090205460ff1690565b348015610ab4575f80fd5b5061054c5f81565b348015610ac7575f80fd5b506104c5610ad636600461357b565b611903565b348015610ae6575f80fd5b506104c5610af53660046135b0565b61190e565b348015610b05575f80fd5b5061054c60195481565b348015610b1a575f80fd5b50602054610439906301000000900460ff1681565b348015610b3a575f80fd5b5060205461043990610100900460ff1681565b348015610b58575f80fd5b506104c5610b673660046132df565b611925565b348015610b77575f80fd5b5061046261196b565b348015610b8b575f80fd5b5061054c601d5481565b348015610ba0575f80fd5b50610462610baf366004613179565b611978565b348015610bbf575f80fd5b506104c5610bce3660046133af565b611b8b565b348015610bde575f80fd5b5061054c600d5481565b348015610bf3575f80fd5b506104c5610c02366004613408565b611c57565b348015610c12575f80fd5b50610462611c7b565b348015610c26575f80fd5b5061054c600e5481565b348015610c3b575f80fd5b50610439610c4a366004613626565b611c8a565b348015610c5a575f80fd5b506104c5610c693660046132df565b611cb7565b348015610c79575f80fd5b506104c5610c88366004613432565b611d07565b348015610c98575f80fd5b50610439610ca736600461364e565b611d41565b348015610cb7575f80fd5b506104c5610cc63660046136a8565b611d93565b348015610cd6575f80fd5b5061054c601f5481565b5f610cea8261213a565b92915050565b60605f8054610cfe90613769565b80601f0160208091040260200160405190810160405280929190818152602001828054610d2a90613769565b8015610d755780601f10610d4c57610100808354040283529160200191610d75565b820191905f5260205f20905b815481529060010190602001808311610d5857829003601f168201915b5050505050905090565b5f610d898261215e565b505f828152600460205260409020546001600160a01b0316610cea565b610db1828233612196565b5050565b610dbd6121a3565b610dde602060029054906101000a900460ff16601c54600184600e546121fc565b610de661241f565b610df06001600b55565b50565b610dfb6124d7565b601d55565b610e086124d7565b6020805461ff0019166101008315159081029190911782556040519081527f302715938fdba1da12ef0d47c363c0f835ff5e42369327fc40d670d504e1731191015b60405180910390a150565b610e5d6124d7565b806016604051602001610e7192919061380a565b60408051601f198184030181529181525f84815260106020522090610e969082613874565b5060405182907f901e1c01b493ffa41590ea147378e25dde9601a9390b52eb75d4e0e2118a44a5905f90a25050565b610ecd6121a3565b610dde602060019054906101000a900460ff16601b54600184600d546121fc565b6001600160a01b038216610f1c57604051633250574960e11b81525f60048201526024015b60405180910390fd5b5f610f28838333612504565b9050836001600160a01b0316816001600160a01b031614610f76576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610f13565b50505050565b610f846121a3565b60208054601d54604080515f808252948101909152610fb1926301000000900460ff1691908490856121fc565b610fb961241f565b50610fc46001600b55565b565b5f805f606460195485610fd99190613943565b610fe3919061395a565b601a546001600160a01b0316969095509350505050565b6110026124d7565b601f55565b5f828152600c6020526040902060010154611021816125d7565b610f7683836125e1565b5f61103583611703565b82106110665760405163295f44f760e21b81526001600160a01b038416600482015260248101839052604401610f13565b506001600160a01b03919091165f908152600660209081526040808320938352929052205490565b6001600160a01b03811633146110b75760405163334bd91960e11b815260040160405180910390fd5b6110c18282612672565b505050565b6110ce6121a3565b60205460ff1661112c5760405162461bcd60e51b8152602060048201526024808201527f436c61696d696e67206973206e6f742061637469766520617420746865206d6f6044820152631b595b9d60e21b6064820152608401610f13565b335f9081526015602052604090205460ff161561118b5760405162461bcd60e51b815260206004820152601860248201527f596f75206861766520616c726561647920636c61696d656400000000000000006044820152606401610f13565b601f548111156111dd5760405162461bcd60e51b815260206004820152601a60248201527f4e6f7420656e6f75676820726573657276656420746f6b656e730000000000006044820152606401610f13565b6040516001600160601b03193360601b166020820152603481018290525f9060540160405160208183030381529060405280519060200120905061122483600f54836126dd565b6112805760405162461bcd60e51b815260206004820152602760248201527f496e76616c69642070726f6f66206f7220796f75277265206e6f742077686974604482015266195b1a5cdd195960ca1b6064820152608401610f13565b6112886126f2565b601e545f5b83811080156112bc57507f00000000000000000000000000000000000000000000000000000000000000008211155b15611319575f8281526011602052604090205460ff16611314575f828152601160205260409020805460ff191660011790556112f83383612752565b8061130281613979565b915050818061131090613979565b9250505b61128d565b80601f5f82825461132a9190613991565b9091555050335f908152601560205260409020805460ff1916600117905550601e5550610db16001600b55565b61135f6124d7565b6113676121a3565b478015610fb957600a546040516001600160a01b039091169082156108fc029083905f818181858888f193505050501580156113a5573d5f803e3d5ffd5b5050610fc46001600b55565b6113b96124d7565b601955565b6113c66124d7565b601a80546001600160a01b0319166001600160a01b0392909216919091179055565b6110c183838360405180602001604052805f81525061190e565b61140a6121a3565b336114148261157e565b6001600160a01b0316146114745760405162461bcd60e51b815260206004820152602160248201527f596f7520617265206e6f7420746865206f776e6572206f662074686973204e466044820152601560fa1b6064820152608401610f13565b5f818152601160205260409020805460ff19169055610de68161276b565b5f61149c60085490565b82106114c45760405163295f44f760e21b81525f600482015260248101839052604401610f13565b600882815481106114d7576114d76139a4565b905f5260205f2001549050919050565b6114ef6124d7565b60176114fb8282613874565b506040517f9bf13f1005bf8940f6b531a89ba63b7fbd1b63269d49cc5612e9268b07d2527d905f90a150565b6040516001600160601b0319606083901b1660208201525f9081906034016040516020818303038152906040528051906020012090506115688585836126dd565b95945050505050565b6115796124d7565b601b55565b5f610cea8261215e565b6017805461159590613769565b80601f01602080910402602001604051908101604052809291908181526020018280546115c190613769565b801561160c5780601f106115e35761010080835404028352916020019161160c565b820191905f5260205f20905b8154815290600101906020018083116115ef57829003601f168201915b505050505081565b61161c6124d7565b6116246121a3565b5f5b81518110156116f8575f828281518110611642576116426139a4565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000008111156116ae5760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081d1bdad95b9259608a1b6044820152606401610f13565b5f8181526011602052604090205460ff166116e5575f818152601160205260409020805460ff191660011790556116e53382612752565b50806116f081613979565b915050611626565b50610df06001600b55565b5f6001600160a01b03821661172d576040516322718ad960e21b81525f6004820152602401610f13565b506001600160a01b03165f9081526003602052604090205490565b6117506124d7565b610fc45f6127a3565b6117616124d7565b601c55565b61176e6124d7565b600d92909255600e55600f55565b60605f61178883611703565b9050805f036117aa57604080515f80825260208201909252905b509392505050565b5f816001600160401b038111156117c3576117c36131d3565b6040519080825280602002602001820160405280156117ec578160200160208202803683370190505b5090505f5b828110156117a257611803858261102b565b828281518110611815576118156139a4565b60209081029190910101528061182a81613979565b9150506117f1565b50919050565b6118406124d7565b6020805463ff000000191663010000008315159081029190911782556040519081527f4fea9b813a6127bfa89d28fb37b367110239e50769e6a9fc6b6400e2e60c857e9101610e4a565b5f918252600c602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6118bc6124d7565b60186118c88282613874565b506040517fff4ccd353885f015d383bdfcccc32f90e1573a6ec9da3c355dc74a39e1021059905f90a150565b606060018054610cfe90613769565b610db13383836127f4565b611919848484610eee565b610f7684848484612892565b61192d6124d7565b6020805460ff191682151590811782556040519081527fc6b9935e9bc27c1896eacf1f4f4957640b4375c9946a2fa5cf78fa30fc3943099101610e4a565b6018805461159590613769565b60605f6119848361157e565b6001600160a01b0316036119f25760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610f13565b5f8281526010602052604081208054611a0a90613769565b90501115611aad575f8281526010602052604090208054611a2a90613769565b80601f0160208091040260200160405190810160405280929190818152602001828054611a5690613769565b8015611aa15780601f10611a7857610100808354040283529160200191611aa1565b820191905f5260205f20905b815481529060010190602001808311611a8457829003601f168201915b50505050509050919050565b5f60178054611abb90613769565b80601f0160208091040260200160405190810160405280929190818152602001828054611ae790613769565b8015611b325780601f10611b0957610100808354040283529160200191611b32565b820191905f5260205f20905b815481529060010190602001808311611b1557829003601f168201915b5050505050905080515f03611b5657505060408051602081019091525f8152919050565b80611b60846129b1565b6016604051602001611b74939291906139b8565b604051602081830303815290604052915050919050565b611b936124d7565b611b9b6121a3565b60405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284919082169063a9059cbb906044016020604051808303815f875af1158015611bea573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c0e91906139f4565b611c4c5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610f13565b506110c16001600b55565b5f828152600c6020526040902060010154611c71816125d7565b610f768383612672565b606060188054610cfe90613769565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b611cbf6124d7565b6020805462ff00001916620100008315159081029190911782556040519081527feebbf6a3bc3ff1c01754ed345f0a2b74aa522579f98cd6685b11767934a8d4b09101610e4a565b611d0f6124d7565b6001600160a01b038116611d3857604051631e4fbdf760e01b81525f6004820152602401610f13565b610df0816127a3565b6040516001600160601b0319606084901b166020820152603481018290525f908190605401604051602081830303815290604052805190602001209050611d898686836126dd565b9695505050505050565b611d9b6124d7565b611da36121a3565b5f8351118015611db4575081518351145b611df05760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a59081a5b9c1d5d609a1b6044820152606401610f13565b5f805b8351811015611ebd5760155f868381518110611e1157611e116139a4565b6020908102919091018101516001600160a01b031682528101919091526040015f205460ff1615611e845760405162461bcd60e51b815260206004820152601d60248201527f526563697069656e742068617320616c726561647920636c61696d65640000006044820152606401610f13565b838181518110611e9657611e966139a4565b602002602001015182611ea99190613a0f565b915080611eb581613979565b915050611df3565b505f611ec860085490565b611ef2907f0000000000000000000000000000000000000000000000000000000000000000613991565b905080821115611f3d5760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da081d1bdad95b9cc81b19599d60521b6044820152606401610f13565b82601f54611f4b9190613a0f565b821115611f9a5760405162461bcd60e51b815260206004820152601a60248201527f4e6f7420656e6f75676820726573657276656420746f6b656e730000000000006044820152606401610f13565b611fa26126f2565b601e545f805b875181108015611fd857507f00000000000000000000000000000000000000000000000000000000000000008311155b1561210b575f878281518110611ff057611ff06139a4565b602002602001015190505b5f8111801561202a57507f00000000000000000000000000000000000000000000000000000000000000008411155b156120b0575f8481526011602052604090205460ff16612090575f848152601160205260409020805460ff191660011790558851612082908a9084908110612074576120746139a4565b602002602001015185612752565b8261208c81613979565b9350505b8361209a81613979565b94505080806120a890613a22565b915050611ffb565b600160155f8b85815181106120c7576120c76139a4565b6020908102919091018101516001600160a01b031682528101919091526040015f20805460ff1916911515919091179055508061210381613979565b915050611fa8565b506121168582613991565b601f5f8282546121269190613991565b90915550506001600b55506110c192505050565b5f6001600160e01b03198216637965db0b60e01b1480610cea5750610cea82612a40565b5f818152600260205260408120546001600160a01b031680610cea57604051637e27328960e01b815260048101849052602401610f13565b6110c18383836001612a64565b6002600b54036121f55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610f13565b6002600b55565b8461223e5760405162461bcd60e51b815260206004820152601260248201527153616c65206973206e6f742061637469766560701b6044820152606401610f13565b335f9081526014602052604090205460ff161561229d5760405162461bcd60e51b815260206004820152601760248201527f596f75206861766520616c7265616479206d696e7465640000000000000000006044820152606401610f13565b8334146122ec5760405162461bcd60e51b815260206004820152601960248201527f45746865722073656e74206973206e6f7420636f7272656374000000000000006044820152606401610f13565b7f0000000000000000000000000000000000000000000000000000000000000000601f5461231960085490565b6123239190613a0f565b106123705760405162461bcd60e51b815260206004820152601b60248201527f416c6c20746f6b656e732068617665206265656e206d696e74656400000000006044820152606401610f13565b8215612418576040516001600160601b03193360601b1660208201525f906034016040516020818303038152906040528051906020012090505f6123b58484846126dd565b9050806124155760405162461bcd60e51b815260206004820152602860248201527f596f7520617265206e6f7420616c6c6f77656420746f206d696e7420696e20746044820152676869732073616c6560c01b6064820152608401610f13565b50505b5050505050565b6124276126f2565b5f601f54601e546124389190613a0f565b5f8181526011602052604090205490915060ff16156124995760405162461bcd60e51b815260206004820152601860248201527f546f6b656e20697320616c726561647920636c61696d656400000000000000006044820152606401610f13565b5f818152601160205260409020805460ff191660011790556124bb3382612752565b50335f908152601460205260409020805460ff19166001179055565b600a546001600160a01b03163314610fc45760405163118cdaa760e01b8152336004820152602401610f13565b5f80612511858585612b68565b90506001600160a01b03811661256d5761256884600880545f838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b612590565b846001600160a01b0316816001600160a01b031614612590576125908185612c5a565b6001600160a01b0385166125ac576125a784612ce7565b6125cf565b846001600160a01b0316816001600160a01b0316146125cf576125cf8585612d8e565b949350505050565b610df08133612ddc565b5f6125ec838361188a565b61266b575f838152600c602090815260408083206001600160a01b03861684529091529020805460ff191660011790556126233390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610cea565b505f610cea565b5f61267d838361188a565b1561266b575f838152600c602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610cea565b5f826126e98584612e15565b14949350505050565b601e545f9081526011602052604090205460ff16801561273457507f0000000000000000000000000000000000000000000000000000000000000000601e5411155b15610fc457601e8054905f61274883613979565b91905055506126f2565b610db1828260405180602001604052805f815250612e59565b5f6127775f835f612504565b90506001600160a01b038116610db157604051637e27328960e01b815260048101839052602401610f13565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b03821661282657604051630b61174360e31b81526001600160a01b0383166004820152602401610f13565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b15610f7657604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906128d4903390889087908790600401613a37565b6020604051808303815f875af192505050801561290e575060408051601f3d908101601f1916820190925261290b91810190613a69565b60015b612975573d80801561293b576040519150601f19603f3d011682016040523d82523d5f602084013e612940565b606091505b5080515f0361296d57604051633250574960e11b81526001600160a01b0385166004820152602401610f13565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b1461241857604051633250574960e11b81526001600160a01b0385166004820152602401610f13565b60605f6129bd83612e6f565b60010190505f816001600160401b038111156129db576129db6131d3565b6040519080825280601f01601f191660200182016040528015612a05576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612a0f57509392505050565b5f6001600160e01b0319821663780e9d6360e01b1480610cea5750610cea82612f46565b8080612a7857506001600160a01b03821615155b15612b39575f612a878461215e565b90506001600160a01b03831615801590612ab35750826001600160a01b0316816001600160a01b031614155b8015612ac65750612ac48184611c8a565b155b15612aef5760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610f13565b8115612b375783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b5f828152600260205260408120546001600160a01b0390811690831615612b9457612b94818486612f95565b6001600160a01b03811615612bce57612baf5f855f80612a64565b6001600160a01b0381165f90815260036020526040902080545f190190555b6001600160a01b03851615612bfc576001600160a01b0385165f908152600360205260409020805460010190555b5f8481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b5f612c6483611703565b5f83815260076020526040902054909150808214612cb5576001600160a01b0384165f9081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b505f9182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008545f90612cf890600190613991565b5f8381526009602052604081205460088054939450909284908110612d1f57612d1f6139a4565b905f5260205f20015490508060088381548110612d3e57612d3e6139a4565b5f918252602080832090910192909255828152600990915260408082208490558582528120556008805480612d7557612d75613a84565b600190038181905f5260205f20015f9055905550505050565b5f6001612d9a84611703565b612da49190613991565b6001600160a01b039093165f908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b612de6828261188a565b610db15760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610f13565b5f81815b84518110156117a257612e4582868381518110612e3857612e386139a4565b6020026020010151612ff9565b915080612e5181613979565b915050612e19565b612e638383613028565b6110c15f848484612892565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310612ead5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612ed9576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310612ef757662386f26fc10000830492506010015b6305f5e1008310612f0f576305f5e100830492506008015b6127108310612f2357612710830492506004015b60648310612f35576064830492506002015b600a8310610cea5760010192915050565b5f6001600160e01b031982166380ac58cd60e01b1480612f7657506001600160e01b03198216635b5e139f60e01b145b80610cea57506301ffc9a760e01b6001600160e01b0319831614610cea565b612fa0838383613089565b6110c1576001600160a01b038316612fce57604051637e27328960e01b815260048101829052602401610f13565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610f13565b5f818310613013575f828152602084905260409020613021565b5f8381526020839052604090205b9392505050565b6001600160a01b03821661305157604051633250574960e11b81525f6004820152602401610f13565b5f61305d83835f612504565b90506001600160a01b038116156110c1576040516339e3563760e11b81525f6004820152602401610f13565b5f6001600160a01b038316158015906125cf5750826001600160a01b0316846001600160a01b031614806130c257506130c28484611c8a565b806125cf5750505f908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b031981168114610df0575f80fd5b5f6020828403121561310f575f80fd5b8135613021816130ea565b5f5b8381101561313457818101518382015260200161311c565b50505f910152565b5f815180845261315381602086016020860161311a565b601f01601f19169290920160200192915050565b602081525f613021602083018461313c565b5f60208284031215613189575f80fd5b5035919050565b80356001600160a01b03811681146131a6575f80fd5b919050565b5f80604083850312156131bc575f80fd5b6131c583613190565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561320f5761320f6131d3565b604052919050565b5f6001600160401b0382111561322f5761322f6131d3565b5060051b60200190565b5f82601f830112613248575f80fd5b8135602061325d61325883613217565b6131e7565b82815260059290921b8401810191818101908684111561327b575f80fd5b8286015b84811015613296578035835291830191830161327f565b509695505050505050565b5f602082840312156132b1575f80fd5b81356001600160401b038111156132c6575f80fd5b6125cf84828501613239565b8015158114610df0575f80fd5b5f602082840312156132ef575f80fd5b8135613021816132d2565b5f6001600160401b03831115613312576133126131d3565b613325601f8401601f19166020016131e7565b9050828152838383011115613338575f80fd5b828260208301375f602084830101529392505050565b5f82601f83011261335d575f80fd5b613021838335602085016132fa565b5f806040838503121561337d575f80fd5b8235915060208301356001600160401b03811115613399575f80fd5b6133a58582860161334e565b9150509250929050565b5f805f606084860312156133c1575f80fd5b6133ca84613190565b92506133d860208501613190565b9150604084013590509250925092565b5f80604083850312156133f9575f80fd5b50508035926020909101359150565b5f8060408385031215613419575f80fd5b8235915061342960208401613190565b90509250929050565b5f60208284031215613442575f80fd5b61302182613190565b5f806040838503121561345c575f80fd5b82356001600160401b03811115613471575f80fd5b61347d85828601613239565b95602094909401359450505050565b5f6020828403121561349c575f80fd5b81356001600160401b038111156134b1575f80fd5b6125cf8482850161334e565b5f805f606084860312156134cf575f80fd5b83356001600160401b038111156134e4575f80fd5b6134f086828701613239565b9350506020840135915061350660408501613190565b90509250925092565b5f805f60608486031215613521575f80fd5b505081359360208301359350604090920135919050565b602080825282518282018190525f9190848201906040850190845b8181101561356f57835183529284019291840191600101613553565b50909695505050505050565b5f806040838503121561358c575f80fd5b61359583613190565b915060208301356135a5816132d2565b809150509250929050565b5f805f80608085870312156135c3575f80fd5b6135cc85613190565b93506135da60208601613190565b92506040850135915060608501356001600160401b038111156135fb575f80fd5b8501601f8101871361360b575f80fd5b61361a878235602084016132fa565b91505092959194509250565b5f8060408385031215613637575f80fd5b61364083613190565b915061342960208401613190565b5f805f8060808587031215613661575f80fd5b84356001600160401b03811115613676575f80fd5b61368287828801613239565b9450506020850135925061369860408601613190565b9396929550929360600135925050565b5f805f606084860312156136ba575f80fd5b83356001600160401b03808211156136d0575f80fd5b818601915086601f8301126136e3575f80fd5b813560206136f361325883613217565b82815260059290921b8401810191818101908a841115613711575f80fd5b948201945b838610156137365761372786613190565b82529482019490820190613716565b9750508701359250508082111561374b575f80fd5b5061375886828701613239565b925050604084013590509250925092565b600181811c9082168061377d57607f821691505b60208210810361183257634e487b7160e01b5f52602260045260245ffd5b5f81546137a781613769565b600182811680156137bf57600181146137d457613800565b60ff1984168752821515830287019450613800565b855f526020805f205f5b858110156137f75781548a8201529084019082016137de565b50505082870194505b5050505092915050565b5f835161381b81846020880161311a565b6115688184018561379b565b601f8211156110c1575f81815260208120601f850160051c8101602086101561384d5750805b601f850160051c820191505b8181101561386c57828155600101613859565b505050505050565b81516001600160401b0381111561388d5761388d6131d3565b6138a18161389b8454613769565b84613827565b602080601f8311600181146138d4575f84156138bd5750858301515b5f19600386901b1c1916600185901b17855561386c565b5f85815260208120601f198616915b82811015613902578886015182559484019460019091019084016138e3565b508582101561391f57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610cea57610cea61392f565b5f8261397457634e487b7160e01b5f52601260045260245ffd5b500490565b5f6001820161398a5761398a61392f565b5060010190565b81810381811115610cea57610cea61392f565b634e487b7160e01b5f52603260045260245ffd5b5f84516139c981846020890161311a565b8451908301906139dd81836020890161311a565b6139e98183018661379b565b979650505050505050565b5f60208284031215613a04575f80fd5b8151613021816132d2565b80820180821115610cea57610cea61392f565b5f81613a3057613a3061392f565b505f190190565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90611d899083018461313c565b5f60208284031215613a79575f80fd5b8151613021816130ea565b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220111ceac837821224994a51141b93f86e3ecac54b9cfe5c12b77a9f1c778848ba64736f6c6343000814003300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000c4461726b536f6c6469657273000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024453000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405260043610610416575f3560e01c80636352211e11610220578063b88d4fde11610129578063d543667c116100b3578063ea46faf411610078578063ea46faf414610c4f578063f2fde38b14610c6e578063f450838214610c8d578063f72df65114610cac578063fe60d12c14610ccb575f80fd5b8063d543667c14610bd3578063d547741f14610be8578063e8a3d48514610c07578063e9399b4514610c1b578063e985e9c514610c30575f80fd5b8063c0597088116100f9578063c059708814610b4d578063c0e7274014610b6c578063c8491a7e14610b80578063c87b56dd14610b95578063d493b9ac14610bb4575f80fd5b8063b88d4fde14610adb578063b8997a9714610afa578063bc8893b414610b0f578063bd9be19714610b2f575f80fd5b80638462151c116101aa578063938e3d7b1161017a578063938e3d7b14610a4857806395d89b4114610a675780639e34070f14610a7b578063a217fddf14610aa9578063a22cb46514610abc575f80fd5b80638462151c146109c15780638c3cefa3146109ed5780638da5cb5b14610a0c57806391d1485414610a29575f80fd5b8063715018a6116101f0578063715018a61461090e57806373b2e80e1461092257806373f5971b1461095057806375b238fc1461096f578063770c0fb1146109a2575f80fd5b80636352211e1461089d5780636c0360eb146108bc5780636f90ef8d146108d057806370a08231146108ef575f80fd5b80632d6e71b6116103225780633e4086e5116102ac5780634c00de821161027c5780634c00de82146108025780634f6ccce71461082157806355f804b314610840578063576c0ac41461085f5780635a3a36a21461087e575f80fd5b80633e4086e51461078657806341e42f30146107a557806342842e0e146107c457806342966c68146107e3575f80fd5b806336568abe116102f257806336568abe146106f1578063372bc1321461071057806338e21cce146107255780633b439351146107535780633ccfd60b14610772575f80fd5b80632d6e71b61461067b5780632f2ff15d1461069a5780632f745c59146106b957806330922d78146106d8575f80fd5b8063162094c4116103a357806322f4596f1161037357806322f4596f146105b557806323b872dd146105e8578063248a9ca31461060757806326092b83146106355780632a55205a1461063d575f80fd5b8063162094c41461055a578063176a00a81461057957806318160ddd1461058c578063224d9bc3146105a0575f80fd5b80630cff542a116103e95780630cff542a146104c75780630dd2ea84146104da57806313eee0c8146104f957806314bcd5441461051857806314ea35e714610537575f80fd5b806301ffc9a71461041a57806306fdde031461044e578063081812fc1461046f578063095ea7b3146104a6575b5f80fd5b348015610425575f80fd5b506104396104343660046130ff565b610ce0565b60405190151581526020015b60405180910390f35b348015610459575f80fd5b50610462610cf0565b6040516104459190613167565b34801561047a575f80fd5b5061048e610489366004613179565b610d7f565b6040516001600160a01b039091168152602001610445565b3480156104b1575f80fd5b506104c56104c03660046131ab565b610da6565b005b6104c56104d53660046132a1565b610db5565b3480156104e5575f80fd5b506020546104399062010000900460ff1681565b348015610504575f80fd5b506104c5610513366004613179565b610df3565b348015610523575f80fd5b506104c56105323660046132df565b610e00565b348015610542575f80fd5b5061054c600f5481565b604051908152602001610445565b348015610565575f80fd5b506104c561057436600461336c565b610e55565b6104c56105873660046132a1565b610ec5565b348015610597575f80fd5b5060085461054c565b3480156105ab575f80fd5b5061054c601b5481565b3480156105c0575f80fd5b5061054c7f00000000000000000000000000000000000000000000000000000000000001bc81565b3480156105f3575f80fd5b506104c56106023660046133af565b610eee565b348015610612575f80fd5b5061054c610621366004613179565b5f908152600c602052604090206001015490565b6104c5610f7c565b348015610648575f80fd5b5061065c6106573660046133e8565b610fc6565b604080516001600160a01b039093168352602083019190915201610445565b348015610686575f80fd5b506104c5610695366004613179565b610ffa565b3480156106a5575f80fd5b506104c56106b4366004613408565b611007565b3480156106c4575f80fd5b5061054c6106d33660046131ab565b61102b565b3480156106e3575f80fd5b506020546104399060ff1681565b3480156106fc575f80fd5b506104c561070b366004613408565b61108e565b34801561071b575f80fd5b5061054c601c5481565b348015610730575f80fd5b5061043961073f366004613432565b60146020525f908152604090205460ff1681565b34801561075e575f80fd5b506104c561076d36600461344b565b6110c6565b34801561077d575f80fd5b506104c5611357565b348015610791575f80fd5b506104c56107a0366004613179565b6113b1565b3480156107b0575f80fd5b506104c56107bf366004613432565b6113be565b3480156107cf575f80fd5b506104c56107de3660046133af565b6113e8565b3480156107ee575f80fd5b506104c56107fd366004613179565b611402565b34801561080d575f80fd5b50601a5461048e906001600160a01b031681565b34801561082c575f80fd5b5061054c61083b366004613179565b611492565b34801561084b575f80fd5b506104c561085a36600461348c565b6114e7565b34801561086a575f80fd5b506104396108793660046134bd565b611527565b348015610889575f80fd5b506104c5610898366004613179565b611571565b3480156108a8575f80fd5b5061048e6108b7366004613179565b61157e565b3480156108c7575f80fd5b50610462611588565b3480156108db575f80fd5b506104c56108ea3660046132a1565b611614565b3480156108fa575f80fd5b5061054c610909366004613432565b611703565b348015610919575f80fd5b506104c5611748565b34801561092d575f80fd5b5061043961093c366004613432565b60156020525f908152604090205460ff1681565b34801561095b575f80fd5b506104c561096a366004613179565b611759565b34801561097a575f80fd5b5061054c7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b3480156109ad575f80fd5b506104c56109bc36600461350f565b611766565b3480156109cc575f80fd5b506109e06109db366004613432565b61177c565b6040516104459190613538565b3480156109f8575f80fd5b506104c5610a073660046132df565b611838565b348015610a17575f80fd5b50600a546001600160a01b031661048e565b348015610a34575f80fd5b50610439610a43366004613408565b61188a565b348015610a53575f80fd5b506104c5610a6236600461348c565b6118b4565b348015610a72575f80fd5b506104626118f4565b348015610a86575f80fd5b50610439610a95366004613179565b5f9081526011602052604090205460ff1690565b348015610ab4575f80fd5b5061054c5f81565b348015610ac7575f80fd5b506104c5610ad636600461357b565b611903565b348015610ae6575f80fd5b506104c5610af53660046135b0565b61190e565b348015610b05575f80fd5b5061054c60195481565b348015610b1a575f80fd5b50602054610439906301000000900460ff1681565b348015610b3a575f80fd5b5060205461043990610100900460ff1681565b348015610b58575f80fd5b506104c5610b673660046132df565b611925565b348015610b77575f80fd5b5061046261196b565b348015610b8b575f80fd5b5061054c601d5481565b348015610ba0575f80fd5b50610462610baf366004613179565b611978565b348015610bbf575f80fd5b506104c5610bce3660046133af565b611b8b565b348015610bde575f80fd5b5061054c600d5481565b348015610bf3575f80fd5b506104c5610c02366004613408565b611c57565b348015610c12575f80fd5b50610462611c7b565b348015610c26575f80fd5b5061054c600e5481565b348015610c3b575f80fd5b50610439610c4a366004613626565b611c8a565b348015610c5a575f80fd5b506104c5610c693660046132df565b611cb7565b348015610c79575f80fd5b506104c5610c88366004613432565b611d07565b348015610c98575f80fd5b50610439610ca736600461364e565b611d41565b348015610cb7575f80fd5b506104c5610cc63660046136a8565b611d93565b348015610cd6575f80fd5b5061054c601f5481565b5f610cea8261213a565b92915050565b60605f8054610cfe90613769565b80601f0160208091040260200160405190810160405280929190818152602001828054610d2a90613769565b8015610d755780601f10610d4c57610100808354040283529160200191610d75565b820191905f5260205f20905b815481529060010190602001808311610d5857829003601f168201915b5050505050905090565b5f610d898261215e565b505f828152600460205260409020546001600160a01b0316610cea565b610db1828233612196565b5050565b610dbd6121a3565b610dde602060029054906101000a900460ff16601c54600184600e546121fc565b610de661241f565b610df06001600b55565b50565b610dfb6124d7565b601d55565b610e086124d7565b6020805461ff0019166101008315159081029190911782556040519081527f302715938fdba1da12ef0d47c363c0f835ff5e42369327fc40d670d504e1731191015b60405180910390a150565b610e5d6124d7565b806016604051602001610e7192919061380a565b60408051601f198184030181529181525f84815260106020522090610e969082613874565b5060405182907f901e1c01b493ffa41590ea147378e25dde9601a9390b52eb75d4e0e2118a44a5905f90a25050565b610ecd6121a3565b610dde602060019054906101000a900460ff16601b54600184600d546121fc565b6001600160a01b038216610f1c57604051633250574960e11b81525f60048201526024015b60405180910390fd5b5f610f28838333612504565b9050836001600160a01b0316816001600160a01b031614610f76576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610f13565b50505050565b610f846121a3565b60208054601d54604080515f808252948101909152610fb1926301000000900460ff1691908490856121fc565b610fb961241f565b50610fc46001600b55565b565b5f805f606460195485610fd99190613943565b610fe3919061395a565b601a546001600160a01b0316969095509350505050565b6110026124d7565b601f55565b5f828152600c6020526040902060010154611021816125d7565b610f7683836125e1565b5f61103583611703565b82106110665760405163295f44f760e21b81526001600160a01b038416600482015260248101839052604401610f13565b506001600160a01b03919091165f908152600660209081526040808320938352929052205490565b6001600160a01b03811633146110b75760405163334bd91960e11b815260040160405180910390fd5b6110c18282612672565b505050565b6110ce6121a3565b60205460ff1661112c5760405162461bcd60e51b8152602060048201526024808201527f436c61696d696e67206973206e6f742061637469766520617420746865206d6f6044820152631b595b9d60e21b6064820152608401610f13565b335f9081526015602052604090205460ff161561118b5760405162461bcd60e51b815260206004820152601860248201527f596f75206861766520616c726561647920636c61696d656400000000000000006044820152606401610f13565b601f548111156111dd5760405162461bcd60e51b815260206004820152601a60248201527f4e6f7420656e6f75676820726573657276656420746f6b656e730000000000006044820152606401610f13565b6040516001600160601b03193360601b166020820152603481018290525f9060540160405160208183030381529060405280519060200120905061122483600f54836126dd565b6112805760405162461bcd60e51b815260206004820152602760248201527f496e76616c69642070726f6f66206f7220796f75277265206e6f742077686974604482015266195b1a5cdd195960ca1b6064820152608401610f13565b6112886126f2565b601e545f5b83811080156112bc57507f00000000000000000000000000000000000000000000000000000000000001bc8211155b15611319575f8281526011602052604090205460ff16611314575f828152601160205260409020805460ff191660011790556112f83383612752565b8061130281613979565b915050818061131090613979565b9250505b61128d565b80601f5f82825461132a9190613991565b9091555050335f908152601560205260409020805460ff1916600117905550601e5550610db16001600b55565b61135f6124d7565b6113676121a3565b478015610fb957600a546040516001600160a01b039091169082156108fc029083905f818181858888f193505050501580156113a5573d5f803e3d5ffd5b5050610fc46001600b55565b6113b96124d7565b601955565b6113c66124d7565b601a80546001600160a01b0319166001600160a01b0392909216919091179055565b6110c183838360405180602001604052805f81525061190e565b61140a6121a3565b336114148261157e565b6001600160a01b0316146114745760405162461bcd60e51b815260206004820152602160248201527f596f7520617265206e6f7420746865206f776e6572206f662074686973204e466044820152601560fa1b6064820152608401610f13565b5f818152601160205260409020805460ff19169055610de68161276b565b5f61149c60085490565b82106114c45760405163295f44f760e21b81525f600482015260248101839052604401610f13565b600882815481106114d7576114d76139a4565b905f5260205f2001549050919050565b6114ef6124d7565b60176114fb8282613874565b506040517f9bf13f1005bf8940f6b531a89ba63b7fbd1b63269d49cc5612e9268b07d2527d905f90a150565b6040516001600160601b0319606083901b1660208201525f9081906034016040516020818303038152906040528051906020012090506115688585836126dd565b95945050505050565b6115796124d7565b601b55565b5f610cea8261215e565b6017805461159590613769565b80601f01602080910402602001604051908101604052809291908181526020018280546115c190613769565b801561160c5780601f106115e35761010080835404028352916020019161160c565b820191905f5260205f20905b8154815290600101906020018083116115ef57829003601f168201915b505050505081565b61161c6124d7565b6116246121a3565b5f5b81518110156116f8575f828281518110611642576116426139a4565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000001bc8111156116ae5760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081d1bdad95b9259608a1b6044820152606401610f13565b5f8181526011602052604090205460ff166116e5575f818152601160205260409020805460ff191660011790556116e53382612752565b50806116f081613979565b915050611626565b50610df06001600b55565b5f6001600160a01b03821661172d576040516322718ad960e21b81525f6004820152602401610f13565b506001600160a01b03165f9081526003602052604090205490565b6117506124d7565b610fc45f6127a3565b6117616124d7565b601c55565b61176e6124d7565b600d92909255600e55600f55565b60605f61178883611703565b9050805f036117aa57604080515f80825260208201909252905b509392505050565b5f816001600160401b038111156117c3576117c36131d3565b6040519080825280602002602001820160405280156117ec578160200160208202803683370190505b5090505f5b828110156117a257611803858261102b565b828281518110611815576118156139a4565b60209081029190910101528061182a81613979565b9150506117f1565b50919050565b6118406124d7565b6020805463ff000000191663010000008315159081029190911782556040519081527f4fea9b813a6127bfa89d28fb37b367110239e50769e6a9fc6b6400e2e60c857e9101610e4a565b5f918252600c602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6118bc6124d7565b60186118c88282613874565b506040517fff4ccd353885f015d383bdfcccc32f90e1573a6ec9da3c355dc74a39e1021059905f90a150565b606060018054610cfe90613769565b610db13383836127f4565b611919848484610eee565b610f7684848484612892565b61192d6124d7565b6020805460ff191682151590811782556040519081527fc6b9935e9bc27c1896eacf1f4f4957640b4375c9946a2fa5cf78fa30fc3943099101610e4a565b6018805461159590613769565b60605f6119848361157e565b6001600160a01b0316036119f25760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610f13565b5f8281526010602052604081208054611a0a90613769565b90501115611aad575f8281526010602052604090208054611a2a90613769565b80601f0160208091040260200160405190810160405280929190818152602001828054611a5690613769565b8015611aa15780601f10611a7857610100808354040283529160200191611aa1565b820191905f5260205f20905b815481529060010190602001808311611a8457829003601f168201915b50505050509050919050565b5f60178054611abb90613769565b80601f0160208091040260200160405190810160405280929190818152602001828054611ae790613769565b8015611b325780601f10611b0957610100808354040283529160200191611b32565b820191905f5260205f20905b815481529060010190602001808311611b1557829003601f168201915b5050505050905080515f03611b5657505060408051602081019091525f8152919050565b80611b60846129b1565b6016604051602001611b74939291906139b8565b604051602081830303815290604052915050919050565b611b936124d7565b611b9b6121a3565b60405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284919082169063a9059cbb906044016020604051808303815f875af1158015611bea573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c0e91906139f4565b611c4c5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610f13565b506110c16001600b55565b5f828152600c6020526040902060010154611c71816125d7565b610f768383612672565b606060188054610cfe90613769565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b611cbf6124d7565b6020805462ff00001916620100008315159081029190911782556040519081527feebbf6a3bc3ff1c01754ed345f0a2b74aa522579f98cd6685b11767934a8d4b09101610e4a565b611d0f6124d7565b6001600160a01b038116611d3857604051631e4fbdf760e01b81525f6004820152602401610f13565b610df0816127a3565b6040516001600160601b0319606084901b166020820152603481018290525f908190605401604051602081830303815290604052805190602001209050611d898686836126dd565b9695505050505050565b611d9b6124d7565b611da36121a3565b5f8351118015611db4575081518351145b611df05760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a59081a5b9c1d5d609a1b6044820152606401610f13565b5f805b8351811015611ebd5760155f868381518110611e1157611e116139a4565b6020908102919091018101516001600160a01b031682528101919091526040015f205460ff1615611e845760405162461bcd60e51b815260206004820152601d60248201527f526563697069656e742068617320616c726561647920636c61696d65640000006044820152606401610f13565b838181518110611e9657611e966139a4565b602002602001015182611ea99190613a0f565b915080611eb581613979565b915050611df3565b505f611ec860085490565b611ef2907f00000000000000000000000000000000000000000000000000000000000001bc613991565b905080821115611f3d5760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da081d1bdad95b9cc81b19599d60521b6044820152606401610f13565b82601f54611f4b9190613a0f565b821115611f9a5760405162461bcd60e51b815260206004820152601a60248201527f4e6f7420656e6f75676820726573657276656420746f6b656e730000000000006044820152606401610f13565b611fa26126f2565b601e545f805b875181108015611fd857507f00000000000000000000000000000000000000000000000000000000000001bc8311155b1561210b575f878281518110611ff057611ff06139a4565b602002602001015190505b5f8111801561202a57507f00000000000000000000000000000000000000000000000000000000000001bc8411155b156120b0575f8481526011602052604090205460ff16612090575f848152601160205260409020805460ff191660011790558851612082908a9084908110612074576120746139a4565b602002602001015185612752565b8261208c81613979565b9350505b8361209a81613979565b94505080806120a890613a22565b915050611ffb565b600160155f8b85815181106120c7576120c76139a4565b6020908102919091018101516001600160a01b031682528101919091526040015f20805460ff1916911515919091179055508061210381613979565b915050611fa8565b506121168582613991565b601f5f8282546121269190613991565b90915550506001600b55506110c192505050565b5f6001600160e01b03198216637965db0b60e01b1480610cea5750610cea82612a40565b5f818152600260205260408120546001600160a01b031680610cea57604051637e27328960e01b815260048101849052602401610f13565b6110c18383836001612a64565b6002600b54036121f55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610f13565b6002600b55565b8461223e5760405162461bcd60e51b815260206004820152601260248201527153616c65206973206e6f742061637469766560701b6044820152606401610f13565b335f9081526014602052604090205460ff161561229d5760405162461bcd60e51b815260206004820152601760248201527f596f75206861766520616c7265616479206d696e7465640000000000000000006044820152606401610f13565b8334146122ec5760405162461bcd60e51b815260206004820152601960248201527f45746865722073656e74206973206e6f7420636f7272656374000000000000006044820152606401610f13565b7f00000000000000000000000000000000000000000000000000000000000001bc601f5461231960085490565b6123239190613a0f565b106123705760405162461bcd60e51b815260206004820152601b60248201527f416c6c20746f6b656e732068617665206265656e206d696e74656400000000006044820152606401610f13565b8215612418576040516001600160601b03193360601b1660208201525f906034016040516020818303038152906040528051906020012090505f6123b58484846126dd565b9050806124155760405162461bcd60e51b815260206004820152602860248201527f596f7520617265206e6f7420616c6c6f77656420746f206d696e7420696e20746044820152676869732073616c6560c01b6064820152608401610f13565b50505b5050505050565b6124276126f2565b5f601f54601e546124389190613a0f565b5f8181526011602052604090205490915060ff16156124995760405162461bcd60e51b815260206004820152601860248201527f546f6b656e20697320616c726561647920636c61696d656400000000000000006044820152606401610f13565b5f818152601160205260409020805460ff191660011790556124bb3382612752565b50335f908152601460205260409020805460ff19166001179055565b600a546001600160a01b03163314610fc45760405163118cdaa760e01b8152336004820152602401610f13565b5f80612511858585612b68565b90506001600160a01b03811661256d5761256884600880545f838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b612590565b846001600160a01b0316816001600160a01b031614612590576125908185612c5a565b6001600160a01b0385166125ac576125a784612ce7565b6125cf565b846001600160a01b0316816001600160a01b0316146125cf576125cf8585612d8e565b949350505050565b610df08133612ddc565b5f6125ec838361188a565b61266b575f838152600c602090815260408083206001600160a01b03861684529091529020805460ff191660011790556126233390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610cea565b505f610cea565b5f61267d838361188a565b1561266b575f838152600c602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610cea565b5f826126e98584612e15565b14949350505050565b601e545f9081526011602052604090205460ff16801561273457507f00000000000000000000000000000000000000000000000000000000000001bc601e5411155b15610fc457601e8054905f61274883613979565b91905055506126f2565b610db1828260405180602001604052805f815250612e59565b5f6127775f835f612504565b90506001600160a01b038116610db157604051637e27328960e01b815260048101839052602401610f13565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b03821661282657604051630b61174360e31b81526001600160a01b0383166004820152602401610f13565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b15610f7657604051630a85bd0160e11b81526001600160a01b0384169063150b7a02906128d4903390889087908790600401613a37565b6020604051808303815f875af192505050801561290e575060408051601f3d908101601f1916820190925261290b91810190613a69565b60015b612975573d80801561293b576040519150601f19603f3d011682016040523d82523d5f602084013e612940565b606091505b5080515f0361296d57604051633250574960e11b81526001600160a01b0385166004820152602401610f13565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b1461241857604051633250574960e11b81526001600160a01b0385166004820152602401610f13565b60605f6129bd83612e6f565b60010190505f816001600160401b038111156129db576129db6131d3565b6040519080825280601f01601f191660200182016040528015612a05576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612a0f57509392505050565b5f6001600160e01b0319821663780e9d6360e01b1480610cea5750610cea82612f46565b8080612a7857506001600160a01b03821615155b15612b39575f612a878461215e565b90506001600160a01b03831615801590612ab35750826001600160a01b0316816001600160a01b031614155b8015612ac65750612ac48184611c8a565b155b15612aef5760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610f13565b8115612b375783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b5f828152600260205260408120546001600160a01b0390811690831615612b9457612b94818486612f95565b6001600160a01b03811615612bce57612baf5f855f80612a64565b6001600160a01b0381165f90815260036020526040902080545f190190555b6001600160a01b03851615612bfc576001600160a01b0385165f908152600360205260409020805460010190555b5f8481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b5f612c6483611703565b5f83815260076020526040902054909150808214612cb5576001600160a01b0384165f9081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b505f9182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008545f90612cf890600190613991565b5f8381526009602052604081205460088054939450909284908110612d1f57612d1f6139a4565b905f5260205f20015490508060088381548110612d3e57612d3e6139a4565b5f918252602080832090910192909255828152600990915260408082208490558582528120556008805480612d7557612d75613a84565b600190038181905f5260205f20015f9055905550505050565b5f6001612d9a84611703565b612da49190613991565b6001600160a01b039093165f908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b612de6828261188a565b610db15760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610f13565b5f81815b84518110156117a257612e4582868381518110612e3857612e386139a4565b6020026020010151612ff9565b915080612e5181613979565b915050612e19565b612e638383613028565b6110c15f848484612892565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310612ead5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612ed9576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310612ef757662386f26fc10000830492506010015b6305f5e1008310612f0f576305f5e100830492506008015b6127108310612f2357612710830492506004015b60648310612f35576064830492506002015b600a8310610cea5760010192915050565b5f6001600160e01b031982166380ac58cd60e01b1480612f7657506001600160e01b03198216635b5e139f60e01b145b80610cea57506301ffc9a760e01b6001600160e01b0319831614610cea565b612fa0838383613089565b6110c1576001600160a01b038316612fce57604051637e27328960e01b815260048101829052602401610f13565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610f13565b5f818310613013575f828152602084905260409020613021565b5f8381526020839052604090205b9392505050565b6001600160a01b03821661305157604051633250574960e11b81525f6004820152602401610f13565b5f61305d83835f612504565b90506001600160a01b038116156110c1576040516339e3563760e11b81525f6004820152602401610f13565b5f6001600160a01b038316158015906125cf5750826001600160a01b0316846001600160a01b031614806130c257506130c28484611c8a565b806125cf5750505f908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b031981168114610df0575f80fd5b5f6020828403121561310f575f80fd5b8135613021816130ea565b5f5b8381101561313457818101518382015260200161311c565b50505f910152565b5f815180845261315381602086016020860161311a565b601f01601f19169290920160200192915050565b602081525f613021602083018461313c565b5f60208284031215613189575f80fd5b5035919050565b80356001600160a01b03811681146131a6575f80fd5b919050565b5f80604083850312156131bc575f80fd5b6131c583613190565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561320f5761320f6131d3565b604052919050565b5f6001600160401b0382111561322f5761322f6131d3565b5060051b60200190565b5f82601f830112613248575f80fd5b8135602061325d61325883613217565b6131e7565b82815260059290921b8401810191818101908684111561327b575f80fd5b8286015b84811015613296578035835291830191830161327f565b509695505050505050565b5f602082840312156132b1575f80fd5b81356001600160401b038111156132c6575f80fd5b6125cf84828501613239565b8015158114610df0575f80fd5b5f602082840312156132ef575f80fd5b8135613021816132d2565b5f6001600160401b03831115613312576133126131d3565b613325601f8401601f19166020016131e7565b9050828152838383011115613338575f80fd5b828260208301375f602084830101529392505050565b5f82601f83011261335d575f80fd5b613021838335602085016132fa565b5f806040838503121561337d575f80fd5b8235915060208301356001600160401b03811115613399575f80fd5b6133a58582860161334e565b9150509250929050565b5f805f606084860312156133c1575f80fd5b6133ca84613190565b92506133d860208501613190565b9150604084013590509250925092565b5f80604083850312156133f9575f80fd5b50508035926020909101359150565b5f8060408385031215613419575f80fd5b8235915061342960208401613190565b90509250929050565b5f60208284031215613442575f80fd5b61302182613190565b5f806040838503121561345c575f80fd5b82356001600160401b03811115613471575f80fd5b61347d85828601613239565b95602094909401359450505050565b5f6020828403121561349c575f80fd5b81356001600160401b038111156134b1575f80fd5b6125cf8482850161334e565b5f805f606084860312156134cf575f80fd5b83356001600160401b038111156134e4575f80fd5b6134f086828701613239565b9350506020840135915061350660408501613190565b90509250925092565b5f805f60608486031215613521575f80fd5b505081359360208301359350604090920135919050565b602080825282518282018190525f9190848201906040850190845b8181101561356f57835183529284019291840191600101613553565b50909695505050505050565b5f806040838503121561358c575f80fd5b61359583613190565b915060208301356135a5816132d2565b809150509250929050565b5f805f80608085870312156135c3575f80fd5b6135cc85613190565b93506135da60208601613190565b92506040850135915060608501356001600160401b038111156135fb575f80fd5b8501601f8101871361360b575f80fd5b61361a878235602084016132fa565b91505092959194509250565b5f8060408385031215613637575f80fd5b61364083613190565b915061342960208401613190565b5f805f8060808587031215613661575f80fd5b84356001600160401b03811115613676575f80fd5b61368287828801613239565b9450506020850135925061369860408601613190565b9396929550929360600135925050565b5f805f606084860312156136ba575f80fd5b83356001600160401b03808211156136d0575f80fd5b818601915086601f8301126136e3575f80fd5b813560206136f361325883613217565b82815260059290921b8401810191818101908a841115613711575f80fd5b948201945b838610156137365761372786613190565b82529482019490820190613716565b9750508701359250508082111561374b575f80fd5b5061375886828701613239565b925050604084013590509250925092565b600181811c9082168061377d57607f821691505b60208210810361183257634e487b7160e01b5f52602260045260245ffd5b5f81546137a781613769565b600182811680156137bf57600181146137d457613800565b60ff1984168752821515830287019450613800565b855f526020805f205f5b858110156137f75781548a8201529084019082016137de565b50505082870194505b5050505092915050565b5f835161381b81846020880161311a565b6115688184018561379b565b601f8211156110c1575f81815260208120601f850160051c8101602086101561384d5750805b601f850160051c820191505b8181101561386c57828155600101613859565b505050505050565b81516001600160401b0381111561388d5761388d6131d3565b6138a18161389b8454613769565b84613827565b602080601f8311600181146138d4575f84156138bd5750858301515b5f19600386901b1c1916600185901b17855561386c565b5f85815260208120601f198616915b82811015613902578886015182559484019460019091019084016138e3565b508582101561391f57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610cea57610cea61392f565b5f8261397457634e487b7160e01b5f52601260045260245ffd5b500490565b5f6001820161398a5761398a61392f565b5060010190565b81810381811115610cea57610cea61392f565b634e487b7160e01b5f52603260045260245ffd5b5f84516139c981846020890161311a565b8451908301906139dd81836020890161311a565b6139e98183018661379b565b979650505050505050565b5f60208284031215613a04575f80fd5b8151613021816132d2565b80820180821115610cea57610cea61392f565b5f81613a3057613a3061392f565b505f190190565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90611d899083018461313c565b5f60208284031215613a79575f80fd5b8151613021816130ea565b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220111ceac837821224994a51141b93f86e3ecac54b9cfe5c12b77a9f1c778848ba64736f6c63430008140033

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

00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000c4461726b536f6c6469657273000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024453000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): DarkSoldiers
Arg [1] : _symbol (string): DS

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [2] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [3] : 4461726b536f6c64696572730000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [5] : 4453000000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

93573:11540:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95284:195;;;;;;;;;;-1:-1:-1;95284:195:0;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;95284:195:0;;;;;;;;70350:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;71522:158::-;;;;;;;;;;-1:-1:-1;71522:158:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1697:32:1;;;1679:51;;1667:2;1652:18;71522:158:0;1533:203:1;71341:115:0;;;;;;;;;;-1:-1:-1;71341:115:0;;;;;:::i;:::-;;:::i;:::-;;98949:205;;;;;;:::i;:::-;;:::i;94731:33::-;;;;;;;;;;-1:-1:-1;94731:33:0;;;;;;;;;;;101725:113;;;;;;;;;;-1:-1:-1;101725:113:0;;;;;:::i;:::-;;:::i;104095:134::-;;;;;;;;;;-1:-1:-1;104095:134:0;;;;;:::i;:::-;;:::i;93745:24::-;;;;;;;;;;;;;;;;;;;4313:25:1;;;4301:2;4286:18;93745:24:0;4167:177:1;100930:189:0;;;;;;;;;;-1:-1:-1;100930:189:0;;;;;:::i;:::-;;:::i;98736:205::-;;;;;;:::i;:::-;;:::i;88106:104::-;;;;;;;;;;-1:-1:-1;88185:10:0;:17;88106:104;;94373:41;;;;;;;;;;;;;;;;93846;;;;;;;;;;;;;;;72191:588;;;;;;;;;;-1:-1:-1;72191:588:0;;;;;:::i;:::-;;:::i;57988:122::-;;;;;;;;;;-1:-1:-1;57988:122:0;;;;;:::i;:::-;58053:7;58080:12;;;:6;:12;;;;;:22;;;;57988:122;99162:292;;;:::i;96155:251::-;;;;;;;;;;-1:-1:-1;96155:251:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;6528:32:1;;;6510:51;;6592:2;6577:18;;6570:34;;;;6483:18;96155:251:0;6336:274:1;101846:94:0;;;;;;;;;;-1:-1:-1;101846:94:0;;;;;:::i;:::-;;:::i;58420:138::-;;;;;;;;;;-1:-1:-1;58420:138:0;;;;;:::i;:::-;;:::i;87770:260::-;;;;;;;;;;-1:-1:-1;87770:260:0;;;;;:::i;:::-;;:::i;94655:29::-;;;;;;;;;;-1:-1:-1;94655:29:0;;;;;;;;59557:251;;;;;;;;;;-1:-1:-1;59557:251:0;;;;;:::i;:::-;;:::i;94442:41::-;;;;;;;;;;;;;;;;94094;;;;;;;;;;-1:-1:-1;94094:41:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;99462:1003;;;;;;;;;;-1:-1:-1;99462:1003:0;;;;;:::i;:::-;;:::i;104657:205::-;;;;;;;;;;;;;:::i;101265:92::-;;;;;;;;;;-1:-1:-1;101265:92:0;;;;;:::i;:::-;;:::i;101365:116::-;;;;;;;;;;-1:-1:-1;101365:116:0;;;;;:::i;:::-;;:::i;72850:134::-;;;;;;;;;;-1:-1:-1;72850:134:0;;;;;:::i;:::-;;:::i;100473:246::-;;;;;;;;;;-1:-1:-1;100473:246:0;;;;;:::i;:::-;;:::i;94335:31::-;;;;;;;;;;-1:-1:-1;94335:31:0;;;;-1:-1:-1;;;;;94335:31:0;;;88287:231;;;;;;;;;;-1:-1:-1;88287:231:0;;;;;:::i;:::-;;:::i;101129:128::-;;;;;;;;;;-1:-1:-1;101129:128:0;;;;;:::i;:::-;;:::i;97021:230::-;;;;;;;;;;-1:-1:-1;97021:230:0;;;;;:::i;:::-;;:::i;101489:110::-;;;;;;;;;;-1:-1:-1;101489:110:0;;;;;:::i;:::-;;:::i;70163:120::-;;;;;;;;;;-1:-1:-1;70163:120:0;;;;;:::i;:::-;;:::i;94240:21::-;;;;;;;;;;;;;:::i;101948:410::-;;;;;;;;;;-1:-1:-1;101948:410:0;;;;;:::i;:::-;;:::i;69888:213::-;;;;;;;;;;-1:-1:-1;69888:213:0;;;;;:::i;:::-;;:::i;49566:103::-;;;;;;;;;;;;;:::i;94142:42::-;;;;;;;;;;-1:-1:-1;94142:42:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;101607:110;;;;;;;;;;-1:-1:-1;101607:110:0;;;;;:::i;:::-;;:::i;93778:61::-;;;;;;;;;;;;;;;103822:265;;;;;;;;;;-1:-1:-1;103822:265:0;;;;;:::i;:::-;;:::i;96534:479::-;;;;;;;;;;-1:-1:-1;96534:479:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;104371:142::-;;;;;;;;;;-1:-1:-1;104371:142:0;;;;;:::i;:::-;;:::i;48891:87::-;;;;;;;;;;-1:-1:-1;48964:6:0;;-1:-1:-1;;;;;48964:6:0;48891:87;;57004:138;;;;;;;;;;-1:-1:-1;57004:138:0;;;;;:::i;:::-;;:::i;100772:150::-;;;;;;;;;;-1:-1:-1;100772:150:0;;;;;:::i;:::-;;:::i;70510:95::-;;;;;;;;;;;;;:::i;96414:108::-;;;;;;;;;;-1:-1:-1;96414:108:0;;;;;:::i;:::-;96473:4;96497:17;;;:8;:17;;;;;;;;;96414:108;56316:49;;;;;;;;;;-1:-1:-1;56316:49:0;56361:4;56316:49;;71752:146;;;;;;;;;;-1:-1:-1;71752:146:0;;;;;:::i;:::-;;:::i;73055:211::-;;;;;;;;;;-1:-1:-1;73055:211:0;;;;;:::i;:::-;;:::i;94301:27::-;;;;;;;;;;;;;;;;94771:36;;;;;;;;;;-1:-1:-1;94771:36:0;;;;;;;;;;;94691:33;;;;;;;;;;-1:-1:-1;94691:33:0;;;;;;;;;;;104521:128;;;;;;;;;;-1:-1:-1;104521:128:0;;;;;:::i;:::-;;:::i;94268:26::-;;;;;;;;;;;;;:::i;94511:40::-;;;;;;;;;;;;;;;;95596:551;;;;;;;;;;-1:-1:-1;95596:551:0;;;;;:::i;:::-;;:::i;104870:238::-;;;;;;;;;;-1:-1:-1;104870:238:0;;;;;:::i;:::-;;:::i;93675:28::-;;;;;;;;;;;;;;;;58851:140;;;;;;;;;;-1:-1:-1;58851:140:0;;;;;:::i;:::-;;:::i;95491:97::-;;;;;;;;;;;;;:::i;93710:28::-;;;;;;;;;;;;;;;;71969:155;;;;;;;;;;-1:-1:-1;71969:155:0;;;;;:::i;:::-;;:::i;104235:130::-;;;;;;;;;;-1:-1:-1;104235:130:0;;;;;:::i;:::-;;:::i;49824:220::-;;;;;;;;;;-1:-1:-1;49824:220:0;;;;;:::i;:::-;;:::i;97259:267::-;;;;;;;;;;-1:-1:-1;97259:267:0;;;;;:::i;:::-;;:::i;102366:1448::-;;;;;;;;;;-1:-1:-1;102366:1448:0;;;;;:::i;:::-;;:::i;94621:25::-;;;;;;;;;;;;;;;;95284:195;95411:4;95435:36;95459:11;95435:23;:36::i;:::-;95428:43;95284:195;-1:-1:-1;;95284:195:0:o;70350:91::-;70395:13;70428:5;70421:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70350:91;:::o;71522:158::-;71589:7;71609:22;71623:7;71609:13;:22::i;:::-;-1:-1:-1;74098:7:0;74125:24;;;:15;:24;;;;;;-1:-1:-1;;;;;74125:24:0;71651:21;74028:129;71341:115;71413:35;71422:2;71426:7;47087:10;71413:8;:35::i;:::-;71341:115;;:::o;98949:205::-;15769:21;:19;:21::i;:::-;99038:81:::1;99063:13;;;;;;;;;;;99078:12;;99092:4;99098:5;99105:13;;99038:24;:81::i;:::-;99130:16;:14;:16::i;:::-;15813:20:::0;15207:1;16333:7;:22;16150:213;15813:20;98949:205;:::o;101725:113::-;48777:13;:11;:13::i;:::-;101803:12:::1;:27:::0;101725:113::o;104095:134::-;48777:13;:11;:13::i;:::-;104160::::1;:21:::0;;-1:-1:-1;;104160:21:0::1;;::::0;::::1;;::::0;;::::1;::::0;;;::::1;::::0;;104197:20:::1;::::0;540:41:1;;;104197:20:0::1;::::0;513:18:1;104197:20:0::1;;;;;;;;104095:134:::0;:::o;100930:189::-;48777:13;:11;:13::i;:::-;101060:6:::1;101068:13;101043:39;;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;101043:39:0;;::::1;::::0;;;;;;101020:13:::1;::::0;;;:4:::1;101043:39;101020:13:::0;;;:63:::1;::::0;:13;:63:::1;:::i;:::-;-1:-1:-1::0;101099:12:0::1;::::0;101103:7;;101099:12:::1;::::0;;;::::1;100930:189:::0;;:::o;98736:205::-;15769:21;:19;:21::i;:::-;98825:81:::1;98850:13;;;;;;;;;;;98865:12;;98879:4;98885:5;98892:13;;98825:24;:81::i;72191:588::-:0;-1:-1:-1;;;;;72286:16:0;;72282:89;;72326:33;;-1:-1:-1;;;72326:33:0;;72356:1;72326:33;;;1679:51:1;1652:18;;72326:33:0;;;;;;;;72282:89;72592:21;72616:34;72624:2;72628:7;47087:10;72616:7;:34::i;:::-;72592:58;;72682:4;-1:-1:-1;;;;;72665:21:0;:13;-1:-1:-1;;;;;72665:21:0;;72661:111;;72710:50;;-1:-1:-1;;;72710:50:0;;-1:-1:-1;;;;;16607:15:1;;;72710:50:0;;;16589:34:1;16639:18;;;16632:34;;;16702:15;;16682:18;;;16675:43;16524:18;;72710:50:0;16349:375:1;72661:111:0;72271:508;72191:588;;;:::o;99162:292::-;15769:21;:19;:21::i;:::-;99353:16:::1;::::0;;99371:12:::1;::::0;99392:16:::1;::::0;;99229:17:::1;99392:16:::0;;;;;::::1;::::0;;;99328:91:::1;::::0;99353:16;;::::1;;;::::0;99371:12;99229:17;;99409:9:::1;99328:24;:91::i;:::-;99430:16;:14;:16::i;:::-;99214:240;15813:20:::0;15207:1;16333:7;:22;16150:213;15813:20;99162:292::o;96155:251::-;96239:16;96257:21;96291:22;96343:3;96329:10;;96317:9;:22;;;;:::i;:::-;96316:30;;;;:::i;:::-;96365:16;;-1:-1:-1;;;;;96365:16:0;;96291:55;;-1:-1:-1;96155:251:0;-1:-1:-1;;;;96155:251:0:o;101846:94::-;48777:13;:11;:13::i;:::-;101912:8:::1;:20:::0;101846:94::o;58420:138::-;58053:7;58080:12;;;:6;:12;;;;;:22;;;56600:16;56611:4;56600:10;:16::i;:::-;58525:25:::1;58536:4;58542:7;58525:10;:25::i;87770:260::-:0;87858:7;87891:16;87901:5;87891:9;:16::i;:::-;87882:5;:25;87878:101;;87931:36;;-1:-1:-1;;;87931:36:0;;-1:-1:-1;;;;;6528:32:1;;87931:36:0;;;6510:51:1;6577:18;;;6570:34;;;6483:18;;87931:36:0;6336:274:1;87878:101:0;-1:-1:-1;;;;;;87996:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;87770:260::o;59557:251::-;-1:-1:-1;;;;;59651:34:0;;47087:10;59651:34;59647:104;;59709:30;;-1:-1:-1;;;59709:30:0;;;;;;;;;;;59647:104;59763:37;59775:4;59781:18;59763:11;:37::i;:::-;;59557:251;;:::o;99462:1003::-;15769:21;:19;:21::i;:::-;99562:9:::1;::::0;::::1;;99554:58;;;::::0;-1:-1:-1;;;99554:58:0;;17590:2:1;99554:58:0::1;::::0;::::1;17572:21:1::0;17629:2;17609:18;;;17602:30;17668:34;17648:18;;;17641:62;-1:-1:-1;;;17719:18:1;;;17712:34;17763:19;;99554:58:0::1;17388:400:1::0;99554:58:0::1;99643:10;99632:22;::::0;;;:10:::1;:22;::::0;;;;;::::1;;99631:23;99623:60;;;::::0;-1:-1:-1;;;99623:60:0;;17995:2:1;99623:60:0::1;::::0;::::1;17977:21:1::0;18034:2;18014:18;;;18007:30;18073:26;18053:18;;;18046:54;18117:18;;99623:60:0::1;17793:348:1::0;99623:60:0::1;99716:8;;99702:10;:22;;99694:61;;;::::0;-1:-1:-1;;;99694:61:0;;18348:2:1;99694:61:0::1;::::0;::::1;18330:21:1::0;18387:2;18367:18;;;18360:30;18426:28;18406:18;;;18399:56;18472:18;;99694:61:0::1;18146:350:1::0;99694:61:0::1;99793:40;::::0;-1:-1:-1;;;;;;99810:10:0::1;18678:2:1::0;18674:15;18670:53;99793:40:0::1;::::0;::::1;18658:66:1::0;18740:12;;;18733:28;;;99768:12:0::1;::::0;18777::1;;99793:40:0::1;;;;;;;;;;;;99783:51;;;;;;99768:66;;99853:42;99872:5;99879:9;;99890:4;99853:18;:42::i;:::-;99845:94;;;::::0;-1:-1:-1;;;99845:94:0;;19002:2:1;99845:94:0::1;::::0;::::1;18984:21:1::0;19041:2;19021:18;;;19014:30;19080:34;19060:18;;;19053:62;-1:-1:-1;;;19131:18:1;;;19124:37;19178:19;;99845:94:0::1;18800:403:1::0;99845:94:0::1;99952:25;:23;:25::i;:::-;100006:14;::::0;99988:15:::1;100068:278;100090:10;100075:12;:25;:50;;;;;100115:10;100104:7;:21;;100075:50;100068:278;;;100147:17;::::0;;;:8:::1;:17;::::0;;;;;::::1;;100142:193;;100185:17;::::0;;;:8:::1;:17;::::0;;;;:24;;-1:-1:-1;;100185:24:0::1;100205:4;100185:24;::::0;;100228:30:::1;100238:10;100194:7:::0;100228:9:::1;:30::i;:::-;100277:14:::0;::::1;::::0;::::1;:::i;:::-;;;;100310:9;;;;;:::i;:::-;;;;100142:193;100068:278;;;100370:12;100358:8;;:24;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;100404:10:0::1;100393:22;::::0;;;:10:::1;:22;::::0;;;;:29;;-1:-1:-1;;100393:29:0::1;100418:4;100393:29;::::0;;-1:-1:-1;100433:14:0::1;:24:::0;-1:-1:-1;15813:20:0;15207:1;16333:7;:22;16150:213;104657:205;48777:13;:11;:13::i;:::-;15769:21:::1;:19;:21::i;:::-;104739::::2;104775:14:::0;;104771:84:::2;;48964:6:::0;;104806:37:::2;::::0;-1:-1:-1;;;;;48964:6:0;;;;104806:37;::::2;;;::::0;104832:10;;104806:37:::2;::::0;;;104832:10;48964:6;104806:37;::::2;;;;;;;;;;;;;::::0;::::2;;;;;;104707:155;15813:20:::1;15207:1:::0;16333:7;:22;16150:213;101265:92;48777:13;:11;:13::i;:::-;101332:10:::1;:17:::0;101265:92::o;101365:116::-;48777:13;:11;:13::i;:::-;101444:16:::1;:29:::0;;-1:-1:-1;;;;;;101444:29:0::1;-1:-1:-1::0;;;;;101444:29:0;;;::::1;::::0;;;::::1;::::0;;101365:116::o;72850:134::-;72937:39;72954:4;72960:2;72964:7;72937:39;;;;;;;;;;;;:16;:39::i;100473:246::-;15769:21;:19;:21::i;:::-;100579:10:::1;100559:16;100567:7:::0;100559::::1;:16::i;:::-;-1:-1:-1::0;;;;;100559:30:0::1;;100537:113;;;::::0;-1:-1:-1;;;100537:113:0;;19683:2:1;100537:113:0::1;::::0;::::1;19665:21:1::0;19722:2;19702:18;;;19695:30;19761:34;19741:18;;;19734:62;-1:-1:-1;;;19812:18:1;;;19805:31;19853:19;;100537:113:0::1;19481:397:1::0;100537:113:0::1;100681:5;100661:17:::0;;;:8:::1;:17;::::0;;;;:25;;-1:-1:-1;;100661:25:0::1;::::0;;100697:14:::1;100670:7:::0;100697:5:::1;:14::i;88287:231::-:0;88353:7;88386:13;88185:10;:17;;88106:104;88386:13;88377:5;:22;88373:103;;88423:41;;-1:-1:-1;;;88423:41:0;;88454:1;88423:41;;;6510:51:1;6577:18;;;6570:34;;;6483:18;;88423:41:0;6336:274:1;88373:103:0;88493:10;88504:5;88493:17;;;;;;;;:::i;:::-;;;;;;;;;88486:24;;88287:231;;;:::o;101129:128::-;48777:13;:11;:13::i;:::-;101205:7:::1;:20;101215:10:::0;101205:7;:20:::1;:::i;:::-;-1:-1:-1::0;101241:8:0::1;::::0;::::1;::::0;;;::::1;101129:128:::0;:::o;97021:230::-;97162:25;;-1:-1:-1;;;;;;20164:2:1;20160:15;;;20156:53;97162:25:0;;;20144:66:1;97120:4:0;;;;20226:12:1;;97162:25:0;;;;;;;;;;;;97152:36;;;;;;97137:51;;97206:37;97225:5;97232:4;97238;97206:18;:37::i;:::-;97199:44;97021:230;-1:-1:-1;;;;;97021:230:0:o;101489:110::-;48777:13;:11;:13::i;:::-;101564:12:::1;:27:::0;101489:110::o;70163:120::-;70226:7;70253:22;70267:7;70253:13;:22::i;94240:21::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;101948:410::-;48777:13;:11;:13::i;:::-;15769:21:::1;:19;:21::i;:::-;102042:9:::2;102037:314;102061:8;:15;102057:1;:19;102037:314;;;102098:15;102116:8;102125:1;102116:11;;;;;;;;:::i;:::-;;;;;;;102098:29;;102161:10;102150:7;:21;;102142:49;;;::::0;-1:-1:-1;;;102142:49:0;;20451:2:1;102142:49:0::2;::::0;::::2;20433:21:1::0;20490:2;20470:18;;;20463:30;-1:-1:-1;;;20509:18:1;;;20502:45;20564:18;;102142:49:0::2;20249:339:1::0;102142:49:0::2;102213:17;::::0;;;:8:::2;:17;::::0;;;;;::::2;;102208:132;;102251:17;::::0;;;:8:::2;:17;::::0;;;;:24;;-1:-1:-1;;102251:24:0::2;102271:4;102251:24;::::0;;102294:30:::2;102304:10;102260:7:::0;102294:9:::2;:30::i;:::-;-1:-1:-1::0;102078:3:0;::::2;::::0;::::2;:::i;:::-;;;;102037:314;;;;15813:20:::1;15207:1:::0;16333:7;:22;16150:213;69888;69951:7;-1:-1:-1;;;;;69975:19:0;;69971:89;;70018:30;;-1:-1:-1;;;70018:30:0;;70045:1;70018:30;;;1679:51:1;1652:18;;70018:30:0;1533:203:1;69971:89:0;-1:-1:-1;;;;;;70077:16:0;;;;;:9;:16;;;;;;;69888:213::o;49566:103::-;48777:13;:11;:13::i;:::-;49631:30:::1;49658:1;49631:18;:30::i;101607:110::-:0;48777:13;:11;:13::i;:::-;101682:12:::1;:27:::0;101607:110::o;103822:265::-;48777:13;:11;:13::i;:::-;103964::::1;:31:::0;;;;104006:13:::1;:31:::0;104048:9:::1;:31:::0;103822:265::o;96534:479::-;96595:16;96624:18;96645:16;96655:5;96645:9;:16::i;:::-;96624:37;;96676:10;96690:1;96676:15;96672:334;;96715:16;;;96729:1;96715:16;;;;;;;;;;;-1:-1:-1;96708:23:0;96534:479;-1:-1:-1;;;96534:479:0:o;96672:334::-;96764:23;96804:10;-1:-1:-1;;;;;96790:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;96790:25:0;;96764:51;;96835:13;96830:137;96862:10;96854:5;:18;96830:137;;;96918:33;96938:5;96945;96918:19;:33::i;:::-;96902:6;96909:5;96902:13;;;;;;;;:::i;:::-;;;;;;;;;;:49;96874:7;;;;:::i;:::-;;;;96830:137;;96672:334;96613:400;96534:479;;;:::o;104371:142::-;48777:13;:11;:13::i;:::-;104440:16:::1;:25:::0;;-1:-1:-1;;104440:25:0::1;::::0;;::::1;;::::0;;::::1;::::0;;;::::1;::::0;;104481:24:::1;::::0;540:41:1;;;104481:24:0::1;::::0;513:18:1;104481:24:0::1;400:187:1::0;57004:138:0;57081:4;57105:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;57105:29:0;;;;;;;;;;;;;;;57004:138::o;100772:150::-;48777:13;:11;:13::i;:::-;100856:12:::1;:29;100871:14:::0;100856:12;:29:::1;:::i;:::-;-1:-1:-1::0;100901:13:0::1;::::0;::::1;::::0;;;::::1;100772:150:::0;:::o;70510:95::-;70557:13;70590:7;70583:14;;;;;:::i;71752:146::-;71838:52;47087:10;71871:8;71881;71838:18;:52::i;73055:211::-;73169:31;73182:4;73188:2;73192:7;73169:12;:31::i;:::-;73211:47;73234:4;73240:2;73244:7;73253:4;73211:22;:47::i;104521:128::-;48777:13;:11;:13::i;:::-;104590:9:::1;:18:::0;;-1:-1:-1;;104590:18:0::1;::::0;::::1;;::::0;;::::1;::::0;;104624:17:::1;::::0;540:41:1;;;104624:17:0::1;::::0;513:18:1;104624:17:0::1;400:187:1::0;94268:26:0;;;;;;;:::i;95596:551::-;95669:13;95731:1;95703:16;95711:7;95703;:16::i;:::-;-1:-1:-1;;;;;95703:30:0;;95695:90;;;;-1:-1:-1;;;95695:90:0;;20795:2:1;95695:90:0;;;20777:21:1;20834:2;20814:18;;;20807:30;20873:34;20853:18;;;20846:62;-1:-1:-1;;;20924:18:1;;;20917:45;20979:19;;95695:90:0;20593:411:1;95695:90:0;95832:1;95808:13;;;:4;:13;;;;;95802:27;;;;;:::i;:::-;;;:31;95798:84;;;95857:13;;;;:4;:13;;;;;95850:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95596:551;;;:::o;95798:84::-;95894:28;95925:7;95894:38;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95953:14;95947:28;95979:1;95947:33;95943:197;;-1:-1:-1;;95997:9:0;;;;;;;;;-1:-1:-1;95997:9:0;;;95596:551;-1:-1:-1;95596:551:0:o;95943:197::-;96070:14;96086:25;96103:7;96086:16;:25::i;:::-;96113:13;96053:74;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;96039:89;;;95596:551;;;:::o;104870:238::-;48777:13;:11;:13::i;:::-;15769:21:::1;:19;:21::i;:::-;105047:33:::2;::::0;-1:-1:-1;;;105047:33:0;;-1:-1:-1;;;;;6528:32:1;;;105047:33:0::2;::::0;::::2;6510:51:1::0;6577:18;;;6570:34;;;105019:12:0;;105047:14;;::::2;::::0;::::2;::::0;6483:18:1;;105047:33:0::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;105039:61;;;::::0;-1:-1:-1;;;105039:61:0;;22042:2:1;105039:61:0::2;::::0;::::2;22024:21:1::0;22081:2;22061:18;;;22054:30;-1:-1:-1;;;22100:18:1;;;22093:45;22155:18;;105039:61:0::2;21840:339:1::0;105039:61:0::2;104990:118;15813:20:::1;15207:1:::0;16333:7;:22;16150:213;58851:140;58053:7;58080:12;;;:6;:12;;;;;:22;;;56600:16;56611:4;56600:10;:16::i;:::-;58957:26:::1;58969:4;58975:7;58957:11;:26::i;95491:97::-:0;95535:13;95568:12;95561:19;;;;;:::i;71969:155::-;-1:-1:-1;;;;;72081:25:0;;;72057:4;72081:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;71969:155::o;104235:130::-;48777:13;:11;:13::i;:::-;104300::::1;:21:::0;;-1:-1:-1;;104300:21:0::1;::::0;;::::1;;::::0;;::::1;::::0;;;::::1;::::0;;104337:20:::1;::::0;540:41:1;;;104337:20:0::1;::::0;513:18:1;104337:20:0::1;400:187:1::0;49824:220:0;48777:13;:11;:13::i;:::-;-1:-1:-1;;;;;49909:22:0;::::1;49905:93;;49955:31;::::0;-1:-1:-1;;;49955:31:0;;49983:1:::1;49955:31;::::0;::::1;1679:51:1::0;1652:18;;49955:31:0::1;1533:203:1::0;49905:93:0::1;50008:28;50027:8;50008:18;:28::i;97259:267::-:0;97425:37;;-1:-1:-1;;;;;;18678:2:1;18674:15;;;18670:53;97425:37:0;;;18658:66:1;18740:12;;;18733:28;;;97383:4:0;;;;18777:12:1;;97425:37:0;;;;;;;;;;;;97415:48;;;;;;97400:63;;97481:37;97500:5;97507:4;97513;97481:18;:37::i;:::-;97474:44;97259:267;-1:-1:-1;;;;;;97259:267:0:o;102366:1448::-;48777:13;:11;:13::i;:::-;15769:21:::1;:19;:21::i;:::-;102525:1:::2;102505:10;:17;:21;:60;;;;;102551:7;:14;102530:10;:17;:35;102505:60;102497:86;;;::::0;-1:-1:-1;;;102497:86:0;;22386:2:1;102497:86:0::2;::::0;::::2;22368:21:1::0;22425:2;22405:18;;;22398:30;-1:-1:-1;;;22444:18:1;;;22437:43;22497:18;;102497:86:0::2;22184:337:1::0;102497:86:0::2;102594:27;102641:9:::0;102636:188:::2;102660:7;:14;102656:1;:18;102636:188;;;102705:10;:25;102716:10;102727:1;102716:13;;;;;;;;:::i;:::-;;::::0;;::::2;::::0;;;;;;;-1:-1:-1;;;;;102705:25:0::2;::::0;;;::::2;::::0;;;;;;-1:-1:-1;102705:25:0;;::::2;;102704:26;102696:68;;;::::0;-1:-1:-1;;;102696:68:0;;22728:2:1;102696:68:0::2;::::0;::::2;22710:21:1::0;22767:2;22747:18;;;22740:30;22806:31;22786:18;;;22779:59;22855:18;;102696:68:0::2;22526:353:1::0;102696:68:0::2;102802:7;102810:1;102802:10;;;;;;;;:::i;:::-;;;;;;;102779:33;;;;;:::i;:::-;::::0;-1:-1:-1;102676:3:0;::::2;::::0;::::2;:::i;:::-;;;;102636:188;;;;102836:18;102870:13;88185:10:::0;:17;;88106:104;102870:13:::2;102857:26;::::0;:10:::2;:26;:::i;:::-;102836:47;;102925:10;102902:19;:33;;102894:68;;;::::0;-1:-1:-1;;;102894:68:0;;23216:2:1;102894:68:0::2;::::0;::::2;23198:21:1::0;23255:2;23235:18;;;23228:30;-1:-1:-1;;;23274:18:1;;;23267:52;23336:18;;102894:68:0::2;23014:346:1::0;102894:68:0::2;103014:3;103005:8;;:12;;;;:::i;:::-;102981:19;:37;;102973:76;;;::::0;-1:-1:-1;;;102973:76:0;;18348:2:1;102973:76:0::2;::::0;::::2;18330:21:1::0;18387:2;18367:18;;;18360:30;18426:28;18406:18;;;18399:56;18472:18;;102973:76:0::2;18146:350:1::0;102973:76:0::2;103062:25;:23;:25::i;:::-;103116:14;::::0;103098:15:::2;::::0;103183:578:::2;103207:10;:17;103203:1;:21;:46;;;;;103239:10;103228:7;:21;;103203:46;103183:578;;;103271:32;103306:7;103314:1;103306:10;;;;;;;;:::i;:::-;;;;;;;103271:45;;103345:358;103379:1;103352:24;:28;:53;;;;;103395:10;103384:7;:21;;103352:53;103345:358;;;103431:17;::::0;;;:8:::2;:17;::::0;;;;;::::2;;103426:189;;103473:17;::::0;;;:8:::2;:17;::::0;;;;:24;;-1:-1:-1;;103473:24:0::2;103493:4;103473:24;::::0;;103530:13;;103520:33:::2;::::0;103530:10;;103541:1;;103530:13;::::2;;;;;:::i;:::-;;;;;;;103545:7;103520:9;:33::i;:::-;103576:19:::0;::::2;::::0;::::2;:::i;:::-;;;;103426:189;103633:9:::0;::::2;::::0;::::2;:::i;:::-;;;;103661:26;;;;;:::i;:::-;;;;103345:358;;;103745:4;103717:10;:25;103728:10;103739:1;103728:13;;;;;;;;:::i;:::-;;::::0;;::::2;::::0;;;;;;;-1:-1:-1;;;;;103717:25:0::2;::::0;;;::::2;::::0;;;;;;-1:-1:-1;103717:25:0;:32;;-1:-1:-1;;103717:32:0::2;::::0;::::2;;::::0;;;::::2;::::0;;-1:-1:-1;103251:3:0;::::2;::::0;::::2;:::i;:::-;;;;103183:578;;;-1:-1:-1::0;103784:21:0::2;103802:3:::0;103784:17;:21:::2;:::i;:::-;103771:8;;:35;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;15207:1:0;16333:7;:22;-1:-1:-1;15813:20:0::1;::::0;-1:-1:-1;;;16150:213:0;56708:204;56793:4;-1:-1:-1;;;;;;56817:47:0;;-1:-1:-1;;;56817:47:0;;:87;;;56868:36;56892:11;56868:23;:36::i;84497:247::-;84560:7;73883:16;;;:7;:16;;;;;;-1:-1:-1;;;;;73883:16:0;;84624:90;;84671:31;;-1:-1:-1;;;84671:31:0;;;;;4313:25:1;;;4286:18;;84671:31:0;4167:177:1;82729:122:0;82810:33;82819:2;82823:7;82832:4;82838;82810:8;:33::i;15849:293::-;15251:1;15983:7;;:19;15975:63;;;;-1:-1:-1;;;15975:63:0;;23708:2:1;15975:63:0;;;23690:21:1;23747:2;23727:18;;;23720:30;23786:33;23766:18;;;23759:61;23837:18;;15975:63:0;23506:355:1;15975:63:0;15251:1;16116:7;:18;15849:293::o;97710:695::-;97876:10;97868:41;;;;-1:-1:-1;;;97868:41:0;;24068:2:1;97868:41:0;;;24050:21:1;24107:2;24087:18;;;24080:30;-1:-1:-1;;;24126:18:1;;;24119:48;24184:18;;97868:41:0;23866:342:1;97868:41:0;97939:10;97929:21;;;;:9;:21;;;;;;;;97928:22;97920:58;;;;-1:-1:-1;;;97920:58:0;;24415:2:1;97920:58:0;;;24397:21:1;24454:2;24434:18;;;24427:30;24493:25;24473:18;;;24466:53;24536:18;;97920:58:0;24213:347:1;97920:58:0;98010:11;97997:9;:24;97989:62;;;;-1:-1:-1;;;97989:62:0;;24767:2:1;97989:62:0;;;24749:21:1;24806:2;24786:18;;;24779:30;24845:27;24825:18;;;24818:55;24890:18;;97989:62:0;24565:349:1;97989:62:0;98097:10;98086:8;;98070:13;88185:10;:17;;88106:104;98070:13;:24;;;;:::i;:::-;:37;98062:77;;;;-1:-1:-1;;;98062:77:0;;25121:2:1;98062:77:0;;;25103:21:1;25160:2;25140:18;;;25133:30;25199:29;25179:18;;;25172:57;25246:18;;98062:77:0;24919:351:1;98062:77:0;98154:17;98150:248;;;98213:28;;-1:-1:-1;;;;;;98230:10:0;20164:2:1;20160:15;20156:53;98213:28:0;;;20144:66:1;98188:12:0;;20226::1;;98213:28:0;;;;;;;;;;;;98203:39;;;;;;98188:54;;98257:13;98273:37;98292:5;98299:4;98305;98273:18;:37::i;:::-;98257:53;;98333:8;98325:61;;;;-1:-1:-1;;;98325:61:0;;25477:2:1;98325:61:0;;;25459:21:1;25516:2;25496:18;;;25489:30;25555:34;25535:18;;;25528:62;-1:-1:-1;;;25606:18:1;;;25599:38;25654:19;;98325:61:0;25275:404:1;98325:61:0;98173:225;;98150:248;97710:695;;;;;:::o;98413:315::-;98458:25;:23;:25::i;:::-;98494:15;98529:8;;98512:14;;:25;;;;:::i;:::-;98559:17;;;;:8;:17;;;;;;98494:43;;-1:-1:-1;98559:17:0;;98558:18;98550:55;;;;-1:-1:-1;;;98550:55:0;;25886:2:1;98550:55:0;;;25868:21:1;25925:2;25905:18;;;25898:30;25964:26;25944:18;;;25937:54;26008:18;;98550:55:0;25684:348:1;98550:55:0;98616:17;;;;:8;:17;;;;;:24;;-1:-1:-1;;98616:24:0;98636:4;98616:24;;;98651:30;98661:10;98625:7;98651:9;:30::i;:::-;-1:-1:-1;98702:10:0;98692:21;;;;:9;:21;;;;;:28;;-1:-1:-1;;98692:28:0;98716:4;98692:28;;;98413:315::o;49056:166::-;48964:6;;-1:-1:-1;;;;;48964:6:0;47087:10;49116:23;49112:103;;49163:40;;-1:-1:-1;;;49163:40:0;;47087:10;49163:40;;;1679:51:1;1652:18;;49163:40:0;1533:203:1;88579:640:0;88674:7;88694:21;88718:32;88732:2;88736:7;88745:4;88718:13;:32::i;:::-;88694:56;-1:-1:-1;;;;;;88767:27:0;;88763:214;;88811:40;88843:7;90043:10;:17;;90016:24;;;;:15;:24;;;;;:44;;;90071:24;;;;;;;;;;;;89939:164;88811:40;88763:214;;;88890:2;-1:-1:-1;;;;;88873:19:0;:13;-1:-1:-1;;;;;88873:19:0;;88869:108;;88909:56;88942:13;88957:7;88909:32;:56::i;:::-;-1:-1:-1;;;;;88991:16:0;;88987:192;;89024:45;89061:7;89024:36;:45::i;:::-;88987:192;;;89108:2;-1:-1:-1;;;;;89091:19:0;:13;-1:-1:-1;;;;;89091:19:0;;89087:92;;89127:40;89155:2;89159:7;89127:27;:40::i;:::-;89198:13;88579:640;-1:-1:-1;;;;88579:640:0:o;57357:105::-;57424:30;57435:4;47087:10;57424;:30::i;60434:324::-;60511:4;60533:22;60541:4;60547:7;60533;:22::i;:::-;60528:223;;60572:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;60572:29:0;;;;;;;;;:36;;-1:-1:-1;;60572:36:0;60604:4;60572:36;;;60655:12;47087:10;;47007:98;60655:12;-1:-1:-1;;;;;60628:40:0;60646:7;-1:-1:-1;;;;;60628:40:0;60640:4;60628:40;;;;;;;;;;-1:-1:-1;60690:4:0;60683:11;;60528:223;-1:-1:-1;60734:5:0;60727:12;;61002:325;61080:4;61101:22;61109:4;61115:7;61101;:22::i;:::-;61097:223;;;61172:5;61140:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;61140:29:0;;;;;;;;;;:37;;-1:-1:-1;;61140:37:0;;;61197:40;47087:10;;61140:12;;61197:40;;61172:5;61197:40;-1:-1:-1;61259:4:0;61252:11;;1336:156;1427:4;1480;1451:25;1464:5;1471:4;1451:12;:25::i;:::-;:33;;1336:156;-1:-1:-1;;;;1336:156:0:o;97534:168::-;97603:14;;97594:24;;;;:8;:24;;;;;;;;:56;;;;;97640:10;97622:14;;:28;;97594:56;97587:108;;;97667:14;:16;;;:14;:16;;;:::i;:::-;;;;;;97587:108;;78848:102;78916:26;78926:2;78930:7;78916:26;;;;;;;;;;;;:9;:26::i;79701:232::-;79753:21;79777:40;79793:1;79797:7;79814:1;79777:7;:40::i;:::-;79753:64;-1:-1:-1;;;;;;79832:27:0;;79828:98;;79883:31;;-1:-1:-1;;;79883:31:0;;;;;4313:25:1;;;4286:18;;79883:31:0;4167:177:1;50204:191:0;50297:6;;;-1:-1:-1;;;;;50314:17:0;;;-1:-1:-1;;;;;;50314:17:0;;;;;;;50347:40;;50297:6;;;50314:17;50297:6;;50347:40;;50278:16;;50347:40;50267:128;50204:191;:::o;83936:318::-;-1:-1:-1;;;;;84044:22:0;;84040:93;;84090:31;;-1:-1:-1;;;84090:31:0;;-1:-1:-1;;;;;1697:32:1;;84090:31:0;;;1679:51:1;1652:18;;84090:31:0;1533:203:1;84040:93:0;-1:-1:-1;;;;;84143:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;84143:46:0;;;;;;;;;;84205:41;;540::1;;;84205::0;;513:18:1;84205:41:0;;;;;;;83936:318;;;:::o;85294:799::-;-1:-1:-1;;;;;85411:14:0;;;:18;85407:679;;85450:71;;-1:-1:-1;;;85450:71:0;;-1:-1:-1;;;;;85450:36:0;;;;;:71;;47087:10;;85501:4;;85507:7;;85516:4;;85450:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85450:71:0;;;;;;;;-1:-1:-1;;85450:71:0;;;;;;;;;;;;:::i;:::-;;;85446:629;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85764:6;:13;85781:1;85764:18;85760:300;;85814:25;;-1:-1:-1;;;85814:25:0;;-1:-1:-1;;;;;1697:32:1;;85814:25:0;;;1679:51:1;1652:18;;85814:25:0;1533:203:1;85760:300:0;86010:6;86004:13;85995:6;85991:2;85987:15;85980:38;85446:629;-1:-1:-1;;;;;;85569:51:0;;-1:-1:-1;;;85569:51:0;85565:132;;85652:25;;-1:-1:-1;;;85652:25:0;;-1:-1:-1;;;;;1697:32:1;;85652:25:0;;;1679:51:1;1652:18;;85652:25:0;1533:203:1;43777:718:0;43833:13;43884:14;43901:17;43912:5;43901:10;:17::i;:::-;43921:1;43901:21;43884:38;;43937:20;43971:6;-1:-1:-1;;;;;43960:18:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;43960:18:0;-1:-1:-1;43937:41:0;-1:-1:-1;44102:28:0;;;44118:2;44102:28;44159:290;-1:-1:-1;;44191:5:0;-1:-1:-1;;;44328:2:0;44317:14;;44312:32;44191:5;44299:46;44391:2;44382:11;;;-1:-1:-1;44412:21:0;44159:290;44412:21;-1:-1:-1;44470:6:0;43777:718;-1:-1:-1;;;43777:718:0:o;87462:224::-;87564:4;-1:-1:-1;;;;;;87588:50:0;;-1:-1:-1;;;87588:50:0;;:90;;;87642:36;87666:11;87642:23;:36::i;83039:678::-;83201:9;:31;;;-1:-1:-1;;;;;;83214:18:0;;;;83201:31;83197:471;;;83249:13;83265:22;83279:7;83265:13;:22::i;:::-;83249:38;-1:-1:-1;;;;;;83418:18:0;;;;;;:35;;;83449:4;-1:-1:-1;;;;;83440:13:0;:5;-1:-1:-1;;;;;83440:13:0;;;83418:35;:69;;;;;83458:29;83475:5;83482:4;83458:16;:29::i;:::-;83457:30;83418:69;83414:144;;;83515:27;;-1:-1:-1;;;83515:27:0;;-1:-1:-1;;;;;1697:32:1;;83515:27:0;;;1679:51:1;1652:18;;83515:27:0;1533:203:1;83414:144:0;83578:9;83574:83;;;83633:7;83629:2;-1:-1:-1;;;;;83613:28:0;83622:5;-1:-1:-1;;;;;83613:28:0;;;;;;;;;;;83574:83;83234:434;83197:471;-1:-1:-1;;83680:24:0;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;83680:29:0;-1:-1:-1;;;;;83680:29:0;;;;;;;;;;83039:678::o;76990:824::-;77076:7;73883:16;;;:7;:16;;;;;;-1:-1:-1;;;;;73883:16:0;;;;77191:18;;;77187:88;;77226:37;77243:4;77249;77255:7;77226:16;:37::i;:::-;-1:-1:-1;;;;;77322:18:0;;;77318:263;;77440:48;77457:1;77461:7;77478:1;77482:5;77440:8;:48::i;:::-;-1:-1:-1;;;;;77534:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;77534:20:0;;;77318:263;-1:-1:-1;;;;;77597:16:0;;;77593:111;;-1:-1:-1;;;;;77659:13:0;;;;;;:9;:13;;;;;:18;;77676:1;77659:18;;;77593:111;77716:16;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;77716:21:0;-1:-1:-1;;;;;77716:21:0;;;;;;;;;77755:27;;77716:16;;77755:27;;;;;;;77802:4;76990:824;-1:-1:-1;;;;76990:824:0:o;90730:977::-;90996:22;91021:15;91031:4;91021:9;:15::i;:::-;91047:18;91068:26;;;:17;:26;;;;;;90996:40;;-1:-1:-1;91201:28:0;;;91197:328;;-1:-1:-1;;;;;91268:18:0;;91246:19;91268:18;;;:12;:18;;;;;;;;:34;;;;;;;;;91319:30;;;;;;:44;;;91436:30;;:17;:30;;;;;:43;;;91197:328;-1:-1:-1;91621:26:0;;;;:17;:26;;;;;;;;91614:33;;;-1:-1:-1;;;;;91665:18:0;;;;;:12;:18;;;;;:34;;;;;;;91658:41;90730:977::o;92002:1079::-;92280:10;:17;92255:22;;92280:21;;92300:1;;92280:21;:::i;:::-;92312:18;92333:24;;;:15;:24;;;;;;92706:10;:26;;92255:46;;-1:-1:-1;92333:24:0;;92255:46;;92706:26;;;;;;:::i;:::-;;;;;;;;;92684:48;;92770:11;92745:10;92756;92745:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;92850:28;;;:15;:28;;;;;;;:41;;;93022:24;;;;;93015:31;93057:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;92073:1008;;;92002:1079;:::o;89520:218::-;89605:14;89638:1;89622:13;89632:2;89622:9;:13::i;:::-;:17;;;;:::i;:::-;-1:-1:-1;;;;;89650:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;89695:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;89520:218:0:o;57598:201::-;57687:22;57695:4;57701:7;57687;:22::i;:::-;57682:110;;57733:47;;-1:-1:-1;;;57733:47:0;;-1:-1:-1;;;;;6528:32:1;;57733:47:0;;;6510:51:1;6577:18;;;6570:34;;;6483:18;;57733:47:0;6336:274:1;2055:296:0;2138:7;2181:4;2138:7;2196:118;2220:5;:12;2216:1;:16;2196:118;;;2269:33;2279:12;2293:5;2299:1;2293:8;;;;;;;;:::i;:::-;;;;;;;2269:9;:33::i;:::-;2254:48;-1:-1:-1;2234:3:0;;;;:::i;:::-;;;;2196:118;;79177:185;79272:18;79278:2;79282:7;79272:5;:18::i;:::-;79301:53;79332:1;79336:2;79340:7;79349:4;79301:22;:53::i;40181:948::-;40234:7;;-1:-1:-1;;;40312:17:0;;40308:106;;-1:-1:-1;;;40350:17:0;;;-1:-1:-1;40396:2:0;40386:12;40308:106;40441:8;40432:5;:17;40428:106;;40479:8;40470:17;;;-1:-1:-1;40516:2:0;40506:12;40428:106;40561:8;40552:5;:17;40548:106;;40599:8;40590:17;;;-1:-1:-1;40636:2:0;40626:12;40548:106;40681:7;40672:5;:16;40668:103;;40718:7;40709:16;;;-1:-1:-1;40754:1:0;40744:11;40668:103;40798:7;40789:5;:16;40785:103;;40835:7;40826:16;;;-1:-1:-1;40871:1:0;40861:11;40785:103;40915:7;40906:5;:16;40902:103;;40952:7;40943:16;;;-1:-1:-1;40988:1:0;40978:11;40902:103;41032:7;41023:5;:16;41019:68;;41070:1;41060:11;41115:6;40181:948;-1:-1:-1;;40181:948:0:o;69519:305::-;69621:4;-1:-1:-1;;;;;;69658:40:0;;-1:-1:-1;;;69658:40:0;;:105;;-1:-1:-1;;;;;;;69715:48:0;;-1:-1:-1;;;69715:48:0;69658:105;:158;;;-1:-1:-1;;;;;;;;;;54144:40:0;;;69780:36;54044:148;75197:376;75310:38;75324:5;75331:7;75340;75310:13;:38::i;:::-;75305:261;;-1:-1:-1;;;;;75369:19:0;;75365:190;;75416:31;;-1:-1:-1;;;75416:31:0;;;;;4313:25:1;;;4286:18;;75416:31:0;4167:177:1;75365:190:0;75495:44;;-1:-1:-1;;;75495:44:0;;-1:-1:-1;;;;;6528:32:1;;75495:44:0;;;6510:51:1;6577:18;;;6570:34;;;6483:18;;75495:44:0;6336:274:1;9485:149:0;9548:7;9579:1;9575;:5;:51;;9827:13;9921:15;;;9957:4;9950:15;;;10004:4;9988:21;;9575:51;;;9827:13;9921:15;;;9957:4;9950:15;;;10004:4;9988:21;;9583:20;9568:58;9485:149;-1:-1:-1;;;9485:149:0:o;78150:335::-;-1:-1:-1;;;;;78218:16:0;;78214:89;;78258:33;;-1:-1:-1;;;78258:33:0;;78288:1;78258:33;;;1679:51:1;1652:18;;78258:33:0;1533:203:1;78214:89:0;78313:21;78337:32;78345:2;78349:7;78366:1;78337:7;:32::i;:::-;78313:56;-1:-1:-1;;;;;;78384:27:0;;;78380:98;;78435:31;;-1:-1:-1;;;78435:31:0;;78463:1;78435:31;;;1679:51:1;1652:18;;78435:31:0;1533:203:1;74477:276:0;74580:4;-1:-1:-1;;;;;74617:21:0;;;;;;:128;;;74665:7;-1:-1:-1;;;;;74656:16:0;:5;-1:-1:-1;;;;;74656:16:0;;:52;;;;74676:32;74693:5;74700:7;74676:16;:32::i;:::-;74656:88;;;-1:-1:-1;;74098:7:0;74125:24;;;:15;:24;;;;;;-1:-1:-1;;;;;74125:24:0;;;74712:32;;;;74597:148;-1:-1:-1;74477:276:0: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:250::-;677:1;687:113;701:6;698:1;695:13;687:113;;;777:11;;;771:18;758:11;;;751:39;723:2;716:10;687:113;;;-1:-1:-1;;834:1:1;816:16;;809:27;592:250::o;847:271::-;889:3;927:5;921:12;954:6;949:3;942:19;970:76;1039:6;1032:4;1027:3;1023:14;1016:4;1009:5;1005:16;970:76;:::i;:::-;1100:2;1079:15;-1:-1:-1;;1075:29:1;1066:39;;;;1107:4;1062:50;;847:271;-1:-1:-1;;847:271:1:o;1123:220::-;1272:2;1261:9;1254:21;1235:4;1292:45;1333:2;1322:9;1318:18;1310:6;1292:45;:::i;1348:180::-;1407:6;1460:2;1448:9;1439:7;1435:23;1431:32;1428:52;;;1476:1;1473;1466:12;1428:52;-1:-1:-1;1499:23:1;;1348:180;-1:-1:-1;1348:180:1:o;1741:173::-;1809:20;;-1:-1:-1;;;;;1858:31:1;;1848:42;;1838:70;;1904:1;1901;1894:12;1838:70;1741:173;;;:::o;1919:254::-;1987:6;1995;2048:2;2036:9;2027:7;2023:23;2019:32;2016:52;;;2064:1;2061;2054:12;2016:52;2087:29;2106:9;2087:29;:::i;:::-;2077:39;2163:2;2148:18;;;;2135:32;;-1:-1:-1;;;1919:254:1:o;2178:127::-;2239:10;2234:3;2230:20;2227:1;2220:31;2270:4;2267:1;2260:15;2294:4;2291:1;2284:15;2310:275;2381:2;2375:9;2446:2;2427:13;;-1:-1:-1;;2423:27:1;2411:40;;-1:-1:-1;;;;;2466:34:1;;2502:22;;;2463:62;2460:88;;;2528:18;;:::i;:::-;2564:2;2557:22;2310:275;;-1:-1:-1;2310:275:1:o;2590:183::-;2650:4;-1:-1:-1;;;;;2675:6:1;2672:30;2669:56;;;2705:18;;:::i;:::-;-1:-1:-1;2750:1:1;2746:14;2762:4;2742:25;;2590:183::o;2778:662::-;2832:5;2885:3;2878:4;2870:6;2866:17;2862:27;2852:55;;2903:1;2900;2893:12;2852:55;2939:6;2926:20;2965:4;2989:60;3005:43;3045:2;3005:43;:::i;:::-;2989:60;:::i;:::-;3083:15;;;3169:1;3165:10;;;;3153:23;;3149:32;;;3114:12;;;;3193:15;;;3190:35;;;3221:1;3218;3211:12;3190:35;3257:2;3249:6;3245:15;3269:142;3285:6;3280:3;3277:15;3269:142;;;3351:17;;3339:30;;3389:12;;;;3302;;3269:142;;;-1:-1:-1;3429:5:1;2778:662;-1:-1:-1;;;;;;2778:662:1:o;3445:348::-;3529:6;3582:2;3570:9;3561:7;3557:23;3553:32;3550:52;;;3598:1;3595;3588:12;3550:52;3638:9;3625:23;-1:-1:-1;;;;;3663:6:1;3660:30;3657:50;;;3703:1;3700;3693:12;3657:50;3726:61;3779:7;3770:6;3759:9;3755:22;3726:61;:::i;3798:118::-;3884:5;3877:13;3870:21;3863:5;3860:32;3850:60;;3906:1;3903;3896:12;3921:241;3977:6;4030:2;4018:9;4009:7;4005:23;4001:32;3998:52;;;4046:1;4043;4036:12;3998:52;4085:9;4072:23;4104:28;4126:5;4104:28;:::i;4349:407::-;4414:5;-1:-1:-1;;;;;4440:6:1;4437:30;4434:56;;;4470:18;;:::i;:::-;4508:57;4553:2;4532:15;;-1:-1:-1;;4528:29:1;4559:4;4524:40;4508:57;:::i;:::-;4499:66;;4588:6;4581:5;4574:21;4628:3;4619:6;4614:3;4610:16;4607:25;4604:45;;;4645:1;4642;4635:12;4604:45;4694:6;4689:3;4682:4;4675:5;4671:16;4658:43;4748:1;4741:4;4732:6;4725:5;4721:18;4717:29;4710:40;4349:407;;;;;:::o;4761:222::-;4804:5;4857:3;4850:4;4842:6;4838:17;4834:27;4824:55;;4875:1;4872;4865:12;4824:55;4897:80;4973:3;4964:6;4951:20;4944:4;4936:6;4932:17;4897:80;:::i;4988:390::-;5066:6;5074;5127:2;5115:9;5106:7;5102:23;5098:32;5095:52;;;5143:1;5140;5133:12;5095:52;5179:9;5166:23;5156:33;;5240:2;5229:9;5225:18;5212:32;-1:-1:-1;;;;;5259:6:1;5256:30;5253:50;;;5299:1;5296;5289:12;5253:50;5322;5364:7;5355:6;5344:9;5340:22;5322:50;:::i;:::-;5312:60;;;4988:390;;;;;:::o;5565:328::-;5642:6;5650;5658;5711:2;5699:9;5690:7;5686:23;5682:32;5679:52;;;5727:1;5724;5717:12;5679:52;5750:29;5769:9;5750:29;:::i;:::-;5740:39;;5798:38;5832:2;5821:9;5817:18;5798:38;:::i;:::-;5788:48;;5883:2;5872:9;5868:18;5855:32;5845:42;;5565:328;;;;;:::o;6083:248::-;6151:6;6159;6212:2;6200:9;6191:7;6187:23;6183:32;6180:52;;;6228:1;6225;6218:12;6180:52;-1:-1:-1;;6251:23:1;;;6321:2;6306:18;;;6293:32;;-1:-1:-1;6083:248:1:o;6615:254::-;6683:6;6691;6744:2;6732:9;6723:7;6719:23;6715:32;6712:52;;;6760:1;6757;6750:12;6712:52;6796:9;6783:23;6773:33;;6825:38;6859:2;6848:9;6844:18;6825:38;:::i;:::-;6815:48;;6615:254;;;;;:::o;6874:186::-;6933:6;6986:2;6974:9;6965:7;6961:23;6957:32;6954:52;;;7002:1;6999;6992:12;6954:52;7025:29;7044:9;7025:29;:::i;7065:416::-;7158:6;7166;7219:2;7207:9;7198:7;7194:23;7190:32;7187:52;;;7235:1;7232;7225:12;7187:52;7275:9;7262:23;-1:-1:-1;;;;;7300:6:1;7297:30;7294:50;;;7340:1;7337;7330:12;7294:50;7363:61;7416:7;7407:6;7396:9;7392:22;7363:61;:::i;:::-;7353:71;7471:2;7456:18;;;;7443:32;;-1:-1:-1;;;;7065:416:1:o;7486:322::-;7555:6;7608:2;7596:9;7587:7;7583:23;7579:32;7576:52;;;7624:1;7621;7614:12;7576:52;7664:9;7651:23;-1:-1:-1;;;;;7689:6:1;7686:30;7683:50;;;7729:1;7726;7719:12;7683:50;7752;7794:7;7785:6;7774:9;7770:22;7752:50;:::i;7813:490::-;7915:6;7923;7931;7984:2;7972:9;7963:7;7959:23;7955:32;7952:52;;;8000:1;7997;7990:12;7952:52;8040:9;8027:23;-1:-1:-1;;;;;8065:6:1;8062:30;8059:50;;;8105:1;8102;8095:12;8059:50;8128:61;8181:7;8172:6;8161:9;8157:22;8128:61;:::i;:::-;8118:71;;;8236:2;8225:9;8221:18;8208:32;8198:42;;8259:38;8293:2;8282:9;8278:18;8259:38;:::i;:::-;8249:48;;7813:490;;;;;:::o;8661:316::-;8738:6;8746;8754;8807:2;8795:9;8786:7;8782:23;8778:32;8775:52;;;8823:1;8820;8813:12;8775:52;-1:-1:-1;;8846:23:1;;;8916:2;8901:18;;8888:32;;-1:-1:-1;8967:2:1;8952:18;;;8939:32;;8661:316;-1:-1:-1;8661:316:1:o;8982:632::-;9153:2;9205:21;;;9275:13;;9178:18;;;9297:22;;;9124:4;;9153:2;9376:15;;;;9350:2;9335:18;;;9124:4;9419:169;9433:6;9430:1;9427:13;9419:169;;;9494:13;;9482:26;;9563:15;;;;9528:12;;;;9455:1;9448:9;9419:169;;;-1:-1:-1;9605:3:1;;8982:632;-1:-1:-1;;;;;;8982:632:1:o;9619:315::-;9684:6;9692;9745:2;9733:9;9724:7;9720:23;9716:32;9713:52;;;9761:1;9758;9751:12;9713:52;9784:29;9803:9;9784:29;:::i;:::-;9774:39;;9863:2;9852:9;9848:18;9835:32;9876:28;9898:5;9876:28;:::i;:::-;9923:5;9913:15;;;9619:315;;;;;:::o;9939:667::-;10034:6;10042;10050;10058;10111:3;10099:9;10090:7;10086:23;10082:33;10079:53;;;10128:1;10125;10118:12;10079:53;10151:29;10170:9;10151:29;:::i;:::-;10141:39;;10199:38;10233:2;10222:9;10218:18;10199:38;:::i;:::-;10189:48;;10284:2;10273:9;10269:18;10256:32;10246:42;;10339:2;10328:9;10324:18;10311:32;-1:-1:-1;;;;;10358:6:1;10355:30;10352:50;;;10398:1;10395;10388:12;10352:50;10421:22;;10474:4;10466:13;;10462:27;-1:-1:-1;10452:55:1;;10503:1;10500;10493:12;10452:55;10526:74;10592:7;10587:2;10574:16;10569:2;10565;10561:11;10526:74;:::i;:::-;10516:84;;;9939:667;;;;;;;:::o;10611:260::-;10679:6;10687;10740:2;10728:9;10719:7;10715:23;10711:32;10708:52;;;10756:1;10753;10746:12;10708:52;10779:29;10798:9;10779:29;:::i;:::-;10769:39;;10827:38;10861:2;10850:9;10846:18;10827:38;:::i;10876:559::-;10987:6;10995;11003;11011;11064:3;11052:9;11043:7;11039:23;11035:33;11032:53;;;11081:1;11078;11071:12;11032:53;11121:9;11108:23;-1:-1:-1;;;;;11146:6:1;11143:30;11140:50;;;11186:1;11183;11176:12;11140:50;11209:61;11262:7;11253:6;11242:9;11238:22;11209:61;:::i;:::-;11199:71;;;11317:2;11306:9;11302:18;11289:32;11279:42;;11340:38;11374:2;11363:9;11359:18;11340:38;:::i;:::-;10876:559;;;;-1:-1:-1;11330:48:1;;11425:2;11410:18;11397:32;;-1:-1:-1;;10876:559:1:o;11440:1214::-;11567:6;11575;11583;11636:2;11624:9;11615:7;11611:23;11607:32;11604:52;;;11652:1;11649;11642:12;11604:52;11692:9;11679:23;-1:-1:-1;;;;;11762:2:1;11754:6;11751:14;11748:34;;;11778:1;11775;11768:12;11748:34;11816:6;11805:9;11801:22;11791:32;;11861:7;11854:4;11850:2;11846:13;11842:27;11832:55;;11883:1;11880;11873:12;11832:55;11919:2;11906:16;11941:4;11965:60;11981:43;12021:2;11981:43;:::i;11965:60::-;12059:15;;;12141:1;12137:10;;;;12129:19;;12125:28;;;12090:12;;;;12165:19;;;12162:39;;;12197:1;12194;12187:12;12162:39;12221:11;;;;12241:148;12257:6;12252:3;12249:15;12241:148;;;12323:23;12342:3;12323:23;:::i;:::-;12311:36;;12274:12;;;;12367;;;;12241:148;;;12408:5;-1:-1:-1;;12451:18:1;;12438:32;;-1:-1:-1;;12482:16:1;;;12479:36;;;12511:1;12508;12501:12;12479:36;;12534:63;12589:7;12578:8;12567:9;12563:24;12534:63;:::i;:::-;12524:73;;;12644:2;12633:9;12629:18;12616:32;12606:42;;11440:1214;;;;;:::o;12659:380::-;12738:1;12734:12;;;;12781;;;12802:61;;12856:4;12848:6;12844:17;12834:27;;12802:61;12909:2;12901:6;12898:14;12878:18;12875:38;12872:161;;12955:10;12950:3;12946:20;12943:1;12936:31;12990:4;12987:1;12980:15;13018:4;13015:1;13008:15;13170:722;13220:3;13261:5;13255:12;13290:36;13316:9;13290:36;:::i;:::-;13345:1;13362:18;;;13389:133;;;;13536:1;13531:355;;;;13355:531;;13389:133;-1:-1:-1;;13422:24:1;;13410:37;;13495:14;;13488:22;13476:35;;13467:45;;;-1:-1:-1;13389:133:1;;13531:355;13562:5;13559:1;13552:16;13591:4;13636:2;13633:1;13623:16;13661:1;13675:165;13689:6;13686:1;13683:13;13675:165;;;13767:14;;13754:11;;;13747:35;13810:16;;;;13704:10;;13675:165;;;13679:3;;;13869:6;13864:3;13860:16;13853:23;;13355:531;;;;;13170:722;;;;:::o;13897:369::-;14073:3;14111:6;14105:13;14127:66;14186:6;14181:3;14174:4;14166:6;14162:17;14127:66;:::i;:::-;14209:51;14252:6;14247:3;14243:16;14235:6;14209:51;:::i;14271:545::-;14373:2;14368:3;14365:11;14362:448;;;14409:1;14434:5;14430:2;14423:17;14479:4;14475:2;14465:19;14549:2;14537:10;14533:19;14530:1;14526:27;14520:4;14516:38;14585:4;14573:10;14570:20;14567:47;;;-1:-1:-1;14608:4:1;14567:47;14663:2;14658:3;14654:12;14651:1;14647:20;14641:4;14637:31;14627:41;;14718:82;14736:2;14729:5;14726:13;14718:82;;;14781:17;;;14762:1;14751:13;14718:82;;;14722:3;;;14271:545;;;:::o;14992:1352::-;15118:3;15112:10;-1:-1:-1;;;;;15137:6:1;15134:30;15131:56;;;15167:18;;:::i;:::-;15196:97;15286:6;15246:38;15278:4;15272:11;15246:38;:::i;:::-;15240:4;15196:97;:::i;:::-;15348:4;;15412:2;15401:14;;15429:1;15424:663;;;;16131:1;16148:6;16145:89;;;-1:-1:-1;16200:19:1;;;16194:26;16145:89;-1:-1:-1;;14949:1:1;14945:11;;;14941:24;14937:29;14927:40;14973:1;14969:11;;;14924:57;16247:81;;15394:944;;15424:663;13117:1;13110:14;;;13154:4;13141:18;;-1:-1:-1;;15460:20:1;;;15578:236;15592:7;15589:1;15586:14;15578:236;;;15681:19;;;15675:26;15660:42;;15773:27;;;;15741:1;15729:14;;;;15608:19;;15578:236;;;15582:3;15842:6;15833:7;15830:19;15827:201;;;15903:19;;;15897:26;-1:-1:-1;;15986:1:1;15982:14;;;15998:3;15978:24;15974:37;15970:42;15955:58;15940:74;;15827:201;-1:-1:-1;;;;;16074:1:1;16058:14;;;16054:22;16041:36;;-1:-1:-1;14992:1352:1:o;16729:127::-;16790:10;16785:3;16781:20;16778:1;16771:31;16821:4;16818:1;16811:15;16845:4;16842:1;16835:15;16861:168;16934:9;;;16965;;16982:15;;;16976:22;;16962:37;16952:71;;17003:18;;:::i;17166:217::-;17206:1;17232;17222:132;;17276:10;17271:3;17267:20;17264:1;17257:31;17311:4;17308:1;17301:15;17339:4;17336:1;17329:15;17222:132;-1:-1:-1;17368:9:1;;17166:217::o;19208:135::-;19247:3;19268:17;;;19265:43;;19288:18;;:::i;:::-;-1:-1:-1;19335:1:1;19324:13;;19208:135::o;19348:128::-;19415:9;;;19436:11;;;19433:37;;;19450:18;;:::i;19883:127::-;19944:10;19939:3;19935:20;19932:1;19925:31;19975:4;19972:1;19965:15;19999:4;19996:1;19989:15;21009:576;21233:3;21271:6;21265:13;21287:66;21346:6;21341:3;21334:4;21326:6;21322:17;21287:66;:::i;:::-;21416:13;;21375:16;;;;21438:70;21416:13;21375:16;21485:4;21473:17;;21438:70;:::i;:::-;21524:55;21569:8;21562:5;21558:20;21550:6;21524:55;:::i;:::-;21517:62;21009:576;-1:-1:-1;;;;;;;21009:576:1:o;21590:245::-;21657:6;21710:2;21698:9;21689:7;21685:23;21681:32;21678:52;;;21726:1;21723;21716:12;21678:52;21758:9;21752:16;21777:28;21799:5;21777:28;:::i;22884:125::-;22949:9;;;22970:10;;;22967:36;;;22983:18;;:::i;23365:136::-;23404:3;23432:5;23422:39;;23441:18;;:::i;:::-;-1:-1:-1;;;23477:18:1;;23365:136::o;26037:489::-;-1:-1:-1;;;;;26306:15:1;;;26288:34;;26358:15;;26353:2;26338:18;;26331:43;26405:2;26390:18;;26383:34;;;26453:3;26448:2;26433:18;;26426:31;;;26231:4;;26474:46;;26500:19;;26492:6;26474:46;:::i;26531:249::-;26600:6;26653:2;26641:9;26632:7;26628:23;26624:32;26621:52;;;26669:1;26666;26659:12;26621:52;26701:9;26695:16;26720:30;26744:5;26720:30;:::i;26785:127::-;26846:10;26841:3;26837:20;26834:1;26827:31;26877:4;26874:1;26867:15;26901:4;26898:1;26891:15

Swarm Source

ipfs://111ceac837821224994a51141b93f86e3ecac54b9cfe5c12b77a9f1c778848ba
Loading...
Loading
Loading...
Loading
[ 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.