APE Price: $1.14 (-2.26%)

Token

RILLAZ DEPIX (DEPIX)

Overview

Max Total Supply

5,500 DEPIX

Holders

983

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
0 DEPIX
0xe9751d830ab931b104f868044462b71860ef4ff1
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
Depix

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 200 runs

Other Settings:
london EvmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at apescan.io on 2024-11-27
*/

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

// lib/creator-token-standards/src/interfaces/ICreatorToken.sol

interface ICreatorToken {
    event TransferValidatorUpdated(address oldValidator, address newValidator);
    function getTransferValidator() external view returns (address validator);
    function setTransferValidator(address validator) external;
    function getTransferValidationFunction() external view returns (bytes4 functionSignature, bool isViewFunction);
}

// lib/creator-token-standards/src/interfaces/ICreatorTokenLegacy.sol

interface ICreatorTokenLegacy {
    event TransferValidatorUpdated(address oldValidator, address newValidator);
    function getTransferValidator() external view returns (address validator);
    function setTransferValidator(address validator) external;
}

// lib/creator-token-standards/src/interfaces/ITransferValidator.sol

interface ITransferValidator {
    function applyCollectionTransferPolicy(address caller, address from, address to) external view;
    function validateTransfer(address caller, address from, address to) external view;
    function validateTransfer(address caller, address from, address to, uint256 tokenId) external view;
    function validateTransfer(address caller, address from, address to, uint256 tokenId, uint256 amount) external;

    function beforeAuthorizedTransfer(address operator, address token, uint256 tokenId) external;
    function afterAuthorizedTransfer(address token, uint256 tokenId) external;
    function beforeAuthorizedTransfer(address operator, address token) external;
    function afterAuthorizedTransfer(address token) external;
    function beforeAuthorizedTransfer(address token, uint256 tokenId) external;
    function beforeAuthorizedTransferWithAmount(address token, uint256 tokenId, uint256 amount) external;
    function afterAuthorizedTransferWithAmount(address token, uint256 tokenId) external;
}

// lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol

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

/**
 * @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);
}

// lib/openzeppelin-contracts/contracts/utils/Address.sol

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

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

// lib/openzeppelin-contracts/contracts/utils/Context.sol

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

/**
 * @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;
    }
}

// lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol

// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)

/**
 * @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 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}
     *
     * _Available since v4.7._
     */
    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.
     *
     * _Available since v4.4._
     */
    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}
     *
     * _Available since v4.7._
     */
    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.
     *
     * _Available since v4.7._
     */
    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.
     *
     * _Available since v4.7._
     */
    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).
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild 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 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // 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 for 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) {
            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.
     *
     * _Available since v4.7._
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild 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 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // 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 for 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) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    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)
        }
    }
}

// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol

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

/**
 * @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);
}

// lib/openzeppelin-contracts/contracts/utils/math/Math.sol

// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

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

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

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

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 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; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 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.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            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 (rounding == Rounding.Up && 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 down.
     *
     * 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 + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * 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 + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * 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 + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * 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 10, 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 + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

// lib/creator-token-standards/src/access/OwnablePermissions.sol

abstract contract OwnablePermissions is Context {
    function _requireCallerIsContractOwner() internal view virtual;
}

// lib/creator-token-standards/src/utils/TransferValidation.sol

/**
 * @title TransferValidation
 * @author Limit Break, Inc.
 * @notice A mix-in that can be combined with ERC-721 contracts to provide more granular hooks.
 * Openzeppelin's ERC721 contract only provides hooks for before and after transfer.  This allows
 * developers to validate or customize transfers within the context of a mint, a burn, or a transfer.
 */
abstract contract TransferValidation is Context {
    
    /// @dev Thrown when the from and to address are both the zero address.
    error ShouldNotMintToBurnAddress();

    /*************************************************************************/
    /*                      Transfers Without Amounts                        */
    /*************************************************************************/

    /// @dev Inheriting contracts should call this function in the _beforeTokenTransfer function to get more granular hooks.
    function _validateBeforeTransfer(address from, address to, uint256 tokenId) internal virtual {
        bool fromZeroAddress = from == address(0);
        bool toZeroAddress = to == address(0);

        if(fromZeroAddress && toZeroAddress) {
            revert ShouldNotMintToBurnAddress();
        } else if(fromZeroAddress) {
            _preValidateMint(_msgSender(), to, tokenId, msg.value);
        } else if(toZeroAddress) {
            _preValidateBurn(_msgSender(), from, tokenId, msg.value);
        } else {
            _preValidateTransfer(_msgSender(), from, to, tokenId, msg.value);
        }
    }

    /// @dev Inheriting contracts should call this function in the _afterTokenTransfer function to get more granular hooks.
    function _validateAfterTransfer(address from, address to, uint256 tokenId) internal virtual {
        bool fromZeroAddress = from == address(0);
        bool toZeroAddress = to == address(0);

        if(fromZeroAddress && toZeroAddress) {
            revert ShouldNotMintToBurnAddress();
        } else if(fromZeroAddress) {
            _postValidateMint(_msgSender(), to, tokenId, msg.value);
        } else if(toZeroAddress) {
            _postValidateBurn(_msgSender(), from, tokenId, msg.value);
        } else {
            _postValidateTransfer(_msgSender(), from, to, tokenId, msg.value);
        }
    }

    /// @dev Optional validation hook that fires before a mint
    function _preValidateMint(address caller, address to, uint256 tokenId, uint256 value) internal virtual {}

    /// @dev Optional validation hook that fires after a mint
    function _postValidateMint(address caller, address to, uint256 tokenId, uint256 value) internal virtual {}

    /// @dev Optional validation hook that fires before a burn
    function _preValidateBurn(address caller, address from, uint256 tokenId, uint256 value) internal virtual {}

    /// @dev Optional validation hook that fires after a burn
    function _postValidateBurn(address caller, address from, uint256 tokenId, uint256 value) internal virtual {}

    /// @dev Optional validation hook that fires before a transfer
    function _preValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 value) internal virtual {}

    /// @dev Optional validation hook that fires after a transfer
    function _postValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 value) internal virtual {}

    /*************************************************************************/
    /*                         Transfers With Amounts                        */
    /*************************************************************************/

    /// @dev Inheriting contracts should call this function in the _beforeTokenTransfer function to get more granular hooks.
    function _validateBeforeTransfer(address from, address to, uint256 tokenId, uint256 amount) internal virtual {
        bool fromZeroAddress = from == address(0);
        bool toZeroAddress = to == address(0);

        if(fromZeroAddress && toZeroAddress) {
            revert ShouldNotMintToBurnAddress();
        } else if(fromZeroAddress) {
            _preValidateMint(_msgSender(), to, tokenId, amount, msg.value);
        } else if(toZeroAddress) {
            _preValidateBurn(_msgSender(), from, tokenId, amount, msg.value);
        } else {
            _preValidateTransfer(_msgSender(), from, to, tokenId, amount, msg.value);
        }
    }

    /// @dev Inheriting contracts should call this function in the _afterTokenTransfer function to get more granular hooks.
    function _validateAfterTransfer(address from, address to, uint256 tokenId, uint256 amount) internal virtual {
        bool fromZeroAddress = from == address(0);
        bool toZeroAddress = to == address(0);

        if(fromZeroAddress && toZeroAddress) {
            revert ShouldNotMintToBurnAddress();
        } else if(fromZeroAddress) {
            _postValidateMint(_msgSender(), to, tokenId, amount, msg.value);
        } else if(toZeroAddress) {
            _postValidateBurn(_msgSender(), from, tokenId, amount, msg.value);
        } else {
            _postValidateTransfer(_msgSender(), from, to, tokenId, amount, msg.value);
        }
    }

    /// @dev Optional validation hook that fires before a mint
    function _preValidateMint(address caller, address to, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}

    /// @dev Optional validation hook that fires after a mint
    function _postValidateMint(address caller, address to, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}

    /// @dev Optional validation hook that fires before a burn
    function _preValidateBurn(address caller, address from, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}

    /// @dev Optional validation hook that fires after a burn
    function _postValidateBurn(address caller, address from, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}

    /// @dev Optional validation hook that fires before a transfer
    function _preValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}

    /// @dev Optional validation hook that fires after a transfer
    function _postValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}
}

// lib/openzeppelin-contracts/contracts/access/Ownable.sol

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

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

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

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

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

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

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

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

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

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

// lib/openzeppelin-contracts/contracts/interfaces/IERC2981.sol

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

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

// lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol

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

/**
 * @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 caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

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

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

// lib/openzeppelin-contracts/contracts/utils/Strings.sol

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

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

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        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), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @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) {
        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] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

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

// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol

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

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

// lib/creator-token-standards/src/utils/AutomaticValidatorTransferApproval.sol

/**
 * @title AutomaticValidatorTransferApproval
 * @author Limit Break, Inc.
 * @notice Base contract mix-in that provides boilerplate code giving the contract owner the
 *         option to automatically approve a 721-C transfer validator implementation for transfers.
 */
abstract contract AutomaticValidatorTransferApproval is OwnablePermissions {

    /// @dev Emitted when the automatic approval flag is modified by the creator.
    event AutomaticApprovalOfTransferValidatorSet(bool autoApproved);

    /// @dev If true, the collection's transfer validator is automatically approved to transfer holder's tokens.
    bool public autoApproveTransfersFromValidator;

    /**
     * @notice Sets if the transfer validator is automatically approved as an operator for all token owners.
     * 
     * @dev    Throws when the caller is not the contract owner.
     * 
     * @param autoApprove If true, the collection's transfer validator will be automatically approved to
     *                    transfer holder's tokens.
     */
    function setAutomaticApprovalOfTransfersFromValidator(bool autoApprove) external {
        _requireCallerIsContractOwner();
        autoApproveTransfersFromValidator = autoApprove;
        emit AutomaticApprovalOfTransferValidatorSet(autoApprove);
    }
}

// lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol

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

/**
 * @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);
}

// lib/creator-token-standards/src/access/OwnableBasic.sol

abstract contract OwnableBasic is OwnablePermissions, Ownable {
    function _requireCallerIsContractOwner() internal view virtual override {
        _checkOwner();
    }
}

// lib/openzeppelin-contracts/contracts/token/common/ERC2981.sol

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

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

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

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

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

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

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

        return (royalty.receiver, royaltyAmount);
    }

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

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

        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
    }

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

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

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

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

// lib/creator-token-standards/src/programmable-royalties/BasicRoyalties.sol

/**
 * @title BasicRoyaltiesBase
 * @author Limit Break, Inc.
 * @dev Base functionality of an NFT mix-in contract implementing the most basic form of programmable royalties.
 */
abstract contract BasicRoyaltiesBase is ERC2981 {

    event DefaultRoyaltySet(address indexed receiver, uint96 feeNumerator);
    event TokenRoyaltySet(uint256 indexed tokenId, address indexed receiver, uint96 feeNumerator);

    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual override {
        super._setDefaultRoyalty(receiver, feeNumerator);
        emit DefaultRoyaltySet(receiver, feeNumerator);
    }

    function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual override {
        super._setTokenRoyalty(tokenId, receiver, feeNumerator);
        emit TokenRoyaltySet(tokenId, receiver, feeNumerator);
    }
}

/**
 * @title BasicRoyalties
 * @author Limit Break, Inc.
 * @notice Constructable BasicRoyalties Contract implementation.
 */
abstract contract BasicRoyalties is BasicRoyaltiesBase {
    constructor(address receiver, uint96 feeNumerator) {
        _setDefaultRoyalty(receiver, feeNumerator);
    }
}

/**
 * @title BasicRoyaltiesInitializable
 * @author Limit Break, Inc.
 * @notice Initializable BasicRoyalties Contract implementation to allow for EIP-1167 clones. 
 */
abstract contract BasicRoyaltiesInitializable is BasicRoyaltiesBase {}

// src/PhaseManager.sol

error NoActivePhase();
error InvalidTimestamps();
error InvalidLimits();
error InvalidPhaseType();
error NoTwinPhase();
error NotWhitelisted();
error InvalidPhaseConfiguration();

enum PhaseType {
    NONE,
    TWIN_PHASE1,
    TWIN_PHASE2,
    ALBARRA_OG_WL,
    RILLAZ_HOLDER_WL,
    COMMUNITY_WL,
    PUBLIC_SALE
}

contract PhaseManager is OwnableBasic {
    struct Phase {
        bytes32 merkleRoot;
        uint96 price;
        uint64 start;
        uint64 end;
        uint8 maxPerWallet;
        uint16 maxSupplyPerPhase;
    }

    // State variables
    mapping(PhaseType => Phase) public phases;

    function configurePhase(
        PhaseType phaseType,
        bytes32 merkleRoot,
        uint96 price,
        uint64 start,
        uint64 end,
        uint8 maxPerWallet,
        uint16 maxSupplyPerPhase
    ) external {
        _requireCallerIsContractOwner();
        if (phaseType == PhaseType.NONE) revert InvalidPhaseType();
        if (end <= start) revert InvalidTimestamps();
        if (maxPerWallet == 0) revert InvalidLimits();
        if (maxSupplyPerPhase == 0) revert InvalidLimits();

        phases[phaseType] = Phase({
            merkleRoot: merkleRoot,
            price: price,
            start: start,
            end: end,
            maxPerWallet: maxPerWallet,
            maxSupplyPerPhase: maxSupplyPerPhase
        });
    }

    function currentPhase() public view returns (Phase memory, PhaseType) {
        uint256 currentTimestamp = block.timestamp;
        for (
            PhaseType i = PhaseType.TWIN_PHASE1;
            i <= type(PhaseType).max;
            i = PhaseType(uint8(i) + 1)
        ) {
            if (
                currentTimestamp >= phases[i].start &&
                currentTimestamp <= phases[i].end
            ) {
                return (phases[i], i);
            }
        }
        return (phases[PhaseType.NONE], PhaseType.NONE);
    }

    function isWhitelistedForPhase(
        PhaseType phaseType,
        address user,
        bytes32[] calldata merkleProof
    ) public view returns (bool) {
        return MerkleProof.verify(
            merkleProof,
            phases[phaseType].merkleRoot,
            keccak256(abi.encodePacked(user))
        );
    }
}

// lib/creator-token-standards/src/utils/CreatorTokenBase.sol

/**
 * @title CreatorTokenBase
 * @author Limit Break, Inc.
 * @notice CreatorTokenBaseV3 is an abstract contract that provides basic functionality for managing token 
 * transfer policies through an implementation of ICreatorTokenTransferValidator/ICreatorTokenTransferValidatorV2/ICreatorTokenTransferValidatorV3. 
 * This contract is intended to be used as a base for creator-specific token contracts, enabling customizable transfer 
 * restrictions and security policies.
 *
 * <h4>Features:</h4>
 * <ul>Ownable: This contract can have an owner who can set and update the transfer validator.</ul>
 * <ul>TransferValidation: Implements the basic token transfer validation interface.</ul>
 *
 * <h4>Benefits:</h4>
 * <ul>Provides a flexible and modular way to implement custom token transfer restrictions and security policies.</ul>
 * <ul>Allows creators to enforce policies such as account and codehash blacklists, whitelists, and graylists.</ul>
 * <ul>Can be easily integrated into other token contracts as a base contract.</ul>
 *
 * <h4>Intended Usage:</h4>
 * <ul>Use as a base contract for creator token implementations that require advanced transfer restrictions and 
 *   security policies.</ul>
 * <ul>Set and update the ICreatorTokenTransferValidator implementation contract to enforce desired policies for the 
 *   creator token.</ul>
 *
 * <h4>Compatibility:</h4>
 * <ul>Backward and Forward Compatible - V1/V2/V3 Creator Token Base will work with V1/V2/V3 Transfer Validators.</ul>
 */
