APE Price: $0.71 (+7.10%)

Token

BoonOpoly (BOON)

Overview

Max Total Supply

0 BOON

Holders

0

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
0x93c1da9a41776f4ec9528578e0f0c698cfe9623c
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
BoonOpoly

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at apescan.io on 2025-01-31
*/

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


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

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * 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[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC1155/IERC1155.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.20;


/**
 * @dev Required interface of an ERC-1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[ERC].
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

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

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(
        address[] calldata accounts,
        uint256[] calldata ids
    ) external view returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the zero address.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
     *
     * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
     * to an untrusted contract, when invoking {onERC1155Received} on the receiver.
     * Ensure to follow the checks-effects-interactions pattern and consider employing
     * reentrancy guards when interacting with untrusted contracts.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `value` amount.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
     * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver.
     * Ensure to follow the checks-effects-interactions pattern and consider employing
     * reentrancy guards when interacting with untrusted contracts.
     *
     * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.
     *
     * Requirements:
     *
     * - `ids` and `values` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external;
}

// File: @openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)

pragma solidity ^0.8.20;


/**
 * @dev Interface of the optional ERC1155MetadataExtension interface, as defined
 * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC].
 */
interface IERC1155MetadataURI is IERC1155 {
    /**
     * @dev Returns the URI for token type `id`.
     *
     * If the `\{id\}` substring is present in the URI, it must be replaced by
     * clients with the actual token type ID.
     */
    function uri(uint256 id) external view returns (string memory);
}

// File: @openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.20;


/**
 * @dev Interface that must be implemented by smart contracts in order to receive
 * ERC-1155 token transfers.
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC-1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC-1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/token/ERC1155/utils/ERC1155Utils.sol


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Utils.sol)

pragma solidity ^0.8.20;



/**
 * @dev Library that provide common ERC-1155 utility functions.
 *
 * See https://eips.ethereum.org/EIPS/eip-1155[ERC-1155].
 *
 * _Available since v5.1._
 */
library ERC1155Utils {
    /**
     * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155-onERC1155Received}
     * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
     *
     * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
     * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept
     * the transfer.
     */
    function checkOnERC1155Received(
        address operator,
        address from,
        address to,
        uint256 id,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length > 0) {
            try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {
                if (response != IERC1155Receiver.onERC1155Received.selector) {
                    // Tokens rejected
                    revert IERC1155Errors.ERC1155InvalidReceiver(to);
                }
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    // non-IERC1155Receiver implementer
                    revert IERC1155Errors.ERC1155InvalidReceiver(to);
                } else {
                    assembly ("memory-safe") {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        }
    }

    /**
     * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155-onERC1155BatchReceived}
     * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
     *
     * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
     * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept
     * the transfer.
     */
    function checkOnERC1155BatchReceived(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory values,
        bytes memory data
    ) internal {
        if (to.code.length > 0) {
            try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (
                bytes4 response
            ) {
                if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
                    // Tokens rejected
                    revert IERC1155Errors.ERC1155InvalidReceiver(to);
                }
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    // non-IERC1155Receiver implementer
                    revert IERC1155Errors.ERC1155InvalidReceiver(to);
                } else {
                    assembly ("memory-safe") {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        }
    }
}

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


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

pragma solidity ^0.8.20;

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

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

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


// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;


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

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


// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides a set of functions to compare values.
 *
 * _Available since v5.1._
 */
library Comparators {
    function lt(uint256 a, uint256 b) internal pure returns (bool) {
        return a < b;
    }

    function gt(uint256 a, uint256 b) internal pure returns (bool) {
        return a > b;
    }
}

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


// OpenZeppelin Contracts (last updated v5.1.0) (utils/SlotDerivation.sol)
// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots
 * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by
 * the solidity language / compiler.
 *
 * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.].
 *
 * Example usage:
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using StorageSlot for bytes32;
 *     using SlotDerivation for bytes32;
 *
 *     // Declare a namespace
 *     string private constant _NAMESPACE = "<namespace>" // eg. OpenZeppelin.Slot
 *
 *     function setValueInNamespace(uint256 key, address newValue) internal {
 *         _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;
 *     }
 *
 *     function getValueInNamespace(uint256 key) internal view returns (address) {
 *         return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;
 *     }
 * }
 * ```
 *
 * TIP: Consider using this library along with {StorageSlot}.
 *
 * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking
 * upgrade safety will ignore the slots accessed through this library.
 *
 * _Available since v5.1._
 */
library SlotDerivation {
    /**
     * @dev Derive an ERC-7201 slot from a string (namespace).
     */
    function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {
        assembly ("memory-safe") {
            mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))
            slot := and(keccak256(0x00, 0x20), not(0xff))
        }
    }

    /**
     * @dev Add an offset to a slot to get the n-th element of a structure or an array.
     */
    function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {
        unchecked {
            return bytes32(uint256(slot) + pos);
        }
    }

    /**
     * @dev Derive the location of the first element in an array from the slot where the length is stored.
     */
    function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, slot)
            result := keccak256(0x00, 0x20)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, and(key, shr(96, not(0))))
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, iszero(iszero(key)))
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, key)
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, key)
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            mstore(0x00, key)
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            let length := mload(key)
            let begin := add(key, 0x20)
            let end := add(begin, length)
            let cache := mload(end)
            mstore(end, slot)
            result := keccak256(begin, add(length, 0x20))
            mstore(end, cache)
        }
    }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {
        assembly ("memory-safe") {
            let length := mload(key)
            let begin := add(key, 0x20)
            let end := add(begin, length)
            let cache := mload(end)
            mstore(end, slot)
            result := keccak256(begin, add(length, 0x20))
            mstore(end, cache)
        }
    }
}

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


// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC-1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(newImplementation.code.length > 0);
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * TIP: Consider using this library along with {SlotDerivation}.
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct Int256Slot {
        int256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Int256Slot` with member `value` located at `slot`.
     */
    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns a `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }
}

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


// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)

pragma solidity ^0.8.20;

/**
 * @dev Helper library for emitting standardized panic codes.
 *
 * ```solidity
 * contract Example {
 *      using Panic for uint256;
 *
 *      // Use any of the declared internal constants
 *      function foo() { Panic.GENERIC.panic(); }
 *
 *      // Alternatively
 *      function foo() { Panic.panic(Panic.GENERIC); }
 * }
 * ```
 *
 * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
 *
 * _Available since v5.1._
 */
// slither-disable-next-line unused-state
library Panic {
    /// @dev generic / unspecified error
    uint256 internal constant GENERIC = 0x00;
    /// @dev used by the assert() builtin
    uint256 internal constant ASSERT = 0x01;
    /// @dev arithmetic underflow or overflow
    uint256 internal constant UNDER_OVERFLOW = 0x11;
    /// @dev division or modulo by zero
    uint256 internal constant DIVISION_BY_ZERO = 0x12;
    /// @dev enum conversion error
    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
    /// @dev invalid encoding in storage
    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
    /// @dev empty array pop
    uint256 internal constant EMPTY_ARRAY_POP = 0x31;
    /// @dev array out of bounds access
    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
    /// @dev resource error (too large allocation or too large array)
    uint256 internal constant RESOURCE_ERROR = 0x41;
    /// @dev calling invalid internal function
    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;

    /// @dev Reverts with a panic code. Recommended to use with
    /// the internal constants with predefined codes.
    function panic(uint256 code) internal pure {
        assembly ("memory-safe") {
            mstore(0x00, 0x4e487b71)
            mstore(0x20, code)
            revert(0x1c, 0x24)
        }
    }
}

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


// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.20;

/**
 * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeCast {
    /**
     * @dev Value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);

    /**
     * @dev An int value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedIntToUint(int256 value);

    /**
     * @dev Value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);

    /**
     * @dev An uint value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedUintToInt(uint256 value);

    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        if (value > type(uint248).max) {
            revert SafeCastOverflowedUintDowncast(248, value);
        }
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        if (value > type(uint240).max) {
            revert SafeCastOverflowedUintDowncast(240, value);
        }
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        if (value > type(uint232).max) {
            revert SafeCastOverflowedUintDowncast(232, value);
        }
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        if (value > type(uint224).max) {
            revert SafeCastOverflowedUintDowncast(224, value);
        }
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        if (value > type(uint216).max) {
            revert SafeCastOverflowedUintDowncast(216, value);
        }
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        if (value > type(uint208).max) {
            revert SafeCastOverflowedUintDowncast(208, value);
        }
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        if (value > type(uint200).max) {
            revert SafeCastOverflowedUintDowncast(200, value);
        }
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        if (value > type(uint192).max) {
            revert SafeCastOverflowedUintDowncast(192, value);
        }
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        if (value > type(uint184).max) {
            revert SafeCastOverflowedUintDowncast(184, value);
        }
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        if (value > type(uint176).max) {
            revert SafeCastOverflowedUintDowncast(176, value);
        }
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        if (value > type(uint168).max) {
            revert SafeCastOverflowedUintDowncast(168, value);
        }
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        if (value > type(uint160).max) {
            revert SafeCastOverflowedUintDowncast(160, value);
        }
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        if (value > type(uint152).max) {
            revert SafeCastOverflowedUintDowncast(152, value);
        }
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        if (value > type(uint144).max) {
            revert SafeCastOverflowedUintDowncast(144, value);
        }
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        if (value > type(uint136).max) {
            revert SafeCastOverflowedUintDowncast(136, value);
        }
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        if (value > type(uint128).max) {
            revert SafeCastOverflowedUintDowncast(128, value);
        }
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        if (value > type(uint120).max) {
            revert SafeCastOverflowedUintDowncast(120, value);
        }
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        if (value > type(uint112).max) {
            revert SafeCastOverflowedUintDowncast(112, value);
        }
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        if (value > type(uint104).max) {
            revert SafeCastOverflowedUintDowncast(104, value);
        }
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        if (value > type(uint96).max) {
            revert SafeCastOverflowedUintDowncast(96, value);
        }
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        if (value > type(uint88).max) {
            revert SafeCastOverflowedUintDowncast(88, value);
        }
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        if (value > type(uint80).max) {
            revert SafeCastOverflowedUintDowncast(80, value);
        }
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        if (value > type(uint72).max) {
            revert SafeCastOverflowedUintDowncast(72, value);
        }
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        if (value > type(uint64).max) {
            revert SafeCastOverflowedUintDowncast(64, value);
        }
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        if (value > type(uint56).max) {
            revert SafeCastOverflowedUintDowncast(56, value);
        }
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        if (value > type(uint48).max) {
            revert SafeCastOverflowedUintDowncast(48, value);
        }
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        if (value > type(uint40).max) {
            revert SafeCastOverflowedUintDowncast(40, value);
        }
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        if (value > type(uint32).max) {
            revert SafeCastOverflowedUintDowncast(32, value);
        }
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        if (value > type(uint24).max) {
            revert SafeCastOverflowedUintDowncast(24, value);
        }
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        if (value > type(uint16).max) {
            revert SafeCastOverflowedUintDowncast(16, value);
        }
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        if (value > type(uint8).max) {
            revert SafeCastOverflowedUintDowncast(8, value);
        }
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        if (value < 0) {
            revert SafeCastOverflowedIntToUint(value);
        }
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(248, value);
        }
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(240, value);
        }
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(232, value);
        }
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(224, value);
        }
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(216, value);
        }
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(208, value);
        }
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(200, value);
        }
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(192, value);
        }
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(184, value);
        }
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(176, value);
        }
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(168, value);
        }
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(160, value);
        }
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(152, value);
        }
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(144, value);
        }
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(136, value);
        }
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(128, value);
        }
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(120, value);
        }
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(112, value);
        }
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(104, value);
        }
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(96, value);
        }
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(88, value);
        }
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(80, value);
        }
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(72, value);
        }
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(64, value);
        }
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(56, value);
        }
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(48, value);
        }
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(40, value);
        }
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(32, value);
        }
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(24, value);
        }
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(16, value);
        }
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(8, value);
        }
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        if (value > uint256(type(int256).max)) {
            revert SafeCastOverflowedUintToInt(value);
        }
        return int256(value);
    }

    /**
     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
     */
    function toUint(bool b) internal pure returns (uint256 u) {
        assembly ("memory-safe") {
            u := iszero(iszero(b))
        }
    }
}

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


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

pragma solidity ^0.8.20;



/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

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

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

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

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

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

    /**
     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
     *
     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
     * one branch when needed, making this function more expensive.
     */
    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
        unchecked {
            // branchless ternary works because:
            // b ^ (a ^ b) == a
            // b ^ 0 == b
            return b ^ ((a ^ b) * SafeCast.toUint(condition));
        }
    }

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

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

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

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

        // The following calculation ensures accurate ceiling division without overflow.
        // Since a is non-zero, (a - 1) / b will not overflow.
        // The largest possible result occurs when (a - 1) / b is type(uint256).max,
        // but the largest value we can obtain is type(uint256).max - 1, which happens
        // when a = type(uint256).max and b = 1.
        unchecked {
            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
        }
    }

    /**
     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     *
     * 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²⁵⁶ and mod 2²⁵⁶ - 1, then use
            // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2²⁵⁶ + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

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

            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
            if (denominator <= prod1) {
                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
            }

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

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

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

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

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

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

                // Flip twos such that it is 2²⁵⁶ / 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²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.
            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⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
            inverse *= 2 - denominator * inverse; // inverse mod 2³²
            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶

            // 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²⁵⁶. Since the preconditions guarantee that the outcome is
            // less than 2²⁵⁶, 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;
        }
    }

    /**
     * @dev 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) {
        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
    }

    /**
     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
     *
     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
     *
     * If the input value is not inversible, 0 is returned.
     *
     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
     */
    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
        unchecked {
            if (n == 0) return 0;

            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
            // Used to compute integers x and y such that: ax + ny = gcd(a, n).
            // When the gcd is 1, then the inverse of a modulo n exists and it's x.
            // ax + ny = 1
            // ax = 1 + (-y)n
            // ax ≡ 1 (mod n) # x is the inverse of a modulo n

            // If the remainder is 0 the gcd is n right away.
            uint256 remainder = a % n;
            uint256 gcd = n;

            // Therefore the initial coefficients are:
            // ax + ny = gcd(a, n) = n
            // 0a + 1n = n
            int256 x = 0;
            int256 y = 1;

            while (remainder != 0) {
                uint256 quotient = gcd / remainder;

                (gcd, remainder) = (
                    // The old remainder is the next gcd to try.
                    remainder,
                    // Compute the next remainder.
                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
                    // where gcd is at most n (capped to type(uint256).max)
                    gcd - remainder * quotient
                );

                (x, y) = (
                    // Increment the coefficient of a.
                    y,
                    // Decrement the coefficient of n.
                    // Can overflow, but the result is casted to uint256 so that the
                    // next value of y is "wrapped around" to a value between 0 and n - 1.
                    x - y * int256(quotient)
                );
            }

            if (gcd != 1) return 0; // No inverse exists.
            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
        }
    }

    /**
     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
     *
     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.
     *
     * NOTE: this function does NOT check that `p` is a prime greater than `2`.
     */
    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
        unchecked {
            return Math.modExp(a, p - 2, p);
        }
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
     *
     * Requirements:
     * - modulus can't be zero
     * - underlying staticcall to precompile must succeed
     *
     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
     * sure the chain you're using it on supports the precompiled contract for modular exponentiation
     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly
     * interpreted as 0.
     */
    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
        (bool success, uint256 result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
     * to operate modulo 0 or if the underlying precompile reverted.
     *
     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
     * of a revert, but the result may be incorrectly interpreted as 0.
     */
    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
        if (m == 0) return (false, 0);
        assembly ("memory-safe") {
            let ptr := mload(0x40)
            // | Offset    | Content    | Content (Hex)                                                      |
            // |-----------|------------|--------------------------------------------------------------------|
            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x60:0x7f | value of b | 0x<.............................................................b> |
            // | 0x80:0x9f | value of e | 0x<.............................................................e> |
            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |
            mstore(ptr, 0x20)
            mstore(add(ptr, 0x20), 0x20)
            mstore(add(ptr, 0x40), 0x20)
            mstore(add(ptr, 0x60), b)
            mstore(add(ptr, 0x80), e)
            mstore(add(ptr, 0xa0), m)

            // Given the result < m, it's guaranteed to fit in 32 bytes,
            // so we can use the memory scratch space located at offset 0.
            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
            result := mload(0x00)
        }
    }

    /**
     * @dev Variant of {modExp} that supports inputs of arbitrary length.
     */
    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
        (bool success, bytes memory result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.
     */
    function tryModExp(
        bytes memory b,
        bytes memory e,
        bytes memory m
    ) internal view returns (bool success, bytes memory result) {
        if (_zeroBytes(m)) return (false, new bytes(0));

        uint256 mLen = m.length;

        // Encode call args in result and move the free memory pointer
        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);

        assembly ("memory-safe") {
            let dataPtr := add(result, 0x20)
            // Write result on top of args to avoid allocating extra memory.
            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
            // Overwrite the length.
            // result.length > returndatasize() is guaranteed because returndatasize() == m.length
            mstore(result, mLen)
            // Set the memory pointer after the returned data.
            mstore(0x40, add(dataPtr, mLen))
        }
    }

    /**
     * @dev Returns whether the provided byte array is zero.
     */
    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
        for (uint256 i = 0; i < byteArray.length; ++i) {
            if (byteArray[i] != 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only
     * using integer operations.
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        unchecked {
            // Take care of easy edge cases when a == 0 or a == 1
            if (a <= 1) {
                return a;
            }

            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
            // the current value as `ε_n = | x_n - sqrt(a) |`.
            //
            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
            // bigger than any uint256.
            //
            // By noticing that
            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
            // to the msb function.
            uint256 aa = a;
            uint256 xn = 1;

            if (aa >= (1 << 128)) {
                aa >>= 128;
                xn <<= 64;
            }
            if (aa >= (1 << 64)) {
                aa >>= 64;
                xn <<= 32;
            }
            if (aa >= (1 << 32)) {
                aa >>= 32;
                xn <<= 16;
            }
            if (aa >= (1 << 16)) {
                aa >>= 16;
                xn <<= 8;
            }
            if (aa >= (1 << 8)) {
                aa >>= 8;
                xn <<= 4;
            }
            if (aa >= (1 << 4)) {
                aa >>= 4;
                xn <<= 2;
            }
            if (aa >= (1 << 2)) {
                xn <<= 1;
            }

            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
            //
            // We can refine our estimation by noticing that the middle of that interval minimizes the error.
            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
            // This is going to be our x_0 (and ε_0)
            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)

            // From here, Newton's method give us:
            // x_{n+1} = (x_n + a / x_n) / 2
            //
            // One should note that:
            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
            //              = ((x_n² + a) / (2 * x_n))² - a
            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
            //              = (x_n² - a)² / (2 * x_n)²
            //              = ((x_n² - a) / (2 * x_n))²
            //              ≥ 0
            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
            //
            // This gives us the proof of quadratic convergence of the sequence:
            // ε_{n+1} = | x_{n+1} - sqrt(a) |
            //         = | (x_n + a / x_n) / 2 - sqrt(a) |
            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
            //         = | (x_n - sqrt(a))² / (2 * x_n) |
            //         = | ε_n² / (2 * x_n) |
            //         = ε_n² / | (2 * x_n) |
            //
            // For the first iteration, we have a special case where x_0 is known:
            // ε_1 = ε_0² / | (2 * x_0) |
            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))
            //     ≤ 2**(e-3) / 3
            //     ≤ 2**(e-3-log2(3))
            //     ≤ 2**(e-4.5)
            //
            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
            // ε_{n+1} = ε_n² / | (2 * x_n) |
            //         ≤ (2**(e-k))² / (2 * 2**(e-1))
            //         ≤ 2**(2*e-2*k) / 2**e
            //         ≤ 2**(e-2*k)
            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above
            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5
            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9
            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18
            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36
            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72

            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
            // sqrt(a) or sqrt(a) + 1.
            return xn - SafeCast.toUint(xn > a / xn);
        }
    }

    /**
     * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        uint256 exp;
        unchecked {
            exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);
            value >>= exp;
            result += exp;

            exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);
            value >>= exp;
            result += exp;

            exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);
            value >>= exp;
            result += exp;

            exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);
            value >>= exp;
            result += exp;

            exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);
            value >>= exp;
            result += exp;

            exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);
            value >>= exp;
            result += exp;

            exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);
            value >>= exp;
            result += exp;

            result += SafeCast.toUint(value > 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
        }
    }

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

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

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

            isGt = SafeCast.toUint(value > (1 << 64) - 1);
            value >>= isGt * 64;
            result += isGt * 8;

            isGt = SafeCast.toUint(value > (1 << 32) - 1);
            value >>= isGt * 32;
            result += isGt * 4;

            isGt = SafeCast.toUint(value > (1 << 16) - 1);
            value >>= isGt * 16;
            result += isGt * 2;

            result += SafeCast.toUint(value > (1 << 8) - 1);
        }
        return result;
    }

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

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

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


// OpenZeppelin Contracts (last updated v5.1.0) (utils/Arrays.sol)
// This file was procedurally generated from scripts/generate/templates/Arrays.js.

pragma solidity ^0.8.20;





/**
 * @dev Collection of functions related to array types.
 */
library Arrays {
    using SlotDerivation for bytes32;
    using StorageSlot for bytes32;

    /**
     * @dev Sort an array of uint256 (in memory) following the provided comparator function.
     *
     * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
     *
     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
     * consume more gas than is available in a block, leading to potential DoS.
     *
     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
     */
    function sort(
        uint256[] memory array,
        function(uint256, uint256) pure returns (bool) comp
    ) internal pure returns (uint256[] memory) {
        _quickSort(_begin(array), _end(array), comp);
        return array;
    }

    /**
     * @dev Variant of {sort} that sorts an array of uint256 in increasing order.
     */
    function sort(uint256[] memory array) internal pure returns (uint256[] memory) {
        sort(array, Comparators.lt);
        return array;
    }

    /**
     * @dev Sort an array of address (in memory) following the provided comparator function.
     *
     * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
     *
     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
     * consume more gas than is available in a block, leading to potential DoS.
     *
     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
     */
    function sort(
        address[] memory array,
        function(address, address) pure returns (bool) comp
    ) internal pure returns (address[] memory) {
        sort(_castToUint256Array(array), _castToUint256Comp(comp));
        return array;
    }

    /**
     * @dev Variant of {sort} that sorts an array of address in increasing order.
     */
    function sort(address[] memory array) internal pure returns (address[] memory) {
        sort(_castToUint256Array(array), Comparators.lt);
        return array;
    }

    /**
     * @dev Sort an array of bytes32 (in memory) following the provided comparator function.
     *
     * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
     *
     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
     * consume more gas than is available in a block, leading to potential DoS.
     *
     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
     */
    function sort(
        bytes32[] memory array,
        function(bytes32, bytes32) pure returns (bool) comp
    ) internal pure returns (bytes32[] memory) {
        sort(_castToUint256Array(array), _castToUint256Comp(comp));
        return array;
    }

    /**
     * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.
     */
    function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {
        sort(_castToUint256Array(array), Comparators.lt);
        return array;
    }

    /**
     * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops
     * at end (exclusive). Sorting follows the `comp` comparator.
     *
     * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.
     *
     * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should
     * be used only if the limits are within a memory array.
     */
    function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {
        unchecked {
            if (end - begin < 0x40) return;

            // Use first element as pivot
            uint256 pivot = _mload(begin);
            // Position where the pivot should be at the end of the loop
            uint256 pos = begin;

            for (uint256 it = begin + 0x20; it < end; it += 0x20) {
                if (comp(_mload(it), pivot)) {
                    // If the value stored at the iterator's position comes before the pivot, we increment the
                    // position of the pivot and move the value there.
                    pos += 0x20;
                    _swap(pos, it);
                }
            }

            _swap(begin, pos); // Swap pivot into place
            _quickSort(begin, pos, comp); // Sort the left side of the pivot
            _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot
        }
    }

    /**
     * @dev Pointer to the memory location of the first element of `array`.
     */
    function _begin(uint256[] memory array) private pure returns (uint256 ptr) {
        assembly ("memory-safe") {
            ptr := add(array, 0x20)
        }
    }

    /**
     * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word
     * that comes just after the last element of the array.
     */
    function _end(uint256[] memory array) private pure returns (uint256 ptr) {
        unchecked {
            return _begin(array) + array.length * 0x20;
        }
    }

    /**
     * @dev Load memory word (as a uint256) at location `ptr`.
     */
    function _mload(uint256 ptr) private pure returns (uint256 value) {
        assembly {
            value := mload(ptr)
        }
    }

    /**
     * @dev Swaps the elements memory location `ptr1` and `ptr2`.
     */
    function _swap(uint256 ptr1, uint256 ptr2) private pure {
        assembly {
            let value1 := mload(ptr1)
            let value2 := mload(ptr2)
            mstore(ptr1, value2)
            mstore(ptr2, value1)
        }
    }

    /// @dev Helper: low level cast address memory array to uint256 memory array
    function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {
        assembly {
            output := input
        }
    }

    /// @dev Helper: low level cast bytes32 memory array to uint256 memory array
    function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {
        assembly {
            output := input
        }
    }

    /// @dev Helper: low level cast address comp function to uint256 comp function
    function _castToUint256Comp(
        function(address, address) pure returns (bool) input
    ) private pure returns (function(uint256, uint256) pure returns (bool) output) {
        assembly {
            output := input
        }
    }

    /// @dev Helper: low level cast bytes32 comp function to uint256 comp function
    function _castToUint256Comp(
        function(bytes32, bytes32) pure returns (bool) input
    ) private pure returns (function(uint256, uint256) pure returns (bool) output) {
        assembly {
            output := input
        }
    }

    /**
     * @dev Searches a sorted `array` and returns the first index that contains
     * a value greater or equal to `element`. If no such index exists (i.e. all
     * values in the array are strictly less than `element`), the array length is
     * returned. Time complexity O(log n).
     *
     * NOTE: The `array` is expected to be sorted in ascending order, and to
     * contain no repeated elements.
     *
     * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks
     * support for repeated elements in the array. The {lowerBound} function should
     * be used instead.
     */
    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        uint256 low = 0;
        uint256 high = array.length;

        if (high == 0) {
            return 0;
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds towards zero (it does integer division with truncation).
            if (unsafeAccess(array, mid).value > element) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
        if (low > 0 && unsafeAccess(array, low - 1).value == element) {
            return low - 1;
        } else {
            return low;
        }
    }

    /**
     * @dev Searches an `array` sorted in ascending order and returns the first
     * index that contains a value greater or equal than `element`. If no such index
     * exists (i.e. all values in the array are strictly less than `element`), the array
     * length is returned. Time complexity O(log n).
     *
     * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].
     */
    function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        uint256 low = 0;
        uint256 high = array.length;

        if (high == 0) {
            return 0;
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds towards zero (it does integer division with truncation).
            if (unsafeAccess(array, mid).value < element) {
                // this cannot overflow because mid < high
                unchecked {
                    low = mid + 1;
                }
            } else {
                high = mid;
            }
        }

        return low;
    }

    /**
     * @dev Searches an `array` sorted in ascending order and returns the first
     * index that contains a value strictly greater than `element`. If no such index
     * exists (i.e. all values in the array are strictly less than `element`), the array
     * length is returned. Time complexity O(log n).
     *
     * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].
     */
    function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        uint256 low = 0;
        uint256 high = array.length;

        if (high == 0) {
            return 0;
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds towards zero (it does integer division with truncation).
            if (unsafeAccess(array, mid).value > element) {
                high = mid;
            } else {
                // this cannot overflow because mid < high
                unchecked {
                    low = mid + 1;
                }
            }
        }

        return low;
    }

    /**
     * @dev Same as {lowerBound}, but with an array in memory.
     */
    function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
        uint256 low = 0;
        uint256 high = array.length;

        if (high == 0) {
            return 0;
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds towards zero (it does integer division with truncation).
            if (unsafeMemoryAccess(array, mid) < element) {
                // this cannot overflow because mid < high
                unchecked {
                    low = mid + 1;
                }
            } else {
                high = mid;
            }
        }

        return low;
    }

    /**
     * @dev Same as {upperBound}, but with an array in memory.
     */
    function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
        uint256 low = 0;
        uint256 high = array.length;

        if (high == 0) {
            return 0;
        }

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds towards zero (it does integer division with truncation).
            if (unsafeMemoryAccess(array, mid) > element) {
                high = mid;
            } else {
                // this cannot overflow because mid < high
                unchecked {
                    low = mid + 1;
                }
            }
        }

        return low;
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
        bytes32 slot;
        assembly ("memory-safe") {
            slot := arr.slot
        }
        return slot.deriveArray().offset(pos).getAddressSlot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
        bytes32 slot;
        assembly ("memory-safe") {
            slot := arr.slot
        }
        return slot.deriveArray().offset(pos).getBytes32Slot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
        bytes32 slot;
        assembly ("memory-safe") {
            slot := arr.slot
        }
        return slot.deriveArray().offset(pos).getUint256Slot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {
        assembly {
            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
        }
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {
        assembly {
            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
        }
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {
        assembly {
            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
        }
    }

    /**
     * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden.
     *
     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
     */
    function unsafeSetLength(address[] storage array, uint256 len) internal {
        assembly ("memory-safe") {
            sstore(array.slot, len)
        }
    }

    /**
     * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden.
     *
     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
     */
    function unsafeSetLength(bytes32[] storage array, uint256 len) internal {
        assembly ("memory-safe") {
            sstore(array.slot, len)
        }
    }

    /**
     * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden.
     *
     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
     */
    function unsafeSetLength(uint256[] storage array, uint256 len) internal {
        assembly ("memory-safe") {
            sstore(array.slot, len)
        }
    }
}

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


// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/ERC1155.sol)

pragma solidity ^0.8.20;








/**
 * @dev Implementation of the basic standard multi-token.
 * See https://eips.ethereum.org/EIPS/eip-1155
 * Originally based on code by Enjin: https://github.com/enjin/erc-1155
 */
abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors {
    using Arrays for uint256[];
    using Arrays for address[];

    mapping(uint256 id => mapping(address account => uint256)) private _balances;

    mapping(address account => mapping(address operator => bool)) private _operatorApprovals;

    // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
    string private _uri;

    /**
     * @dev See {_setURI}.
     */
    constructor(string memory uri_) {
        _setURI(uri_);
    }

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

    /**
     * @dev See {IERC1155MetadataURI-uri}.
     *
     * This implementation returns the same URI for *all* token types. It relies
     * on the token type ID substitution mechanism
     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the ERC].
     *
     * Clients calling this function must replace the `\{id\}` substring with the
     * actual token type ID.
     */
    function uri(uint256 /* id */) public view virtual returns (string memory) {
        return _uri;
    }

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

    /**
     * @dev See {IERC1155-balanceOfBatch}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(
        address[] memory accounts,
        uint256[] memory ids
    ) public view virtual returns (uint256[] memory) {
        if (accounts.length != ids.length) {
            revert ERC1155InvalidArrayLength(ids.length, accounts.length);
        }

        uint256[] memory batchBalances = new uint256[](accounts.length);

        for (uint256 i = 0; i < accounts.length; ++i) {
            batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));
        }

        return batchBalances;
    }

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

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

    /**
     * @dev See {IERC1155-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual {
        address sender = _msgSender();
        if (from != sender && !isApprovedForAll(from, sender)) {
            revert ERC1155MissingApprovalForAll(sender, from);
        }
        _safeTransferFrom(from, to, id, value, data);
    }

    /**
     * @dev See {IERC1155-safeBatchTransferFrom}.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory values,
        bytes memory data
    ) public virtual {
        address sender = _msgSender();
        if (from != sender && !isApprovedForAll(from, sender)) {
            revert ERC1155MissingApprovalForAll(sender, from);
        }
        _safeBatchTransferFrom(from, to, ids, values, data);
    }

    /**
     * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from`
     * (or `to`) is the zero address.
     *
     * Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received}
     *   or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value.
     * - `ids` and `values` must have the same length.
     *
     * NOTE: The ERC-1155 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead.
     */
    function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual {
        if (ids.length != values.length) {
            revert ERC1155InvalidArrayLength(ids.length, values.length);
        }

        address operator = _msgSender();

        for (uint256 i = 0; i < ids.length; ++i) {
            uint256 id = ids.unsafeMemoryAccess(i);
            uint256 value = values.unsafeMemoryAccess(i);

            if (from != address(0)) {
                uint256 fromBalance = _balances[id][from];
                if (fromBalance < value) {
                    revert ERC1155InsufficientBalance(from, fromBalance, value, id);
                }
                unchecked {
                    // Overflow not possible: value <= fromBalance
                    _balances[id][from] = fromBalance - value;
                }
            }

            if (to != address(0)) {
                _balances[id][to] += value;
            }
        }

        if (ids.length == 1) {
            uint256 id = ids.unsafeMemoryAccess(0);
            uint256 value = values.unsafeMemoryAccess(0);
            emit TransferSingle(operator, from, to, id, value);
        } else {
            emit TransferBatch(operator, from, to, ids, values);
        }
    }

    /**
     * @dev Version of {_update} that performs the token acceptance check by calling
     * {IERC1155Receiver-onERC1155Received} or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it
     * contains code (eg. is a smart contract at the moment of execution).
     *
     * IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any
     * update to the contract state after this function would break the check-effect-interaction pattern. Consider
     * overriding {_update} instead.
     */
    function _updateWithAcceptanceCheck(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory values,
        bytes memory data
    ) internal virtual {
        _update(from, to, ids, values);
        if (to != address(0)) {
            address operator = _msgSender();
            if (ids.length == 1) {
                uint256 id = ids.unsafeMemoryAccess(0);
                uint256 value = values.unsafeMemoryAccess(0);
                ERC1155Utils.checkOnERC1155Received(operator, from, to, id, value, data);
            } else {
                ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, data);
            }
        }
    }

    /**
     * @dev Transfers a `value` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `from` must have a balance of tokens of type `id` of at least `value` amount.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal {
        if (to == address(0)) {
            revert ERC1155InvalidReceiver(address(0));
        }
        if (from == address(0)) {
            revert ERC1155InvalidSender(address(0));
        }
        (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
        _updateWithAcceptanceCheck(from, to, ids, values, data);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     * - `ids` and `values` must have the same length.
     */
    function _safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory values,
        bytes memory data
    ) internal {
        if (to == address(0)) {
            revert ERC1155InvalidReceiver(address(0));
        }
        if (from == address(0)) {
            revert ERC1155InvalidSender(address(0));
        }
        _updateWithAcceptanceCheck(from, to, ids, values, data);
    }

    /**
     * @dev Sets a new URI for all token types, by relying on the token type ID
     * substitution mechanism
     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the ERC].
     *
     * By this mechanism, any occurrence of the `\{id\}` substring in either the
     * URI or any of the values in the JSON file at said URI will be replaced by
     * clients with the token type ID.
     *
     * For example, the `https://token-cdn-domain/\{id\}.json` URI would be
     * interpreted by clients as
     * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
     * for token type ID 0x4cce0.
     *
     * See {uri}.
     *
     * Because these URIs cannot be meaningfully represented by the {URI} event,
     * this function emits no events.
     */
    function _setURI(string memory newuri) internal virtual {
        _uri = newuri;
    }

    /**
     * @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {
        if (to == address(0)) {
            revert ERC1155InvalidReceiver(address(0));
        }
        (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
        _updateWithAcceptanceCheck(address(0), to, ids, values, data);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `values` must have the same length.
     * - `to` cannot be the zero address.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal {
        if (to == address(0)) {
            revert ERC1155InvalidReceiver(address(0));
        }
        _updateWithAcceptanceCheck(address(0), to, ids, values, data);
    }

    /**
     * @dev Destroys a `value` amount of tokens of type `id` from `from`
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `from` must have at least `value` amount of tokens of type `id`.
     */
    function _burn(address from, uint256 id, uint256 value) internal {
        if (from == address(0)) {
            revert ERC1155InvalidSender(address(0));
        }
        (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
        _updateWithAcceptanceCheck(from, address(0), ids, values, "");
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `from` must have at least `value` amount of tokens of type `id`.
     * - `ids` and `values` must have the same length.
     */
    function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal {
        if (from == address(0)) {
            revert ERC1155InvalidSender(address(0));
        }
        _updateWithAcceptanceCheck(from, address(0), ids, values, "");
    }

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

    /**
     * @dev Creates an array in memory with only one value for each of the elements provided.
     */
    function _asSingletonArrays(
        uint256 element1,
        uint256 element2
    ) private pure returns (uint256[] memory array1, uint256[] memory array2) {
        assembly ("memory-safe") {
            // Load the free memory pointer
            array1 := mload(0x40)
            // Set array length to 1
            mstore(array1, 1)
            // Store the single element at the next word after the length (where content starts)
            mstore(add(array1, 0x20), element1)

            // Repeat for next array locating it right after the first array
            array2 := add(array1, 0x40)
            mstore(array2, 1)
            mstore(add(array2, 0x20), element2)

            // Update the free memory pointer by pointing after the second array
            mstore(0x40, add(array2, 0x40))
        }
    }
}

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


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

pragma solidity ^0.8.20;


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

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

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

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

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

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

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

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


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

pragma solidity ^0.8.20;


/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
     *
     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
     * one branch when needed, making this function more expensive.
     */
    function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
        unchecked {
            // branchless ternary works because:
            // b ^ (a ^ b) == a
            // b ^ 0 == b
            return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
        }
    }

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

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

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

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
            // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
            // taking advantage of the most significant (or "sign" bit) in two's complement representation.
            // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
            // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
            int256 mask = n >> 255;

            // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
            return uint256((n + mask) ^ mask);
        }
    }
}

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


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

pragma solidity ^0.8.20;




/**
 * @dev String operations.
 */
library Strings {
    using SafeCast for *;

    bytes16 private constant HEX_DIGITS = "0123456789abcdef";
    uint8 private constant ADDRESS_LENGTH = 20;

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

    /**
     * @dev The string being parsed contains characters that are not in scope of the given base.
     */
    error StringsInvalidChar();

    /**
     * @dev The string being parsed is not a properly formatted address.
     */
    error StringsInvalidAddressFormat();

    /**
     * @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;
            assembly ("memory-safe") {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                assembly ("memory-safe") {
                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

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

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

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

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

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
     * representation, according to EIP-55.
     */
    function toChecksumHexString(address addr) internal pure returns (string memory) {
        bytes memory buffer = bytes(toHexString(addr));

        // hash the hex part of buffer (skip length + 2 bytes, length 40)
        uint256 hashValue;
        assembly ("memory-safe") {
            hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
        }

        for (uint256 i = 41; i > 1; --i) {
            // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
            if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
                // case shift by xoring with 0x20
                buffer[i] ^= 0x20;
            }
            hashValue >>= 4;
        }
        return string(buffer);
    }

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

    /**
     * @dev Parse a decimal string and returns the value as a `uint256`.
     *
     * Requirements:
     * - The string must be formatted as `[0-9]*`
     * - The result must fit into an `uint256` type
     */
    function parseUint(string memory input) internal pure returns (uint256) {
        return parseUint(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `[0-9]*`
     * - The result must fit into an `uint256` type
     */
    function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
        (bool success, uint256 value) = tryParseUint(input, begin, end);
        if (!success) revert StringsInvalidChar();
        return value;
    }

    /**
     * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {
        return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid
     * character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseUint(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, uint256 value) {
        if (end > bytes(input).length || begin > end) return (false, 0);
        return _tryParseUintUncheckedBounds(input, begin, end);
    }

    /**
     * @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that
     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
     */
    function _tryParseUintUncheckedBounds(
        string memory input,
        uint256 begin,
        uint256 end
    ) private pure returns (bool success, uint256 value) {
        bytes memory buffer = bytes(input);

        uint256 result = 0;
        for (uint256 i = begin; i < end; ++i) {
            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
            if (chr > 9) return (false, 0);
            result *= 10;
            result += chr;
        }
        return (true, result);
    }

    /**
     * @dev Parse a decimal string and returns the value as a `int256`.
     *
     * Requirements:
     * - The string must be formatted as `[-+]?[0-9]*`
     * - The result must fit in an `int256` type.
     */
    function parseInt(string memory input) internal pure returns (int256) {
        return parseInt(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `[-+]?[0-9]*`
     * - The result must fit in an `int256` type.
     */
    function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {
        (bool success, int256 value) = tryParseInt(input, begin, end);
        if (!success) revert StringsInvalidChar();
        return value;
    }

    /**
     * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if
     * the result does not fit in a `int256`.
     *
     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
     */
    function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {
        return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);
    }

    uint256 private constant ABS_MIN_INT256 = 2 ** 255;

    /**
     * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid
     * character or if the result does not fit in a `int256`.
     *
     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
     */
    function tryParseInt(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, int256 value) {
        if (end > bytes(input).length || begin > end) return (false, 0);
        return _tryParseIntUncheckedBounds(input, begin, end);
    }

    /**
     * @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that
     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
     */
    function _tryParseIntUncheckedBounds(
        string memory input,
        uint256 begin,
        uint256 end
    ) private pure returns (bool success, int256 value) {
        bytes memory buffer = bytes(input);

        // Check presence of a negative sign.
        bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
        bool positiveSign = sign == bytes1("+");
        bool negativeSign = sign == bytes1("-");
        uint256 offset = (positiveSign || negativeSign).toUint();

        (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);

        if (absSuccess && absValue < ABS_MIN_INT256) {
            return (true, negativeSign ? -int256(absValue) : int256(absValue));
        } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {
            return (true, type(int256).min);
        } else return (false, 0);
    }

    /**
     * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`.
     *
     * Requirements:
     * - The string must be formatted as `(0x)?[0-9a-fA-F]*`
     * - The result must fit in an `uint256` type.
     */
    function parseHexUint(string memory input) internal pure returns (uint256) {
        return parseHexUint(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`
     * - The result must fit in an `uint256` type.
     */
    function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
        (bool success, uint256 value) = tryParseHexUint(input, begin, end);
        if (!success) revert StringsInvalidChar();
        return value;
    }

    /**
     * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {
        return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an
     * invalid character.
     *
     * NOTE: This function will revert if the result does not fit in a `uint256`.
     */
    function tryParseHexUint(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, uint256 value) {
        if (end > bytes(input).length || begin > end) return (false, 0);
        return _tryParseHexUintUncheckedBounds(input, begin, end);
    }

    /**
     * @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that
     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
     */
    function _tryParseHexUintUncheckedBounds(
        string memory input,
        uint256 begin,
        uint256 end
    ) private pure returns (bool success, uint256 value) {
        bytes memory buffer = bytes(input);

        // skip 0x prefix if present
        bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
        uint256 offset = hasPrefix.toUint() * 2;

        uint256 result = 0;
        for (uint256 i = begin + offset; i < end; ++i) {
            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
            if (chr > 15) return (false, 0);
            result *= 16;
            unchecked {
                // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
                // This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked.
                result += chr;
            }
        }
        return (true, result);
    }

    /**
     * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`.
     *
     * Requirements:
     * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`
     */
    function parseAddress(string memory input) internal pure returns (address) {
        return parseAddress(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and
     * `end` (excluded).
     *
     * Requirements:
     * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`
     */
    function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {
        (bool success, address value) = tryParseAddress(input, begin, end);
        if (!success) revert StringsInvalidAddressFormat();
        return value;
    }

    /**
     * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
     * formatted address. See {parseAddress} requirements.
     */
    function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
        return tryParseAddress(input, 0, bytes(input).length);
    }

    /**
     * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
     * formatted address. See {parseAddress} requirements.
     */
    function tryParseAddress(
        string memory input,
        uint256 begin,
        uint256 end
    ) internal pure returns (bool success, address value) {
        if (end > bytes(input).length || begin > end) return (false, address(0));

        bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
        uint256 expectedLength = 40 + hasPrefix.toUint() * 2;

        // check that input is the correct length
        if (end - begin == expectedLength) {
            // length guarantees that this does not overflow, and value is at most type(uint160).max
            (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);
            return (s, address(uint160(v)));
        } else {
            return (false, address(0));
        }
    }

    function _tryParseChr(bytes1 chr) private pure returns (uint8) {
        uint8 value = uint8(chr);

        // Try to parse `chr`:
        // - Case 1: [0-9]
        // - Case 2: [a-f]
        // - Case 3: [A-F]
        // - otherwise not supported
        unchecked {
            if (value > 47 && value < 58) value -= 48;
            else if (value > 96 && value < 103) value -= 87;
            else if (value > 64 && value < 71) value -= 55;
            else return type(uint8).max;
        }

        return value;
    }

    /**
     * @dev Reads a bytes32 from a bytes array without bounds checking.
     *
     * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
     * assembly block as such would prevent some optimizations.
     */
    function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
        // This is not memory safe in the general case, but all calls to this private function are within bounds.
        assembly ("memory-safe") {
            value := mload(add(buffer, add(0x20, offset)))
        }
    }
}

// File: BoonOpolyClaim.sol

/*
 ____                                _____                        ___                 
/\  _`\                             /\  __`\                     /\_ \                
\ \ \L\ \    ___     ___     ___    \ \ \/\ \    _____     ___   \//\ \     __  __    
 \ \  _ <'  / __`\  / __`\ /' _ `\   \ \ \ \ \  /\ '__`\  / __`\   \ \ \   /\ \/\ \   
  \ \ \L\ \/\ \L\ \/\ \L\ \/\ \/\ \   \ \ \_\ \ \ \ \L\ \/\ \L\ \   \_\ \_ \ \ \_\ \  
   \ \____/\ \____/\ \____/\ \_\ \_\   \ \_____\ \ \ ,__/\ \____/   /\____\ \/`____ \ 
    \/___/  \/___/  \/___/  \/_/\/_/    \/_____/  \ \ \/  \/___/    \/____/  `/___/> \
                                                   \ \_\                        /\___/
                                                    \/_/                        \/__/  
*/

pragma solidity ^0.8.17;




contract BoonOpoly is ERC1155, Ownable {
    using Strings for uint256;

    string public name = "BoonOpoly"; 
    string public symbol = "BOON"; 
    string private baseURI;
    uint256 public totalMinted;
    uint256 public maxTotalSupply = 1000; // Matches the sum of all maxSupply values

    mapping(uint256 => uint256) public maxSupply;
    mapping(uint256 => uint256) public totalSupply;
    uint256[] private remainingPool;

    mapping(bytes32 => bool) public validMintCodes; // Store pre-approved hashes
    mapping(bytes32 => bool) public usedMintCodes;  // Prevent reuse

    event MintCodesAdded(uint256 count);
    event MintSuccess(address indexed minter, uint256 tokenId);
    event DebugMintCode(bytes32 indexed mintHash, bool isValid, bool isUsed);

    constructor(string memory baseURI_) ERC1155(baseURI_) Ownable(msg.sender) {
        baseURI = baseURI_;
        _initializeSupply();
        _populateRemainingPool();
    }

    /**
     * @dev Manually sets maxSupply for token IDs 1..70, using a 71-length array
     *      (index 0 unused). 
     */
    function _initializeSupply() internal {
        uint256[71] memory predefinedValues;

        // IDs 1 through 70
        predefinedValues[1] = 10;  
        predefinedValues[2] = 10;  
        predefinedValues[3] = 1;   
        predefinedValues[4] = 10;  
        predefinedValues[5] = 10;  
        predefinedValues[6] = 1;   
        predefinedValues[7] = 10;  
        predefinedValues[8] = 10;  
        predefinedValues[9] = 1;   
        predefinedValues[10] = 10; 
        predefinedValues[11] = 10; 
        predefinedValues[12] = 1;  
        predefinedValues[13] = 10; 
        predefinedValues[14] = 10; 
        predefinedValues[15] = 1;  
        predefinedValues[16] = 10; 
        predefinedValues[17] = 1;  
        predefinedValues[18] = 10; 
        predefinedValues[19] = 10; 
        predefinedValues[20] = 1;  
        predefinedValues[21] = 10; 
        predefinedValues[22] = 10; 
        predefinedValues[23] = 1;  
        predefinedValues[24] = 10; 
        predefinedValues[25] = 10; 
        predefinedValues[26] = 1;  
        predefinedValues[27] = 10; 
        predefinedValues[28] = 10; 
        predefinedValues[29] = 1;  
        predefinedValues[30] = 10; 
        predefinedValues[31] = 10; 
        predefinedValues[32] = 1;  
        predefinedValues[33] = 10; 
        predefinedValues[34] = 10; 
        predefinedValues[35] = 1;  
        predefinedValues[36] = 10; 
        predefinedValues[37] = 10; 
        predefinedValues[38] = 1;  
        predefinedValues[39] = 10; 
        predefinedValues[40] = 10; 
        predefinedValues[41] = 1;  
        predefinedValues[42] = 10; 
        predefinedValues[43] = 10; 
        predefinedValues[44] = 1;  
        predefinedValues[45] = 10; 
        predefinedValues[46] = 10; 
        predefinedValues[47] = 1;  
        predefinedValues[48] = 1;  
        predefinedValues[49] = 1;  
        predefinedValues[50] = 1;  
        predefinedValues[51] = 1;  
        predefinedValues[52] = 1;  
        predefinedValues[53] = 540; 
        predefinedValues[54] = 5;  
        predefinedValues[55] = 5;  
        predefinedValues[56] = 1;  
        predefinedValues[57] = 10; 
        predefinedValues[58] = 8;  
        predefinedValues[59] = 10; 
        predefinedValues[60] = 10; 
        predefinedValues[61] = 10; 
        predefinedValues[62] = 10; 
        predefinedValues[63] = 10; 
        predefinedValues[64] = 10; 
        predefinedValues[65] = 5;  
        predefinedValues[66] = 10; 
        predefinedValues[67] = 10; 
        predefinedValues[68] = 10; 
        predefinedValues[69] = 4;  
        predefinedValues[70] = 1;  

        // Assign each to maxSupply
        for (uint256 i = 1; i <= 70; i++) {
            maxSupply[i] = predefinedValues[i];
        }
    }

    /**
     * @dev Populate remainingPool with each tokenId repeated maxSupply[tokenId] times.
     *      
     */
    function _populateRemainingPool() internal {
        for (uint256 tokenId = 1; tokenId <= 70; tokenId++) {
            for (uint256 i = 0; i < maxSupply[tokenId]; i++) {
                remainingPool.push(tokenId);
            }
        }
    }

    /**
     * @dev Add new hashed mint codes (in batches up to 100). Only owner can call.
     */
    function addMintCodesBatch(bytes32[] memory hashedCodes) external onlyOwner {
        require(hashedCodes.length > 0, "Must provide codes");
        require(hashedCodes.length <= 100, "Batch limit: 100 codes per transaction");

        for (uint256 i = 0; i < hashedCodes.length; i++) {
            validMintCodes[hashedCodes[i]] = true;
            // Emit debug so we confirm the code was recorded
            emit DebugMintCode(hashedCodes[i], true, false);
        }

        emit MintCodesAdded(hashedCodes.length);
    }

    /**
     * @dev Mint a random token using a one-time-use mint code. 
     *      Probability of getting each tokenId is proportional to its supply.
     */
    function mintWithCode(string memory mintCode) external {
        require(totalMinted < maxTotalSupply, "All tokens minted");
        require(remainingPool.length > 0, "No tokens left to mint");

        bytes32 mintHash = keccak256(abi.encodePacked(mintCode));
        emit DebugMintCode(mintHash, validMintCodes[mintHash], usedMintCodes[mintHash]);

        require(validMintCodes[mintHash], "Invalid mint code");
        require(!usedMintCodes[mintHash], "Mint code already used");
        usedMintCodes[mintHash] = true;

        uint256 randomIndex = _random() % remainingPool.length;
        uint256 tokenId = remainingPool[randomIndex];

        require(totalSupply[tokenId] < maxSupply[tokenId], "TokenId max supply reached");

        totalSupply[tokenId] += 1;
        totalMinted += 1;
        _mint(msg.sender, tokenId, 1, "");

        _removeFromPool(randomIndex);
        emit MintSuccess(msg.sender, tokenId);
    }

    /**
     * @notice Helper function for verifying what hash any plain-text code produces.
     */
    function getMintHash(string memory mintCode) external pure returns (bytes32) {
        return keccak256(abi.encodePacked(mintCode));
    }

    /**
     * @dev Simple pseudo-random generator. 
     */
    function _random() internal view returns (uint256) {
        return uint256(
            keccak256(
                abi.encodePacked(
                    block.prevrandao,
                    block.timestamp,
                    msg.sender,
                    tx.gasprice,
                    blockhash(block.number - 1)
                )
            )
        );
    }

    /**
     * @dev Remove a tokenId from remainingPool by swapping with the last element.
     */
    function _removeFromPool(uint256 index) internal {
        require(index < remainingPool.length, "Index out of bounds");
        remainingPool[index] = remainingPool[remainingPool.length - 1];
        remainingPool.pop();
    }

    /**
     * @dev Returns metadata URI for the given tokenId.
     */
    function uri(uint256 tokenId) public view override returns (string memory) {
        require(tokenId > 0 && tokenId <= 70, "Invalid tokenId");
        return string(abi.encodePacked(baseURI, "/", tokenId.toString(), ".json"));
    }

    /**
     * @dev Owner can update the base URI if needed.
     */
    function setBaseURI(string memory baseURI_) external onlyOwner {
        baseURI = baseURI_;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"baseURI_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mintHash","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"isValid","type":"bool"},{"indexed":false,"internalType":"bool","name":"isUsed","type":"bool"}],"name":"DebugMintCode","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"count","type":"uint256"}],"name":"MintCodesAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"MintSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"bytes32[]","name":"hashedCodes","type":"bytes32[]"}],"name":"addMintCodesBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"mintCode","type":"string"}],"name":"getMintHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"mintCode","type":"string"}],"name":"mintWithCode","outputs":[],"stateMutability":"nonpayable","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":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"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":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"usedMintCodes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"validMintCodes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