abstract contract CreatorTokenBase is OwnablePermissions, TransferValidation, ICreatorToken {

    /// @dev Thrown when setting a transfer validator address that has no deployed code.
    error CreatorTokenBase__InvalidTransferValidatorContract();

    /// @dev The default transfer validator that will be used if no transfer validator has been set by the creator.
    address public constant DEFAULT_TRANSFER_VALIDATOR = address(0x721C00182a990771244d7A71B9FA2ea789A3b433);

    /// @dev Used to determine if the default transfer validator is applied.
    /// @dev Set to true when the creator sets a transfer validator address.
    bool private isValidatorInitialized;
    /// @dev Address of the transfer validator to apply to transactions.
    address private transferValidator;

    /**
     * @notice Sets the transfer validator for the token contract.
     *
     * @dev    Throws when provided validator contract is not the zero address and does not have code.
     * @dev    Throws when the caller is not the contract owner.
     *
     * @dev    <h4>Postconditions:</h4>
     *         1. The transferValidator address is updated.
     *         2. The `TransferValidatorUpdated` event is emitted.
     *
     * @param transferValidator_ The address of the transfer validator contract.
     */
    function setTransferValidator(address transferValidator_) public {
        _requireCallerIsContractOwner();

        bool isValidTransferValidator = transferValidator_.code.length > 0;

        if(transferValidator_ != address(0) && !isValidTransferValidator) {
            revert CreatorTokenBase__InvalidTransferValidatorContract();
        }

        emit TransferValidatorUpdated(address(getTransferValidator()), transferValidator_);

        isValidatorInitialized = true;
        transferValidator = transferValidator_;
    }

    /**
     * @notice Returns the transfer validator contract address for this token contract.
     */
    function getTransferValidator() public view override returns (address validator) {
        validator = transferValidator;

        if (validator == address(0)) {
            if (!isValidatorInitialized) {
                validator = DEFAULT_TRANSFER_VALIDATOR;
            }
        }
    }

    /**
     * @dev Pre-validates a token transfer, reverting if the transfer is not allowed by this token's security policy.
     *      Inheriting contracts are responsible for overriding the _beforeTokenTransfer function, or its equivalent
     *      and calling _validateBeforeTransfer so that checks can be properly applied during token transfers.
     *
     * @dev Be aware that if the msg.sender is the transfer validator, the transfer is automatically permitted, as the
     *      transfer validator is expected to pre-validate the transfer.
     *
     * @dev Throws when the transfer doesn't comply with the collection's transfer policy, if the transferValidator is
     *      set to a non-zero address.
     *
     * @param caller  The address of the caller.
     * @param from    The address of the sender.
     * @param to      The address of the receiver.
     * @param tokenId The token id being transferred.
     */
    function _preValidateTransfer(
        address caller, 
        address from, 
        address to, 
        uint256 tokenId, 
        uint256 /*value*/) internal virtual override {
        address validator = getTransferValidator();

        if (validator != address(0)) {
            if (msg.sender == validator) {
                return;
            }

            ITransferValidator(validator).validateTransfer(caller, from, to, tokenId);
        }
    }

    /**
     * @dev Pre-validates a token transfer, reverting if the transfer is not allowed by this token's security policy.
     *      Inheriting contracts are responsible for overriding the _beforeTokenTransfer function, or its equivalent
     *      and calling _validateBeforeTransfer so that checks can be properly applied during token transfers.
     *
     * @dev Be aware that if the msg.sender is the transfer validator, the transfer is automatically permitted, as the
     *      transfer validator is expected to pre-validate the transfer.
     * 
     * @dev Used for ERC20 and ERC1155 token transfers which have an amount value to validate in the transfer validator.
     * @dev The `tokenId` for ERC20 tokens should be set to `0`.
     *
     * @dev Throws when the transfer doesn't comply with the collection's transfer policy, if the transferValidator is
     *      set to a non-zero address.
     *
     * @param caller  The address of the caller.
     * @param from    The address of the sender.
     * @param to      The address of the receiver.
     * @param tokenId The token id being transferred.
     * @param amount  The amount of token being transferred.
     */
    function _preValidateTransfer(
        address caller, 
        address from, 
        address to, 
        uint256 tokenId, 
        uint256 amount,
        uint256 /*value*/) internal virtual override {
        address validator = getTransferValidator();

        if (validator != address(0)) {
            if (msg.sender == validator) {
                return;
            }

            ITransferValidator(validator).validateTransfer(caller, from, to, tokenId, amount);
        }
    }
}

// lib/openzeppelin-contracts/contracts/token/ERC721/ERC721.sol

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

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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        _approve(to, tokenId);
    }

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

        return _tokenApprovals[tokenId];
    }

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

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

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

        _transfer(from, to, tokenId);
    }

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

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

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

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

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

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

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

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

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

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

        // Check that tokenId was not minted by `_beforeTokenTransfer` hook
        require(!_exists(tokenId), "ERC721: token already minted");

        unchecked {
            // Will not overflow unless all 2**256 token ids are minted to the same owner.
            // Given that tokens are minted one by one, it is impossible in practice that
            // this ever happens. Might change if we allow batch minting.
            // The ERC fails to describe this case.
            _balances[to] += 1;
        }

        _owners[tokenId] = to;

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

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

    /**
     * @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 virtual {
        address owner = ERC721.ownerOf(tokenId);

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

        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
        owner = ERC721.ownerOf(tokenId);

        // Clear approvals
        delete _tokenApprovals[tokenId];

        unchecked {
            // Cannot overflow, as that would require more tokens to be burned/transferred
            // out than the owner initially received through minting and transferring in.
            _balances[owner] -= 1;
        }
        delete _owners[tokenId];

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

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

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

        _beforeTokenTransfer(from, to, tokenId, 1);

        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");

        // Clear approvals from the previous owner
        delete _tokenApprovals[tokenId];

        unchecked {
            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
            // `from`'s balance is the number of token held, which is at least one before the current
            // transfer.
            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
            // all 2**256 token ids to be minted, which in practice is impossible.
            _balances[from] -= 1;
            _balances[to] += 1;
        }
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId, 1);
    }

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

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

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

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

    /**
     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
     * - When `from` is zero, the tokens will be minted for `to`.
     * - When `to` is zero, ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual {}

    /**
     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
     * - When `from` is zero, the tokens were minted for `to`.
     * - When `to` is zero, ``from``'s tokens were burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual {}

    /**
     * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
     *
     * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant
     * being 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`.
     */
    // solhint-disable-next-line func-name-mixedcase
    function __unsafe_increaseBalance(address account, uint256 amount) internal {
        _balances[account] += amount;
    }
}

// lib/creator-token-standards/src/token/erc721/ERC721OpenZeppelin.sol

abstract contract ERC721OpenZeppelinBase is ERC721 {

    // Token name
    string internal _contractName;

    // Token symbol
    string internal _contractSymbol;

    function name() public view virtual override returns (string memory) {
        return _contractName;
    }

    function symbol() public view virtual override returns (string memory) {
        return _contractSymbol;
    }

    function _setNameAndSymbol(string memory name_, string memory symbol_) internal {
        _contractName = name_;
        _contractSymbol = symbol_;
    }
}

abstract contract ERC721OpenZeppelin is ERC721OpenZeppelinBase {
    constructor(string memory name_, string memory symbol_) ERC721("", "") {
        _setNameAndSymbol(name_, symbol_);
    }
}

abstract contract ERC721OpenZeppelinInitializable is OwnablePermissions, ERC721OpenZeppelinBase {

    error ERC721OpenZeppelinInitializable__AlreadyInitializedERC721();

    /// @notice Specifies whether or not the contract is initialized
    bool private _erc721Initialized;

    /// @dev Initializes parameters of ERC721 tokens.
    /// These cannot be set in the constructor because this contract is optionally compatible with EIP-1167.
    function initializeERC721(string memory name_, string memory symbol_) public {
        _requireCallerIsContractOwner();

        if(_erc721Initialized) {
            revert ERC721OpenZeppelinInitializable__AlreadyInitializedERC721();
        }

        _erc721Initialized = true;

        _setNameAndSymbol(name_, symbol_);
    }
}

// lib/creator-token-standards/src/erc721c/ERC721C.sol

/**
 * @title ERC721C
 * @author Limit Break, Inc.
 * @notice Extends OpenZeppelin's ERC721 implementation with Creator Token functionality, which
 *         allows the contract owner to update the transfer validation logic by managing a security policy in
 *         an external transfer validation security policy registry.  See {CreatorTokenTransferValidator}.
 */
abstract contract ERC721C is ERC721OpenZeppelin, CreatorTokenBase, AutomaticValidatorTransferApproval {

    /**
     * @notice Overrides behavior of isApprovedFor all such that if an operator is not explicitly approved
     *         for all, the contract owner can optionally auto-approve the 721-C transfer validator for transfers.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool isApproved) {
        isApproved = super.isApprovedForAll(owner, operator);

        if (!isApproved) {
            if (autoApproveTransfersFromValidator) {
                isApproved = operator == address(getTransferValidator());
            }
        }
    }

    /**
     * @notice Indicates whether the contract implements the specified interface.
     * @dev Overrides supportsInterface in ERC165.
     * @param interfaceId The interface id
     * @return true if the contract implements the specified interface, false otherwise
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return 
        interfaceId == type(ICreatorToken).interfaceId || 
        interfaceId == type(ICreatorTokenLegacy).interfaceId || 
        super.supportsInterface(interfaceId);
    }

    /**
     * @notice Returns the function selector for the transfer validator's validation function to be called 
     * @notice for transaction simulation. 
     */
    function getTransferValidationFunction() external pure returns (bytes4 functionSignature, bool isViewFunction) {
        functionSignature = bytes4(keccak256("validateTransfer(address,address,address,uint256)"));
        isViewFunction = true;
    }

    /// @dev Ties the open-zeppelin _beforeTokenTransfer hook to more granular transfer validation logic
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize) internal virtual override {
        for (uint256 i = 0; i < batchSize;) {
            _validateBeforeTransfer(from, to, firstTokenId + i);
            unchecked {
                ++i;
            }
        }
    }

    /// @dev Ties the open-zeppelin _afterTokenTransfer hook to more granular transfer validation logic
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize) internal virtual override {
        for (uint256 i = 0; i < batchSize;) {
            _validateAfterTransfer(from, to, firstTokenId + i);
            unchecked {
                ++i;
            }
        }
    }
}

/**
 * @title ERC721CInitializable
 * @author Limit Break, Inc.
 * @notice Initializable implementation of ERC721C to allow for EIP-1167 proxy clones.
 */
abstract contract ERC721CInitializable is ERC721OpenZeppelinInitializable, CreatorTokenBase, AutomaticValidatorTransferApproval {

    /**
     * @notice Overrides behavior of isApprovedFor all such that if an operator is not explicitly approved
     *         for all, the contract owner can optionally auto-approve the 721-C transfer validator for transfers.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool isApproved) {
        isApproved = super.isApprovedForAll(owner, operator);

        if (!isApproved) {
            if (autoApproveTransfersFromValidator) {
                isApproved = operator == address(getTransferValidator());
            }
        }
    }

    /**
     * @notice Indicates whether the contract implements the specified interface.
     * @dev Overrides supportsInterface in ERC165.
     * @param interfaceId The interface id
     * @return true if the contract implements the specified interface, false otherwise
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return 
        interfaceId == type(ICreatorToken).interfaceId || 
        interfaceId == type(ICreatorTokenLegacy).interfaceId || 
        super.supportsInterface(interfaceId);
    }

    /**
     * @notice Returns the function selector for the transfer validator's validation function to be called 
     * @notice for transaction simulation. 
     */
    function getTransferValidationFunction() external pure returns (bytes4 functionSignature, bool isViewFunction) {
        functionSignature = bytes4(keccak256("validateTransfer(address,address,address,uint256)"));
        isViewFunction = true;
    }

    /// @dev Ties the open-zeppelin _beforeTokenTransfer hook to more granular transfer validation logic
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize) internal virtual override {
        for (uint256 i = 0; i < batchSize;) {
            _validateBeforeTransfer(from, to, firstTokenId + i);
            unchecked {
                ++i;
            }
        }
    }

    /// @dev Ties the open-zeppelin _afterTokenTransfer hook to more granular transfer validation logic
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize) internal virtual override {
        for (uint256 i = 0; i < batchSize;) {
            _validateAfterTransfer(from, to, firstTokenId + i);
            unchecked {
                ++i;
            }
        }
    }
}

// src/Depix.sol

error IncorrectValue();
error AlreadyMinted();
error NotOwner();
error TransferFailed();
error TwinSupplyReached();
error MaxSupplyReached();
error MaxPerWalletExceeded();
error InvalidAmount();
error InvalidAddress();
error InvalidURI();
error InvalidPhase();
error InvalidProof();

abstract contract RILLAZC {
    function ownerOf(uint256 tokenId) public view virtual returns (address);
}

contract Depix is ERC721C, BasicRoyalties, OwnableBasic {
    RILLAZC immutable RILLAZ;
    PhaseManager immutable phaseManager;
    address immutable MINT_FUNDS_RECEIVER;
    
    uint256 constant MAX_SUPPLY = 10000;
    uint256 constant TWIN_MAX_SUPPLY = 3500;
    
    uint256 public currentSupply;
    uint256 public tokenCounter = 10000;
    string private baseTokenURI;
    mapping(uint256 => bool) public hasTwinMap;
    
    mapping(PhaseType => uint256) public mintedPerPhase;
    mapping(address => mapping(PhaseType => uint256)) public userMintedPerPhase;

    constructor(
        address royaltyReceiver_,
        uint96 royaltyFeeNumerator_,
        string memory name_,
        string memory symbol_,
        RILLAZC rillaz_,
        PhaseManager phaseManager_
    )
        ERC721OpenZeppelin(name_, symbol_)
        BasicRoyalties(royaltyReceiver_, royaltyFeeNumerator_)
        OwnableBasic()
    {
        if (royaltyReceiver_ == address(0)) revert InvalidAddress();
        if (address(rillaz_) == address(0)) revert InvalidAddress();
        if (address(phaseManager_) == address(0)) revert InvalidAddress();
        
        RILLAZ = rillaz_;
        phaseManager = phaseManager_;
        MINT_FUNDS_RECEIVER = royaltyReceiver_;
    }

    function mintTwin(
        uint256[] calldata tokenIds,
        bytes32[] calldata merkleProof
    ) external payable {
        uint256 len = tokenIds.length;
        if (len == 0) revert InvalidAmount();
        
        (PhaseManager.Phase memory phase, PhaseType phaseType) = phaseManager.currentPhase();
        if (phaseType == PhaseType.NONE || phaseType > PhaseType.TWIN_PHASE2) 
            revert NoTwinPhase();

        if (userMintedPerPhase[msg.sender][phaseType] + len > phase.maxPerWallet) 
            revert MaxPerWalletExceeded();
        if (twinSupply() + len > TWIN_MAX_SUPPLY) 
            revert TwinSupplyReached();
       

        bool isWhitelisted = phaseManager.isWhitelistedForPhase(phaseType, msg.sender, merkleProof);
        if (isWhitelisted && msg.value != 0) 
            revert IncorrectValue();

        userMintedPerPhase[msg.sender][phaseType] += len;
        mintedPerPhase[phaseType] += len;
        currentSupply += len;
        
        for (uint256 i = 0; i < len; i++) {
            if (RILLAZ.ownerOf(tokenIds[i]) != msg.sender) revert NotOwner();
            if (hasTwinMap[tokenIds[i]]) revert AlreadyMinted();
            hasTwinMap[tokenIds[i]] = true;
            _mint(msg.sender, tokenIds[i]);
        }
        if (!isWhitelisted) {
            uint256 mintCost = phase.price * len;
            if (msg.value != mintCost) revert IncorrectValue();
            (bool success, ) = MINT_FUNDS_RECEIVER.call{value: msg.value}("");
            if (!success) revert TransferFailed();
        }
    }

    function publicMint(
        uint256 amount,
        bytes32[] calldata merkleProof
    ) external payable {
        if (amount == 0) revert InvalidAmount();
        (PhaseManager.Phase memory phase, PhaseType phaseType) = phaseManager.currentPhase();
        if (phaseType <= PhaseType.TWIN_PHASE2) revert InvalidPhase();
        
        if (userMintedPerPhase[msg.sender][phaseType] + amount > phase.maxPerWallet) 
            revert MaxPerWalletExceeded();
        if (currentSupply + amount > MAX_SUPPLY) 
            revert MaxSupplyReached();
        if (mintedPerPhase[phaseType] + amount > phase.maxSupplyPerPhase)
            revert MaxSupplyReached();

        if (phaseType < PhaseType.PUBLIC_SALE) {
            if (merkleProof.length == 0) revert InvalidProof();
            if (!phaseManager.isWhitelistedForPhase(phaseType, msg.sender, merkleProof)) 
                revert NotWhitelisted();
        }

        if (phase.price > 0) {
            uint256 mintCost = phase.price * amount;
            if (msg.value != mintCost) revert IncorrectValue();
        } else {
            if (msg.value != 0) revert IncorrectValue();
        }

        // Update state
        userMintedPerPhase[msg.sender][phaseType] += amount;
        mintedPerPhase[phaseType] += amount;
        currentSupply += amount;

        if (phase.price > 0) {
            (bool success, ) = MINT_FUNDS_RECEIVER.call{value: msg.value}("");
            if (!success) revert TransferFailed();
        }

        for (uint256 i = 0; i < amount; i++) {
            _mint(msg.sender, tokenCounter);
            tokenCounter++;
        }
    }

    function setDefaultRoyalty(address receiver, uint96 feeNumerator) public {
        _requireCallerIsContractOwner();
        _setDefaultRoyalty(receiver, feeNumerator);
    }

    function setTokenRoyalty(
        uint256 tokenId,
        address receiver,
        uint96 feeNumerator
    ) public {
        _requireCallerIsContractOwner();
        _setTokenRoyalty(tokenId, receiver, feeNumerator);
    }

    function setBaseURI(string calldata baseURI) external {
        _requireCallerIsContractOwner();
        if (bytes(baseURI).length == 0) revert InvalidURI();
        baseTokenURI = baseURI;
    }

    function twinSupply() public view returns (uint256) {
        return mintedPerPhase[PhaseType.TWIN_PHASE1] + mintedPerPhase[PhaseType.TWIN_PHASE2];
    }

    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override(ERC721C, ERC2981) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

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

    function getMintedPerPhase(PhaseType phaseType) external view returns (uint256) {
        return mintedPerPhase[phaseType];
    }

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

    function getUserMintedPerPhase(address user, PhaseType phaseType) external view returns (uint256) {
        return userMintedPerPhase[user][phaseType];
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"royaltyReceiver_","type":"address"},{"internalType":"uint96","name":"royaltyFeeNumerator_","type":"uint96"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"contract RILLAZC","name":"rillaz_","type":"address"},{"internalType":"contract PhaseManager","name":"phaseManager_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyMinted","type":"error"},{"inputs":[],"name":"CreatorTokenBase__InvalidTransferValidatorContract","type":"error"},{"inputs":[],"name":"IncorrectValue","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidPhase","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"InvalidURI","type":"error"},{"inputs":[],"name":"MaxPerWalletExceeded","type":"error"},{"inputs":[],"name":"MaxSupplyReached","type":"error"},{"inputs":[],"name":"NoTwinPhase","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"NotWhitelisted","type":"error"},{"inputs":[],"name":"ShouldNotMintToBurnAddress","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"TwinSupplyReached","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":"autoApproved","type":"bool"}],"name":"AutomaticApprovalOfTransferValidatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"DefaultRoyaltySet","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":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"TokenRoyaltySet","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":false,"internalType":"address","name":"oldValidator","type":"address"},{"indexed":false,"internalType":"address","name":"newValidator","type":"address"}],"name":"TransferValidatorUpdated","type":"event"},{"inputs":[],"name":"DEFAULT_TRANSFER_VALIDATOR","outputs":[{"internalType":"address","name":"","type":"address"}],"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":[],"name":"autoApproveTransfersFromValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum PhaseType","name":"phaseType","type":"uint8"}],"name":"getMintedPerPhase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransferValidationFunction","outputs":[{"internalType":"bytes4","name":"functionSignature","type":"bytes4"},{"internalType":"bool","name":"isViewFunction","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransferValidator","outputs":[{"internalType":"address","name":"validator","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"enum PhaseType","name":"phaseType","type":"uint8"}],"name":"getUserMintedPerPhase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"hasTwinMap","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":"isApproved","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"mintTwin","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"enum PhaseType","name":"","type":"uint8"}],"name":"mintedPerPhase","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":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"autoApprove","type":"bool"}],"name":"setAutomaticApprovalOfTransfersFromValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setTokenRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"transferValidator_","type":"address"}],"name":"setTransferValidator","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":[],"name":"tokenCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"twinSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"enum PhaseType","name":"","type":"uint8"}],"name":"userMintedPerPhase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