60806040526040518060400160405280600981526020017f426f6f6e4f706f6c790000000000000000000000000000000000000000000000815250600490816100489190610e00565b506040518060400160405280600481526020017f424f4f4e000000000000000000000000000000000000000000000000000000008152506005908161008d9190610e00565b506103e860085534801561009f575f80fd5b50604051614abd380380614abd83398181016040528101906100c19190610fef565b33816100d28161018560201b60201c565b505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610143575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161013a9190611075565b60405180910390fd5b6101528161019860201b60201c565b5080600690816101629190610e00565b5061017161025b60201b60201c565b61017f610b3060201b60201c565b5061112f565b80600290816101949190610e00565b5050565b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b610263610ba3565b600a816001604781106102795761027861108e565b5b602002018181525050600a816002604781106102985761029761108e565b5b6020020181815250506001816003604781106102b7576102b661108e565b5b602002018181525050600a816004604781106102d6576102d561108e565b5b602002018181525050600a816005604781106102f5576102f461108e565b5b6020020181815250506001816006604781106103145761031361108e565b5b602002018181525050600a816007604781106103335761033261108e565b5b602002018181525050600a816008604781106103525761035161108e565b5b6020020181815250506001816009604781106103715761037061108e565b5b602002018181525050600a81600a604781106103905761038f61108e565b5b602002018181525050600a81600b604781106103af576103ae61108e565b5b602002018181525050600181600c604781106103ce576103cd61108e565b5b602002018181525050600a81600d604781106103ed576103ec61108e565b5b602002018181525050600a81600e6047811061040c5761040b61108e565b5b602002018181525050600181600f6047811061042b5761042a61108e565b5b602002018181525050600a8160106047811061044a5761044961108e565b5b6020020181815250506001816011604781106104695761046861108e565b5b602002018181525050600a816012604781106104885761048761108e565b5b602002018181525050600a816013604781106104a7576104a661108e565b5b6020020181815250506001816014604781106104c6576104c561108e565b5b602002018181525050600a816015604781106104e5576104e461108e565b5b602002018181525050600a816016604781106105045761050361108e565b5b6020020181815250506001816017604781106105235761052261108e565b5b602002018181525050600a816018604781106105425761054161108e565b5b602002018181525050600a816019604781106105615761056061108e565b5b602002018181525050600181601a604781106105805761057f61108e565b5b602002018181525050600a81601b6047811061059f5761059e61108e565b5b602002018181525050600a81601c604781106105be576105bd61108e565b5b602002018181525050600181601d604781106105dd576105dc61108e565b5b602002018181525050600a81601e604781106105fc576105fb61108e565b5b602002018181525050600a81601f6047811061061b5761061a61108e565b5b60200201818152505060018160206047811061063a5761063961108e565b5b602002018181525050600a816021604781106106595761065861108e565b5b602002018181525050600a816022604781106106785761067761108e565b5b6020020181815250506001816023604781106106975761069661108e565b5b602002018181525050600a816024604781106106b6576106b561108e565b5b602002018181525050600a816025604781106106d5576106d461108e565b5b6020020181815250506001816026604781106106f4576106f361108e565b5b602002018181525050600a816027604781106107135761071261108e565b5b602002018181525050600a816028604781106107325761073161108e565b5b6020020181815250506001816029604781106107515761075061108e565b5b602002018181525050600a81602a604781106107705761076f61108e565b5b602002018181525050600a81602b6047811061078f5761078e61108e565b5b602002018181525050600181602c604781106107ae576107ad61108e565b5b602002018181525050600a81602d604781106107cd576107cc61108e565b5b602002018181525050600a81602e604781106107ec576107eb61108e565b5b602002018181525050600181602f6047811061080b5761080a61108e565b5b60200201818152505060018160306047811061082a5761082961108e565b5b6020020181815250506001816031604781106108495761084861108e565b5b6020020181815250506001816032604781106108685761086761108e565b5b6020020181815250506001816033604781106108875761088661108e565b5b6020020181815250506001816034604781106108a6576108a561108e565b5b60200201818152505061021c816035604781106108c6576108c561108e565b5b6020020181815250506005816036604781106108e5576108e461108e565b5b6020020181815250506005816037604781106109045761090361108e565b5b6020020181815250506001816038604781106109235761092261108e565b5b602002018181525050600a816039604781106109425761094161108e565b5b602002018181525050600881603a604781106109615761096061108e565b5b602002018181525050600a81603b604781106109805761097f61108e565b5b602002018181525050600a81603c6047811061099f5761099e61108e565b5b602002018181525050600a81603d604781106109be576109bd61108e565b5b602002018181525050600a81603e604781106109dd576109dc61108e565b5b602002018181525050600a81603f604781106109fc576109fb61108e565b5b602002018181525050600a81604060478110610a1b57610a1a61108e565b5b602002018181525050600581604160478110610a3a57610a3961108e565b5b602002018181525050600a81604260478110610a5957610a5861108e565b5b602002018181525050600a81604360478110610a7857610a7761108e565b5b602002018181525050600a81604460478110610a9757610a9661108e565b5b602002018181525050600481604560478110610ab657610ab561108e565b5b602002018181525050600181604660478110610ad557610ad461108e565b5b6020020181815250505f600190505b60468111610b2c57818160478110610aff57610afe61108e565b5b602002015160095f8381526020019081526020015f20819055508080610b24906110e8565b915050610ae4565b5050565b5f600190505b60468111610ba0575f5b60095f8381526020019081526020015f2054811015610b8c57600b82908060018154018082558091505060019003905f5260205f20015f90919091909150558080600101915050610b40565b508080610b98906110e8565b915050610b36565b50565b604051806108e00160405280604790602082028036833780820191505090505090565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610c4157607f821691505b602082108103610c5457610c53610bfd565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302610cb67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610c7b565b610cc08683610c7b565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f610d04610cff610cfa84610cd8565b610ce1565b610cd8565b9050919050565b5f819050919050565b610d1d83610cea565b610d31610d2982610d0b565b848454610c87565b825550505050565b5f90565b610d45610d39565b610d50818484610d14565b505050565b5b81811015610d7357610d685f82610d3d565b600181019050610d56565b5050565b601f821115610db857610d8981610c5a565b610d9284610c6c565b81016020851015610da1578190505b610db5610dad85610c6c565b830182610d55565b50505b505050565b5f82821c905092915050565b5f610dd85f1984600802610dbd565b1980831691505092915050565b5f610df08383610dc9565b9150826002028217905092915050565b610e0982610bc6565b67ffffffffffffffff811115610e2257610e21610bd0565b5b610e2c8254610c2a565b610e37828285610d77565b5f60209050601f831160018114610e68575f8415610e56578287015190505b610e608582610de5565b865550610ec7565b601f198416610e7686610c5a565b5f5b82811015610e9d57848901518255600182019150602085019450602081019050610e78565b86831015610eba5784890151610eb6601f891682610dc9565b8355505b6001600288020188555050505b505050505050565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b610f0182610ee8565b810181811067ffffffffffffffff82111715610f2057610f1f610bd0565b5b80604052505050565b5f610f32610ecf565b9050610f3e8282610ef8565b919050565b5f67ffffffffffffffff821115610f5d57610f5c610bd0565b5b610f6682610ee8565b9050602081019050919050565b8281835e5f83830152505050565b5f610f93610f8e84610f43565b610f29565b905082815260208101848484011115610faf57610fae610ee4565b5b610fba848285610f73565b509392505050565b5f82601f830112610fd657610fd5610ee0565b5b8151610fe6848260208601610f81565b91505092915050565b5f6020828403121561100457611003610ed8565b5b5f82015167ffffffffffffffff81111561102157611020610edc565b5b61102d84828501610fc2565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61105f82611036565b9050919050565b61106f81611055565b82525050565b5f6020820190506110885f830184611066565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6110f282610cd8565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611124576111236110bb565b5b600182019050919050565b6139818061113c5f395ff3fe608060405234801561000f575f80fd5b506004361061014a575f3560e01c8063715018a6116100c1578063bd85b0391161007a578063bd85b0391461039a578063e985e9c5146103ca578063f242432a146103fa578063f2fde38b14610416578063f3e542b114610432578063fbd9e6d7146104625761014a565b8063715018a6146102ea578063869f7594146102f45780638da5cb5b1461032457806395d89b4114610342578063a22cb46514610360578063a2309ff81461037c5761014a565b80632bdead67116101135780632bdead671461021a5780632eb2c2d61461024a5780633cd9d366146102665780634e1273f41461028257806355f804b3146102b2578063660ad581146102ce5761014a565b8062fdd58e1461014e57806301ffc9a71461017e57806306fdde03146101ae5780630e89341c146101cc5780632ab4d052146101fc575b5f80fd5b61016860048036038101906101639190612214565b610492565b6040516101759190612261565b60405180910390f35b610198600480360381019061019391906122cf565b6104e7565b6040516101a59190612314565b60405180910390f35b6101b66105c8565b6040516101c3919061239d565b60405180910390f35b6101e660048036038101906101e191906123bd565b610654565b6040516101f3919061239d565b60405180910390f35b6102046106d7565b6040516102119190612261565b60405180910390f35b610234600480360381019061022f9190612514565b6106dd565b6040516102419190612573565b60405180910390f35b610264600480360381019061025f91906126ee565b61070c565b005b610280600480360381019061027b9190612514565b6107b3565b005b61029c60048036038101906102979190612879565b610b1a565b6040516102a991906129a6565b60405180910390f35b6102cc60048036038101906102c79190612514565b610c21565b005b6102e860048036038101906102e39190612ab0565b610c3c565b005b6102f2610db8565b005b61030e600480360381019061030991906123bd565b610dcb565b60405161031b9190612261565b60405180910390f35b61032c610de0565b6040516103399190612b06565b60405180910390f35b61034a610e08565b604051610357919061239d565b60405180910390f35b61037a60048036038101906103759190612b49565b610e94565b005b610384610eaa565b6040516103919190612261565b60405180910390f35b6103b460048036038101906103af91906123bd565b610eb0565b6040516103c19190612261565b60405180910390f35b6103e460048036038101906103df9190612b87565b610ec5565b6040516103f19190612314565b60405180910390f35b610414600480360381019061040f9190612bc5565b610f53565b005b610430600480360381019061042b9190612c58565b610ffa565b005b61044c60048036038101906104479190612c83565b61107e565b6040516104599190612314565b60405180910390f35b61047c60048036038101906104779190612c83565b61109b565b6040516104899190612314565b60405180910390f35b5f805f8381526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806105b157507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806105c157506105c0826110b8565b5b9050919050565b600480546105d590612cdb565b80601f016020809104026020016040519081016040528092919081815260200182805461060190612cdb565b801561064c5780601f106106235761010080835404028352916020019161064c565b820191905f5260205f20905b81548152906001019060200180831161062f57829003601f168201915b505050505081565b60605f82118015610666575060468211155b6106a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161069c90612d55565b60405180910390fd5b60066106b083611121565b6040516020016106c1929190612ed3565b6040516020818303038152906040529050919050565b60085481565b5f816040516020016106ef9190612f0c565b604051602081830303815290604052805190602001209050919050565b5f6107156111eb565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415801561075a57506107588682610ec5565b155b1561079e5780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401610795929190612f22565b60405180910390fd5b6107ab86868686866111f2565b505050505050565b600854600754106107f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f090612f93565b60405180910390fd5b5f600b8054905011610840576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083790612ffb565b60405180910390fd5b5f816040516020016108529190612f0c565b604051602081830303815290604052805190602001209050807fdeb8163679653dd103b544e8fc87a1d13a101d771df35c659a2737e60ce19f75600c5f8481526020019081526020015f205f9054906101000a900460ff16600d5f8581526020019081526020015f205f9054906101000a900460ff166040516108d6929190613019565b60405180910390a2600c5f8281526020019081526020015f205f9054906101000a900460ff1661093b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109329061308a565b60405180910390fd5b600d5f8281526020019081526020015f205f9054906101000a900460ff1615610999576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610990906130f2565b60405180910390fd5b6001600d5f8381526020019081526020015f205f6101000a81548160ff0219169083151502179055505f600b805490506109d16112e6565b6109db919061313d565b90505f600b82815481106109f2576109f161316d565b5b905f5260205f200154905060095f8281526020019081526020015f2054600a5f8381526020019081526020015f205410610a61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a58906131e4565b60405180910390fd5b6001600a5f8381526020019081526020015f205f828254610a82919061322f565b92505081905550600160075f828254610a9b919061322f565b92505081905550610abd3382600160405180602001604052805f81525061132a565b610ac6826113bf565b3373ffffffffffffffffffffffffffffffffffffffff167fcda531bfd68624f13205c0a23cd4d5a7f09792cbb399603114f2b04aaa1bf5cf82604051610b0c9190612261565b60405180910390a250505050565b60608151835114610b6657815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401610b5d929190613262565b60405180910390fd5b5f835167ffffffffffffffff811115610b8257610b816123f0565b5b604051908082528060200260200182016040528015610bb05781602001602082028036833780820191505090505b5090505f5b8451811015610c1657610bec610bd4828761147c90919063ffffffff16565b610be7838761148f90919063ffffffff16565b610492565b828281518110610bff57610bfe61316d565b5b602002602001018181525050806001019050610bb5565b508091505092915050565b610c296114a2565b8060069081610c389190613414565b5050565b610c446114a2565b5f815111610c87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c7e9061352d565b60405180910390fd5b606481511115610ccc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc3906135bb565b60405180910390fd5b5f5b8151811015610d7c576001600c5f848481518110610cef57610cee61316d565b5b602002602001015181526020019081526020015f205f6101000a81548160ff021916908315150217905550818181518110610d2d57610d2c61316d565b5b60200260200101517fdeb8163679653dd103b544e8fc87a1d13a101d771df35c659a2737e60ce19f7560015f604051610d67929190613019565b60405180910390a28080600101915050610cce565b507f4ff7494e45201c2881ee358d40945fab727ff0e1ad9bb01401ce443685493d7a8151604051610dad9190612261565b60405180910390a150565b610dc06114a2565b610dc95f611529565b565b6009602052805f5260405f205f915090505481565b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60058054610e1590612cdb565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4190612cdb565b8015610e8c5780601f10610e6357610100808354040283529160200191610e8c565b820191905f5260205f20905b815481529060010190602001808311610e6f57829003601f168201915b505050505081565b610ea6610e9f6111eb565b83836115ec565b5050565b60075481565b600a602052805f5260405f205f915090505481565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f610f5c6111eb565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015610fa15750610f9f8682610ec5565b155b15610fe55780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401610fdc929190612f22565b60405180910390fd5b610ff28686868686611755565b505050505050565b6110026114a2565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611072575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016110699190612b06565b60405180910390fd5b61107b81611529565b50565b600d602052805f5260405f205f915054906101000a900460ff1681565b600c602052805f5260405f205f915054906101000a900460ff1681565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60605f600161112f8461185b565b0190505f8167ffffffffffffffff81111561114d5761114c6123f0565b5b6040519080825280601f01601f19166020018201604052801561117f5781602001600182028036833780820191505090505b5090505f82602001820190505b6001156111e0578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816111d5576111d4613110565b5b0494505f850361118c575b819350505050919050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611262575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016112599190612b06565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036112d2575f6040517f01a835140000000000000000000000000000000000000000000000000000000081526004016112c99190612b06565b60405180910390fd5b6112df85858585856119ac565b5050505050565b5f4442333a6001436112f891906135d9565b4060405160200161130d959493929190613691565b604051602081830303815290604052805190602001205f1c905090565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361139a575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016113919190612b06565b60405180910390fd5b5f806113a68585611a58565b915091506113b75f878484876119ac565b505050505050565b600b805490508110611406576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113fd90613739565b60405180910390fd5b600b6001600b8054905061141a91906135d9565b8154811061142b5761142a61316d565b5b905f5260205f200154600b82815481106114485761144761316d565b5b905f5260205f200181905550600b80548061146657611465613757565b5b600190038181905f5260205f20015f9055905550565b5f60208202602084010151905092915050565b5f60208202602084010151905092915050565b6114aa6111eb565b73ffffffffffffffffffffffffffffffffffffffff166114c8610de0565b73ffffffffffffffffffffffffffffffffffffffff1614611527576114eb6111eb565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161151e9190612b06565b60405180910390fd5b565b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361165c575f6040517fced3e1000000000000000000000000000000000000000000000000000000000081526004016116539190612b06565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516117489190612314565b60405180910390a3505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036117c5575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016117bc9190612b06565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611835575f6040517f01a8351400000000000000000000000000000000000000000000000000000000815260040161182c9190612b06565b60405180910390fd5b5f806118418585611a58565b9150915061185287878484876119ac565b50505050505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106118b7577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816118ad576118ac613110565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106118f4576d04ee2d6d415b85acef810000000083816118ea576118e9613110565b5b0492506020810190505b662386f26fc10000831061192357662386f26fc10000838161191957611918613110565b5b0492506010810190505b6305f5e100831061194c576305f5e100838161194257611941613110565b5b0492506008810190505b612710831061197157612710838161196757611966613110565b5b0492506004810190505b60648310611994576064838161198a57611989613110565b5b0492506002810190505b600a83106119a3576001810190505b80915050919050565b6119b885858585611a88565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614611a51575f6119f46111eb565b90506001845103611a40575f611a135f8661148f90919063ffffffff16565b90505f611a295f8661148f90919063ffffffff16565b9050611a39838989858589611e18565b5050611a4f565b611a4e818787878787611fc7565b5b505b5050505050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b8051825114611ad257815181516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401611ac9929190613262565b60405180910390fd5b5f611adb6111eb565b90505f5b8351811015611cd7575f611afc828661148f90919063ffffffff16565b90505f611b12838661148f90919063ffffffff16565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614611c35575f805f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015611be157888183856040517f03dee4c5000000000000000000000000000000000000000000000000000000008152600401611bd89493929190613784565b60405180910390fd5b8181035f808581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614611cca57805f808481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611cc2919061322f565b925050819055505b5050806001019050611adf565b506001835103611d92575f611cf55f8561148f90919063ffffffff16565b90505f611d0b5f8561148f90919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051611d83929190613262565b60405180910390a45050611e11565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051611e089291906137c7565b60405180910390a45b5050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115611fbf578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401611e7895949392919061384e565b6020604051808303815f875af1925050508015611eb357506040513d601f19601f82011682018060405250810190611eb091906138ba565b60015b611f34573d805f8114611ee1576040519150601f19603f3d011682016040523d82523d5f602084013e611ee6565b606091505b505f815103611f2c57846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611f239190612b06565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611fbd57846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611fb49190612b06565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b111561216e578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b81526004016120279594939291906138e5565b6020604051808303815f875af192505050801561206257506040513d601f19601f8201168201806040525081019061205f91906138ba565b60015b6120e3573d805f8114612090576040519150601f19603f3d011682016040523d82523d5f602084013e612095565b606091505b505f8151036120db57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016120d29190612b06565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461216c57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016121639190612b06565b60405180910390fd5b505b505050505050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6121b082612187565b9050919050565b6121c0816121a6565b81146121ca575f80fd5b50565b5f813590506121db816121b7565b92915050565b5f819050919050565b6121f3816121e1565b81146121fd575f80fd5b50565b5f8135905061220e816121ea565b92915050565b5f806040838503121561222a5761222961217f565b5b5f612237858286016121cd565b925050602061224885828601612200565b9150509250929050565b61225b816121e1565b82525050565b5f6020820190506122745f830184612252565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6122ae8161227a565b81146122b8575f80fd5b50565b5f813590506122c9816122a5565b92915050565b5f602082840312156122e4576122e361217f565b5b5f6122f1848285016122bb565b91505092915050565b5f8115159050919050565b61230e816122fa565b82525050565b5f6020820190506123275f830184612305565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61236f8261232d565b6123798185612337565b9350612389818560208601612347565b61239281612355565b840191505092915050565b5f6020820190508181035f8301526123b58184612365565b905092915050565b5f602082840312156123d2576123d161217f565b5b5f6123df84828501612200565b91505092915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61242682612355565b810181811067ffffffffffffffff82111715612445576124446123f0565b5b80604052505050565b5f612457612176565b9050612463828261241d565b919050565b5f67ffffffffffffffff821115612482576124816123f0565b5b61248b82612355565b9050602081019050919050565b828183375f83830152505050565b5f6124b86124b384612468565b61244e565b9050828152602081018484840111156124d4576124d36123ec565b5b6124df848285612498565b509392505050565b5f82601f8301126124fb576124fa6123e8565b5b813561250b8482602086016124a6565b91505092915050565b5f602082840312156125295761252861217f565b5b5f82013567ffffffffffffffff81111561254657612545612183565b5b612552848285016124e7565b91505092915050565b5f819050919050565b61256d8161255b565b82525050565b5f6020820190506125865f830184612564565b92915050565b5f67ffffffffffffffff8211156125a6576125a56123f0565b5b602082029050602081019050919050565b5f80fd5b5f6125cd6125c88461258c565b61244e565b905080838252602082019050602084028301858111156125f0576125ef6125b7565b5b835b8181101561261957806126058882612200565b8452602084019350506020810190506125f2565b5050509392505050565b5f82601f830112612637576126366123e8565b5b81356126478482602086016125bb565b91505092915050565b5f67ffffffffffffffff82111561266a576126696123f0565b5b61267382612355565b9050602081019050919050565b5f61269261268d84612650565b61244e565b9050828152602081018484840111156126ae576126ad6123ec565b5b6126b9848285612498565b509392505050565b5f82601f8301126126d5576126d46123e8565b5b81356126e5848260208601612680565b91505092915050565b5f805f805f60a086880312156127075761270661217f565b5b5f612714888289016121cd565b9550506020612725888289016121cd565b945050604086013567ffffffffffffffff81111561274657612745612183565b5b61275288828901612623565b935050606086013567ffffffffffffffff81111561277357612772612183565b5b61277f88828901612623565b925050608086013567ffffffffffffffff8111156127a05761279f612183565b5b6127ac888289016126c1565b9150509295509295909350565b5f67ffffffffffffffff8211156127d3576127d26123f0565b5b602082029050602081019050919050565b5f6127f66127f1846127b9565b61244e565b90508083825260208201905060208402830185811115612819576128186125b7565b5b835b81811015612842578061282e88826121cd565b84526020840193505060208101905061281b565b5050509392505050565b5f82601f8301126128605761285f6123e8565b5b81356128708482602086016127e4565b91505092915050565b5f806040838503121561288f5761288e61217f565b5b5f83013567ffffffffffffffff8111156128ac576128ab612183565b5b6128b88582860161284c565b925050602083013567ffffffffffffffff8111156128d9576128d8612183565b5b6128e585828601612623565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b612921816121e1565b82525050565b5f6129328383612918565b60208301905092915050565b5f602082019050919050565b5f612954826128ef565b61295e81856128f9565b935061296983612909565b805f5b838110156129995781516129808882612927565b975061298b8361293e565b92505060018101905061296c565b5085935050505092915050565b5f6020820190508181035f8301526129be818461294a565b905092915050565b5f67ffffffffffffffff8211156129e0576129df6123f0565b5b602082029050602081019050919050565b6129fa8161255b565b8114612a04575f80fd5b50565b5f81359050612a15816129f1565b92915050565b5f612a2d612a28846129c6565b61244e565b90508083825260208201905060208402830185811115612a5057612a4f6125b7565b5b835b81811015612a795780612a658882612a07565b845260208401935050602081019050612a52565b5050509392505050565b5f82601f830112612a9757612a966123e8565b5b8135612aa7848260208601612a1b565b91505092915050565b5f60208284031215612ac557612ac461217f565b5b5f82013567ffffffffffffffff811115612ae257612ae1612183565b5b612aee84828501612a83565b91505092915050565b612b00816121a6565b82525050565b5f602082019050612b195f830184612af7565b92915050565b612b28816122fa565b8114612b32575f80fd5b50565b5f81359050612b4381612b1f565b92915050565b5f8060408385031215612b5f57612b5e61217f565b5b5f612b6c858286016121cd565b9250506020612b7d85828601612b35565b9150509250929050565b5f8060408385031215612b9d57612b9c61217f565b5b5f612baa858286016121cd565b9250506020612bbb858286016121cd565b9150509250929050565b5f805f805f60a08688031215612bde57612bdd61217f565b5b5f612beb888289016121cd565b9550506020612bfc888289016121cd565b9450506040612c0d88828901612200565b9350506060612c1e88828901612200565b925050608086013567ffffffffffffffff811115612c3f57612c3e612183565b5b612c4b888289016126c1565b9150509295509295909350565b5f60208284031215612c6d57612c6c61217f565b5b5f612c7a848285016121cd565b91505092915050565b5f60208284031215612c9857612c9761217f565b5b5f612ca584828501612a07565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680612cf257607f821691505b602082108103612d0557612d04612cae565b5b50919050565b7f496e76616c696420746f6b656e496400000000000000000000000000000000005f82015250565b5f612d3f600f83612337565b9150612d4a82612d0b565b602082019050919050565b5f6020820190508181035f830152612d6c81612d33565b9050919050565b5f81905092915050565b5f819050815f5260205f209050919050565b5f8154612d9b81612cdb565b612da58186612d73565b9450600182165f8114612dbf5760018114612dd457612e06565b60ff1983168652811515820286019350612e06565b612ddd85612d7d565b5f5b83811015612dfe57815481890152600182019150602081019050612ddf565b838801955050505b50505092915050565b7f2f000000000000000000000000000000000000000000000000000000000000005f82015250565b5f612e43600183612d73565b9150612e4e82612e0f565b600182019050919050565b5f612e638261232d565b612e6d8185612d73565b9350612e7d818560208601612347565b80840191505092915050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f612ebd600583612d73565b9150612ec882612e89565b600582019050919050565b5f612ede8285612d8f565b9150612ee982612e37565b9150612ef58284612e59565b9150612f0082612eb1565b91508190509392505050565b5f612f178284612e59565b915081905092915050565b5f604082019050612f355f830185612af7565b612f426020830184612af7565b9392505050565b7f416c6c20746f6b656e73206d696e7465640000000000000000000000000000005f82015250565b5f612f7d601183612337565b9150612f8882612f49565b602082019050919050565b5f6020820190508181035f830152612faa81612f71565b9050919050565b7f4e6f20746f6b656e73206c65667420746f206d696e74000000000000000000005f82015250565b5f612fe5601683612337565b9150612ff082612fb1565b602082019050919050565b5f6020820190508181035f83015261301281612fd9565b9050919050565b5f60408201905061302c5f830185612305565b6130396020830184612305565b9392505050565b7f496e76616c6964206d696e7420636f64650000000000000000000000000000005f82015250565b5f613074601183612337565b915061307f82613040565b602082019050919050565b5f6020820190508181035f8301526130a181613068565b9050919050565b7f4d696e7420636f646520616c72656164792075736564000000000000000000005f82015250565b5f6130dc601683612337565b91506130e7826130a8565b602082019050919050565b5f6020820190508181035f830152613109816130d0565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613147826121e1565b9150613152836121e1565b92508261316257613161613110565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f546f6b656e4964206d617820737570706c7920726561636865640000000000005f82015250565b5f6131ce601a83612337565b91506131d98261319a565b602082019050919050565b5f6020820190508181035f8301526131fb816131c2565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f613239826121e1565b9150613244836121e1565b925082820190508082111561325c5761325b613202565b5b92915050565b5f6040820190506132755f830185612252565b6132826020830184612252565b9392505050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026132d37fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613298565b6132dd8683613298565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61331861331361330e846121e1565b6132f5565b6121e1565b9050919050565b5f819050919050565b613331836132fe565b61334561333d8261331f565b8484546132a4565b825550505050565b5f90565b61335961334d565b613364818484613328565b505050565b5b818110156133875761337c5f82613351565b60018101905061336a565b5050565b601f8211156133cc5761339d81612d7d565b6133a684613289565b810160208510156133b5578190505b6133c96133c185613289565b830182613369565b50505b505050565b5f82821c905092915050565b5f6133ec5f19846008026133d1565b1980831691505092915050565b5f61340483836133dd565b9150826002028217905092915050565b61341d8261232d565b67ffffffffffffffff811115613436576134356123f0565b5b6134408254612cdb565b61344b82828561338b565b5f60209050601f83116001811461347c575f841561346a578287015190505b61347485826133f9565b8655506134db565b601f19841661348a86612d7d565b5f5b828110156134b15784890151825560018201915060208501945060208101905061348c565b868310156134ce57848901516134ca601f8916826133dd565b8355505b6001600288020188555050505b505050505050565b7f4d7573742070726f7669646520636f64657300000000000000000000000000005f82015250565b5f613517601283612337565b9150613522826134e3565b602082019050919050565b5f6020820190508181035f8301526135448161350b565b9050919050565b7f4261746368206c696d69743a2031303020636f64657320706572207472616e735f8201527f616374696f6e0000000000000000000000000000000000000000000000000000602082015250565b5f6135a5602683612337565b91506135b08261354b565b604082019050919050565b5f6020820190508181035f8301526135d281613599565b9050919050565b5f6135e3826121e1565b91506135ee836121e1565b925082820390508181111561360657613605613202565b5b92915050565b5f819050919050565b613626613621826121e1565b61360c565b82525050565b5f8160601b9050919050565b5f6136428261362c565b9050919050565b5f61365382613638565b9050919050565b61366b613666826121a6565b613649565b82525050565b5f819050919050565b61368b6136868261255b565b613671565b82525050565b5f61369c8288613615565b6020820191506136ac8287613615565b6020820191506136bc828661365a565b6014820191506136cc8285613615565b6020820191506136dc828461367a565b6020820191508190509695505050505050565b7f496e646578206f7574206f6620626f756e6473000000000000000000000000005f82015250565b5f613723601383612337565b915061372e826136ef565b602082019050919050565b5f6020820190508181035f83015261375081613717565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f6080820190506137975f830187612af7565b6137a46020830186612252565b6137b16040830185612252565b6137be6060830184612252565b95945050505050565b5f6040820190508181035f8301526137df818561294a565b905081810360208301526137f3818461294a565b90509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f613820826137fc565b61382a8185613806565b935061383a818560208601612347565b61384381612355565b840191505092915050565b5f60a0820190506138615f830188612af7565b61386e6020830187612af7565b61387b6040830186612252565b6138886060830185612252565b818103608083015261389a8184613816565b90509695505050505050565b5f815190506138b4816122a5565b92915050565b5f602082840312156138cf576138ce61217f565b5b5f6138dc848285016138a6565b91505092915050565b5f60a0820190506138f85f830188612af7565b6139056020830187612af7565b8181036040830152613917818661294a565b9050818103606083015261392b818561294a565b9050818103608083015261393f8184613816565b9050969550505050505056fea2646970667358221220f3b9dbe8f233bafd56f338eb9a6ef67325f3cf980ff73ff25a42f053f316227364736f6c634300081a003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000043697066733a2f2f626166796265696763336279616472726c70696d35376a376e366c617164343571727a66706c3664677a626134736a7a6372366c76617469656a6d2f0000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561000f575f80fd5b506004361061014a575f3560e01c8063715018a6116100c1578063bd85b0391161007a578063bd85b0391461039a578063e985e9c5146103ca578063f242432a146103fa578063f2fde38b14610416578063f3e542b114610432578063fbd9e6d7146104625761014a565b8063715018a6146102ea578063869f7594146102f45780638da5cb5b1461032457806395d89b4114610342578063a22cb46514610360578063a2309ff81461037c5761014a565b80632bdead67116101135780632bdead671461021a5780632eb2c2d61461024a5780633cd9d366146102665780634e1273f41461028257806355f804b3146102b2578063660ad581146102ce5761014a565b8062fdd58e1461014e57806301ffc9a71461017e57806306fdde03146101ae5780630e89341c146101cc5780632ab4d052146101fc575b5f80fd5b61016860048036038101906101639190612214565b610492565b6040516101759190612261565b60405180910390f35b610198600480360381019061019391906122cf565b6104e7565b6040516101a59190612314565b60405180910390f35b6101b66105c8565b6040516101c3919061239d565b60405180910390f35b6101e660048036038101906101e191906123bd565b610654565b6040516101f3919061239d565b60405180910390f35b6102046106d7565b6040516102119190612261565b60405180910390f35b610234600480360381019061022f9190612514565b6106dd565b6040516102419190612573565b60405180910390f35b610264600480360381019061025f91906126ee565b61070c565b005b610280600480360381019061027b9190612514565b6107b3565b005b61029c60048036038101906102979190612879565b610b1a565b6040516102a991906129a6565b60405180910390f35b6102cc60048036038101906102c79190612514565b610c21565b005b6102e860048036038101906102e39190612ab0565b610c3c565b005b6102f2610db8565b005b61030e600480360381019061030991906123bd565b610dcb565b60405161031b9190612261565b60405180910390f35b61032c610de0565b6040516103399190612b06565b60405180910390f35b61034a610e08565b604051610357919061239d565b60405180910390f35b61037a60048036038101906103759190612b49565b610e94565b005b610384610eaa565b6040516103919190612261565b60405180910390f35b6103b460048036038101906103af91906123bd565b610eb0565b6040516103c19190612261565b60405180910390f35b6103e460048036038101906103df9190612b87565b610ec5565b6040516103f19190612314565b60405180910390f35b610414600480360381019061040f9190612bc5565b610f53565b005b610430600480360381019061042b9190612c58565b610ffa565b005b61044c60048036038101906104479190612c83565b61107e565b6040516104599190612314565b60405180910390f35b61047c60048036038101906104779190612c83565b61109b565b6040516104899190612314565b60405180910390f35b5f805f8381526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806105b157507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806105c157506105c0826110b8565b5b9050919050565b600480546105d590612cdb565b80601f016020809104026020016040519081016040528092919081815260200182805461060190612cdb565b801561064c5780601f106106235761010080835404028352916020019161064c565b820191905f5260205f20905b81548152906001019060200180831161062f57829003601f168201915b505050505081565b60605f82118015610666575060468211155b6106a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161069c90612d55565b60405180910390fd5b60066106b083611121565b6040516020016106c1929190612ed3565b6040516020818303038152906040529050919050565b60085481565b5f816040516020016106ef9190612f0c565b604051602081830303815290604052805190602001209050919050565b5f6107156111eb565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415801561075a57506107588682610ec5565b155b1561079e5780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401610795929190612f22565b60405180910390fd5b6107ab86868686866111f2565b505050505050565b600854600754106107f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f090612f93565b60405180910390fd5b5f600b8054905011610840576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083790612ffb565b60405180910390fd5b5f816040516020016108529190612f0c565b604051602081830303815290604052805190602001209050807fdeb8163679653dd103b544e8fc87a1d13a101d771df35c659a2737e60ce19f75600c5f8481526020019081526020015f205f9054906101000a900460ff16600d5f8581526020019081526020015f205f9054906101000a900460ff166040516108d6929190613019565b60405180910390a2600c5f8281526020019081526020015f205f9054906101000a900460ff1661093b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109329061308a565b60405180910390fd5b600d5f8281526020019081526020015f205f9054906101000a900460ff1615610999576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610990906130f2565b60405180910390fd5b6001600d5f8381526020019081526020015f205f6101000a81548160ff0219169083151502179055505f600b805490506109d16112e6565b6109db919061313d565b90505f600b82815481106109f2576109f161316d565b5b905f5260205f200154905060095f8281526020019081526020015f2054600a5f8381526020019081526020015f205410610a61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a58906131e4565b60405180910390fd5b6001600a5f8381526020019081526020015f205f828254610a82919061322f565b92505081905550600160075f828254610a9b919061322f565b92505081905550610abd3382600160405180602001604052805f81525061132a565b610ac6826113bf565b3373ffffffffffffffffffffffffffffffffffffffff167fcda531bfd68624f13205c0a23cd4d5a7f09792cbb399603114f2b04aaa1bf5cf82604051610b0c9190612261565b60405180910390a250505050565b60608151835114610b6657815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401610b5d929190613262565b60405180910390fd5b5f835167ffffffffffffffff811115610b8257610b816123f0565b5b604051908082528060200260200182016040528015610bb05781602001602082028036833780820191505090505b5090505f5b8451811015610c1657610bec610bd4828761147c90919063ffffffff16565b610be7838761148f90919063ffffffff16565b610492565b828281518110610bff57610bfe61316d565b5b602002602001018181525050806001019050610bb5565b508091505092915050565b610c296114a2565b8060069081610c389190613414565b5050565b610c446114a2565b5f815111610c87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c7e9061352d565b60405180910390fd5b606481511115610ccc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc3906135bb565b60405180910390fd5b5f5b8151811015610d7c576001600c5f848481518110610cef57610cee61316d565b5b602002602001015181526020019081526020015f205f6101000a81548160ff021916908315150217905550818181518110610d2d57610d2c61316d565b5b60200260200101517fdeb8163679653dd103b544e8fc87a1d13a101d771df35c659a2737e60ce19f7560015f604051610d67929190613019565b60405180910390a28080600101915050610cce565b507f4ff7494e45201c2881ee358d40945fab727ff0e1ad9bb01401ce443685493d7a8151604051610dad9190612261565b60405180910390a150565b610dc06114a2565b610dc95f611529565b565b6009602052805f5260405f205f915090505481565b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60058054610e1590612cdb565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4190612cdb565b8015610e8c5780601f10610e6357610100808354040283529160200191610e8c565b820191905f5260205f20905b815481529060010190602001808311610e6f57829003601f168201915b505050505081565b610ea6610e9f6111eb565b83836115ec565b5050565b60075481565b600a602052805f5260405f205f915090505481565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f610f5c6111eb565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015610fa15750610f9f8682610ec5565b155b15610fe55780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401610fdc929190612f22565b60405180910390fd5b610ff28686868686611755565b505050505050565b6110026114a2565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611072575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016110699190612b06565b60405180910390fd5b61107b81611529565b50565b600d602052805f5260405f205f915054906101000a900460ff1681565b600c602052805f5260405f205f915054906101000a900460ff1681565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60605f600161112f8461185b565b0190505f8167ffffffffffffffff81111561114d5761114c6123f0565b5b6040519080825280601f01601f19166020018201604052801561117f5781602001600182028036833780820191505090505b5090505f82602001820190505b6001156111e0578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816111d5576111d4613110565b5b0494505f850361118c575b819350505050919050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611262575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016112599190612b06565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036112d2575f6040517f01a835140000000000000000000000000000000000000000000000000000000081526004016112c99190612b06565b60405180910390fd5b6112df85858585856119ac565b5050505050565b5f4442333a6001436112f891906135d9565b4060405160200161130d959493929190613691565b604051602081830303815290604052805190602001205f1c905090565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361139a575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016113919190612b06565b60405180910390fd5b5f806113a68585611a58565b915091506113b75f878484876119ac565b505050505050565b600b805490508110611406576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113fd90613739565b60405180910390fd5b600b6001600b8054905061141a91906135d9565b8154811061142b5761142a61316d565b5b905f5260205f200154600b82815481106114485761144761316d565b5b905f5260205f200181905550600b80548061146657611465613757565b5b600190038181905f5260205f20015f9055905550565b5f60208202602084010151905092915050565b5f60208202602084010151905092915050565b6114aa6111eb565b73ffffffffffffffffffffffffffffffffffffffff166114c8610de0565b73ffffffffffffffffffffffffffffffffffffffff1614611527576114eb6111eb565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161151e9190612b06565b60405180910390fd5b565b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361165c575f6040517fced3e1000000000000000000000000000000000000000000000000000000000081526004016116539190612b06565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516117489190612314565b60405180910390a3505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036117c5575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016117bc9190612b06565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611835575f6040517f01a8351400000000000000000000000000000000000000000000000000000000815260040161182c9190612b06565b60405180910390fd5b5f806118418585611a58565b9150915061185287878484876119ac565b50505050505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106118b7577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816118ad576118ac613110565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106118f4576d04ee2d6d415b85acef810000000083816118ea576118e9613110565b5b0492506020810190505b662386f26fc10000831061192357662386f26fc10000838161191957611918613110565b5b0492506010810190505b6305f5e100831061194c576305f5e100838161194257611941613110565b5b0492506008810190505b612710831061197157612710838161196757611966613110565b5b0492506004810190505b60648310611994576064838161198a57611989613110565b5b0492506002810190505b600a83106119a3576001810190505b80915050919050565b6119b885858585611a88565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614611a51575f6119f46111eb565b90506001845103611a40575f611a135f8661148f90919063ffffffff16565b90505f611a295f8661148f90919063ffffffff16565b9050611a39838989858589611e18565b5050611a4f565b611a4e818787878787611fc7565b5b505b5050505050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b8051825114611ad257815181516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401611ac9929190613262565b60405180910390fd5b5f611adb6111eb565b90505f5b8351811015611cd7575f611afc828661148f90919063ffffffff16565b90505f611b12838661148f90919063ffffffff16565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614611c35575f805f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015611be157888183856040517f03dee4c5000000000000000000000000000000000000000000000000000000008152600401611bd89493929190613784565b60405180910390fd5b8181035f808581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614611cca57805f808481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611cc2919061322f565b925050819055505b5050806001019050611adf565b506001835103611d92575f611cf55f8561148f90919063ffffffff16565b90505f611d0b5f8561148f90919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051611d83929190613262565b60405180910390a45050611e11565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051611e089291906137c7565b60405180910390a45b5050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115611fbf578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401611e7895949392919061384e565b6020604051808303815f875af1925050508015611eb357506040513d601f19601f82011682018060405250810190611eb091906138ba565b60015b611f34573d805f8114611ee1576040519150601f19603f3d011682016040523d82523d5f602084013e611ee6565b606091505b505f815103611f2c57846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611f239190612b06565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611fbd57846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611fb49190612b06565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b111561216e578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b81526004016120279594939291906138e5565b6020604051808303815f875af192505050801561206257506040513d601f19601f8201168201806040525081019061205f91906138ba565b60015b6120e3573d805f8114612090576040519150601f19603f3d011682016040523d82523d5f602084013e612095565b606091505b505f8151036120db57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016120d29190612b06565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461216c57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016121639190612b06565b60405180910390fd5b505b505050505050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6121b082612187565b9050919050565b6121c0816121a6565b81146121ca575f80fd5b50565b5f813590506121db816121b7565b92915050565b5f819050919050565b6121f3816121e1565b81146121fd575f80fd5b50565b5f8135905061220e816121ea565b92915050565b5f806040838503121561222a5761222961217f565b5b5f612237858286016121cd565b925050602061224885828601612200565b9150509250929050565b61225b816121e1565b82525050565b5f6020820190506122745f830184612252565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6122ae8161227a565b81146122b8575f80fd5b50565b5f813590506122c9816122a5565b92915050565b5f602082840312156122e4576122e361217f565b5b5f6122f1848285016122bb565b91505092915050565b5f8115159050919050565b61230e816122fa565b82525050565b5f6020820190506123275f830184612305565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61236f8261232d565b6123798185612337565b9350612389818560208601612347565b61239281612355565b840191505092915050565b5f6020820190508181035f8301526123b58184612365565b905092915050565b5f602082840312156123d2576123d161217f565b5b5f6123df84828501612200565b91505092915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61242682612355565b810181811067ffffffffffffffff82111715612445576124446123f0565b5b80604052505050565b5f612457612176565b9050612463828261241d565b919050565b5f67ffffffffffffffff821115612482576124816123f0565b5b61248b82612355565b9050602081019050919050565b828183375f83830152505050565b5f6124b86124b384612468565b61244e565b9050828152602081018484840111156124d4576124d36123ec565b5b6124df848285612498565b509392505050565b5f82601f8301126124fb576124fa6123e8565b5b813561250b8482602086016124a6565b91505092915050565b5f602082840312156125295761252861217f565b5b5f82013567ffffffffffffffff81111561254657612545612183565b5b612552848285016124e7565b91505092915050565b5f819050919050565b61256d8161255b565b82525050565b5f6020820190506125865f830184612564565b92915050565b5f67ffffffffffffffff8211156125a6576125a56123f0565b5b602082029050602081019050919050565b5f80fd5b5f6125cd6125c88461258c565b61244e565b905080838252602082019050602084028301858111156125f0576125ef6125b7565b5b835b8181101561261957806126058882612200565b8452602084019350506020810190506125f2565b5050509392505050565b5f82601f830112612637576126366123e8565b5b81356126478482602086016125bb565b91505092915050565b5f67ffffffffffffffff82111561266a576126696123f0565b5b61267382612355565b9050602081019050919050565b5f61269261268d84612650565b61244e565b9050828152602081018484840111156126ae576126ad6123ec565b5b6126b9848285612498565b509392505050565b5f82601f8301126126d5576126d46123e8565b5b81356126e5848260208601612680565b91505092915050565b5f805f805f60a086880312156127075761270661217f565b5b5f612714888289016121cd565b9550506020612725888289016121cd565b945050604086013567ffffffffffffffff81111561274657612745612183565b5b61275288828901612623565b935050606086013567ffffffffffffffff81111561277357612772612183565b5b61277f88828901612623565b925050608086013567ffffffffffffffff8111156127a05761279f612183565b5b6127ac888289016126c1565b9150509295509295909350565b5f67ffffffffffffffff8211156127d3576127d26123f0565b5b602082029050602081019050919050565b5f6127f66127f1846127b9565b61244e565b90508083825260208201905060208402830185811115612819576128186125b7565b5b835b81811015612842578061282e88826121cd565b84526020840193505060208101905061281b565b5050509392505050565b5f82601f8301126128605761285f6123e8565b5b81356128708482602086016127e4565b91505092915050565b5f806040838503121561288f5761288e61217f565b5b5f83013567ffffffffffffffff8111156128ac576128ab612183565b5b6128b88582860161284c565b925050602083013567ffffffffffffffff8111156128d9576128d8612183565b5b6128e585828601612623565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b612921816121e1565b82525050565b5f6129328383612918565b60208301905092915050565b5f602082019050919050565b5f612954826128ef565b61295e81856128f9565b935061296983612909565b805f5b838110156129995781516129808882612927565b975061298b8361293e565b92505060018101905061296c565b5085935050505092915050565b5f6020820190508181035f8301526129be818461294a565b905092915050565b5f67ffffffffffffffff8211156129e0576129df6123f0565b5b602082029050602081019050919050565b6129fa8161255b565b8114612a04575f80fd5b50565b5f81359050612a15816129f1565b92915050565b5f612a2d612a28846129c6565b61244e565b90508083825260208201905060208402830185811115612a5057612a4f6125b7565b5b835b81811015612a795780612a658882612a07565b845260208401935050602081019050612a52565b5050509392505050565b5f82601f830112612a9757612a966123e8565b5b8135612aa7848260208601612a1b565b91505092915050565b5f60208284031215612ac557612ac461217f565b5b5f82013567ffffffffffffffff811115612ae257612ae1612183565b5b612aee84828501612a83565b91505092915050565b612b00816121a6565b82525050565b5f602082019050612b195f830184612af7565b92915050565b612b28816122fa565b8114612b32575f80fd5b50565b5f81359050612b4381612b1f565b92915050565b5f8060408385031215612b5f57612b5e61217f565b5b5f612b6c858286016121cd565b9250506020612b7d85828601612b35565b9150509250929050565b5f8060408385031215612b9d57612b9c61217f565b5b5f612baa858286016121cd565b9250506020612bbb858286016121cd565b9150509250929050565b5f805f805f60a08688031215612bde57612bdd61217f565b5b5f612beb888289016121cd565b9550506020612bfc888289016121cd565b9450506040612c0d88828901612200565b9350506060612c1e88828901612200565b925050608086013567ffffffffffffffff811115612c3f57612c3e612183565b5b612c4b888289016126c1565b9150509295509295909350565b5f60208284031215612c6d57612c6c61217f565b5b5f612c7a848285016121cd565b91505092915050565b5f60208284031215612c9857612c9761217f565b5b5f612ca584828501612a07565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680612cf257607f821691505b602082108103612d0557612d04612cae565b5b50919050565b7f496e76616c696420746f6b656e496400000000000000000000000000000000005f82015250565b5f612d3f600f83612337565b9150612d4a82612d0b565b602082019050919050565b5f6020820190508181035f830152612d6c81612d33565b9050919050565b5f81905092915050565b5f819050815f5260205f209050919050565b5f8154612d9b81612cdb565b612da58186612d73565b9450600182165f8114612dbf5760018114612dd457612e06565b60ff1983168652811515820286019350612e06565b612ddd85612d7d565b5f5b83811015612dfe57815481890152600182019150602081019050612ddf565b838801955050505b50505092915050565b7f2f000000000000000000000000000000000000000000000000000000000000005f82015250565b5f612e43600183612d73565b9150612e4e82612e0f565b600182019050919050565b5f612e638261232d565b612e6d8185612d73565b9350612e7d818560208601612347565b80840191505092915050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f612ebd600583612d73565b9150612ec882612e89565b600582019050919050565b5f612ede8285612d8f565b9150612ee982612e37565b9150612ef58284612e59565b9150612f0082612eb1565b91508190509392505050565b5f612f178284612e59565b915081905092915050565b5f604082019050612f355f830185612af7565b612f426020830184612af7565b9392505050565b7f416c6c20746f6b656e73206d696e7465640000000000000000000000000000005f82015250565b5f612f7d601183612337565b9150612f8882612f49565b602082019050919050565b5f6020820190508181035f830152612faa81612f71565b9050919050565b7f4e6f20746f6b656e73206c65667420746f206d696e74000000000000000000005f82015250565b5f612fe5601683612337565b9150612ff082612fb1565b602082019050919050565b5f6020820190508181035f83015261301281612fd9565b9050919050565b5f60408201905061302c5f830185612305565b6130396020830184612305565b9392505050565b7f496e76616c6964206d696e7420636f64650000000000000000000000000000005f82015250565b5f613074601183612337565b915061307f82613040565b602082019050919050565b5f6020820190508181035f8301526130a181613068565b9050919050565b7f4d696e7420636f646520616c72656164792075736564000000000000000000005f82015250565b5f6130dc601683612337565b91506130e7826130a8565b602082019050919050565b5f6020820190508181035f830152613109816130d0565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613147826121e1565b9150613152836121e1565b92508261316257613161613110565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f546f6b656e4964206d617820737570706c7920726561636865640000000000005f82015250565b5f6131ce601a83612337565b91506131d98261319a565b602082019050919050565b5f6020820190508181035f8301526131fb816131c2565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f613239826121e1565b9150613244836121e1565b925082820190508082111561325c5761325b613202565b5b92915050565b5f6040820190506132755f830185612252565b6132826020830184612252565b9392505050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026132d37fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613298565b6132dd8683613298565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61331861331361330e846121e1565b6132f5565b6121e1565b9050919050565b5f819050919050565b613331836132fe565b61334561333d8261331f565b8484546132a4565b825550505050565b5f90565b61335961334d565b613364818484613328565b505050565b5b818110156133875761337c5f82613351565b60018101905061336a565b5050565b601f8211156133cc5761339d81612d7d565b6133a684613289565b810160208510156133b5578190505b6133c96133c185613289565b830182613369565b50505b505050565b5f82821c905092915050565b5f6133ec5f19846008026133d1565b1980831691505092915050565b5f61340483836133dd565b9150826002028217905092915050565b61341d8261232d565b67ffffffffffffffff811115613436576134356123f0565b5b6134408254612cdb565b61344b82828561338b565b5f60209050601f83116001811461347c575f841561346a578287015190505b61347485826133f9565b8655506134db565b601f19841661348a86612d7d565b5f5b828110156134b15784890151825560018201915060208501945060208101905061348c565b868310156134ce57848901516134ca601f8916826133dd565b8355505b6001600288020188555050505b505050505050565b7f4d7573742070726f7669646520636f64657300000000000000000000000000005f82015250565b5f613517601283612337565b9150613522826134e3565b602082019050919050565b5f6020820190508181035f8301526135448161350b565b9050919050565b7f4261746368206c696d69743a2031303020636f64657320706572207472616e735f8201527f616374696f6e0000000000000000000000000000000000000000000000000000602082015250565b5f6135a5602683612337565b91506135b08261354b565b604082019050919050565b5f6020820190508181035f8301526135d281613599565b9050919050565b5f6135e3826121e1565b91506135ee836121e1565b925082820390508181111561360657613605613202565b5b92915050565b5f819050919050565b613626613621826121e1565b61360c565b82525050565b5f8160601b9050919050565b5f6136428261362c565b9050919050565b5f61365382613638565b9050919050565b61366b613666826121a6565b613649565b82525050565b5f819050919050565b61368b6136868261255b565b613671565b82525050565b5f61369c8288613615565b6020820191506136ac8287613615565b6020820191506136bc828661365a565b6014820191506136cc8285613615565b6020820191506136dc828461367a565b6020820191508190509695505050505050565b7f496e646578206f7574206f6620626f756e6473000000000000000000000000005f82015250565b5f613723601383612337565b915061372e826136ef565b602082019050919050565b5f6020820190508181035f83015261375081613717565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f6080820190506137975f830187612af7565b6137a46020830186612252565b6137b16040830185612252565b6137be6060830184612252565b95945050505050565b5f6040820190508181035f8301526137df818561294a565b905081810360208301526137f3818461294a565b90509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f613820826137fc565b61382a8185613806565b935061383a818560208601612347565b61384381612355565b840191505092915050565b5f60a0820190506138615f830188612af7565b61386e6020830187612af7565b61387b6040830186612252565b6138886060830185612252565b818103608083015261389a8184613816565b90509695505050505050565b5f815190506138b4816122a5565b92915050565b5f602082840312156138cf576138ce61217f565b5b5f6138dc848285016138a6565b91505092915050565b5f60a0820190506138f85f830188612af7565b6139056020830187612af7565b8181036040830152613917818661294a565b9050818103606083015261392b818561294a565b9050818103608083015261393f8184613816565b9050969550505050505056fea2646970667358221220f3b9dbe8f233bafd56f338eb9a6ef67325f3cf980ff73ff25a42f053f316227364736f6c634300081a0033

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

00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000043697066733a2f2f626166796265696763336279616472726c70696d35376a376e366c617164343571727a66706c3664677a626134736a7a6372366c76617469656a6d2f0000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : baseURI_ (string): ipfs://bafybeigc3byadrrlpim57j7n6laqd45qrzfpl6dgzba4sjzcr6lvatiejm/

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000043
Arg [2] : 697066733a2f2f626166796265696763336279616472726c70696d35376a376e
Arg [3] : 366c617164343571727a66706c3664677a626134736a7a6372366c7661746965
Arg [4] : 6a6d2f0000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

155925:7665:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119405:134;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;118514:310;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156005:32;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;163172:235;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156144:36;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;162154:140;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;121228:441;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;161090:952;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;119705:567;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;163487:100;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;160381:537;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;134377:103;;;:::i;:::-;;156232:44;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;133702:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156045:29;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120345:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;156111:26;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156283:46;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120563:159;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120794:357;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;134635:220;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;156458:45;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156376:46;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119405:134;119482:7;119509:9;:13;119519:2;119509:13;;;;;;;;;;;:22;119523:7;119509:22;;;;;;;;;;;;;;;;119502:29;;119405:134;;;;:::o;118514:310::-;118616:4;118668:26;118653:41;;;:11;:41;;;;:110;;;;118726:37;118711:52;;;:11;:52;;;;118653:110;:163;;;;118780:36;118804:11;118780:23;:36::i;:::-;118653:163;118633:183;;118514:310;;;:::o;156005:32::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;163172:235::-;163232:13;163276:1;163266:7;:11;:28;;;;;163292:2;163281:7;:13;;163266:28;163258:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;163356:7;163370:18;:7;:16;:18::i;:::-;163339:59;;;;;;;;;:::i;:::-;;;;;;;;;;;;;163325:74;;163172:235;;;:::o;156144:36::-;;;;:::o;162154:140::-;162222:7;162276:8;162259:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;162249:37;;;;;;162242:44;;162154:140;;;:::o;121228:441::-;121429:14;121446:12;:10;:12::i;:::-;121429:29;;121481:6;121473:14;;:4;:14;;;;:49;;;;;121492:30;121509:4;121515:6;121492:16;:30::i;:::-;121491:31;121473:49;121469:131;;;121575:6;121583:4;121546:42;;;;;;;;;;;;:::i;:::-;;;;;;;;121469:131;121610:51;121633:4;121639:2;121643:3;121648:6;121656:4;121610:22;:51::i;:::-;121418:251;121228:441;;;;;:::o;161090:952::-;161178:14;;161164:11;;:28;161156:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;161256:1;161233:13;:20;;;;:24;161225:59;;;;;;;;;;;;:::i;:::-;;;;;;;;;161297:16;161343:8;161326:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;161316:37;;;;;;161297:56;;161383:8;161369:74;161393:14;:24;161408:8;161393:24;;;;;;;;;;;;;;;;;;;;;161419:13;:23;161433:8;161419:23;;;;;;;;;;;;;;;;;;;;;161369:74;;;;;;;:::i;:::-;;;;;;;;161464:14;:24;161479:8;161464:24;;;;;;;;;;;;;;;;;;;;;161456:54;;;;;;;;;;;;:::i;:::-;;;;;;;;;161530:13;:23;161544:8;161530:23;;;;;;;;;;;;;;;;;;;;;161529:24;161521:59;;;;;;;;;;;;:::i;:::-;;;;;;;;;161617:4;161591:13;:23;161605:8;161591:23;;;;;;;;;;;;:30;;;;;;;;;;;;;;;;;;161634:19;161668:13;:20;;;;161656:9;:7;:9::i;:::-;:32;;;;:::i;:::-;161634:54;;161699:15;161717:13;161731:11;161717:26;;;;;;;;:::i;:::-;;;;;;;;;;161699:44;;161787:9;:18;161797:7;161787:18;;;;;;;;;;;;161764:11;:20;161776:7;161764:20;;;;;;;;;;;;:41;161756:80;;;;;;;;;;;;:::i;:::-;;;;;;;;;161873:1;161849:11;:20;161861:7;161849:20;;;;;;;;;;;;:25;;;;;;;:::i;:::-;;;;;;;;161900:1;161885:11;;:16;;;;;;;:::i;:::-;;;;;;;;161912:33;161918:10;161930:7;161939:1;161912:33;;;;;;;;;;;;:5;:33::i;:::-;161958:28;161974:11;161958:15;:28::i;:::-;162014:10;162002:32;;;162026:7;162002:32;;;;;;:::i;:::-;;;;;;;;161145:897;;;161090:952;:::o;119705:567::-;119832:16;119884:3;:10;119865:8;:15;:29;119861:123;;119944:3;:10;119956:8;:15;119918:54;;;;;;;;;;;;:::i;:::-;;;;;;;;119861:123;119996:30;120043:8;:15;120029:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119996:63;;120077:9;120072:160;120096:8;:15;120092:1;:19;120072:160;;;120152:68;120162:30;120190:1;120162:8;:27;;:30;;;;:::i;:::-;120194:25;120217:1;120194:3;:22;;:25;;;;:::i;:::-;120152:9;:68::i;:::-;120133:13;120147:1;120133:16;;;;;;;;:::i;:::-;;;;;;;:87;;;;;120113:3;;;;;120072:160;;;;120251:13;120244:20;;;119705:567;;;;:::o;163487:100::-;133588:13;:11;:13::i;:::-;163571:8:::1;163561:7;:18;;;;;;:::i;:::-;;163487:100:::0;:::o;160381:537::-;133588:13;:11;:13::i;:::-;160497:1:::1;160476:11;:18;:22;160468:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;160562:3;160540:11;:18;:25;;160532:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;160626:9;160621:238;160645:11;:18;160641:1;:22;160621:238;;;160718:4;160685:14;:30;160700:11;160712:1;160700:14;;;;;;;;:::i;:::-;;;;;;;;160685:30;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;160819:11;160831:1;160819:14;;;;;;;;:::i;:::-;;;;;;;;160805:42;160835:4;160841:5;160805:42;;;;;;;:::i;:::-;;;;;;;;160665:3;;;;;;;160621:238;;;;160876:34;160891:11;:18;160876:34;;;;;;:::i;:::-;;;;;;;;160381:537:::0;:::o;134377:103::-;133588:13;:11;:13::i;:::-;134442:30:::1;134469:1;134442:18;:30::i;:::-;134377:103::o:0;156232:44::-;;;;;;;;;;;;;;;;;:::o;133702:87::-;133748:7;133775:6;;;;;;;;;;;133768:13;;133702:87;:::o;156045:29::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;120345:146::-;120431:52;120450:12;:10;:12::i;:::-;120464:8;120474;120431:18;:52::i;:::-;120345:146;;:::o;156111:26::-;;;;:::o;156283:46::-;;;;;;;;;;;;;;;;;:::o;120563:159::-;120653:4;120677:18;:27;120696:7;120677:27;;;;;;;;;;;;;;;:37;120705:8;120677:37;;;;;;;;;;;;;;;;;;;;;;;;;120670:44;;120563:159;;;;:::o;120794:357::-;120918:14;120935:12;:10;:12::i;:::-;120918:29;;120970:6;120962:14;;:4;:14;;;;:49;;;;;120981:30;120998:4;121004:6;120981:16;:30::i;:::-;120980:31;120962:49;120958:131;;;121064:6;121072:4;121035:42;;;;;;;;;;;;:::i;:::-;;;;;;;;120958:131;121099:44;121117:4;121123:2;121127;121131:5;121138:4;121099:17;:44::i;:::-;120907:244;120794:357;;;;;:::o;134635:220::-;133588:13;:11;:13::i;:::-;134740:1:::1;134720:22;;:8;:22;;::::0;134716:93:::1;;134794:1;134766:31;;;;;;;;;;;:::i;:::-;;;;;;;;134716:93;134819:28;134838:8;134819:18;:28::i;:::-;134635:220:::0;:::o;156458:45::-;;;;;;;;;;;;;;;;;;;;;;:::o;156376:46::-;;;;;;;;;;;;;;;;;;;;;;:::o;21160:148::-;21236:4;21275:25;21260:40;;;:11;:40;;;;21253:47;;21160:148;;;:::o;138798:650::-;138854:13;138905:14;138942:1;138922:17;138933:5;138922:10;:17::i;:::-;:21;138905:38;;138958:20;138992:6;138981:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;138958:41;;139014:11;139111:6;139107:2;139103:15;139095:6;139091:28;139084:35;;139148:254;139155:4;139148:254;;;139180:5;;;;;;;;139286:10;139281:2;139274:5;139270:14;139265:32;139260:3;139252:46;139344:2;139335:11;;;;;;:::i;:::-;;;;;139378:1;139369:5;:10;139148:254;139365:21;139148:254;139423:6;139416:13;;;;;138798:650;;;:::o;20057:98::-;20110:7;20137:10;20130:17;;20057:98;:::o;126366:459::-;126580:1;126566:16;;:2;:16;;;126562:90;;126637:1;126606:34;;;;;;;;;;;:::i;:::-;;;;;;;;126562:90;126682:1;126666:18;;:4;:18;;;126662:90;;126737:1;126708:32;;;;;;;;;;;:::i;:::-;;;;;;;;126662:90;126762:55;126789:4;126795:2;126799:3;126804:6;126812:4;126762:26;:55::i;:::-;126366:459;;;;;:::o;162366:382::-;162408:7;162524:16;162563:15;162601:10;162634:11;162693:1;162678:12;:16;;;;:::i;:::-;162668:27;162485:229;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;162457:272;;;;;;162435:305;;162428:312;;162366:382;:::o;128147:352::-;128258:1;128244:16;;:2;:16;;;128240:90;;128315:1;128284:34;;;;;;;;;;;:::i;:::-;;;;;;;;128240:90;128341:20;128363:23;128390:29;128409:2;128413:5;128390:18;:29::i;:::-;128340:79;;;;128430:61;128465:1;128469:2;128473:3;128478:6;128486:4;128430:26;:61::i;:::-;128229:270;;128147:352;;;;:::o;162858:231::-;162934:13;:20;;;;162926:5;:28;162918:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;163012:13;163049:1;163026:13;:20;;;;:24;;;;:::i;:::-;163012:39;;;;;;;;:::i;:::-;;;;;;;;;;162989:13;163003:5;162989:20;;;;;;;;:::i;:::-;;;;;;;;;:62;;;;163062:13;:19;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;162858:231;:::o;115189:201::-;115275:11;115365:4;115360:3;115356:14;115349:4;115344:3;115340:14;115336:35;115330:42;115323:49;;115189:201;;;;:::o;116009:::-;116095:11;116185:4;116180:3;116176:14;116169:4;116164:3;116160:14;116156:35;116150:42;116143:49;;116009:201;;;;:::o;133867:166::-;133938:12;:10;:12::i;:::-;133927:23;;:7;:5;:7::i;:::-;:23;;;133923:103;;134001:12;:10;:12::i;:::-;133974:40;;;;;;;;;;;:::i;:::-;;;;;;;;133923:103;133867:166::o;135015:191::-;135089:16;135108:6;;;;;;;;;;;135089:25;;135134:8;135125:6;;:17;;;;;;;;;;;;;;;;;;135189:8;135158:40;;135179:8;135158:40;;;;;;;;;;;;135078:128;135015:191;:::o;130741:321::-;130869:1;130849:22;;:8;:22;;;130845:96;;130926:1;130895:34;;;;;;;;;;;:::i;:::-;;;;;;;;130845:96;130989:8;130951:18;:25;130970:5;130951:25;;;;;;;;;;;;;;;:35;130977:8;130951:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;131035:8;131013:41;;131028:5;131013:41;;;131045:8;131013:41;;;;;;:::i;:::-;;;;;;;;130741:321;;;:::o;125480:472::-;125617:1;125603:16;;:2;:16;;;125599:90;;125674:1;125643:34;;;;;;;;;;;:::i;:::-;;;;;;;;125599:90;125719:1;125703:18;;:4;:18;;;125699:90;;125774:1;125745:32;;;;;;;;;;;:::i;:::-;;;;;;;;125699:90;125800:20;125822:23;125849:29;125868:2;125872:5;125849:18;:29::i;:::-;125799:79;;;;125889:55;125916:4;125922:2;125926:3;125931:6;125939:4;125889:26;:55::i;:::-;125588:364;;125480:472;;;;;:::o;95713:948::-;95766:7;95786:14;95803:1;95786:18;;95853:8;95844:5;:17;95840:106;;95891:8;95882:17;;;;;;:::i;:::-;;;;;95928:2;95918:12;;;;95840:106;95973:8;95964:5;:17;95960:106;;96011:8;96002:17;;;;;;:::i;:::-;;;;;96048:2;96038:12;;;;95960:106;96093:8;96084:5;:17;96080:106;;96131:8;96122:17;;;;;;:::i;:::-;;;;;96168:2;96158:12;;;;96080:106;96213:7;96204:5;:16;96200:103;;96250:7;96241:16;;;;;;:::i;:::-;;;;;96286:1;96276:11;;;;96200:103;96330:7;96321:5;:16;96317:103;;96367:7;96358:16;;;;;;:::i;:::-;;;;;96403:1;96393:11;;;;96317:103;96447:7;96438:5;:16;96434:103;;96484:7;96475:16;;;;;;:::i;:::-;;;;;96520:1;96510:11;;;;96434:103;96564:7;96555:5;:16;96551:68;;96602:1;96592:11;;;;96551:68;96647:6;96640:13;;;95713:948;;;:::o;124291:718::-;124499:30;124507:4;124513:2;124517:3;124522:6;124499:7;:30::i;:::-;124558:1;124544:16;;:2;:16;;;124540:462;;124577:16;124596:12;:10;:12::i;:::-;124577:31;;124641:1;124627:3;:10;:15;124623:368;;124663:10;124676:25;124699:1;124676:3;:22;;:25;;;;:::i;:::-;124663:38;;124720:13;124736:28;124762:1;124736:6;:25;;:28;;;;:::i;:::-;124720:44;;124783:72;124819:8;124829:4;124835:2;124839;124843:5;124850:4;124783:35;:72::i;:::-;124644:227;;124623:368;;;124896:79;124937:8;124947:4;124953:2;124957:3;124962:6;124970:4;124896:40;:79::i;:::-;124623:368;124562:440;124540:462;124291:718;;;;;:::o;131183:842::-;131294:23;131319;131456:4;131450:11;131440:21;;131528:1;131520:6;131513:17;131668:8;131661:4;131653:6;131649:17;131642:35;131793:4;131785:6;131781:17;131771:27;;131827:1;131819:6;131812:17;131869:8;131862:4;131854:6;131850:17;131843:35;132001:4;131993:6;131989:17;131983:4;131976:31;131183:842;;;;;:::o;122386:1315::-;122522:6;:13;122508:3;:10;:27;122504:119;;122585:3;:10;122597:6;:13;122559:52;;;;;;;;;;;;:::i;:::-;;;;;;;;122504:119;122635:16;122654:12;:10;:12::i;:::-;122635:31;;122684:9;122679:709;122703:3;:10;122699:1;:14;122679:709;;;122735:10;122748:25;122771:1;122748:3;:22;;:25;;;;:::i;:::-;122735:38;;122788:13;122804:28;122830:1;122804:6;:25;;:28;;;;:::i;:::-;122788:44;;122869:1;122853:18;;:4;:18;;;122849:429;;122892:19;122914:9;:13;122924:2;122914:13;;;;;;;;;;;:19;122928:4;122914:19;;;;;;;;;;;;;;;;122892:41;;122970:5;122956:11;:19;122952:131;;;123034:4;123040:11;123053:5;123060:2;123007:56;;;;;;;;;;;;;;:::i;:::-;;;;;;;;122952:131;123238:5;123224:11;:19;123202:9;:13;123212:2;123202:13;;;;;;;;;;;:19;123216:4;123202:19;;;;;;;;;;;;;;;:41;;;;122873:405;122849:429;123312:1;123298:16;;:2;:16;;;123294:83;;123356:5;123335:9;:13;123345:2;123335:13;;;;;;;;;;;:17;123349:2;123335:17;;;;;;;;;;;;;;;;:26;;;;;;;:::i;:::-;;;;;;;;123294:83;122720:668;;122715:3;;;;;122679:709;;;;123418:1;123404:3;:10;:15;123400:294;;123436:10;123449:25;123472:1;123449:3;:22;;:25;;;;:::i;:::-;123436:38;;123489:13;123505:28;123531:1;123505:6;:25;;:28;;;;:::i;:::-;123489:44;;123584:2;123553:45;;123578:4;123553:45;;123568:8;123553:45;;;123588:2;123592:5;123553:45;;;;;;;:::i;:::-;;;;;;;;123421:189;;123400:294;;;123666:2;123636:46;;123660:4;123636:46;;123650:8;123636:46;;;123670:3;123675:6;123636:46;;;;;;;:::i;:::-;;;;;;;;123400:294;122493:1208;122386:1315;;;;:::o;16760:984::-;16984:1;16967:2;:14;;;:18;16963:774;;;17023:2;17006:38;;;17045:8;17055:4;17061:2;17065:5;17072:4;17006:71;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;17002:724;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17399:1;17382:6;:13;:18;17378:333;;17527:2;17489:41;;;;;;;;;;;:::i;:::-;;;;;;;;17378:333;17661:6;17655:13;17646:6;17642:2;17638:15;17631:38;17002:724;17139:43;;;17127:55;;;:8;:55;;;;17123:192;;17292:2;17254:41;;;;;;;;;;;:::i;:::-;;;;;;;;17123:192;17078:252;16963:774;16760:984;;;;;;:::o;18302:1053::-;18551:1;18534:2;:14;;;:18;18530:818;;;18590:2;18573:43;;;18617:8;18627:4;18633:3;18638:6;18646:4;18573:78;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;18569:768;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19010:1;18993:6;:13;:18;18989:333;;19138:2;19100:41;;;;;;;;;;;:::i;:::-;;;;;;;;18989:333;19272:6;19266:13;19257:6;19253:2;19249:15;19242:38;18569:768;18745:48;;;18733:60;;;:8;:60;;;;18729:197;;18903:2;18865:41;;;;;;;;;;;:::i;:::-;;;;;;;;18729:197;18652:289;18530:818;18302:1053;;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:126;371:7;411:42;404:5;400:54;389:65;;334:126;;;:::o;466:96::-;503:7;532:24;550:5;532:24;:::i;:::-;521:35;;466:96;;;:::o;568:122::-;641:24;659:5;641:24;:::i;:::-;634:5;631:35;621:63;;680:1;677;670:12;621:63;568:122;:::o;696:139::-;742:5;780:6;767:20;758:29;;796:33;823:5;796:33;:::i;:::-;696:139;;;;:::o;841:77::-;878:7;907:5;896:16;;841:77;;;:::o;924:122::-;997:24;1015:5;997:24;:::i;:::-;990:5;987:35;977:63;;1036:1;1033;1026:12;977:63;924:122;:::o;1052:139::-;1098:5;1136:6;1123:20;1114:29;;1152:33;1179:5;1152:33;:::i;:::-;1052:139;;;;:::o;1197:474::-;1265:6;1273;1322:2;1310:9;1301:7;1297:23;1293:32;1290:119;;;1328:79;;:::i;:::-;1290:119;1448:1;1473:53;1518:7;1509:6;1498:9;1494:22;1473:53;:::i;:::-;1463:63;;1419:117;1575:2;1601:53;1646:7;1637:6;1626:9;1622:22;1601:53;:::i;:::-;1591:63;;1546:118;1197:474;;;;;:::o;1677:118::-;1764:24;1782:5;1764:24;:::i;:::-;1759:3;1752:37;1677:118;;:::o;1801:222::-;1894:4;1932:2;1921:9;1917:18;1909:26;;1945:71;2013:1;2002:9;1998:17;1989:6;1945:71;:::i;:::-;1801:222;;;;:::o;2029:149::-;2065:7;2105:66;2098:5;2094:78;2083:89;;2029:149;;;:::o;2184:120::-;2256:23;2273:5;2256:23;:::i;:::-;2249:5;2246:34;2236:62;;2294:1;2291;2284:12;2236:62;2184:120;:::o;2310:137::-;2355:5;2393:6;2380:20;2371:29;;2409:32;2435:5;2409:32;:::i;:::-;2310:137;;;;:::o;2453:327::-;2511:6;2560:2;2548:9;2539:7;2535:23;2531:32;2528:119;;;2566:79;;:::i;:::-;2528:119;2686:1;2711:52;2755:7;2746:6;2735:9;2731:22;2711:52;:::i;:::-;2701:62;;2657:116;2453:327;;;;:::o;2786:90::-;2820:7;2863:5;2856:13;2849:21;2838:32;;2786:90;;;:::o;2882:109::-;2963:21;2978:5;2963:21;:::i;:::-;2958:3;2951:34;2882:109;;:::o;2997:210::-;3084:4;3122:2;3111:9;3107:18;3099:26;;3135:65;3197:1;3186:9;3182:17;3173:6;3135:65;:::i;:::-;2997:210;;;;:::o;3213:99::-;3265:6;3299:5;3293:12;3283:22;;3213:99;;;:::o;3318:169::-;3402:11;3436:6;3431:3;3424:19;3476:4;3471:3;3467:14;3452:29;;3318:169;;;;:::o;3493:139::-;3582:6;3577:3;3572;3566:23;3623:1;3614:6;3609:3;3605:16;3598:27;3493:139;;;:::o;3638:102::-;3679:6;3730:2;3726:7;3721:2;3714:5;3710:14;3706:28;3696:38;;3638:102;;;:::o;3746:377::-;3834:3;3862:39;3895:5;3862:39;:::i;:::-;3917:71;3981:6;3976:3;3917:71;:::i;:::-;3910:78;;3997:65;4055:6;4050:3;4043:4;4036:5;4032:16;3997:65;:::i;:::-;4087:29;4109:6;4087:29;:::i;:::-;4082:3;4078:39;4071:46;;3838:285;3746:377;;;;:::o;4129:313::-;4242:4;4280:2;4269:9;4265:18;4257:26;;4329:9;4323:4;4319:20;4315:1;4304:9;4300:17;4293:47;4357:78;4430:4;4421:6;4357:78;:::i;:::-;4349:86;;4129:313;;;;:::o;4448:329::-;4507:6;4556:2;4544:9;4535:7;4531:23;4527:32;4524:119;;;4562:79;;:::i;:::-;4524:119;4682:1;4707:53;4752:7;4743:6;4732:9;4728:22;4707:53;:::i;:::-;4697:63;;4653:117;4448:329;;;;:::o;4783:117::-;4892:1;4889;4882:12;4906:117;5015:1;5012;5005:12;5029:180;5077:77;5074:1;5067:88;5174:4;5171:1;5164:15;5198:4;5195:1;5188:15;5215:281;5298:27;5320:4;5298:27;:::i;:::-;5290:6;5286:40;5428:6;5416:10;5413:22;5392:18;5380:10;5377:34;5374:62;5371:88;;;5439:18;;:::i;:::-;5371:88;5479:10;5475:2;5468:22;5258:238;5215:281;;:::o;5502:129::-;5536:6;5563:20;;:::i;:::-;5553:30;;5592:33;5620:4;5612:6;5592:33;:::i;:::-;5502:129;;;:::o;5637:308::-;5699:4;5789:18;5781:6;5778:30;5775:56;;;5811:18;;:::i;:::-;5775:56;5849:29;5871:6;5849:29;:::i;:::-;5841:37;;5933:4;5927;5923:15;5915:23;;5637:308;;;:::o;5951:148::-;6049:6;6044:3;6039;6026:30;6090:1;6081:6;6076:3;6072:16;6065:27;5951:148;;;:::o;6105:425::-;6183:5;6208:66;6224:49;6266:6;6224:49;:::i;:::-;6208:66;:::i;:::-;6199:75;;6297:6;6290:5;6283:21;6335:4;6328:5;6324:16;6373:3;6364:6;6359:3;6355:16;6352:25;6349:112;;;6380:79;;:::i;:::-;6349:112;6470:54;6517:6;6512:3;6507;6470:54;:::i;:::-;6189:341;6105:425;;;;;:::o;6550:340::-;6606:5;6655:3;6648:4;6640:6;6636:17;6632:27;6622:122;;6663:79;;:::i;:::-;6622:122;6780:6;6767:20;6805:79;6880:3;6872:6;6865:4;6857:6;6853:17;6805:79;:::i;:::-;6796:88;;6612:278;6550:340;;;;:::o;6896:509::-;6965:6;7014:2;7002:9;6993:7;6989:23;6985:32;6982:119;;;7020:79;;:::i;:::-;6982:119;7168:1;7157:9;7153:17;7140:31;7198:18;7190:6;7187:30;7184:117;;;7220:79;;:::i;:::-;7184:117;7325:63;7380:7;7371:6;7360:9;7356:22;7325:63;:::i;:::-;7315:73;;7111:287;6896:509;;;;:::o;7411:77::-;7448:7;7477:5;7466:16;;7411:77;;;:::o;7494:118::-;7581:24;7599:5;7581:24;:::i;:::-;7576:3;7569:37;7494:118;;:::o;7618:222::-;7711:4;7749:2;7738:9;7734:18;7726:26;;7762:71;7830:1;7819:9;7815:17;7806:6;7762:71;:::i;:::-;7618:222;;;;:::o;7846:311::-;7923:4;8013:18;8005:6;8002:30;7999:56;;;8035:18;;:::i;:::-;7999:56;8085:4;8077:6;8073:17;8065:25;;8145:4;8139;8135:15;8127:23;;7846:311;;;:::o;8163:117::-;8272:1;8269;8262:12;8303:710;8399:5;8424:81;8440:64;8497:6;8440:64;:::i;:::-;8424:81;:::i;:::-;8415:90;;8525:5;8554:6;8547:5;8540:21;8588:4;8581:5;8577:16;8570:23;;8641:4;8633:6;8629:17;8621:6;8617:30;8670:3;8662:6;8659:15;8656:122;;;8689:79;;:::i;:::-;8656:122;8804:6;8787:220;8821:6;8816:3;8813:15;8787:220;;;8896:3;8925:37;8958:3;8946:10;8925:37;:::i;:::-;8920:3;8913:50;8992:4;8987:3;8983:14;8976:21;;8863:144;8847:4;8842:3;8838:14;8831:21;;8787:220;;;8791:21;8405:608;;8303:710;;;;;:::o;9036:370::-;9107:5;9156:3;9149:4;9141:6;9137:17;9133:27;9123:122;;9164:79;;:::i;:::-;9123:122;9281:6;9268:20;9306:94;9396:3;9388:6;9381:4;9373:6;9369:17;9306:94;:::i;:::-;9297:103;;9113:293;9036:370;;;;:::o;9412:307::-;9473:4;9563:18;9555:6;9552:30;9549:56;;;9585:18;;:::i;:::-;9549:56;9623:29;9645:6;9623:29;:::i;:::-;9615:37;;9707:4;9701;9697:15;9689:23;;9412:307;;;:::o;9725:423::-;9802:5;9827:65;9843:48;9884:6;9843:48;:::i;:::-;9827:65;:::i;:::-;9818:74;;9915:6;9908:5;9901:21;9953:4;9946:5;9942:16;9991:3;9982:6;9977:3;9973:16;9970:25;9967:112;;;9998:79;;:::i;:::-;9967:112;10088:54;10135:6;10130:3;10125;10088:54;:::i;:::-;9808:340;9725:423;;;;;:::o;10167:338::-;10222:5;10271:3;10264:4;10256:6;10252:17;10248:27;10238:122;;10279:79;;:::i;:::-;10238:122;10396:6;10383:20;10421:78;10495:3;10487:6;10480:4;10472:6;10468:17;10421:78;:::i;:::-;10412:87;;10228:277;10167:338;;;;:::o;10511:1509::-;10665:6;10673;10681;10689;10697;10746:3;10734:9;10725:7;10721:23;10717:33;10714:120;;;10753:79;;:::i;:::-;10714:120;10873:1;10898:53;10943:7;10934:6;10923:9;10919:22;10898:53;:::i;:::-;10888:63;;10844:117;11000:2;11026:53;11071:7;11062:6;11051:9;11047:22;11026:53;:::i;:::-;11016:63;;10971:118;11156:2;11145:9;11141:18;11128:32;11187:18;11179:6;11176:30;11173:117;;;11209:79;;:::i;:::-;11173:117;11314:78;11384:7;11375:6;11364:9;11360:22;11314:78;:::i;:::-;11304:88;;11099:303;11469:2;11458:9;11454:18;11441:32;11500:18;11492:6;11489:30;11486:117;;;11522:79;;:::i;:::-;11486:117;11627:78;11697:7;11688:6;11677:9;11673:22;11627:78;:::i;:::-;11617:88;;11412:303;11782:3;11771:9;11767:19;11754:33;11814:18;11806:6;11803:30;11800:117;;;11836:79;;:::i;:::-;11800:117;11941:62;11995:7;11986:6;11975:9;11971:22;11941:62;:::i;:::-;11931:72;;11725:288;10511:1509;;;;;;;;:::o;12026:311::-;12103:4;12193:18;12185:6;12182:30;12179:56;;;12215:18;;:::i;:::-;12179:56;12265:4;12257:6;12253:17;12245:25;;12325:4;12319;12315:15;12307:23;;12026:311;;;:::o;12360:710::-;12456:5;12481:81;12497:64;12554:6;12497:64;:::i;:::-;12481:81;:::i;:::-;12472:90;;12582:5;12611:6;12604:5;12597:21;12645:4;12638:5;12634:16;12627:23;;12698:4;12690:6;12686:17;12678:6;12674:30;12727:3;12719:6;12716:15;12713:122;;;12746:79;;:::i;:::-;12713:122;12861:6;12844:220;12878:6;12873:3;12870:15;12844:220;;;12953:3;12982:37;13015:3;13003:10;12982:37;:::i;:::-;12977:3;12970:50;13049:4;13044:3;13040:14;13033:21;;12920:144;12904:4;12899:3;12895:14;12888:21;;12844:220;;;12848:21;12462:608;;12360:710;;;;;:::o;13093:370::-;13164:5;13213:3;13206:4;13198:6;13194:17;13190:27;13180:122;;13221:79;;:::i;:::-;13180:122;13338:6;13325:20;13363:94;13453:3;13445:6;13438:4;13430:6;13426:17;13363:94;:::i;:::-;13354:103;;13170:293;13093:370;;;;:::o;13469:894::-;13587:6;13595;13644:2;13632:9;13623:7;13619:23;13615:32;13612:119;;;13650:79;;:::i;:::-;13612:119;13798:1;13787:9;13783:17;13770:31;13828:18;13820:6;13817:30;13814:117;;;13850:79;;:::i;:::-;13814:117;13955:78;14025:7;14016:6;14005:9;14001:22;13955:78;:::i;:::-;13945:88;;13741:302;14110:2;14099:9;14095:18;14082:32;14141:18;14133:6;14130:30;14127:117;;;14163:79;;:::i;:::-;14127:117;14268:78;14338:7;14329:6;14318:9;14314:22;14268:78;:::i;:::-;14258:88;;14053:303;13469:894;;;;;:::o;14369:114::-;14436:6;14470:5;14464:12;14454:22;;14369:114;;;:::o;14489:184::-;14588:11;14622:6;14617:3;14610:19;14662:4;14657:3;14653:14;14638:29;;14489:184;;;;:::o;14679:132::-;14746:4;14769:3;14761:11;;14799:4;14794:3;14790:14;14782:22;;14679:132;;;:::o;14817:108::-;14894:24;14912:5;14894:24;:::i;:::-;14889:3;14882:37;14817:108;;:::o;14931:179::-;15000:10;15021:46;15063:3;15055:6;15021:46;:::i;:::-;15099:4;15094:3;15090:14;15076:28;;14931:179;;;;:::o;15116:113::-;15186:4;15218;15213:3;15209:14;15201:22;;15116:113;;;:::o;15265:732::-;15384:3;15413:54;15461:5;15413:54;:::i;:::-;15483:86;15562:6;15557:3;15483:86;:::i;:::-;15476:93;;15593:56;15643:5;15593:56;:::i;:::-;15672:7;15703:1;15688:284;15713:6;15710:1;15707:13;15688:284;;;15789:6;15783:13;15816:63;15875:3;15860:13;15816:63;:::i;:::-;15809:70;;15902:60;15955:6;15902:60;:::i;:::-;15892:70;;15748:224;15735:1;15732;15728:9;15723:14;;15688:284;;;15692:14;15988:3;15981:10;;15389:608;;;15265:732;;;;:::o;16003:373::-;16146:4;16184:2;16173:9;16169:18;16161:26;;16233:9;16227:4;16223:20;16219:1;16208:9;16204:17;16197:47;16261:108;16364:4;16355:6;16261:108;:::i;:::-;16253:116;;16003:373;;;;:::o;16382:311::-;16459:4;16549:18;16541:6;16538:30;16535:56;;;16571:18;;:::i;:::-;16535:56;16621:4;16613:6;16609:17;16601:25;;16681:4;16675;16671:15;16663:23;;16382:311;;;:::o;16699:122::-;16772:24;16790:5;16772:24;:::i;:::-;16765:5;16762:35;16752:63;;16811:1;16808;16801:12;16752:63;16699:122;:::o;16827:139::-;16873:5;16911:6;16898:20;16889:29;;16927:33;16954:5;16927:33;:::i;:::-;16827:139;;;;:::o;16989:710::-;17085:5;17110:81;17126:64;17183:6;17126:64;:::i;:::-;17110:81;:::i;:::-;17101:90;;17211:5;17240:6;17233:5;17226:21;17274:4;17267:5;17263:16;17256:23;;17327:4;17319:6;17315:17;17307:6;17303:30;17356:3;17348:6;17345:15;17342:122;;;17375:79;;:::i;:::-;17342:122;17490:6;17473:220;17507:6;17502:3;17499:15;17473:220;;;17582:3;17611:37;17644:3;17632:10;17611:37;:::i;:::-;17606:3;17599:50;17678:4;17673:3;17669:14;17662:21;;17549:144;17533:4;17528:3;17524:14;17517:21;;17473:220;;;17477:21;17091:608;;16989:710;;;;;:::o;17722:370::-;17793:5;17842:3;17835:4;17827:6;17823:17;17819:27;17809:122;;17850:79;;:::i;:::-;17809:122;17967:6;17954:20;17992:94;18082:3;18074:6;18067:4;18059:6;18055:17;17992:94;:::i;:::-;17983:103;;17799:293;17722:370;;;;:::o;18098:539::-;18182:6;18231:2;18219:9;18210:7;18206:23;18202:32;18199:119;;;18237:79;;:::i;:::-;18199:119;18385:1;18374:9;18370:17;18357:31;18415:18;18407:6;18404:30;18401:117;;;18437:79;;:::i;:::-;18401:117;18542:78;18612:7;18603:6;18592:9;18588:22;18542:78;:::i;:::-;18532:88;;18328:302;18098:539;;;;:::o;18643:118::-;18730:24;18748:5;18730:24;:::i;:::-;18725:3;18718:37;18643:118;;:::o;18767:222::-;18860:4;18898:2;18887:9;18883:18;18875:26;;18911:71;18979:1;18968:9;18964:17;18955:6;18911:71;:::i;:::-;18767:222;;;;:::o;18995:116::-;19065:21;19080:5;19065:21;:::i;:::-;19058:5;19055:32;19045:60;;19101:1;19098;19091:12;19045:60;18995:116;:::o;19117:133::-;19160:5;19198:6;19185:20;19176:29;;19214:30;19238:5;19214:30;:::i;:::-;19117:133;;;;:::o;19256:468::-;19321:6;19329;19378:2;19366:9;19357:7;19353:23;19349:32;19346:119;;;19384:79;;:::i;:::-;19346:119;19504:1;19529:53;19574:7;19565:6;19554:9;19550:22;19529:53;:::i;:::-;19519:63;;19475:117;19631:2;19657:50;19699:7;19690:6;19679:9;19675:22;19657:50;:::i;:::-;19647:60;;19602:115;19256:468;;;;;:::o;19730:474::-;19798:6;19806;19855:2;19843:9;19834:7;19830:23;19826:32;19823:119;;;19861:79;;:::i;:::-;19823:119;19981:1;20006:53;20051:7;20042:6;20031:9;20027:22;20006:53;:::i;:::-;19996:63;;19952:117;20108:2;20134:53;20179:7;20170:6;20159:9;20155:22;20134:53;:::i;:::-;20124:63;;20079:118;19730:474;;;;;:::o;20210:1089::-;20314:6;20322;20330;20338;20346;20395:3;20383:9;20374:7;20370:23;20366:33;20363:120;;;20402:79;;:::i;:::-;20363:120;20522:1;20547:53;20592:7;20583:6;20572:9;20568:22;20547:53;:::i;:::-;20537:63;;20493:117;20649:2;20675:53;20720:7;20711:6;20700:9;20696:22;20675:53;:::i;:::-;20665:63;;20620:118;20777:2;20803:53;20848:7;20839:6;20828:9;20824:22;20803:53;:::i;:::-;20793:63;;20748:118;20905:2;20931:53;20976:7;20967:6;20956:9;20952:22;20931:53;:::i;:::-;20921:63;;20876:118;21061:3;21050:9;21046:19;21033:33;21093:18;21085:6;21082:30;21079:117;;;21115:79;;:::i;:::-;21079:117;21220:62;21274:7;21265:6;21254:9;21250:22;21220:62;:::i;:::-;21210:72;;21004:288;20210:1089;;;;;;;;:::o;21305:329::-;21364:6;21413:2;21401:9;21392:7;21388:23;21384:32;21381:119;;;21419:79;;:::i;:::-;21381:119;21539:1;21564:53;21609:7;21600:6;21589:9;21585:22;21564:53;:::i;:::-;21554:63;;21510:117;21305:329;;;;:::o;21640:::-;21699:6;21748:2;21736:9;21727:7;21723:23;21719:32;21716:119;;;21754:79;;:::i;:::-;21716:119;21874:1;21899:53;21944:7;21935:6;21924:9;21920:22;21899:53;:::i;:::-;21889:63;;21845:117;21640:329;;;;:::o;21975:180::-;22023:77;22020:1;22013:88;22120:4;22117:1;22110:15;22144:4;22141:1;22134:15;22161:320;22205:6;22242:1;22236:4;22232:12;22222:22;;22289:1;22283:4;22279:12;22310:18;22300:81;;22366:4;22358:6;22354:17;22344:27;;22300:81;22428:2;22420:6;22417:14;22397:18;22394:38;22391:84;;22447:18;;:::i;:::-;22391:84;22212:269;22161:320;;;:::o;22487:165::-;22627:17;22623:1;22615:6;22611:14;22604:41;22487:165;:::o;22658:366::-;22800:3;22821:67;22885:2;22880:3;22821:67;:::i;:::-;22814:74;;22897:93;22986:3;22897:93;:::i;:::-;23015:2;23010:3;23006:12;22999:19;;22658:366;;;:::o;23030:419::-;23196:4;23234:2;23223:9;23219:18;23211:26;;23283:9;23277:4;23273:20;23269:1;23258:9;23254:17;23247:47;23311:131;23437:4;23311:131;:::i;:::-;23303:139;;23030:419;;;:::o;23455:148::-;23557:11;23594:3;23579:18;;23455:148;;;;:::o;23609:141::-;23658:4;23681:3;23673:11;;23704:3;23701:1;23694:14;23738:4;23735:1;23725:18;23717:26;;23609:141;;;:::o;23780:874::-;23883:3;23920:5;23914:12;23949:36;23975:9;23949:36;:::i;:::-;24001:89;24083:6;24078:3;24001:89;:::i;:::-;23994:96;;24121:1;24110:9;24106:17;24137:1;24132:166;;;;24312:1;24307:341;;;;24099:549;;24132:166;24216:4;24212:9;24201;24197:25;24192:3;24185:38;24278:6;24271:14;24264:22;24256:6;24252:35;24247:3;24243:45;24236:52;;24132:166;;24307:341;24374:38;24406:5;24374:38;:::i;:::-;24434:1;24448:154;24462:6;24459:1;24456:13;24448:154;;;24536:7;24530:14;24526:1;24521:3;24517:11;24510:35;24586:1;24577:7;24573:15;24562:26;;24484:4;24481:1;24477:12;24472:17;;24448:154;;;24631:6;24626:3;24622:16;24615:23;;24314:334;;24099:549;;23887:767;;23780:874;;;;:::o;24660:151::-;24800:3;24796:1;24788:6;24784:14;24777:27;24660:151;:::o;24817:400::-;24977:3;24998:84;25080:1;25075:3;24998:84;:::i;:::-;24991:91;;25091:93;25180:3;25091:93;:::i;:::-;25209:1;25204:3;25200:11;25193:18;;24817:400;;;:::o;25223:390::-;25329:3;25357:39;25390:5;25357:39;:::i;:::-;25412:89;25494:6;25489:3;25412:89;:::i;:::-;25405:96;;25510:65;25568:6;25563:3;25556:4;25549:5;25545:16;25510:65;:::i;:::-;25600:6;25595:3;25591:16;25584:23;;25333:280;25223:390;;;;:::o;25619:155::-;25759:7;25755:1;25747:6;25743:14;25736:31;25619:155;:::o;25780:400::-;25940:3;25961:84;26043:1;26038:3;25961:84;:::i;:::-;25954:91;;26054:93;26143:3;26054:93;:::i;:::-;26172:1;26167:3;26163:11;26156:18;;25780:400;;;:::o;26186:961::-;26565:3;26587:92;26675:3;26666:6;26587:92;:::i;:::-;26580:99;;26696:148;26840:3;26696:148;:::i;:::-;26689:155;;26861:95;26952:3;26943:6;26861:95;:::i;:::-;26854:102;;26973:148;27117:3;26973:148;:::i;:::-;26966:155;;27138:3;27131:10;;26186:961;;;;;:::o;27153:275::-;27285:3;27307:95;27398:3;27389:6;27307:95;:::i;:::-;27300:102;;27419:3;27412:10;;27153:275;;;;:::o;27434:332::-;27555:4;27593:2;27582:9;27578:18;27570:26;;27606:71;27674:1;27663:9;27659:17;27650:6;27606:71;:::i;:::-;27687:72;27755:2;27744:9;27740:18;27731:6;27687:72;:::i;:::-;27434:332;;;;;:::o;27772:167::-;27912:19;27908:1;27900:6;27896:14;27889:43;27772:167;:::o;27945:366::-;28087:3;28108:67;28172:2;28167:3;28108:67;:::i;:::-;28101:74;;28184:93;28273:3;28184:93;:::i;:::-;28302:2;28297:3;28293:12;28286:19;;27945:366;;;:::o;28317:419::-;28483:4;28521:2;28510:9;28506:18;28498:26;;28570:9;28564:4;28560:20;28556:1;28545:9;28541:17;28534:47;28598:131;28724:4;28598:131;:::i;:::-;28590:139;;28317:419;;;:::o;28742:172::-;28882:24;28878:1;28870:6;28866:14;28859:48;28742:172;:::o;28920:366::-;29062:3;29083:67;29147:2;29142:3;29083:67;:::i;:::-;29076:74;;29159:93;29248:3;29159:93;:::i;:::-;29277:2;29272:3;29268:12;29261:19;;28920:366;;;:::o;29292:419::-;29458:4;29496:2;29485:9;29481:18;29473:26;;29545:9;29539:4;29535:20;29531:1;29520:9;29516:17;29509:47;29573:131;29699:4;29573:131;:::i;:::-;29565:139;;29292:419;;;:::o;29717:308::-;29826:4;29864:2;29853:9;29849:18;29841:26;;29877:65;29939:1;29928:9;29924:17;29915:6;29877:65;:::i;:::-;29952:66;30014:2;30003:9;29999:18;29990:6;29952:66;:::i;:::-;29717:308;;;;;:::o;30031:167::-;30171:19;30167:1;30159:6;30155:14;30148:43;30031:167;:::o;30204:366::-;30346:3;30367:67;30431:2;30426:3;30367:67;:::i;:::-;30360:74;;30443:93;30532:3;30443:93;:::i;:::-;30561:2;30556:3;30552:12;30545:19;;30204:366;;;:::o;30576:419::-;30742:4;30780:2;30769:9;30765:18;30757:26;;30829:9;30823:4;30819:20;30815:1;30804:9;30800:17;30793:47;30857:131;30983:4;30857:131;:::i;:::-;30849:139;;30576:419;;;:::o;31001:172::-;31141:24;31137:1;31129:6;31125:14;31118:48;31001:172;:::o;31179:366::-;31321:3;31342:67;31406:2;31401:3;31342:67;:::i;:::-;31335:74;;31418:93;31507:3;31418:93;:::i;:::-;31536:2;31531:3;31527:12;31520:19;;31179:366;;;:::o;31551:419::-;31717:4;31755:2;31744:9;31740:18;31732:26;;31804:9;31798:4;31794:20;31790:1;31779:9;31775:17;31768:47;31832:131;31958:4;31832:131;:::i;:::-;31824:139;;31551:419;;;:::o;31976:180::-;32024:77;32021:1;32014:88;32121:4;32118:1;32111:15;32145:4;32142:1;32135:15;32162:176;32194:1;32211:20;32229:1;32211:20;:::i;:::-;32206:25;;32245:20;32263:1;32245:20;:::i;:::-;32240:25;;32284:1;32274:35;;32289:18;;:::i;:::-;32274:35;32330:1;32327;32323:9;32318:14;;32162:176;;;;:::o;32344:180::-;32392:77;32389:1;32382:88;32489:4;32486:1;32479:15;32513:4;32510:1;32503:15;32530:176;32670:28;32666:1;32658:6;32654:14;32647:52;32530:176;:::o;32712:366::-;32854:3;32875:67;32939:2;32934:3;32875:67;:::i;:::-;32868:74;;32951:93;33040:3;32951:93;:::i;:::-;33069:2;33064:3;33060:12;33053:19;;32712:366;;;:::o;33084:419::-;33250:4;33288:2;33277:9;33273:18;33265:26;;33337:9;33331:4;33327:20;33323:1;33312:9;33308:17;33301:47;33365:131;33491:4;33365:131;:::i;:::-;33357:139;;33084:419;;;:::o;33509:180::-;33557:77;33554:1;33547:88;33654:4;33651:1;33644:15;33678:4;33675:1;33668:15;33695:191;33735:3;33754:20;33772:1;33754:20;:::i;:::-;33749:25;;33788:20;33806:1;33788:20;:::i;:::-;33783:25;;33831:1;33828;33824:9;33817:16;;33852:3;33849:1;33846:10;33843:36;;;33859:18;;:::i;:::-;33843:36;33695:191;;;;:::o;33892:332::-;34013:4;34051:2;34040:9;34036:18;34028:26;;34064:71;34132:1;34121:9;34117:17;34108:6;34064:71;:::i;:::-;34145:72;34213:2;34202:9;34198:18;34189:6;34145:72;:::i;:::-;33892:332;;;;;:::o;34230:93::-;34267:6;34314:2;34309;34302:5;34298:14;34294:23;34284:33;;34230:93;;;:::o;34329:107::-;34373:8;34423:5;34417:4;34413:16;34392:37;;34329:107;;;;:::o;34442:393::-;34511:6;34561:1;34549:10;34545:18;34584:97;34614:66;34603:9;34584:97;:::i;:::-;34702:39;34732:8;34721:9;34702:39;:::i;:::-;34690:51;;34774:4;34770:9;34763:5;34759:21;34750:30;;34823:4;34813:8;34809:19;34802:5;34799:30;34789:40;;34518:317;;34442:393;;;;;:::o;34841:60::-;34869:3;34890:5;34883:12;;34841:60;;;:::o;34907:142::-;34957:9;34990:53;35008:34;35017:24;35035:5;35017:24;:::i;:::-;35008:34;:::i;:::-;34990:53;:::i;:::-;34977:66;;34907:142;;;:::o;35055:75::-;35098:3;35119:5;35112:12;;35055:75;;;:::o;35136:269::-;35246:39;35277:7;35246:39;:::i;:::-;35307:91;35356:41;35380:16;35356:41;:::i;:::-;35348:6;35341:4;35335:11;35307:91;:::i;:::-;35301:4;35294:105;35212:193;35136:269;;;:::o;35411:73::-;35456:3;35411:73;:::o;35490:189::-;35567:32;;:::i;:::-;35608:65;35666:6;35658;35652:4;35608:65;:::i;:::-;35543:136;35490:189;;:::o;35685:186::-;35745:120;35762:3;35755:5;35752:14;35745:120;;;35816:39;35853:1;35846:5;35816:39;:::i;:::-;35789:1;35782:5;35778:13;35769:22;;35745:120;;;35685:186;;:::o;35877:543::-;35978:2;35973:3;35970:11;35967:446;;;36012:38;36044:5;36012:38;:::i;:::-;36096:29;36114:10;36096:29;:::i;:::-;36086:8;36082:44;36279:2;36267:10;36264:18;36261:49;;;36300:8;36285:23;;36261:49;36323:80;36379:22;36397:3;36379:22;:::i;:::-;36369:8;36365:37;36352:11;36323:80;:::i;:::-;35982:431;;35967:446;35877:543;;;:::o;36426:117::-;36480:8;36530:5;36524:4;36520:16;36499:37;;36426:117;;;;:::o;36549:169::-;36593:6;36626:51;36674:1;36670:6;36662:5;36659:1;36655:13;36626:51;:::i;:::-;36622:56;36707:4;36701;36697:15;36687:25;;36600:118;36549:169;;;;:::o;36723:295::-;36799:4;36945:29;36970:3;36964:4;36945:29;:::i;:::-;36937:37;;37007:3;37004:1;37000:11;36994:4;36991:21;36983:29;;36723:295;;;;:::o;37023:1395::-;37140:37;37173:3;37140:37;:::i;:::-;37242:18;37234:6;37231:30;37228:56;;;37264:18;;:::i;:::-;37228:56;37308:38;37340:4;37334:11;37308:38;:::i;:::-;37393:67;37453:6;37445;37439:4;37393:67;:::i;:::-;37487:1;37511:4;37498:17;;37543:2;37535:6;37532:14;37560:1;37555:618;;;;38217:1;38234:6;38231:77;;;38283:9;38278:3;38274:19;38268:26;38259:35;;38231:77;38334:67;38394:6;38387:5;38334:67;:::i;:::-;38328:4;38321:81;38190:222;37525:887;;37555:618;37607:4;37603:9;37595:6;37591:22;37641:37;37673:4;37641:37;:::i;:::-;37700:1;37714:208;37728:7;37725:1;37722:14;37714:208;;;37807:9;37802:3;37798:19;37792:26;37784:6;37777:42;37858:1;37850:6;37846:14;37836:24;;37905:2;37894:9;37890:18;37877:31;;37751:4;37748:1;37744:12;37739:17;;37714:208;;;37950:6;37941:7;37938:19;37935:179;;;38008:9;38003:3;37999:19;37993:26;38051:48;38093:4;38085:6;38081:17;38070:9;38051:48;:::i;:::-;38043:6;38036:64;37958:156;37935:179;38160:1;38156;38148:6;38144:14;38140:22;38134:4;38127:36;37562:611;;;37525:887;;37115:1303;;;37023:1395;;:::o;38424:168::-;38564:20;38560:1;38552:6;38548:14;38541:44;38424:168;:::o;38598:366::-;38740:3;38761:67;38825:2;38820:3;38761:67;:::i;:::-;38754:74;;38837:93;38926:3;38837:93;:::i;:::-;38955:2;38950:3;38946:12;38939:19;;38598:366;;;:::o;38970:419::-;39136:4;39174:2;39163:9;39159:18;39151:26;;39223:9;39217:4;39213:20;39209:1;39198:9;39194:17;39187:47;39251:131;39377:4;39251:131;:::i;:::-;39243:139;;38970:419;;;:::o;39395:225::-;39535:34;39531:1;39523:6;39519:14;39512:58;39604:8;39599:2;39591:6;39587:15;39580:33;39395:225;:::o;39626:366::-;39768:3;39789:67;39853:2;39848:3;39789:67;:::i;:::-;39782:74;;39865:93;39954:3;39865:93;:::i;:::-;39983:2;39978:3;39974:12;39967:19;;39626:366;;;:::o;39998:419::-;40164:4;40202:2;40191:9;40187:18;40179:26;;40251:9;40245:4;40241:20;40237:1;40226:9;40222:17;40215:47;40279:131;40405:4;40279:131;:::i;:::-;40271:139;;39998:419;;;:::o;40423:194::-;40463:4;40483:20;40501:1;40483:20;:::i;:::-;40478:25;;40517:20;40535:1;40517:20;:::i;:::-;40512:25;;40561:1;40558;40554:9;40546:17;;40585:1;40579:4;40576:11;40573:37;;;40590:18;;:::i;:::-;40573:37;40423:194;;;;:::o;40623:79::-;40662:7;40691:5;40680:16;;40623:79;;;:::o;40708:157::-;40813:45;40833:24;40851:5;40833:24;:::i;:::-;40813:45;:::i;:::-;40808:3;40801:58;40708:157;;:::o;40871:94::-;40904:8;40952:5;40948:2;40944:14;40923:35;;40871:94;;;:::o;40971:::-;41010:7;41039:20;41053:5;41039:20;:::i;:::-;41028:31;;40971:94;;;:::o;41071:100::-;41110:7;41139:26;41159:5;41139:26;:::i;:::-;41128:37;;41071:100;;;:::o;41177:157::-;41282:45;41302:24;41320:5;41302:24;:::i;:::-;41282:45;:::i;:::-;41277:3;41270:58;41177:157;;:::o;41340:79::-;41379:7;41408:5;41397:16;;41340:79;;;:::o;41425:157::-;41530:45;41550:24;41568:5;41550:24;:::i;:::-;41530:45;:::i;:::-;41525:3;41518:58;41425:157;;:::o;41588:820::-;41812:3;41827:75;41898:3;41889:6;41827:75;:::i;:::-;41927:2;41922:3;41918:12;41911:19;;41940:75;42011:3;42002:6;41940:75;:::i;:::-;42040:2;42035:3;42031:12;42024:19;;42053:75;42124:3;42115:6;42053:75;:::i;:::-;42153:2;42148:3;42144:12;42137:19;;42166:75;42237:3;42228:6;42166:75;:::i;:::-;42266:2;42261:3;42257:12;42250:19;;42279:75;42350:3;42341:6;42279:75;:::i;:::-;42379:2;42374:3;42370:12;42363:19;;42399:3;42392:10;;41588:820;;;;;;;;:::o;42414:169::-;42554:21;42550:1;42542:6;42538:14;42531:45;42414:169;:::o;42589:366::-;42731:3;42752:67;42816:2;42811:3;42752:67;:::i;:::-;42745:74;;42828:93;42917:3;42828:93;:::i;:::-;42946:2;42941:3;42937:12;42930:19;;42589:366;;;:::o;42961:419::-;43127:4;43165:2;43154:9;43150:18;43142:26;;43214:9;43208:4;43204:20;43200:1;43189:9;43185:17;43178:47;43242:131;43368:4;43242:131;:::i;:::-;43234:139;;42961:419;;;:::o;43386:180::-;43434:77;43431:1;43424:88;43531:4;43528:1;43521:15;43555:4;43552:1;43545:15;43572:553;43749:4;43787:3;43776:9;43772:19;43764:27;;43801:71;43869:1;43858:9;43854:17;43845:6;43801:71;:::i;:::-;43882:72;43950:2;43939:9;43935:18;43926:6;43882:72;:::i;:::-;43964;44032:2;44021:9;44017:18;44008:6;43964:72;:::i;:::-;44046;44114:2;44103:9;44099:18;44090:6;44046:72;:::i;:::-;43572:553;;;;;;;:::o;44131:634::-;44352:4;44390:2;44379:9;44375:18;44367:26;;44439:9;44433:4;44429:20;44425:1;44414:9;44410:17;44403:47;44467:108;44570:4;44561:6;44467:108;:::i;:::-;44459:116;;44622:9;44616:4;44612:20;44607:2;44596:9;44592:18;44585:48;44650:108;44753:4;44744:6;44650:108;:::i;:::-;44642:116;;44131:634;;;;;:::o;44771:98::-;44822:6;44856:5;44850:12;44840:22;;44771:98;;;:::o;44875:168::-;44958:11;44992:6;44987:3;44980:19;45032:4;45027:3;45023:14;45008:29;;44875:168;;;;:::o;45049:373::-;45135:3;45163:38;45195:5;45163:38;:::i;:::-;45217:70;45280:6;45275:3;45217:70;:::i;:::-;45210:77;;45296:65;45354:6;45349:3;45342:4;45335:5;45331:16;45296:65;:::i;:::-;45386:29;45408:6;45386:29;:::i;:::-;45381:3;45377:39;45370:46;;45139:283;45049:373;;;;:::o;45428:751::-;45651:4;45689:3;45678:9;45674:19;45666:27;;45703:71;45771:1;45760:9;45756:17;45747:6;45703:71;:::i;:::-;45784:72;45852:2;45841:9;45837:18;45828:6;45784:72;:::i;:::-;45866;45934:2;45923:9;45919:18;45910:6;45866:72;:::i;:::-;45948;46016:2;46005:9;46001:18;45992:6;45948:72;:::i;:::-;46068:9;46062:4;46058:20;46052:3;46041:9;46037:19;46030:49;46096:76;46167:4;46158:6;46096:76;:::i;:::-;46088:84;;45428:751;;;;;;;;:::o;46185:141::-;46241:5;46272:6;46266:13;46257:22;;46288:32;46314:5;46288:32;:::i;:::-;46185:141;;;;:::o;46332:349::-;46401:6;46450:2;46438:9;46429:7;46425:23;46421:32;46418:119;;;46456:79;;:::i;:::-;46418:119;46576:1;46601:63;46656:7;46647:6;46636:9;46632:22;46601:63;:::i;:::-;46591:73;;46547:127;46332:349;;;;:::o;46687:1053::-;47010:4;47048:3;47037:9;47033:19;47025:27;;47062:71;47130:1;47119:9;47115:17;47106:6;47062:71;:::i;:::-;47143:72;47211:2;47200:9;47196:18;47187:6;47143:72;:::i;:::-;47262:9;47256:4;47252:20;47247:2;47236:9;47232:18;47225:48;47290:108;47393:4;47384:6;47290:108;:::i;:::-;47282:116;;47445:9;47439:4;47435:20;47430:2;47419:9;47415:18;47408:48;47473:108;47576:4;47567:6;47473:108;:::i;:::-;47465:116;;47629:9;47623:4;47619:20;47613:3;47602:9;47598:19;47591:49;47657:76;47728:4;47719:6;47657:76;:::i;:::-;47649:84;;46687:1053;;;;;;;;:::o

Swarm Source

ipfs://f3b9dbe8f233bafd56f338eb9a6ef67325f3cf980ff73ff25a42f053f3162273
[ 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.