60e0604052612710600d5534801561001657600080fd5b50604051613783380380613783833981016040819052610035916103d1565b8585858560405180602001604052806000815250604051806020016040528060008152508160009081610068919061051c565b506001610075828261051c565b505050610088828261013960201b60201c565b5061009590508282610157565b506100a19050336101ac565b6001600160a01b0386166100c85760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b0382166100ef5760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b0381166101165760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b03918216608052811660a0529390931660c052506105da915050565b6006610145838261051c565b506007610152828261051c565b505050565b61016182826101fe565b6040516001600160601b03821681526001600160a01b038316907f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9060200160405180910390a25050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6127106001600160601b03821611156102715760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b60648201526084015b60405180910390fd5b6001600160a01b0382166102c75760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610268565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600955565b6001600160a01b038116811461031557600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261033f57600080fd5b81516001600160401b0381111561035857610358610318565b604051601f8201601f19908116603f011681016001600160401b038111828210171561038657610386610318565b60405281815283820160200185101561039e57600080fd5b60005b828110156103bd576020818601810151838301820152016103a1565b506000918101602001919091529392505050565b60008060008060008060c087890312156103ea57600080fd5b86516103f581610300565b60208801519096506001600160601b038116811461041257600080fd5b60408801519095506001600160401b0381111561042e57600080fd5b61043a89828a0161032e565b606089015190955090506001600160401b0381111561045857600080fd5b61046489828a0161032e565b935050608087015161047581610300565b60a088015190925061048681610300565b809150509295509295509295565b600181811c908216806104a857607f821691505b6020821081036104c857634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561015257806000526020600020601f840160051c810160208510156104f55750805b601f840160051c820191505b818110156105155760008155600101610501565b5050505050565b81516001600160401b0381111561053557610535610318565b610549816105438454610494565b846104ce565b6020601f82116001811461057d57600083156105655750848201515b600019600385901b1c1916600184901b178455610515565b600084815260208120601f198516915b828110156105ad578785015182556020948501946001909201910161058d565b50848210156105cb5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b60805160a05160c05161315e61062560003960008181610e3101526117b201526000818161095401528181610aee015281816113b901526115d301526000610c5f015261315e6000f3fe60806040526004361061021a5760003560e01c8063659f875b11610123578063b88d4fde116100ab578063eef998101161006f578063eef9981014610660578063f2fde38b14610673578063f631e96914610693578063f9528e2a146106a8578063ffe5387e146106d857600080fd5b8063b88d4fde146105bd578063c87b56dd146105dd578063d082e381146105fd578063d2bf649214610613578063e985e9c51461064057600080fd5b80638da5cb5b116100f25780638da5cb5b1461052a57806395d89b41146105485780639e05d2401461055d578063a22cb4651461057d578063a9fc664e1461059d57600080fd5b8063659f875b146104bf57806370a08231146104df578063715018a6146104ff578063771282f61461051457600080fd5b80632157c649116101a657806355f804b31161017557806355f804b3146104065780635944c753146104265780635f555fb9146104465780636221d13c1461047e5780636352211e1461049f57600080fd5b80632157c6491461037457806323b872dd146103875780632a55205a146103a757806342842e0e146103e657600080fd5b8063081812fc116101ed578063081812fc146102d8578063095ea7b3146102f8578063098144d4146103185780630d705df61461032d57806318160ddd1461035557600080fd5b8063014635461461021f57806301ffc9a71461026457806304634d8d1461029457806306fdde03146102b6575b600080fd5b34801561022b57600080fd5b5061024773721c00182a990771244d7a71b9fa2ea789a3b43381565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561027057600080fd5b5061028461027f366004612695565b6106f8565b604051901515815260200161025b565b3480156102a057600080fd5b506102b46102af3660046126dc565b610709565b005b3480156102c257600080fd5b506102cb61071f565b60405161025b9190612765565b3480156102e457600080fd5b506102476102f3366004612778565b6107b1565b34801561030457600080fd5b506102b4610313366004612791565b6107d8565b34801561032457600080fd5b506102476108f2565b34801561033957600080fd5b506040805163657711f560e11b8152600160208201520161025b565b34801561036157600080fd5b50600c545b60405190815260200161025b565b6102b4610382366004612801565b61092c565b34801561039357600080fd5b506102b46103a2366004612870565b610ece565b3480156103b357600080fd5b506103c76103c23660046128b1565b610eff565b604080516001600160a01b03909316835260208301919091520161025b565b3480156103f257600080fd5b506102b4610401366004612870565b610fad565b34801561041257600080fd5b506102b46104213660046128d3565b610fc8565b34801561043257600080fd5b506102b4610441366004612945565b610fff565b34801561045257600080fd5b50610366610461366004612994565b601160209081526000928352604080842090915290825290205481565b34801561048a57600080fd5b5060085461028490600160a81b900460ff1681565b3480156104ab57600080fd5b506102476104ba366004612778565b611012565b3480156104cb57600080fd5b506103666104da366004612994565b611072565b3480156104eb57600080fd5b506103666104fa3660046129c2565b6110c5565b34801561050b57600080fd5b506102b461114b565b34801561052057600080fd5b50610366600c5481565b34801561053657600080fd5b50600b546001600160a01b0316610247565b34801561055457600080fd5b506102cb61115f565b34801561056957600080fd5b506102b46105783660046129ed565b61116e565b34801561058957600080fd5b506102b4610598366004612a0a565b6111ce565b3480156105a957600080fd5b506102b46105b83660046129c2565b6111d9565b3480156105c957600080fd5b506102b46105d8366004612aa6565b611290565b3480156105e957600080fd5b506102cb6105f8366004612778565b6112c8565b34801561060957600080fd5b50610366600d5481565b34801561061f57600080fd5b5061036661062e366004612b6d565b60106020526000908152604090205481565b34801561064c57600080fd5b5061028461065b366004612b8a565b61132f565b6102b461066e366004612bb8565b611393565b34801561067f57600080fd5b506102b461068e3660046129c2565b611880565b34801561069f57600080fd5b506103666118f9565b3480156106b457600080fd5b506102846106c3366004612778565b600f6020526000908152604090205460ff1681565b3480156106e457600080fd5b506103666106f3366004612b6d565b611959565b600061070382611998565b92915050565b6107116119bd565b61071b82826119c5565b5050565b60606006805461072e90612c03565b80601f016020809104026020016040519081016040528092919081815260200182805461075a90612c03565b80156107a75780601f1061077c576101008083540402835291602001916107a7565b820191906000526020600020905b81548152906001019060200180831161078a57829003601f168201915b5050505050905090565b60006107bc82611a1a565b506000908152600460205260409020546001600160a01b031690565b60006107e382611012565b9050806001600160a01b0316836001600160a01b0316036108555760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b03821614806108715750610871813361132f565b6108e35760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000606482015260840161084c565b6108ed8383611a79565b505050565b60085461010090046001600160a01b0316806109295760085460ff16610929575073721c00182a990771244d7a71b9fa2ea789a3b4335b90565b82600081900361094f5760405163162908e360e11b815260040160405180910390fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663055ad42e6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156109b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d49190612c76565b909250905060008160068111156109ed576109ed612d1b565b1480610a0a57506002816006811115610a0857610a08612d1b565b115b15610a2857604051635ce1196360e01b815260040160405180910390fd5b608082015133600090815260116020526040812060ff909216918591846006811115610a5657610a56612d1b565b6006811115610a6757610a67612d1b565b815260200190815260200160002054610a809190612d47565b1115610a9f57604051637ab0312d60e11b815260040160405180910390fd5b610dac83610aab6118f9565b610ab59190612d47565b1115610ad457604051637201d58360e01b815260040160405180910390fd5b60405163f31755b760e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f31755b790610b2990859033908b908b90600401612d5a565b602060405180830381865afa158015610b46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6a9190612dc9565b9050808015610b7857503415155b15610b9657604051636956f2ab60e11b815260040160405180910390fd5b3360009081526011602052604081208591846006811115610bb957610bb9612d1b565b6006811115610bca57610bca612d1b565b81526020019081526020016000206000828254610be79190612d47565b9091555084905060106000846006811115610c0457610c04612d1b565b6006811115610c1557610c15612d1b565b81526020019081526020016000206000828254610c329190612d47565b9250508190555083600c6000828254610c4b9190612d47565b90915550600090505b84811015610dea57337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e8b8b85818110610c9e57610c9e612de6565b905060200201356040518263ffffffff1660e01b8152600401610cc391815260200190565b602060405180830381865afa158015610ce0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d049190612dfc565b6001600160a01b031614610d2b576040516330cd747160e01b815260040160405180910390fd5b600f60008a8a84818110610d4157610d41612de6565b602090810292909201358352508101919091526040016000205460ff1615610d7c57604051631bbdf5c560e31b815260040160405180910390fd5b6001600f60008b8b85818110610d9457610d94612de6565b90506020020135815260200190815260200160002060006101000a81548160ff021916908315150217905550610de2338a8a84818110610dd657610dd6612de6565b90506020020135611ae7565b600101610c54565b5080610ec45760008484602001516001600160601b0316610e0b9190612e19565b9050803414610e2d57604051636956f2ab60e11b815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163460405160006040518083038185875af1925050503d8060008114610e9a576040519150601f19603f3d011682016040523d82523d6000602084013e610e9f565b606091505b5050905080610ec1576040516312171d8360e31b815260040160405180910390fd5b50505b5050505050505050565b610ed83382611c8a565b610ef45760405162461bcd60e51b815260040161084c90612e30565b6108ed838383611ce9565b6000828152600a602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092528291610f745750604080518082019091526009546001600160a01b0381168252600160a01b90046001600160601b031660208201525b602081015160009061271090610f93906001600160601b031687612e19565b610f9d9190612e7d565b91519350909150505b9250929050565b6108ed83838360405180602001604052806000815250611290565b610fd06119bd565b6000819003610ff257604051633ba0191160e01b815260040160405180910390fd5b600e6108ed828483612ee6565b6110076119bd565b6108ed838383611e62565b6000818152600260205260408120546001600160a01b0316806107035760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161084c565b6001600160a01b03821660009081526011602052604081208183600681111561109d5761109d612d1b565b60068111156110ae576110ae612d1b565b815260200190815260200160002054905092915050565b60006001600160a01b03821661112f5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840161084c565b506001600160a01b031660009081526003602052604090205490565b611153611ebc565b61115d6000611f16565b565b60606007805461072e90612c03565b6111766119bd565b60088054821515600160a81b0260ff60a81b199091161790556040517f6787c7f9a80aa0f5ceddab2c54f1f5169c0b88e75dd5e19d5e858a64144c7dbc906111c390831515815260200190565b60405180910390a150565b61071b338383611f68565b6111e16119bd565b6001600160a01b038116803b151590158015906111fc575080155b1561121a576040516332483afb60e01b815260040160405180910390fd5b7fcc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac6112436108f2565b604080516001600160a01b03928316815291851660208301520160405180910390a150600880546001600160a01b03909216610100026001600160a81b0319909216919091176001179055565b61129a3383611c8a565b6112b65760405162461bcd60e51b815260040161084c90612e30565b6112c28484848461202e565b50505050565b60606112d382611a1a565b60006112dd612061565b905060008151116112fd5760405180602001604052806000815250611328565b8061130784612070565b604051602001611318929190612fa5565b6040516020818303038152906040525b9392505050565b6001600160a01b0382811660009081526005602090815260408083209385168352929052205460ff168061070357600854600160a81b900460ff1615610703576113776108f2565b6001600160a01b0316826001600160a01b031614905092915050565b826000036113b45760405163162908e360e11b815260040160405180910390fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663055ad42e6040518163ffffffff1660e01b815260040160e060405180830381865afa158015611415573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114399190612c76565b9092509050600281600681111561145257611452612d1b565b116114705760405163268dbf6760e21b815260040160405180910390fd5b608082015133600090815260116020526040812060ff90921691879184600681111561149e5761149e612d1b565b60068111156114af576114af612d1b565b8152602001908152602001600020546114c89190612d47565b11156114e757604051637ab0312d60e11b815260040160405180910390fd5b61271085600c546114f89190612d47565b11156115175760405163d05cb60960e01b815260040160405180910390fd5b8160a0015161ffff16856010600084600681111561153757611537612d1b565b600681111561154857611548612d1b565b8152602001908152602001600020546115619190612d47565b11156115805760405163d05cb60960e01b815260040160405180910390fd5b600681600681111561159457611594612d1b565b101561166c5760008390036115bc576040516309bde33960e01b815260040160405180910390fd5b60405163f31755b760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f31755b79061160e908490339089908990600401612d5a565b602060405180830381865afa15801561162b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164f9190612dc9565b61166c57604051630b094f2760e31b815260040160405180910390fd5b60208201516001600160601b0316156116c25760008583602001516001600160601b031661169a9190612e19565b90508034146116bc57604051636956f2ab60e11b815260040160405180910390fd5b506116e1565b34156116e157604051636956f2ab60e11b815260040160405180910390fd5b336000908152601160205260408120869183600681111561170457611704612d1b565b600681111561171557611715612d1b565b815260200190815260200160002060008282546117329190612d47565b909155508590506010600083600681111561174f5761174f612d1b565b600681111561176057611760612d1b565b8152602001908152602001600020600082825461177d9190612d47565b9250508190555084600c60008282546117969190612d47565b909155505060208201516001600160601b0316156118445760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163460405160006040518083038185875af1925050503d806000811461181b576040519150601f19603f3d011682016040523d82523d6000602084013e611820565b606091505b5050905080611842576040516312171d8360e31b815260040160405180910390fd5b505b60005b858110156118785761185b33600d54611ae7565b600d805490600061186b83612fd4565b9091555050600101611847565b505050505050565b611888611ebc565b6001600160a01b0381166118ed5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161084c565b6118f681611f16565b50565b60106020527f853b2fefe141400fef543280f93d98bd49996069f632d0d20236afeeed8e46a254600160009081527f8c6065603763fec3f5742441d3833f3f43b982453612d76adb39a885e3006b5f54909161195491612d47565b905090565b60006010600083600681111561197157611971612d1b565b600681111561198257611982612d1b565b8152602001908152602001600020549050919050565b60006001600160e01b0319821663152a902d60e11b1480610703575061070382612102565b61115d611ebc565b6119cf8282612142565b6040516001600160601b03821681526001600160a01b038316907f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9060200160405180910390a25050565b6000818152600260205260409020546001600160a01b03166118f65760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161084c565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611aae82611012565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6001600160a01b038216611b3d5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161084c565b6000818152600260205260409020546001600160a01b031615611ba25760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161084c565b611bb06000838360016121fc565b6000818152600260205260409020546001600160a01b031615611c155760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161084c565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a461071b60008383600161222a565b600080611c9683611012565b9050806001600160a01b0316846001600160a01b03161480611cbd5750611cbd818561132f565b80611ce15750836001600160a01b0316611cd6846107b1565b6001600160a01b0316145b949350505050565b826001600160a01b0316611cfc82611012565b6001600160a01b031614611d225760405162461bcd60e51b815260040161084c90612fed565b6001600160a01b038216611d845760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161084c565b611d9183838360016121fc565b826001600160a01b0316611da482611012565b6001600160a01b031614611dca5760405162461bcd60e51b815260040161084c90612fed565b600081815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260038552838620805460001901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a46108ed838383600161222a565b611e6d838383612251565b6040516001600160601b03821681526001600160a01b0383169084907f7f5b076c952c0ec86e5425963c1326dd0f03a3595c19f81d765e8ff559a6e33c906020015b60405180910390a3505050565b600b546001600160a01b0316331461115d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161084c565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b031603611fc95760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161084c565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101611eaf565b612039848484611ce9565b6120458484848461231c565b6112c25760405162461bcd60e51b815260040161084c90613032565b6060600e805461072e90612c03565b6060600061207d8361241d565b60010190506000816001600160401b0381111561209c5761209c612a38565b6040519080825280601f01601f1916602001820160405280156120c6576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450846120d057509392505050565b60006001600160e01b03198216632b435fdb60e21b148061213357506001600160e01b0319821663503e914d60e11b145b806107035750610703826124f5565b6127106001600160601b038216111561216d5760405162461bcd60e51b815260040161084c90613084565b6001600160a01b0382166121c35760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c696420726563656976657200000000000000604482015260640161084c565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600955565b60005b818110156122235761221b85856122168487612d47565b612545565b6001016121ff565b5050505050565b60005b818110156122235761224985856122448487612d47565b61259b565b60010161222d565b6127106001600160601b038216111561227c5760405162461bcd60e51b815260040161084c90613084565b6001600160a01b0382166122d25760405162461bcd60e51b815260206004820152601b60248201527f455243323938313a20496e76616c696420706172616d65746572730000000000604482015260640161084c565b6040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182526000968752600a90529190942093519051909116600160a01b029116179055565b60006001600160a01b0384163b1561241257604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906123609033908990889088906004016130ce565b6020604051808303816000875af192505050801561239b575060408051601f3d908101601f191682019092526123989181019061310b565b60015b6123f8573d8080156123c9576040519150601f19603f3d011682016040523d82523d6000602084013e6123ce565b606091505b5080516000036123f05760405162461bcd60e51b815260040161084c90613032565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611ce1565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061245c5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612488576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106124a657662386f26fc10000830492506010015b6305f5e10083106124be576305f5e100830492506008015b61271083106124d257612710830492506004015b606483106124e4576064830492506002015b600a83106107035760010192915050565b60006001600160e01b031982166380ac58cd60e01b148061252657506001600160e01b03198216635b5e139f60e01b145b8061070357506301ffc9a760e01b6001600160e01b0319831614610703565b6001600160a01b03838116159083161581801561255f5750805b1561257d57604051635cbd944160e01b815260040160405180910390fd5b8115612589575b612223565b806125845761222333868686346125e2565b6001600160a01b0383811615908316158180156125b55750805b156125d357604051635cbd944160e01b815260040160405180910390fd5b81612584578061258457612223565b60006125ec6108f2565b90506001600160a01b03811615611878576001600160a01b03811633036126135750612223565b60405163657711f560e11b81526001600160a01b038781166004830152868116602483015285811660448301526064820185905282169063caee23ea9060840160006040518083038186803b15801561266b57600080fd5b505afa158015610ec1573d6000803e3d6000fd5b6001600160e01b0319811681146118f657600080fd5b6000602082840312156126a757600080fd5b81356113288161267f565b6001600160a01b03811681146118f657600080fd5b6001600160601b03811681146118f657600080fd5b600080604083850312156126ef57600080fd5b82356126fa816126b2565b9150602083013561270a816126c7565b809150509250929050565b60005b83811015612730578181015183820152602001612718565b50506000910152565b60008151808452612751816020860160208601612715565b601f01601f19169290920160200192915050565b6020815260006113286020830184612739565b60006020828403121561278a57600080fd5b5035919050565b600080604083850312156127a457600080fd5b82356127af816126b2565b946020939093013593505050565b60008083601f8401126127cf57600080fd5b5081356001600160401b038111156127e657600080fd5b6020830191508360208260051b8501011115610fa657600080fd5b6000806000806040858703121561281757600080fd5b84356001600160401b0381111561282d57600080fd5b612839878288016127bd565b90955093505060208501356001600160401b0381111561285857600080fd5b612864878288016127bd565b95989497509550505050565b60008060006060848603121561288557600080fd5b8335612890816126b2565b925060208401356128a0816126b2565b929592945050506040919091013590565b600080604083850312156128c457600080fd5b50508035926020909101359150565b600080602083850312156128e657600080fd5b82356001600160401b038111156128fc57600080fd5b8301601f8101851361290d57600080fd5b80356001600160401b0381111561292357600080fd5b85602082840101111561293557600080fd5b6020919091019590945092505050565b60008060006060848603121561295a57600080fd5b83359250602084013561296c816126b2565b9150604084013561297c816126c7565b809150509250925092565b600781106118f657600080fd5b600080604083850312156129a757600080fd5b82356129b2816126b2565b9150602083013561270a81612987565b6000602082840312156129d457600080fd5b8135611328816126b2565b80151581146118f657600080fd5b6000602082840312156129ff57600080fd5b8135611328816129df565b60008060408385031215612a1d57600080fd5b8235612a28816126b2565b9150602083013561270a816129df565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715612a7057612a70612a38565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612a9e57612a9e612a38565b604052919050565b60008060008060808587031215612abc57600080fd5b8435612ac7816126b2565b93506020850135612ad7816126b2565b92506040850135915060608501356001600160401b03811115612af957600080fd5b8501601f81018713612b0a57600080fd5b80356001600160401b03811115612b2357612b23612a38565b612b36601f8201601f1916602001612a76565b818152886020838501011115612b4b57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600060208284031215612b7f57600080fd5b813561132881612987565b60008060408385031215612b9d57600080fd5b8235612ba8816126b2565b9150602083013561270a816126b2565b600080600060408486031215612bcd57600080fd5b8335925060208401356001600160401b03811115612bea57600080fd5b612bf6868287016127bd565b9497909650939450505050565b600181811c90821680612c1757607f821691505b602082108103612c3757634e487b7160e01b600052602260045260246000fd5b50919050565b80516001600160401b0381168114612c5457600080fd5b919050565b805161ffff81168114612c5457600080fd5b8051612c5481612987565b60008082840360e0811215612c8a57600080fd5b60c0811215612c9857600080fd5b50612ca1612a4e565b835181526020840151612cb3816126c7565b6020820152612cc460408501612c3d565b6040820152612cd560608501612c3d565b6060820152608084015160ff81168114612cee57600080fd5b6080820152612cff60a08501612c59565b60a08201529150612d1260c08401612c6b565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561070357610703612d31565b600060078610612d7a57634e487b7160e01b600052602160045260246000fd5b8582526001600160a01b038516602083015260606040830181905282018390526001600160fb1b03831115612dae57600080fd5b8260051b808560808501379190910160800195945050505050565b600060208284031215612ddb57600080fd5b8151611328816129df565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612e0e57600080fd5b8151611328816126b2565b808202811582820484141761070357610703612d31565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b600082612e9a57634e487b7160e01b600052601260045260246000fd5b500490565b601f8211156108ed57806000526020600020601f840160051c81016020851015612ec65750805b601f840160051c820191505b818110156122235760008155600101612ed2565b6001600160401b03831115612efd57612efd612a38565b612f1183612f0b8354612c03565b83612e9f565b6000601f841160018114612f455760008515612f2d5750838201355b600019600387901b1c1916600186901b178355612223565b600083815260209020601f19861690835b82811015612f765786850135825560209485019460019092019101612f56565b5086821015612f935760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008351612fb7818460208801612715565b835190830190612fcb818360208801612715565b01949350505050565b600060018201612fe657612fe6612d31565b5060010190565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252602a908201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646040820152692073616c65507269636560b01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061310190830184612739565b9695505050505050565b60006020828403121561311d57600080fd5b81516113288161267f56fea26469706673582212201d6985df8d2906dd48dc614fb509c3c604845d84fc68b6054a73a9a1fe91a99b64736f6c634300081c00330000000000000000000000000ec274490c0b60efa74fdfce62a777c90e1bced400000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000008954f7a8eb01e94efb10d610837f115fe95aafb10000000000000000000000000032e7f6633d0696ec89c049bf58578c1f84a4d6000000000000000000000000000000000000000000000000000000000000000c52494c4c415a204445504958000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054445504958000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x60806040526004361061021a5760003560e01c8063659f875b11610123578063b88d4fde116100ab578063eef998101161006f578063eef9981014610660578063f2fde38b14610673578063f631e96914610693578063f9528e2a146106a8578063ffe5387e146106d857600080fd5b8063b88d4fde146105bd578063c87b56dd146105dd578063d082e381146105fd578063d2bf649214610613578063e985e9c51461064057600080fd5b80638da5cb5b116100f25780638da5cb5b1461052a57806395d89b41146105485780639e05d2401461055d578063a22cb4651461057d578063a9fc664e1461059d57600080fd5b8063659f875b146104bf57806370a08231146104df578063715018a6146104ff578063771282f61461051457600080fd5b80632157c649116101a657806355f804b31161017557806355f804b3146104065780635944c753146104265780635f555fb9146104465780636221d13c1461047e5780636352211e1461049f57600080fd5b80632157c6491461037457806323b872dd146103875780632a55205a146103a757806342842e0e146103e657600080fd5b8063081812fc116101ed578063081812fc146102d8578063095ea7b3146102f8578063098144d4146103185780630d705df61461032d57806318160ddd1461035557600080fd5b8063014635461461021f57806301ffc9a71461026457806304634d8d1461029457806306fdde03146102b6575b600080fd5b34801561022b57600080fd5b5061024773721c00182a990771244d7a71b9fa2ea789a3b43381565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561027057600080fd5b5061028461027f366004612695565b6106f8565b604051901515815260200161025b565b3480156102a057600080fd5b506102b46102af3660046126dc565b610709565b005b3480156102c257600080fd5b506102cb61071f565b60405161025b9190612765565b3480156102e457600080fd5b506102476102f3366004612778565b6107b1565b34801561030457600080fd5b506102b4610313366004612791565b6107d8565b34801561032457600080fd5b506102476108f2565b34801561033957600080fd5b506040805163657711f560e11b8152600160208201520161025b565b34801561036157600080fd5b50600c545b60405190815260200161025b565b6102b4610382366004612801565b61092c565b34801561039357600080fd5b506102b46103a2366004612870565b610ece565b3480156103b357600080fd5b506103c76103c23660046128b1565b610eff565b604080516001600160a01b03909316835260208301919091520161025b565b3480156103f257600080fd5b506102b4610401366004612870565b610fad565b34801561041257600080fd5b506102b46104213660046128d3565b610fc8565b34801561043257600080fd5b506102b4610441366004612945565b610fff565b34801561045257600080fd5b50610366610461366004612994565b601160209081526000928352604080842090915290825290205481565b34801561048a57600080fd5b5060085461028490600160a81b900460ff1681565b3480156104ab57600080fd5b506102476104ba366004612778565b611012565b3480156104cb57600080fd5b506103666104da366004612994565b611072565b3480156104eb57600080fd5b506103666104fa3660046129c2565b6110c5565b34801561050b57600080fd5b506102b461114b565b34801561052057600080fd5b50610366600c5481565b34801561053657600080fd5b50600b546001600160a01b0316610247565b34801561055457600080fd5b506102cb61115f565b34801561056957600080fd5b506102b46105783660046129ed565b61116e565b34801561058957600080fd5b506102b4610598366004612a0a565b6111ce565b3480156105a957600080fd5b506102b46105b83660046129c2565b6111d9565b3480156105c957600080fd5b506102b46105d8366004612aa6565b611290565b3480156105e957600080fd5b506102cb6105f8366004612778565b6112c8565b34801561060957600080fd5b50610366600d5481565b34801561061f57600080fd5b5061036661062e366004612b6d565b60106020526000908152604090205481565b34801561064c57600080fd5b5061028461065b366004612b8a565b61132f565b6102b461066e366004612bb8565b611393565b34801561067f57600080fd5b506102b461068e3660046129c2565b611880565b34801561069f57600080fd5b506103666118f9565b3480156106b457600080fd5b506102846106c3366004612778565b600f6020526000908152604090205460ff1681565b3480156106e457600080fd5b506103666106f3366004612b6d565b611959565b600061070382611998565b92915050565b6107116119bd565b61071b82826119c5565b5050565b60606006805461072e90612c03565b80601f016020809104026020016040519081016040528092919081815260200182805461075a90612c03565b80156107a75780601f1061077c576101008083540402835291602001916107a7565b820191906000526020600020905b81548152906001019060200180831161078a57829003601f168201915b5050505050905090565b60006107bc82611a1a565b506000908152600460205260409020546001600160a01b031690565b60006107e382611012565b9050806001600160a01b0316836001600160a01b0316036108555760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b03821614806108715750610871813361132f565b6108e35760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000606482015260840161084c565b6108ed8383611a79565b505050565b60085461010090046001600160a01b0316806109295760085460ff16610929575073721c00182a990771244d7a71b9fa2ea789a3b4335b90565b82600081900361094f5760405163162908e360e11b815260040160405180910390fd5b6000807f0000000000000000000000000032e7f6633d0696ec89c049bf58578c1f84a4d66001600160a01b031663055ad42e6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156109b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d49190612c76565b909250905060008160068111156109ed576109ed612d1b565b1480610a0a57506002816006811115610a0857610a08612d1b565b115b15610a2857604051635ce1196360e01b815260040160405180910390fd5b608082015133600090815260116020526040812060ff909216918591846006811115610a5657610a56612d1b565b6006811115610a6757610a67612d1b565b815260200190815260200160002054610a809190612d47565b1115610a9f57604051637ab0312d60e11b815260040160405180910390fd5b610dac83610aab6118f9565b610ab59190612d47565b1115610ad457604051637201d58360e01b815260040160405180910390fd5b60405163f31755b760e01b81526000906001600160a01b037f0000000000000000000000000032e7f6633d0696ec89c049bf58578c1f84a4d6169063f31755b790610b2990859033908b908b90600401612d5a565b602060405180830381865afa158015610b46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6a9190612dc9565b9050808015610b7857503415155b15610b9657604051636956f2ab60e11b815260040160405180910390fd5b3360009081526011602052604081208591846006811115610bb957610bb9612d1b565b6006811115610bca57610bca612d1b565b81526020019081526020016000206000828254610be79190612d47565b9091555084905060106000846006811115610c0457610c04612d1b565b6006811115610c1557610c15612d1b565b81526020019081526020016000206000828254610c329190612d47565b9250508190555083600c6000828254610c4b9190612d47565b90915550600090505b84811015610dea57337f0000000000000000000000008954f7a8eb01e94efb10d610837f115fe95aafb16001600160a01b0316636352211e8b8b85818110610c9e57610c9e612de6565b905060200201356040518263ffffffff1660e01b8152600401610cc391815260200190565b602060405180830381865afa158015610ce0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d049190612dfc565b6001600160a01b031614610d2b576040516330cd747160e01b815260040160405180910390fd5b600f60008a8a84818110610d4157610d41612de6565b602090810292909201358352508101919091526040016000205460ff1615610d7c57604051631bbdf5c560e31b815260040160405180910390fd5b6001600f60008b8b85818110610d9457610d94612de6565b90506020020135815260200190815260200160002060006101000a81548160ff021916908315150217905550610de2338a8a84818110610dd657610dd6612de6565b90506020020135611ae7565b600101610c54565b5080610ec45760008484602001516001600160601b0316610e0b9190612e19565b9050803414610e2d57604051636956f2ab60e11b815260040160405180910390fd5b60007f0000000000000000000000000ec274490c0b60efa74fdfce62a777c90e1bced46001600160a01b03163460405160006040518083038185875af1925050503d8060008114610e9a576040519150601f19603f3d011682016040523d82523d6000602084013e610e9f565b606091505b5050905080610ec1576040516312171d8360e31b815260040160405180910390fd5b50505b5050505050505050565b610ed83382611c8a565b610ef45760405162461bcd60e51b815260040161084c90612e30565b6108ed838383611ce9565b6000828152600a602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092528291610f745750604080518082019091526009546001600160a01b0381168252600160a01b90046001600160601b031660208201525b602081015160009061271090610f93906001600160601b031687612e19565b610f9d9190612e7d565b91519350909150505b9250929050565b6108ed83838360405180602001604052806000815250611290565b610fd06119bd565b6000819003610ff257604051633ba0191160e01b815260040160405180910390fd5b600e6108ed828483612ee6565b6110076119bd565b6108ed838383611e62565b6000818152600260205260408120546001600160a01b0316806107035760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161084c565b6001600160a01b03821660009081526011602052604081208183600681111561109d5761109d612d1b565b60068111156110ae576110ae612d1b565b815260200190815260200160002054905092915050565b60006001600160a01b03821661112f5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840161084c565b506001600160a01b031660009081526003602052604090205490565b611153611ebc565b61115d6000611f16565b565b60606007805461072e90612c03565b6111766119bd565b60088054821515600160a81b0260ff60a81b199091161790556040517f6787c7f9a80aa0f5ceddab2c54f1f5169c0b88e75dd5e19d5e858a64144c7dbc906111c390831515815260200190565b60405180910390a150565b61071b338383611f68565b6111e16119bd565b6001600160a01b038116803b151590158015906111fc575080155b1561121a576040516332483afb60e01b815260040160405180910390fd5b7fcc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac6112436108f2565b604080516001600160a01b03928316815291851660208301520160405180910390a150600880546001600160a01b03909216610100026001600160a81b0319909216919091176001179055565b61129a3383611c8a565b6112b65760405162461bcd60e51b815260040161084c90612e30565b6112c28484848461202e565b50505050565b60606112d382611a1a565b60006112dd612061565b905060008151116112fd5760405180602001604052806000815250611328565b8061130784612070565b604051602001611318929190612fa5565b6040516020818303038152906040525b9392505050565b6001600160a01b0382811660009081526005602090815260408083209385168352929052205460ff168061070357600854600160a81b900460ff1615610703576113776108f2565b6001600160a01b0316826001600160a01b031614905092915050565b826000036113b45760405163162908e360e11b815260040160405180910390fd5b6000807f0000000000000000000000000032e7f6633d0696ec89c049bf58578c1f84a4d66001600160a01b031663055ad42e6040518163ffffffff1660e01b815260040160e060405180830381865afa158015611415573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114399190612c76565b9092509050600281600681111561145257611452612d1b565b116114705760405163268dbf6760e21b815260040160405180910390fd5b608082015133600090815260116020526040812060ff90921691879184600681111561149e5761149e612d1b565b60068111156114af576114af612d1b565b8152602001908152602001600020546114c89190612d47565b11156114e757604051637ab0312d60e11b815260040160405180910390fd5b61271085600c546114f89190612d47565b11156115175760405163d05cb60960e01b815260040160405180910390fd5b8160a0015161ffff16856010600084600681111561153757611537612d1b565b600681111561154857611548612d1b565b8152602001908152602001600020546115619190612d47565b11156115805760405163d05cb60960e01b815260040160405180910390fd5b600681600681111561159457611594612d1b565b101561166c5760008390036115bc576040516309bde33960e01b815260040160405180910390fd5b60405163f31755b760e01b81526001600160a01b037f0000000000000000000000000032e7f6633d0696ec89c049bf58578c1f84a4d6169063f31755b79061160e908490339089908990600401612d5a565b602060405180830381865afa15801561162b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164f9190612dc9565b61166c57604051630b094f2760e31b815260040160405180910390fd5b60208201516001600160601b0316156116c25760008583602001516001600160601b031661169a9190612e19565b90508034146116bc57604051636956f2ab60e11b815260040160405180910390fd5b506116e1565b34156116e157604051636956f2ab60e11b815260040160405180910390fd5b336000908152601160205260408120869183600681111561170457611704612d1b565b600681111561171557611715612d1b565b815260200190815260200160002060008282546117329190612d47565b909155508590506010600083600681111561174f5761174f612d1b565b600681111561176057611760612d1b565b8152602001908152602001600020600082825461177d9190612d47565b9250508190555084600c60008282546117969190612d47565b909155505060208201516001600160601b0316156118445760007f0000000000000000000000000ec274490c0b60efa74fdfce62a777c90e1bced46001600160a01b03163460405160006040518083038185875af1925050503d806000811461181b576040519150601f19603f3d011682016040523d82523d6000602084013e611820565b606091505b5050905080611842576040516312171d8360e31b815260040160405180910390fd5b505b60005b858110156118785761185b33600d54611ae7565b600d805490600061186b83612fd4565b9091555050600101611847565b505050505050565b611888611ebc565b6001600160a01b0381166118ed5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161084c565b6118f681611f16565b50565b60106020527f853b2fefe141400fef543280f93d98bd49996069f632d0d20236afeeed8e46a254600160009081527f8c6065603763fec3f5742441d3833f3f43b982453612d76adb39a885e3006b5f54909161195491612d47565b905090565b60006010600083600681111561197157611971612d1b565b600681111561198257611982612d1b565b8152602001908152602001600020549050919050565b60006001600160e01b0319821663152a902d60e11b1480610703575061070382612102565b61115d611ebc565b6119cf8282612142565b6040516001600160601b03821681526001600160a01b038316907f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9060200160405180910390a25050565b6000818152600260205260409020546001600160a01b03166118f65760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161084c565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611aae82611012565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6001600160a01b038216611b3d5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161084c565b6000818152600260205260409020546001600160a01b031615611ba25760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161084c565b611bb06000838360016121fc565b6000818152600260205260409020546001600160a01b031615611c155760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161084c565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a461071b60008383600161222a565b600080611c9683611012565b9050806001600160a01b0316846001600160a01b03161480611cbd5750611cbd818561132f565b80611ce15750836001600160a01b0316611cd6846107b1565b6001600160a01b0316145b949350505050565b826001600160a01b0316611cfc82611012565b6001600160a01b031614611d225760405162461bcd60e51b815260040161084c90612fed565b6001600160a01b038216611d845760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161084c565b611d9183838360016121fc565b826001600160a01b0316611da482611012565b6001600160a01b031614611dca5760405162461bcd60e51b815260040161084c90612fed565b600081815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260038552838620805460001901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a46108ed838383600161222a565b611e6d838383612251565b6040516001600160601b03821681526001600160a01b0383169084907f7f5b076c952c0ec86e5425963c1326dd0f03a3595c19f81d765e8ff559a6e33c906020015b60405180910390a3505050565b600b546001600160a01b0316331461115d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161084c565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b031603611fc95760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161084c565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101611eaf565b612039848484611ce9565b6120458484848461231c565b6112c25760405162461bcd60e51b815260040161084c90613032565b6060600e805461072e90612c03565b6060600061207d8361241d565b60010190506000816001600160401b0381111561209c5761209c612a38565b6040519080825280601f01601f1916602001820160405280156120c6576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450846120d057509392505050565b60006001600160e01b03198216632b435fdb60e21b148061213357506001600160e01b0319821663503e914d60e11b145b806107035750610703826124f5565b6127106001600160601b038216111561216d5760405162461bcd60e51b815260040161084c90613084565b6001600160a01b0382166121c35760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c696420726563656976657200000000000000604482015260640161084c565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600955565b60005b818110156122235761221b85856122168487612d47565b612545565b6001016121ff565b5050505050565b60005b818110156122235761224985856122448487612d47565b61259b565b60010161222d565b6127106001600160601b038216111561227c5760405162461bcd60e51b815260040161084c90613084565b6001600160a01b0382166122d25760405162461bcd60e51b815260206004820152601b60248201527f455243323938313a20496e76616c696420706172616d65746572730000000000604482015260640161084c565b6040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182526000968752600a90529190942093519051909116600160a01b029116179055565b60006001600160a01b0384163b1561241257604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906123609033908990889088906004016130ce565b6020604051808303816000875af192505050801561239b575060408051601f3d908101601f191682019092526123989181019061310b565b60015b6123f8573d8080156123c9576040519150601f19603f3d011682016040523d82523d6000602084013e6123ce565b606091505b5080516000036123f05760405162461bcd60e51b815260040161084c90613032565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611ce1565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061245c5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612488576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106124a657662386f26fc10000830492506010015b6305f5e10083106124be576305f5e100830492506008015b61271083106124d257612710830492506004015b606483106124e4576064830492506002015b600a83106107035760010192915050565b60006001600160e01b031982166380ac58cd60e01b148061252657506001600160e01b03198216635b5e139f60e01b145b8061070357506301ffc9a760e01b6001600160e01b0319831614610703565b6001600160a01b03838116159083161581801561255f5750805b1561257d57604051635cbd944160e01b815260040160405180910390fd5b8115612589575b612223565b806125845761222333868686346125e2565b6001600160a01b0383811615908316158180156125b55750805b156125d357604051635cbd944160e01b815260040160405180910390fd5b81612584578061258457612223565b60006125ec6108f2565b90506001600160a01b03811615611878576001600160a01b03811633036126135750612223565b60405163657711f560e11b81526001600160a01b038781166004830152868116602483015285811660448301526064820185905282169063caee23ea9060840160006040518083038186803b15801561266b57600080fd5b505afa158015610ec1573d6000803e3d6000fd5b6001600160e01b0319811681146118f657600080fd5b6000602082840312156126a757600080fd5b81356113288161267f565b6001600160a01b03811681146118f657600080fd5b6001600160601b03811681146118f657600080fd5b600080604083850312156126ef57600080fd5b82356126fa816126b2565b9150602083013561270a816126c7565b809150509250929050565b60005b83811015612730578181015183820152602001612718565b50506000910152565b60008151808452612751816020860160208601612715565b601f01601f19169290920160200192915050565b6020815260006113286020830184612739565b60006020828403121561278a57600080fd5b5035919050565b600080604083850312156127a457600080fd5b82356127af816126b2565b946020939093013593505050565b60008083601f8401126127cf57600080fd5b5081356001600160401b038111156127e657600080fd5b6020830191508360208260051b8501011115610fa657600080fd5b6000806000806040858703121561281757600080fd5b84356001600160401b0381111561282d57600080fd5b612839878288016127bd565b90955093505060208501356001600160401b0381111561285857600080fd5b612864878288016127bd565b95989497509550505050565b60008060006060848603121561288557600080fd5b8335612890816126b2565b925060208401356128a0816126b2565b929592945050506040919091013590565b600080604083850312156128c457600080fd5b50508035926020909101359150565b600080602083850312156128e657600080fd5b82356001600160401b038111156128fc57600080fd5b8301601f8101851361290d57600080fd5b80356001600160401b0381111561292357600080fd5b85602082840101111561293557600080fd5b6020919091019590945092505050565b60008060006060848603121561295a57600080fd5b83359250602084013561296c816126b2565b9150604084013561297c816126c7565b809150509250925092565b600781106118f657600080fd5b600080604083850312156129a757600080fd5b82356129b2816126b2565b9150602083013561270a81612987565b6000602082840312156129d457600080fd5b8135611328816126b2565b80151581146118f657600080fd5b6000602082840312156129ff57600080fd5b8135611328816129df565b60008060408385031215612a1d57600080fd5b8235612a28816126b2565b9150602083013561270a816129df565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715612a7057612a70612a38565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612a9e57612a9e612a38565b604052919050565b60008060008060808587031215612abc57600080fd5b8435612ac7816126b2565b93506020850135612ad7816126b2565b92506040850135915060608501356001600160401b03811115612af957600080fd5b8501601f81018713612b0a57600080fd5b80356001600160401b03811115612b2357612b23612a38565b612b36601f8201601f1916602001612a76565b818152886020838501011115612b4b57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600060208284031215612b7f57600080fd5b813561132881612987565b60008060408385031215612b9d57600080fd5b8235612ba8816126b2565b9150602083013561270a816126b2565b600080600060408486031215612bcd57600080fd5b8335925060208401356001600160401b03811115612bea57600080fd5b612bf6868287016127bd565b9497909650939450505050565b600181811c90821680612c1757607f821691505b602082108103612c3757634e487b7160e01b600052602260045260246000fd5b50919050565b80516001600160401b0381168114612c5457600080fd5b919050565b805161ffff81168114612c5457600080fd5b8051612c5481612987565b60008082840360e0811215612c8a57600080fd5b60c0811215612c9857600080fd5b50612ca1612a4e565b835181526020840151612cb3816126c7565b6020820152612cc460408501612c3d565b6040820152612cd560608501612c3d565b6060820152608084015160ff81168114612cee57600080fd5b6080820152612cff60a08501612c59565b60a08201529150612d1260c08401612c6b565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561070357610703612d31565b600060078610612d7a57634e487b7160e01b600052602160045260246000fd5b8582526001600160a01b038516602083015260606040830181905282018390526001600160fb1b03831115612dae57600080fd5b8260051b808560808501379190910160800195945050505050565b600060208284031215612ddb57600080fd5b8151611328816129df565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612e0e57600080fd5b8151611328816126b2565b808202811582820484141761070357610703612d31565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b600082612e9a57634e487b7160e01b600052601260045260246000fd5b500490565b601f8211156108ed57806000526020600020601f840160051c81016020851015612ec65750805b601f840160051c820191505b818110156122235760008155600101612ed2565b6001600160401b03831115612efd57612efd612a38565b612f1183612f0b8354612c03565b83612e9f565b6000601f841160018114612f455760008515612f2d5750838201355b600019600387901b1c1916600186901b178355612223565b600083815260209020601f19861690835b82811015612f765786850135825560209485019460019092019101612f56565b5086821015612f935760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008351612fb7818460208801612715565b835190830190612fcb818360208801612715565b01949350505050565b600060018201612fe657612fe6612d31565b5060010190565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252602a908201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646040820152692073616c65507269636560b01b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061310190830184612739565b9695505050505050565b60006020828403121561311d57600080fd5b81516113288161267f56fea26469706673582212201d6985df8d2906dd48dc614fb509c3c604845d84fc68b6054a73a9a1fe91a99b64736f6c634300081c0033

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

0000000000000000000000000ec274490c0b60efa74fdfce62a777c90e1bced400000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000008954f7a8eb01e94efb10d610837f115fe95aafb10000000000000000000000000032e7f6633d0696ec89c049bf58578c1f84a4d6000000000000000000000000000000000000000000000000000000000000000c52494c4c415a204445504958000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054445504958000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : royaltyReceiver_ (address): 0x0eC274490C0B60EfA74FDFce62A777c90E1BceD4
Arg [1] : royaltyFeeNumerator_ (uint96): 500
Arg [2] : name_ (string): RILLAZ DEPIX
Arg [3] : symbol_ (string): DEPIX
Arg [4] : rillaz_ (address): 0x8954f7a8Eb01e94EfB10d610837f115Fe95aafb1
Arg [5] : phaseManager_ (address): 0x0032e7f6633d0696Ec89c049bf58578C1F84A4d6

-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 0000000000000000000000000ec274490c0b60efa74fdfce62a777c90e1bced4
Arg [1] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [4] : 0000000000000000000000008954f7a8eb01e94efb10d610837f115fe95aafb1
Arg [5] : 0000000000000000000000000032e7f6633d0696ec89c049bf58578c1f84a4d6
Arg [6] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [7] : 52494c4c415a2044455049580000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [9] : 4445504958000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

98351:6068:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67651:104;;;;;;;;;;;;67712:42;67651:104;;;;;-1:-1:-1;;;;;178:32:1;;;160:51;;148:2;133:18;67651:104:0;;;;;;;;103708:187;;;;;;;;;;-1:-1:-1;103708:187:0;;;;;:::i;:::-;;:::i;:::-;;;773:14:1;;766:22;748:41;;736:2;721:18;103708:187:0;608::1;102914:176:0;;;;;;;;;;-1:-1:-1;102914:176:0;;;;;:::i;:::-;;:::i;:::-;;90548:108;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;76541:171::-;;;;;;;;;;-1:-1:-1;76541:171:0;;;;;:::i;:::-;;:::i;76059:416::-;;;;;;;;;;-1:-1:-1;76059:416:0;;;;;:::i;:::-;;:::i;69269:298::-;;;;;;;;;;;;;:::i;93866:252::-;;;;;;;;;;-1:-1:-1;93866:252:0;;;-1:-1:-1;;;2994:52:1;;94106:4:0;3077:2:1;3062:18;;3055:50;2967:18;93866:252:0;2828:283:1;104155:94:0;;;;;;;;;;-1:-1:-1;104228:13:0;;104155:94;;;3262:25:1;;;3250:2;3235:18;104155:94:0;3116:177:1;99650:1583:0;;;;;;:::i;:::-;;:::i;77241:335::-;;;;;;;;;;-1:-1:-1;77241:335:0;;;;;:::i;:::-;;:::i;59285:442::-;;;;;;;;;;-1:-1:-1;59285:442:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;5499:32:1;;;5481:51;;5563:2;5548:18;;5541:34;;;;5454:18;59285:442:0;5307:274:1;77647:185:0;;;;;;;;;;-1:-1:-1;77647:185:0;;;;;:::i;:::-;;:::i;103338:199::-;;;;;;;;;;-1:-1:-1;103338:199:0;;;;;:::i;:::-;;:::i;103098:232::-;;;;;;;;;;-1:-1:-1;103098:232:0;;;;;:::i;:::-;;:::i;98855:75::-;;;;;;;;;;-1:-1:-1;98855:75:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;55935:45;;;;;;;;;;-1:-1:-1;55935:45:0;;;;-1:-1:-1;;;55935:45:0;;;;;;74739:223;;;;;;;;;;-1:-1:-1;74739:223:0;;;;;:::i;:::-;;:::i;104257:159::-;;;;;;;;;;-1:-1:-1;104257:159:0;;;;;:::i;:::-;;:::i;74470:207::-;;;;;;;;;;-1:-1:-1;74470:207:0;;;;;:::i;:::-;;:::i;45143:103::-;;;;;;;;;;;;;:::i;98631:28::-;;;;;;;;;;;;;;;;44495:87;;;;;;;;;;-1:-1:-1;44568:6:0;;-1:-1:-1;;;;;44568:6:0;44495:87;;90664:112;;;;;;;;;;;;;:::i;56360:257::-;;;;;;;;;;-1:-1:-1;56360:257:0;;;;;:::i;:::-;;:::i;76784:155::-;;;;;;;;;;-1:-1:-1;76784:155:0;;;;;:::i;:::-;;:::i;68610:544::-;;;;;;;;;;-1:-1:-1;68610:544:0;;;;;:::i;:::-;;:::i;77903:322::-;;;;;;;;;;-1:-1:-1;77903:322:0;;;;;:::i;:::-;;:::i;75373:281::-;;;;;;;;;;-1:-1:-1;75373:281:0;;;;;:::i;:::-;;:::i;98666:35::-;;;;;;;;;;;;;;;;98797:51;;;;;;;;;;-1:-1:-1;98797:51:0;;;;;:::i;:::-;;;;;;;;;;;;;;92733:370;;;;;;;;;;-1:-1:-1;92733:370:0;;;;;:::i;:::-;;:::i;101241:1665::-;;;;;;:::i;:::-;;:::i;45401:201::-;;;;;;;;;;-1:-1:-1;45401:201:0;;;;;:::i;:::-;;:::i;103545:155::-;;;;;;;;;;;;;:::i;98742:42::-;;;;;;;;;;-1:-1:-1;98742:42:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;104016:131;;;;;;;;;;-1:-1:-1;104016:131:0;;;;;:::i;:::-;;:::i;103708:187::-;103827:4;103851:36;103875:11;103851:23;:36::i;:::-;103844:43;103708:187;-1:-1:-1;;103708:187:0:o;102914:176::-;102998:31;:29;:31::i;:::-;103040:42;103059:8;103069:12;103040:18;:42::i;:::-;102914:176;;:::o;90548:108::-;90602:13;90635;90628:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90548:108;:::o;76541:171::-;76617:7;76637:23;76652:7;76637:14;:23::i;:::-;-1:-1:-1;76680:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;76680:24:0;;76541:171::o;76059:416::-;76140:13;76156:23;76171:7;76156:14;:23::i;:::-;76140:39;;76204:5;-1:-1:-1;;;;;76198:11:0;:2;-1:-1:-1;;;;;76198:11:0;;76190:57;;;;-1:-1:-1;;;76190:57:0;;11870:2:1;76190:57:0;;;11852:21:1;11909:2;11889:18;;;11882:30;11948:34;11928:18;;;11921:62;-1:-1:-1;;;11999:18:1;;;11992:31;12040:19;;76190:57:0;;;;;;;;;13136:10;-1:-1:-1;;;;;76282:21:0;;;;:62;;-1:-1:-1;76307:37:0;76324:5;13136:10;92733:370;:::i;76307:37::-;76260:173;;;;-1:-1:-1;;;76260:173:0;;12272:2:1;76260:173:0;;;12254:21:1;12311:2;12291:18;;;12284:30;12350:34;12330:18;;;12323:62;12421:31;12401:18;;;12394:59;12470:19;;76260:173:0;12070:425:1;76260:173:0;76446:21;76455:2;76459:7;76446:8;:21::i;:::-;76129:346;76059:416;;:::o;69269:298::-;69373:17;;;;;-1:-1:-1;;;;;69373:17:0;;69403:157;;69452:22;;;;69447:102;;-1:-1:-1;67712:42:0;69447:102;69269:298;:::o;99650:1583::-;99796:8;99782:11;99826:8;;;99822:36;;99843:15;;-1:-1:-1;;;99843:15:0;;;;;;;;;;;99822:36;99880:31;99913:19;99936:12;-1:-1:-1;;;;;99936:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99879:84;;-1:-1:-1;99879:84:0;-1:-1:-1;99991:14:0;99978:9;:27;;;;;;;;:::i;:::-;;:64;;;-1:-1:-1;100021:21:0;100009:9;:33;;;;;;;;:::i;:::-;;99978:64;99974:104;;;100065:13;;-1:-1:-1;;;100065:13:0;;;;;;;;;;;99974:104;100145:18;;;;100114:10;100095:30;;;;:18;:30;;;;;:68;;;;;100139:3;;100126:9;100095:41;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:47;;;;:::i;:::-;:68;100091:117;;;100186:22;;-1:-1:-1;;;100186:22:0;;;;;;;;;;;100091:117;98614:4;100238:3;100223:12;:10;:12::i;:::-;:18;;;;:::i;:::-;:36;100219:82;;;100282:19;;-1:-1:-1;;;100282:19:0;;;;;;;;;;;100219:82;100344:70;;-1:-1:-1;;;100344:70:0;;100323:18;;-1:-1:-1;;;;;100344:12:0;:34;;;;:70;;100379:9;;100390:10;;100402:11;;;;100344:70;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100323:91;;100429:13;:31;;;;-1:-1:-1;100446:9:0;:14;;100429:31;100425:74;;;100483:16;;-1:-1:-1;;;100483:16:0;;;;;;;;;;;100425:74;100531:10;100512:30;;;;:18;:30;;;;;100557:3;;100543:9;100512:41;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:48;;;;;;;:::i;:::-;;;;-1:-1:-1;100600:3:0;;-1:-1:-1;100571:14:0;:25;100586:9;100571:25;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:32;;;;;;;:::i;:::-;;;;;;;;100631:3;100614:13;;:20;;;;;;;:::i;:::-;;;;-1:-1:-1;100660:9:0;;-1:-1:-1;100655:281:0;100679:3;100675:1;:7;100655:281;;;100739:10;100708:6;-1:-1:-1;;;;;100708:14:0;;100723:8;;100732:1;100723:11;;;;;;;:::i;:::-;;;;;;;100708:27;;;;;;;;;;;;;3262:25:1;;3250:2;3235:18;;3116:177;100708:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;100708:41:0;;100704:64;;100758:10;;-1:-1:-1;;;100758:10:0;;;;;;;;;;;100704:64;100787:10;:23;100798:8;;100807:1;100798:11;;;;;;;:::i;:::-;;;;;;;;;;100787:23;;-1:-1:-1;100787:23:0;;;;;;;;-1:-1:-1;100787:23:0;;;;100783:51;;;100819:15;;-1:-1:-1;;;100819:15:0;;;;;;;;;;;100783:51;100875:4;100849:10;:23;100860:8;;100869:1;100860:11;;;;;;;:::i;:::-;;;;;;;100849:23;;;;;;;;;;;;:30;;;;;;;;;;;;;;;;;;100894;100900:10;100912:8;;100921:1;100912:11;;;;;;;:::i;:::-;;;;;;;100894:5;:30::i;:::-;100684:3;;100655:281;;;;100951:13;100946:280;;100981:16;101014:3;101000:5;:11;;;-1:-1:-1;;;;;101000:17:0;;;;;:::i;:::-;100981:36;;101049:8;101036:9;:21;101032:50;;101066:16;;-1:-1:-1;;;101066:16:0;;;;;;;;;;;101032:50;101098:12;101116:19;-1:-1:-1;;;;;101116:24:0;101148:9;101116:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101097:65;;;101182:7;101177:37;;101198:16;;-1:-1:-1;;;101198:16:0;;;;;;;;;;;101177:37;100966:260;;100946:280;99771:1462;;;;99650:1583;;;;:::o;77241:335::-;77436:41;13136:10;77469:7;77436:18;:41::i;:::-;77428:99;;;;-1:-1:-1;;;77428:99:0;;;;;;;:::i;:::-;77540:28;77550:4;77556:2;77560:7;77540:9;:28::i;59285:442::-;59382:7;59440:27;;;:17;:27;;;;;;;;59411:56;;;;;;;;;-1:-1:-1;;;;;59411:56:0;;;;;-1:-1:-1;;;59411:56:0;;;-1:-1:-1;;;;;59411:56:0;;;;;;;;59382:7;;59480:92;;-1:-1:-1;59531:29:0;;;;;;;;;59541:19;59531:29;-1:-1:-1;;;;;59531:29:0;;;;-1:-1:-1;;;59531:29:0;;-1:-1:-1;;;;;59531:29:0;;;;;59480:92;59622:23;;;;59584:21;;60093:5;;59609:36;;-1:-1:-1;;;;;59609:36:0;:10;:36;:::i;:::-;59608:58;;;;:::i;:::-;59687:16;;;-1:-1:-1;59584:82:0;;-1:-1:-1;;59285:442:0;;;;;;:::o;77647:185::-;77785:39;77802:4;77808:2;77812:7;77785:39;;;;;;;;;;;;:16;:39::i;103338:199::-;103403:31;:29;:31::i;:::-;103474:1;103449:26;;;103445:51;;103484:12;;-1:-1:-1;;;103484:12:0;;;;;;;;;;;103445:51;103507:12;:22;103522:7;;103507:12;:22;:::i;103098:232::-;103231:31;:29;:31::i;:::-;103273:49;103290:7;103299:8;103309:12;103273:16;:49::i;74739:223::-;74811:7;79626:16;;;:7;:16;;;;;;-1:-1:-1;;;;;79626:16:0;;74875:56;;;;-1:-1:-1;;;74875:56:0;;19195:2:1;74875:56:0;;;19177:21:1;19234:2;19214:18;;;19207:30;-1:-1:-1;;;19253:18:1;;;19246:54;19317:18;;74875:56:0;18993:348:1;104257:159:0;-1:-1:-1;;;;;104373:24:0;;104346:7;104373:24;;;:18;:24;;;;;104346:7;104398:9;104373:35;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;104366:42;;104257:159;;;;:::o;74470:207::-;74542:7;-1:-1:-1;;;;;74570:19:0;;74562:73;;;;-1:-1:-1;;;74562:73:0;;19548:2:1;74562:73:0;;;19530:21:1;19587:2;19567:18;;;19560:30;19626:34;19606:18;;;19599:62;-1:-1:-1;;;19677:18:1;;;19670:39;19726:19;;74562:73:0;19346:405:1;74562:73:0;-1:-1:-1;;;;;;74653:16:0;;;;;:9;:16;;;;;;;74470:207::o;45143:103::-;44381:13;:11;:13::i;:::-;45208:30:::1;45235:1;45208:18;:30::i;:::-;45143:103::o:0;90664:112::-;90720:13;90753:15;90746:22;;;;;:::i;56360:257::-;56452:31;:29;:31::i;:::-;56494:33;:47;;;;;-1:-1:-1;;;56494:47:0;-1:-1:-1;;;;56494:47:0;;;;;;56557:52;;;;;;56530:11;773:14:1;766:22;748:41;;736:2;721:18;;608:187;56557:52:0;;;;;;;;56360:257;:::o;76784:155::-;76879:52;13136:10;76912:8;76922;76879:18;:52::i;68610:544::-;68686:31;:29;:31::i;:::-;-1:-1:-1;;;;;68762:30:0;;;;:34;;;68812:32;;;;:61;;;68849:24;68848:25;68812:61;68809:152;;;68897:52;;-1:-1:-1;;;68897:52:0;;;;;;;;;;;68809:152;68978:77;69011:22;:20;:22::i;:::-;68978:77;;;-1:-1:-1;;;;;19948:32:1;;;19930:51;;20017:32;;;20012:2;19997:18;;19990:60;19903:18;68978:77:0;;;;;;;-1:-1:-1;69068:22:0;:29;;-1:-1:-1;;;;;69108:38:0;;;69068:29;69108:38;-1:-1:-1;;;;;;69108:38:0;;;;;;;69093:4;69108:38;;;68610:544::o;77903:322::-;78077:41;13136:10;78110:7;78077:18;:41::i;:::-;78069:99;;;;-1:-1:-1;;;78069:99:0;;;;;;;:::i;:::-;78179:38;78193:4;78199:2;78203:7;78212:4;78179:13;:38::i;:::-;77903:322;;;;:::o;75373:281::-;75446:13;75472:23;75487:7;75472:14;:23::i;:::-;75508:21;75532:10;:8;:10::i;:::-;75508:34;;75584:1;75566:7;75560:21;:25;:86;;;;;;;;;;;;;;;;;75612:7;75621:18;:7;:16;:18::i;:::-;75595:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;75560:86;75553:93;75373:281;-1:-1:-1;;;75373:281:0:o;92733:370::-;-1:-1:-1;;;;;77131:25:0;;;92830:15;77131:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;92923:173;;92959:33;;-1:-1:-1;;;92959:33:0;;;;92955:130;;;93046:22;:20;:22::i;:::-;-1:-1:-1;;;;;93026:43:0;:8;-1:-1:-1;;;;;93026:43:0;;93013:56;;92733:370;;;;:::o;101241:1665::-;101366:6;101376:1;101366:11;101362:39;;101386:15;;-1:-1:-1;;;101386:15:0;;;;;;;;;;;101362:39;101413:31;101446:19;101469:12;-1:-1:-1;;;;;101469:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101412:84;;-1:-1:-1;101412:84:0;-1:-1:-1;101524:21:0;101511:9;:34;;;;;;;;:::i;:::-;;101507:61;;101554:14;;-1:-1:-1;;;101554:14:0;;;;;;;;;;;101507:61;101646:18;;;;101612:10;101593:30;;;;:18;:30;;;;;:71;;;;;101637:6;;101624:9;101593:41;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:50;;;;:::i;:::-;:71;101589:120;;;101687:22;;-1:-1:-1;;;101687:22:0;;;;;;;;;;;101589:120;98567:5;101740:6;101724:13;;:22;;;;:::i;:::-;:35;101720:80;;;101782:18;;-1:-1:-1;;;101782:18:0;;;;;;;;;;;101720:80;101852:5;:23;;;101815:60;;101843:6;101815:14;:25;101830:9;101815:25;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:34;;;;:::i;:::-;:60;101811:104;;;101897:18;;-1:-1:-1;;;101897:18:0;;;;;;;;;;;101811:104;101944:21;101932:9;:33;;;;;;;;:::i;:::-;;101928:249;;;102008:1;101986:23;;;101982:50;;102018:14;;-1:-1:-1;;;102018:14:0;;;;;;;;;;;101982:50;102052:70;;-1:-1:-1;;;102052:70:0;;-1:-1:-1;;;;;102052:12:0;:34;;;;:70;;102087:9;;102098:10;;102110:11;;;;102052:70;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102047:118;;102149:16;;-1:-1:-1;;;102149:16:0;;;;;;;;;;;102047:118;102193:11;;;;-1:-1:-1;;;;;102193:15:0;;102189:228;;102225:16;102258:6;102244:5;:11;;;-1:-1:-1;;;;;102244:20:0;;;;;:::i;:::-;102225:39;;102296:8;102283:9;:21;102279:50;;102313:16;;-1:-1:-1;;;102313:16:0;;;;;;;;;;;102279:50;102210:131;102189:228;;;102366:9;:14;102362:43;;102389:16;;-1:-1:-1;;;102389:16:0;;;;;;;;;;;102362:43;102473:10;102454:30;;;;:18;:30;;;;;102499:6;;102485:9;102454:41;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:51;;;;;;;:::i;:::-;;;;-1:-1:-1;102545:6:0;;-1:-1:-1;102516:14:0;:25;102531:9;102516:25;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:35;;;;;;;:::i;:::-;;;;;;;;102579:6;102562:13;;:23;;;;;;;:::i;:::-;;;;-1:-1:-1;;102602:11:0;;;;-1:-1:-1;;;;;102602:15:0;;102598:165;;102635:12;102653:19;-1:-1:-1;;;;;102653:24:0;102685:9;102653:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102634:65;;;102719:7;102714:37;;102735:16;;-1:-1:-1;;;102735:16:0;;;;;;;;;;;102714:37;102619:144;102598:165;102780:9;102775:124;102799:6;102795:1;:10;102775:124;;;102827:31;102833:10;102845:12;;102827:5;:31::i;:::-;102873:12;:14;;;:12;:14;;;:::i;:::-;;;;-1:-1:-1;;102807:3:0;;102775:124;;;;101351:1555;;101241:1665;;;:::o;45401:201::-;44381:13;:11;:13::i;:::-;-1:-1:-1;;;;;45490:22:0;::::1;45482:73;;;::::0;-1:-1:-1;;;45482:73:0;;20904:2:1;45482:73:0::1;::::0;::::1;20886:21:1::0;20943:2;20923:18;;;20916:30;20982:34;20962:18;;;20955:62;-1:-1:-1;;;21033:18:1;;;21026:36;21079:19;;45482:73:0::1;20702:402:1::0;45482:73:0::1;45566:28;45585:8;45566:18;:28::i;:::-;45401:201:::0;:::o;103545:155::-;103655:14;:37;;;;103630:21;103588:7;103615:37;;;;;103588:7;;103615:77;;;:::i;:::-;103608:84;;103545:155;:::o;104016:131::-;104087:7;104114:14;:25;104129:9;104114:25;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;104107:32;;104016:131;;;:::o;59015:215::-;59117:4;-1:-1:-1;;;;;;59141:41:0;;-1:-1:-1;;;59141:41:0;;:81;;;59186:36;59210:11;59186:23;:36::i;57544:104::-;57627:13;:11;:13::i;62282:217::-;62386:48;62411:8;62421:12;62386:24;:48::i;:::-;62450:41;;-1:-1:-1;;;;;21271:39:1;;21253:58;;-1:-1:-1;;;;;62450:41:0;;;;;21241:2:1;21226:18;62450:41:0;;;;;;;62282:217;;:::o;86360:135::-;80028:4;79626:16;;;:7;:16;;;;;;-1:-1:-1;;;;;79626:16:0;86434:53;;;;-1:-1:-1;;;86434:53:0;;19195:2:1;86434:53:0;;;19177:21:1;19234:2;19214:18;;;19207:30;-1:-1:-1;;;19253:18:1;;;19246:54;19317:18;;86434:53:0;18993:348:1;85639:174:0;85714:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;85714:29:0;-1:-1:-1;;;;;85714:29:0;;;;;;;;:24;;85768:23;85714:24;85768:14;:23::i;:::-;-1:-1:-1;;;;;85759:46:0;;;;;;;;;;;85639:174;;:::o;81856:942::-;-1:-1:-1;;;;;81936:16:0;;81928:61;;;;-1:-1:-1;;;81928:61:0;;21524:2:1;81928:61:0;;;21506:21:1;;;21543:18;;;21536:30;21602:34;21582:18;;;21575:62;21654:18;;81928:61:0;21322:356:1;81928:61:0;80028:4;79626:16;;;:7;:16;;;;;;-1:-1:-1;;;;;79626:16:0;80052:31;82000:58;;;;-1:-1:-1;;;82000:58:0;;21885:2:1;82000:58:0;;;21867:21:1;21924:2;21904:18;;;21897:30;21963;21943:18;;;21936:58;22011:18;;82000:58:0;21683:352:1;82000:58:0;82071:48;82100:1;82104:2;82108:7;82117:1;82071:20;:48::i;:::-;80028:4;79626:16;;;:7;:16;;;;;;-1:-1:-1;;;;;79626:16:0;80052:31;82209:58;;;;-1:-1:-1;;;82209:58:0;;21885:2:1;82209:58:0;;;21867:21:1;21924:2;21904:18;;;21897:30;21963;21943:18;;;21936:58;22011:18;;82209:58:0;21683:352:1;82209:58:0;-1:-1:-1;;;;;82616:13:0;;;;;;:9;:13;;;;;;;;:18;;82633:1;82616:18;;;82658:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;82658:21:0;;;;;82697:33;82666:7;;82616:13;;82697:33;;82616:13;;82697:33;82743:47;82771:1;82775:2;82779:7;82788:1;82743:19;:47::i;80258:264::-;80351:4;80368:13;80384:23;80399:7;80384:14;:23::i;:::-;80368:39;;80437:5;-1:-1:-1;;;;;80426:16:0;:7;-1:-1:-1;;;;;80426:16:0;;:52;;;;80446:32;80463:5;80470:7;80446:16;:32::i;:::-;80426:87;;;;80506:7;-1:-1:-1;;;;;80482:31:0;:20;80494:7;80482:11;:20::i;:::-;-1:-1:-1;;;;;80482:31:0;;80426:87;80418:96;80258:264;-1:-1:-1;;;;80258:264:0:o;84257:1263::-;84416:4;-1:-1:-1;;;;;84389:31:0;:23;84404:7;84389:14;:23::i;:::-;-1:-1:-1;;;;;84389:31:0;;84381:81;;;;-1:-1:-1;;;84381:81:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;84481:16:0;;84473:65;;;;-1:-1:-1;;;84473:65:0;;22648:2:1;84473:65:0;;;22630:21:1;22687:2;22667:18;;;22660:30;22726:34;22706:18;;;22699:62;-1:-1:-1;;;22777:18:1;;;22770:34;22821:19;;84473:65:0;22446:400:1;84473:65:0;84551:42;84572:4;84578:2;84582:7;84591:1;84551:20;:42::i;:::-;84723:4;-1:-1:-1;;;;;84696:31:0;:23;84711:7;84696:14;:23::i;:::-;-1:-1:-1;;;;;84696:31:0;;84688:81;;;;-1:-1:-1;;;84688:81:0;;;;;;;:::i;:::-;84841:24;;;;:15;:24;;;;;;;;84834:31;;-1:-1:-1;;;;;;84834:31:0;;;;;;-1:-1:-1;;;;;85317:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;85317:20:0;;;85352:13;;;;;;;;;:18;;84834:31;85352:18;;;85392:16;;;:7;:16;;;;;;:21;;;;;;;;;;85431:27;;84857:7;;85431:27;;;85471:41;85491:4;85497:2;85501:7;85510:1;85471:19;:41::i;62507:246::-;62626:55;62649:7;62658:8;62668:12;62626:22;:55::i;:::-;62697:48;;-1:-1:-1;;;;;21271:39:1;;21253:58;;-1:-1:-1;;;;;62697:48:0;;;62713:7;;62697:48;;21241:2:1;21226:18;62697:48:0;;;;;;;;62507:246;;;:::o;44660:132::-;44568:6;;-1:-1:-1;;;;;44568:6:0;13136:10;44724:23;44716:68;;;;-1:-1:-1;;;44716:68:0;;23053:2:1;44716:68:0;;;23035:21:1;;;23072:18;;;23065:30;23131:34;23111:18;;;23104:62;23183:18;;44716:68:0;22851:356:1;45762:191:0;45855:6;;;-1:-1:-1;;;;;45872:17:0;;;-1:-1:-1;;;;;;45872:17:0;;;;;;;45905:40;;45855:6;;;45872:17;45855:6;;45905:40;;45836:16;;45905:40;45825:128;45762:191;:::o;85956:315::-;86111:8;-1:-1:-1;;;;;86102:17:0;:5;-1:-1:-1;;;;;86102:17:0;;86094:55;;;;-1:-1:-1;;;86094:55:0;;23414:2:1;86094:55:0;;;23396:21:1;23453:2;23433:18;;;23426:30;23492:27;23472:18;;;23465:55;23537:18;;86094:55:0;23212:349:1;86094:55:0;-1:-1:-1;;;;;86160:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;86160:46:0;;;;;;;;;;86222:41;;748::1;;;86222::0;;721:18:1;86222:41:0;608:187:1;79106:313:0;79262:28;79272:4;79278:2;79282:7;79262:9;:28::i;:::-;79309:47;79332:4;79338:2;79342:7;79351:4;79309:22;:47::i;:::-;79301:110;;;;-1:-1:-1;;;79301:110:0;;;;;;;:::i;103903:105::-;103955:13;103988:12;103981:19;;;;;:::i;52318:716::-;52374:13;52425:14;52442:17;52453:5;52442:10;:17::i;:::-;52462:1;52442:21;52425:38;;52478:20;52512:6;-1:-1:-1;;;;;52501:18:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52501:18:0;-1:-1:-1;52478:41:0;-1:-1:-1;52643:28:0;;;52659:2;52643:28;52700:288;-1:-1:-1;;52732:5:0;-1:-1:-1;;;52869:2:0;52858:14;;52853:30;52732:5;52840:44;52930:2;52921:11;;;-1:-1:-1;52951:21:0;52700:288;52951:21;-1:-1:-1;53009:6:0;52318:716;-1:-1:-1;;;52318:716:0:o;93397:289::-;93482:4;-1:-1:-1;;;;;;93516:46:0;;-1:-1:-1;;;93516:46:0;;:112;;-1:-1:-1;;;;;;;93576:52:0;;-1:-1:-1;;;93576:52:0;93516:112;:162;;;;93642:36;93666:11;93642:23;:36::i;60377:332::-;60093:5;-1:-1:-1;;;;;60480:33:0;;;;60472:88;;;;-1:-1:-1;;;60472:88:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;60579:22:0;;60571:60;;;;-1:-1:-1;;;60571:60:0;;24598:2:1;60571:60:0;;;24580:21:1;24637:2;24617:18;;;24610:30;24676:27;24656:18;;;24649:55;24721:18;;60571:60:0;24396:349:1;60571:60:0;60666:35;;;;;;;;;-1:-1:-1;;;;;60666:35:0;;;;;;-1:-1:-1;;;;;60666:35:0;;;;;;;;;;-1:-1:-1;;;60644:57:0;;;;:19;:57;60377:332::o;94232:354::-;94408:9;94403:176;94427:9;94423:1;:13;94403:176;;;94454:51;94478:4;94484:2;94488:16;94503:1;94488:12;:16;:::i;:::-;94454:23;:51::i;:::-;94549:3;;94403:176;;;;94232:354;;;;:::o;94699:352::-;94874:9;94869:175;94893:9;94889:1;:13;94869:175;;;94920:50;94943:4;94949:2;94953:16;94968:1;94953:12;:16;:::i;:::-;94920:22;:50::i;:::-;95014:3;;94869:175;;61160:390;60093:5;-1:-1:-1;;;;;61312:33:0;;;;61304:88;;;;-1:-1:-1;;;61304:88:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;61411:22:0;;61403:62;;;;-1:-1:-1;;;61403:62:0;;24952:2:1;61403:62:0;;;24934:21:1;24991:2;24971:18;;;24964:30;25030:29;25010:18;;;25003:57;25077:18;;61403:62:0;24750:351:1;61403:62:0;61507:35;;;;;;;;-1:-1:-1;;;;;61507:35:0;;;;;-1:-1:-1;;;;;61507:35:0;;;;;;;;;;-1:-1:-1;61478:26:0;;;:17;:26;;;;;;:64;;;;;;;-1:-1:-1;;;61478:64:0;;;;;;61160:390::o;87059:853::-;87213:4;-1:-1:-1;;;;;87234:13:0;;4499:19;:23;87230:675;;87270:71;;-1:-1:-1;;;87270:71:0;;-1:-1:-1;;;;;87270:36:0;;;;;:71;;13136:10;;87321:4;;87327:7;;87336:4;;87270:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;87270:71:0;;;;;;;;-1:-1:-1;;87270:71:0;;;;;;;;;;;;:::i;:::-;;;87266:584;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87511:6;:13;87528:1;87511:18;87507:328;;87554:60;;-1:-1:-1;;;87554:60:0;;;;;;;:::i;87507:328::-;87785:6;87779:13;87770:6;87766:2;87762:15;87755:38;87266:584;-1:-1:-1;;;;;;87392:51:0;-1:-1:-1;;;87392:51:0;;-1:-1:-1;87385:58:0;;87230:675;-1:-1:-1;87889:4:0;87059:853;;;;;;:::o;33853:922::-;33906:7;;-1:-1:-1;;;33984:15:0;;33980:102;;-1:-1:-1;;;34020:15:0;;;-1:-1:-1;34064:2:0;34054:12;33980:102;34109:6;34100:5;:15;34096:102;;34145:6;34136:15;;;-1:-1:-1;34180:2:0;34170:12;34096:102;34225:6;34216:5;:15;34212:102;;34261:6;34252:15;;;-1:-1:-1;34296:2:0;34286:12;34212:102;34341:5;34332;:14;34328:99;;34376:5;34367:14;;;-1:-1:-1;34410:1:0;34400:11;34328:99;34454:5;34445;:14;34441:99;;34489:5;34480:14;;;-1:-1:-1;34523:1:0;34513:11;34441:99;34567:5;34558;:14;34554:99;;34602:5;34593:14;;;-1:-1:-1;34636:1:0;34626:11;34554:99;34680:5;34671;:14;34667:66;;34716:1;34706:11;34761:6;33853:922;-1:-1:-1;;33853:922:0:o;74101:305::-;74203:4;-1:-1:-1;;;;;;74240:40:0;;-1:-1:-1;;;74240:40:0;;:105;;-1:-1:-1;;;;;;;74297:48:0;;-1:-1:-1;;;74297:48:0;74240:105;:158;;;-1:-1:-1;;;;;;;;;;55162:40:0;;;74362:36;55053:157;37740:623;-1:-1:-1;;;;;37867:18:0;;;;;37917:16;;;37867:18;37949:32;;;;;37968:13;37949:32;37946:410;;;38005:28;;-1:-1:-1;;;38005:28:0;;;;;;;;;;;37946:410;38054:15;38051:305;;;38086:54;38051:305;;;38161:13;38191:56;38158:198;38280:64;13136:10;38315:4;38321:2;38325:7;38334:9;38280:20;:64::i;38496:625::-;-1:-1:-1;;;;;38622:18:0;;;;;38672:16;;;38622:18;38704:32;;;;;38723:13;38704:32;38701:413;;;38760:28;;-1:-1:-1;;;38760:28:0;;;;;;;;;;;38701:413;38809:15;38841:55;38806:308;38917:13;38947:57;38914:200;39037:65;45401:201::o;70527:472::-;70722:17;70742:22;:20;:22::i;:::-;70722:42;-1:-1:-1;;;;;;70781:23:0;;;70777:215;;-1:-1:-1;;;;;70825:23:0;;:10;:23;70821:70;;70869:7;;;70821:70;70907:73;;-1:-1:-1;;;70907:73:0;;-1:-1:-1;;;;;26099:32:1;;;70907:73:0;;;26081:51:1;26168:32;;;26148:18;;;26141:60;26237:32;;;26217:18;;;26210:60;26286:18;;;26279:34;;;70907:46:0;;;;;26053:19:1;;70907:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;222:131:1;-1:-1:-1;;;;;;296:32:1;;286:43;;276:71;;343:1;340;333:12;358:245;416:6;469:2;457:9;448:7;444:23;440:32;437:52;;;485:1;482;475:12;437:52;524:9;511:23;543:30;567:5;543:30;:::i;800:131::-;-1:-1:-1;;;;;875:31:1;;865:42;;855:70;;921:1;918;911:12;936:137;-1:-1:-1;;;;;1014:5:1;1010:38;1003:5;1000:49;990:77;;1063:1;1060;1053:12;1078:386;1145:6;1153;1206:2;1194:9;1185:7;1181:23;1177:32;1174:52;;;1222:1;1219;1212:12;1174:52;1261:9;1248:23;1280:31;1305:5;1280:31;:::i;:::-;1330:5;-1:-1:-1;1387:2:1;1372:18;;1359:32;1400;1359;1400;:::i;:::-;1451:7;1441:17;;;1078:386;;;;;:::o;1469:250::-;1554:1;1564:113;1578:6;1575:1;1572:13;1564:113;;;1654:11;;;1648:18;1635:11;;;1628:39;1600:2;1593:10;1564:113;;;-1:-1:-1;;1711:1:1;1693:16;;1686:27;1469:250::o;1724:271::-;1766:3;1804:5;1798:12;1831:6;1826:3;1819:19;1847:76;1916:6;1909:4;1904:3;1900:14;1893:4;1886:5;1882:16;1847:76;:::i;:::-;1977:2;1956:15;-1:-1:-1;;1952:29:1;1943:39;;;;1984:4;1939:50;;1724:271;-1:-1:-1;;1724:271:1:o;2000:220::-;2149:2;2138:9;2131:21;2112:4;2169:45;2210:2;2199:9;2195:18;2187:6;2169:45;:::i;2225:226::-;2284:6;2337:2;2325:9;2316:7;2312:23;2308:32;2305:52;;;2353:1;2350;2343:12;2305:52;-1:-1:-1;2398:23:1;;2225:226;-1:-1:-1;2225:226:1:o;2456:367::-;2524:6;2532;2585:2;2573:9;2564:7;2560:23;2556:32;2553:52;;;2601:1;2598;2591:12;2553:52;2640:9;2627:23;2659:31;2684:5;2659:31;:::i;:::-;2709:5;2787:2;2772:18;;;;2759:32;;-1:-1:-1;;;2456:367:1:o;3298:::-;3361:8;3371:6;3425:3;3418:4;3410:6;3406:17;3402:27;3392:55;;3443:1;3440;3433:12;3392:55;-1:-1:-1;3466:20:1;;-1:-1:-1;;;;;3498:30:1;;3495:50;;;3541:1;3538;3531:12;3495:50;3578:4;3570:6;3566:17;3554:29;;3638:3;3631:4;3621:6;3618:1;3614:14;3606:6;3602:27;3598:38;3595:47;3592:67;;;3655:1;3652;3645:12;3670:768;3792:6;3800;3808;3816;3869:2;3857:9;3848:7;3844:23;3840:32;3837:52;;;3885:1;3882;3875:12;3837:52;3925:9;3912:23;-1:-1:-1;;;;;3950:6:1;3947:30;3944:50;;;3990:1;3987;3980:12;3944:50;4029:70;4091:7;4082:6;4071:9;4067:22;4029:70;:::i;:::-;4118:8;;-1:-1:-1;4003:96:1;-1:-1:-1;;4206:2:1;4191:18;;4178:32;-1:-1:-1;;;;;4222:32:1;;4219:52;;;4267:1;4264;4257:12;4219:52;4306:72;4370:7;4359:8;4348:9;4344:24;4306:72;:::i;:::-;3670:768;;;;-1:-1:-1;4397:8:1;-1:-1:-1;;;;3670:768:1:o;4443:508::-;4520:6;4528;4536;4589:2;4577:9;4568:7;4564:23;4560:32;4557:52;;;4605:1;4602;4595:12;4557:52;4644:9;4631:23;4663:31;4688:5;4663:31;:::i;:::-;4713:5;-1:-1:-1;4770:2:1;4755:18;;4742:32;4783:33;4742:32;4783:33;:::i;:::-;4443:508;;4835:7;;-1:-1:-1;;;4915:2:1;4900:18;;;;4887:32;;4443:508::o;4956:346::-;5024:6;5032;5085:2;5073:9;5064:7;5060:23;5056:32;5053:52;;;5101:1;5098;5091:12;5053:52;-1:-1:-1;;5146:23:1;;;5266:2;5251:18;;;5238:32;;-1:-1:-1;4956:346:1:o;5586:587::-;5657:6;5665;5718:2;5706:9;5697:7;5693:23;5689:32;5686:52;;;5734:1;5731;5724:12;5686:52;5774:9;5761:23;-1:-1:-1;;;;;5799:6:1;5796:30;5793:50;;;5839:1;5836;5829:12;5793:50;5862:22;;5915:4;5907:13;;5903:27;-1:-1:-1;5893:55:1;;5944:1;5941;5934:12;5893:55;5984:2;5971:16;-1:-1:-1;;;;;6002:6:1;5999:30;5996:50;;;6042:1;6039;6032:12;5996:50;6087:7;6082:2;6073:6;6069:2;6065:15;6061:24;6058:37;6055:57;;;6108:1;6105;6098:12;6055:57;6139:2;6131:11;;;;;6161:6;;-1:-1:-1;5586:587:1;-1:-1:-1;;;5586:587:1:o;6178:506::-;6254:6;6262;6270;6323:2;6311:9;6302:7;6298:23;6294:32;6291:52;;;6339:1;6336;6329:12;6291:52;6384:23;;;-1:-1:-1;6483:2:1;6468:18;;6455:32;6496:33;6455:32;6496:33;:::i;:::-;6548:7;-1:-1:-1;6607:2:1;6592:18;;6579:32;6620;6579;6620;:::i;:::-;6671:7;6661:17;;;6178:506;;;;;:::o;6689:108::-;6771:1;6764:5;6761:12;6751:40;;6787:1;6784;6777:12;6802:409;6884:6;6892;6945:2;6933:9;6924:7;6920:23;6916:32;6913:52;;;6961:1;6958;6951:12;6913:52;7000:9;6987:23;7019:31;7044:5;7019:31;:::i;:::-;7069:5;-1:-1:-1;7126:2:1;7111:18;;7098:32;7139:40;7098:32;7139:40;:::i;7216:247::-;7275:6;7328:2;7316:9;7307:7;7303:23;7299:32;7296:52;;;7344:1;7341;7334:12;7296:52;7383:9;7370:23;7402:31;7427:5;7402:31;:::i;7468:118::-;7554:5;7547:13;7540:21;7533:5;7530:32;7520:60;;7576:1;7573;7566:12;7591:241;7647:6;7700:2;7688:9;7679:7;7675:23;7671:32;7668:52;;;7716:1;7713;7706:12;7668:52;7755:9;7742:23;7774:28;7796:5;7774:28;:::i;7837:382::-;7902:6;7910;7963:2;7951:9;7942:7;7938:23;7934:32;7931:52;;;7979:1;7976;7969:12;7931:52;8018:9;8005:23;8037:31;8062:5;8037:31;:::i;:::-;8087:5;-1:-1:-1;8144:2:1;8129:18;;8116:32;8157:30;8116:32;8157:30;:::i;8224:127::-;8285:10;8280:3;8276:20;8273:1;8266:31;8316:4;8313:1;8306:15;8340:4;8337:1;8330:15;8356:253;8428:2;8422:9;8470:4;8458:17;;-1:-1:-1;;;;;8490:34:1;;8526:22;;;8487:62;8484:88;;;8552:18;;:::i;:::-;8588:2;8581:22;8356:253;:::o;8614:275::-;8685:2;8679:9;8750:2;8731:13;;-1:-1:-1;;8727:27:1;8715:40;;-1:-1:-1;;;;;8770:34:1;;8806:22;;;8767:62;8764:88;;;8832:18;;:::i;:::-;8868:2;8861:22;8614:275;;-1:-1:-1;8614:275:1:o;8894:1162::-;8989:6;8997;9005;9013;9066:3;9054:9;9045:7;9041:23;9037:33;9034:53;;;9083:1;9080;9073:12;9034:53;9122:9;9109:23;9141:31;9166:5;9141:31;:::i;:::-;9191:5;-1:-1:-1;9248:2:1;9233:18;;9220:32;9261:33;9220:32;9261:33;:::i;:::-;9313:7;-1:-1:-1;9393:2:1;9378:18;;9365:32;;-1:-1:-1;9474:2:1;9459:18;;9446:32;-1:-1:-1;;;;;9490:30:1;;9487:50;;;9533:1;9530;9523:12;9487:50;9556:22;;9609:4;9601:13;;9597:27;-1:-1:-1;9587:55:1;;9638:1;9635;9628:12;9587:55;9678:2;9665:16;-1:-1:-1;;;;;9696:6:1;9693:30;9690:56;;;9726:18;;:::i;:::-;9768:57;9815:2;9792:17;;-1:-1:-1;;9788:31:1;9821:2;9784:40;9768:57;:::i;:::-;9848:6;9841:5;9834:21;9896:7;9891:2;9882:6;9878:2;9874:15;9870:24;9867:37;9864:57;;;9917:1;9914;9907:12;9864:57;9972:6;9967:2;9963;9959:11;9954:2;9947:5;9943:14;9930:49;10024:1;10019:2;10010:6;10003:5;9999:18;9995:27;9988:38;10045:5;10035:15;;;;;8894:1162;;;;;;;:::o;10061:268::-;10134:6;10187:2;10175:9;10166:7;10162:23;10158:32;10155:52;;;10203:1;10200;10193:12;10155:52;10242:9;10229:23;10261:38;10293:5;10261:38;:::i;10334:388::-;10402:6;10410;10463:2;10451:9;10442:7;10438:23;10434:32;10431:52;;;10479:1;10476;10469:12;10431:52;10518:9;10505:23;10537:31;10562:5;10537:31;:::i;:::-;10587:5;-1:-1:-1;10644:2:1;10629:18;;10616:32;10657:33;10616:32;10657:33;:::i;10727:551::-;10822:6;10830;10838;10891:2;10879:9;10870:7;10866:23;10862:32;10859:52;;;10907:1;10904;10897:12;10859:52;10952:23;;;-1:-1:-1;11050:2:1;11035:18;;11022:32;-1:-1:-1;;;;;11066:30:1;;11063:50;;;11109:1;11106;11099:12;11063:50;11148:70;11210:7;11201:6;11190:9;11186:22;11148:70;:::i;:::-;10727:551;;11237:8;;-1:-1:-1;11122:96:1;;-1:-1:-1;;;;10727:551:1:o;11283:380::-;11362:1;11358:12;;;;11405;;;11426:61;;11480:4;11472:6;11468:17;11458:27;;11426:61;11533:2;11525:6;11522:14;11502:18;11499:38;11496:161;;11579:10;11574:3;11570:20;11567:1;11560:31;11614:4;11611:1;11604:15;11642:4;11639:1;11632:15;11496:161;;11283:380;;;:::o;12500:175::-;12578:13;;-1:-1:-1;;;;;12620:30:1;;12610:41;;12600:69;;12665:1;12662;12655:12;12600:69;12500:175;;;:::o;12680:163::-;12758:13;;12811:6;12800:18;;12790:29;;12780:57;;12833:1;12830;12823:12;12848:152;12934:13;;12956:38;12934:13;12956:38;:::i;13005:986::-;13121:6;13129;13173:9;13164:7;13160:23;13203:3;13199:2;13195:12;13192:32;;;13220:1;13217;13210:12;13192:32;13244:4;13240:2;13236:13;13233:33;;;13262:1;13259;13252:12;13233:33;;13288:22;;:::i;:::-;13339:9;13333:16;13326:5;13319:31;13395:2;13384:9;13380:18;13374:25;13408:32;13432:7;13408:32;:::i;:::-;13467:2;13456:14;;13449:31;13512:48;13556:2;13541:18;;13512:48;:::i;:::-;13507:2;13500:5;13496:14;13489:72;13593:48;13637:2;13626:9;13622:18;13593:48;:::i;:::-;13588:2;13581:5;13577:14;13570:72;13687:3;13676:9;13672:19;13666:26;13736:4;13727:7;13723:18;13714:7;13711:31;13701:59;;13756:1;13753;13746:12;13701:59;13787:3;13776:15;;13769:32;13834:49;13878:3;13863:19;;13834:49;:::i;:::-;13828:3;13817:15;;13810:74;13821:5;-1:-1:-1;13927:58:1;13979:4;13964:20;;13927:58;:::i;:::-;13917:68;;13005:986;;;;;:::o;13996:127::-;14057:10;14052:3;14048:20;14045:1;14038:31;14088:4;14085:1;14078:15;14112:4;14109:1;14102:15;14128:127;14189:10;14184:3;14180:20;14177:1;14170:31;14220:4;14217:1;14210:15;14244:4;14241:1;14234:15;14260:125;14325:9;;;14346:10;;;14343:36;;;14359:18;;:::i;14390:778::-;14610:4;14650:1;14642:6;14639:13;14629:144;;14695:10;14690:3;14686:20;14683:1;14676:31;14730:4;14727:1;14720:15;14758:4;14755:1;14748:15;14629:144;14782:25;;;-1:-1:-1;;;;;14843:32:1;;14838:2;14823:18;;14816:60;14912:2;14907;14892:18;;14885:30;;;14931:18;;14924:34;;;-1:-1:-1;;;;;14970:31:1;;14967:51;;;15014:1;15011;15004:12;14967:51;15048:6;15045:1;15041:14;15106:6;15098;15092:3;15081:9;15077:19;15064:49;15134:22;;;;15158:3;15130:32;;14390:778;-1:-1:-1;;;;;14390:778:1:o;15173:245::-;15240:6;15293:2;15281:9;15272:7;15268:23;15264:32;15261:52;;;15309:1;15306;15299:12;15261:52;15341:9;15335:16;15360:28;15382:5;15360:28;:::i;15423:127::-;15484:10;15479:3;15475:20;15472:1;15465:31;15515:4;15512:1;15505:15;15539:4;15536:1;15529:15;15555:251;15625:6;15678:2;15666:9;15657:7;15653:23;15649:32;15646:52;;;15694:1;15691;15684:12;15646:52;15726:9;15720:16;15745:31;15770:5;15745:31;:::i;15811:168::-;15884:9;;;15915;;15932:15;;;15926:22;;15912:37;15902:71;;15953:18;;:::i;16194:409::-;16396:2;16378:21;;;16435:2;16415:18;;;16408:30;16474:34;16469:2;16454:18;;16447:62;-1:-1:-1;;;16540:2:1;16525:18;;16518:43;16593:3;16578:19;;16194:409::o;16740:217::-;16780:1;16806;16796:132;;16850:10;16845:3;16841:20;16838:1;16831:31;16885:4;16882:1;16875:15;16913:4;16910:1;16903:15;16796:132;-1:-1:-1;16942:9:1;;16740:217::o;17088:518::-;17190:2;17185:3;17182:11;17179:421;;;17226:5;17223:1;17216:16;17270:4;17267:1;17257:18;17340:2;17328:10;17324:19;17321:1;17317:27;17311:4;17307:38;17376:4;17364:10;17361:20;17358:47;;;-1:-1:-1;17399:4:1;17358:47;17454:2;17449:3;17445:12;17442:1;17438:20;17432:4;17428:31;17418:41;;17509:81;17527:2;17520:5;17517:13;17509:81;;;17586:1;17572:16;;17553:1;17542:13;17509:81;;17782:1206;-1:-1:-1;;;;;17901:3:1;17898:27;17895:53;;;17928:18;;:::i;:::-;17957:94;18047:3;18007:38;18039:4;18033:11;18007:38;:::i;:::-;18001:4;17957:94;:::i;:::-;18077:1;18102:2;18097:3;18094:11;18119:1;18114:616;;;;18774:1;18791:3;18788:93;;;-1:-1:-1;18847:19:1;;;18834:33;18788:93;-1:-1:-1;;17739:1:1;17735:11;;;17731:24;17727:29;17717:40;17763:1;17759:11;;;17714:57;18894:78;;18087:895;;18114:616;17035:1;17028:14;;;17072:4;17059:18;;-1:-1:-1;;18150:17:1;;;18251:9;18273:229;18287:7;18284:1;18281:14;18273:229;;;18376:19;;;18363:33;18348:49;;18483:4;18468:20;;;;18436:1;18424:14;;;;18303:12;18273:229;;;18277:3;18530;18521:7;18518:16;18515:159;;;18654:1;18650:6;18644:3;18638;18635:1;18631:11;18627:21;18623:34;18619:39;18606:9;18601:3;18597:19;18584:33;18580:79;18572:6;18565:95;18515:159;;;18717:1;18711:3;18708:1;18704:11;18700:19;18694:4;18687:33;18087:895;;17782:1206;;;:::o;20061:496::-;20240:3;20278:6;20272:13;20294:66;20353:6;20348:3;20341:4;20333:6;20329:17;20294:66;:::i;:::-;20423:13;;20382:16;;;;20445:70;20423:13;20382:16;20492:4;20480:17;;20445:70;:::i;:::-;20531:20;;20061:496;-1:-1:-1;;;;20061:496:1:o;20562:135::-;20601:3;20622:17;;;20619:43;;20642:18;;:::i;:::-;-1:-1:-1;20689:1:1;20678:13;;20562:135::o;22040:401::-;22242:2;22224:21;;;22281:2;22261:18;;;22254:30;22320:34;22315:2;22300:18;;22293:62;-1:-1:-1;;;22386:2:1;22371:18;;22364:35;22431:3;22416:19;;22040:401::o;23566:414::-;23768:2;23750:21;;;23807:2;23787:18;;;23780:30;23846:34;23841:2;23826:18;;23819:62;-1:-1:-1;;;23912:2:1;23897:18;;23890:48;23970:3;23955:19;;23566:414::o;23985:406::-;24187:2;24169:21;;;24226:2;24206:18;;;24199:30;24265:34;24260:2;24245:18;;24238:62;-1:-1:-1;;;24331:2:1;24316:18;;24309:40;24381:3;24366:19;;23985:406::o;25106:485::-;-1:-1:-1;;;;;25337:32:1;;;25319:51;;25406:32;;25401:2;25386:18;;25379:60;25470:2;25455:18;;25448:34;;;25518:3;25513:2;25498:18;;25491:31;;;-1:-1:-1;;25539:46:1;;25565:19;;25557:6;25539:46;:::i;:::-;25531:54;25106:485;-1:-1:-1;;;;;;25106:485:1:o;25596:249::-;25665:6;25718:2;25706:9;25697:7;25693:23;25689:32;25686:52;;;25734:1;25731;25724:12;25686:52;25766:9;25760:16;25785:30;25809:5;25785:30;:::i

Swarm Source

ipfs://1d6985df8d2906dd48dc614fb509c3c604845d84fc68b6054a73a9a1fe91a99b
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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