ETH Price: $1,973.67 (+0.26%)
 

Overview

Max Total Supply

6,969 SHIBU

Holders

160

Market

Volume (24H)

0.0036 ETH

Min Price (24H)

$2.37 @ 0.001200 ETH

Max Price (24H)

$2.37 @ 0.001200 ETH

Other Info

Balance
11 SHIBU
0x2ae57ecc52240ff0df36c979799bb2bcf957fb15
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
Shibutis

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license
/**
 *Submitted for verification at Etherscan.io on 2025-10-21
*/

// SPDX-License-Identifier: MIT
// File: erc721a/contracts/IERC721A.sol


// ERC721A Contracts v4.3.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;

/**
 * @dev Interface of ERC721A.
 */
interface IERC721A {
    /**
     * The caller must own the token or be an approved operator.
     */
    error ApprovalCallerNotOwnerNorApproved();

    /**
     * The token does not exist.
     */
    error ApprovalQueryForNonexistentToken();

    /**
     * Cannot query the balance for the zero address.
     */
    error BalanceQueryForZeroAddress();

    /**
     * Cannot mint to the zero address.
     */
    error MintToZeroAddress();

    /**
     * The quantity of tokens minted must be more than zero.
     */
    error MintZeroQuantity();

    /**
     * The token does not exist.
     */
    error OwnerQueryForNonexistentToken();

    /**
     * The caller must own the token or be an approved operator.
     */
    error TransferCallerNotOwnerNorApproved();

    /**
     * The token must be owned by `from`.
     */
    error TransferFromIncorrectOwner();

    /**
     * Cannot safely transfer to a contract that does not implement the
     * ERC721Receiver interface.
     */
    error TransferToNonERC721ReceiverImplementer();

    /**
     * Cannot transfer to the zero address.
     */
    error TransferToZeroAddress();

    /**
     * The token does not exist.
     */
    error URIQueryForNonexistentToken();

    /**
     * The `quantity` minted with ERC2309 exceeds the safety limit.
     */
    error MintERC2309QuantityExceedsLimit();

    /**
     * The `extraData` cannot be set on an unintialized ownership slot.
     */
    error OwnershipNotInitializedForExtraData();

    /**
     * `_sequentialUpTo()` must be greater than `_startTokenId()`.
     */
    error SequentialUpToTooSmall();

    /**
     * The `tokenId` of a sequential mint exceeds `_sequentialUpTo()`.
     */
    error SequentialMintExceedsLimit();

    /**
     * Spot minting requires a `tokenId` greater than `_sequentialUpTo()`.
     */
    error SpotMintTokenIdTooSmall();

    /**
     * Cannot mint over a token that already exists.
     */
    error TokenAlreadyExists();

    /**
     * The feature is not compatible with spot mints.
     */
    error NotCompatibleWithSpotMints();

    // =============================================================
    //                            STRUCTS
    // =============================================================

    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Stores the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
        // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
        uint24 extraData;
    }

    // =============================================================
    //                         TOKEN COUNTERS
    // =============================================================

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() external view returns (uint256);

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);

    // =============================================================
    //                            IERC721
    // =============================================================

    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

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

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

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

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

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

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

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

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

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

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

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

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

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

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

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

    // =============================================================
    //                           IERC2309
    // =============================================================

    /**
     * @dev Emitted when tokens in `fromTokenId` to `toTokenId`
     * (inclusive) is transferred from `from` to `to`, as defined in the
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
     *
     * See {_mintERC2309} for more details.
     */
    event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}

// File: erc721a/contracts/ERC721A.sol


// ERC721A Contracts v4.3.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;


/**
 * @dev Interface of ERC721 token receiver.
 */
interface ERC721A__IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

/**
 * @title ERC721A
 *
 * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721)
 * Non-Fungible Token Standard, including the Metadata extension.
 * Optimized for lower gas during batch mints.
 *
 * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...)
 * starting from `_startTokenId()`.
 *
 * The `_sequentialUpTo()` function can be overriden to enable spot mints
 * (i.e. non-consecutive mints) for `tokenId`s greater than `_sequentialUpTo()`.
 *
 * Assumptions:
 *
 * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
 * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256).
 */
contract ERC721A is IERC721A {
    // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364).
    struct TokenApprovalRef {
        address value;
    }

    // =============================================================
    //                           CONSTANTS
    // =============================================================

    // Mask of an entry in packed address data.
    uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;

    // The bit position of `numberMinted` in packed address data.
    uint256 private constant _BITPOS_NUMBER_MINTED = 64;

    // The bit position of `numberBurned` in packed address data.
    uint256 private constant _BITPOS_NUMBER_BURNED = 128;

    // The bit position of `aux` in packed address data.
    uint256 private constant _BITPOS_AUX = 192;

    // Mask of all 256 bits in packed address data except the 64 bits for `aux`.
    uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;

    // The bit position of `startTimestamp` in packed ownership.
    uint256 private constant _BITPOS_START_TIMESTAMP = 160;

    // The bit mask of the `burned` bit in packed ownership.
    uint256 private constant _BITMASK_BURNED = 1 << 224;

    // The bit position of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITPOS_NEXT_INITIALIZED = 225;

    // The bit mask of the `nextInitialized` bit in packed ownership.
    uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225;

    // The bit position of `extraData` in packed ownership.
    uint256 private constant _BITPOS_EXTRA_DATA = 232;

    // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`.
    uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1;

    // The mask of the lower 160 bits for addresses.
    uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;

    // The maximum `quantity` that can be minted with {_mintERC2309}.
    // This limit is to prevent overflows on the address data entries.
    // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309}
    // is required to cause an overflow, which is unrealistic.
    uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000;

    // The `Transfer` event signature is given by:
    // `keccak256(bytes("Transfer(address,address,uint256)"))`.
    bytes32 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    // =============================================================
    //                            STORAGE
    // =============================================================

    // The next token ID to be minted.
    uint256 private _currentIndex;

    // The number of tokens burned.
    uint256 private _burnCounter;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned.
    // See {_packedOwnershipOf} implementation for details.
    //
    // Bits Layout:
    // - [0..159]   `addr`
    // - [160..223] `startTimestamp`
    // - [224]      `burned`
    // - [225]      `nextInitialized`
    // - [232..255] `extraData`
    mapping(uint256 => uint256) private _packedOwnerships;

    // Mapping owner address to address data.
    //
    // Bits Layout:
    // - [0..63]    `balance`
    // - [64..127]  `numberMinted`
    // - [128..191] `numberBurned`
    // - [192..255] `aux`
    mapping(address => uint256) private _packedAddressData;

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

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

    // The amount of tokens minted above `_sequentialUpTo()`.
    // We call these spot mints (i.e. non-sequential mints).
    uint256 private _spotMinted;

    // =============================================================
    //                          CONSTRUCTOR
    // =============================================================

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

        if (_sequentialUpTo() < _startTokenId()) _revert(SequentialUpToTooSmall.selector);
    }

    // =============================================================
    //                   TOKEN COUNTING OPERATIONS
    // =============================================================

    /**
     * @dev Returns the starting token ID for sequential mints.
     *
     * Override this function to change the starting token ID for sequential mints.
     *
     * Note: The value returned must never change after any tokens have been minted.
     */
    function _startTokenId() internal view virtual returns (uint256) {
        return 0;
    }

    /**
     * @dev Returns the maximum token ID (inclusive) for sequential mints.
     *
     * Override this function to return a value less than 2**256 - 1,
     * but greater than `_startTokenId()`, to enable spot (non-sequential) mints.
     *
     * Note: The value returned must never change after any tokens have been minted.
     */
    function _sequentialUpTo() internal view virtual returns (uint256) {
        return type(uint256).max;
    }

    /**
     * @dev Returns the next token ID to be minted.
     */
    function _nextTokenId() internal view virtual returns (uint256) {
        return _currentIndex;
    }

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() public view virtual override returns (uint256 result) {
        // Counter underflow is impossible as `_burnCounter` cannot be incremented
        // more than `_currentIndex + _spotMinted - _startTokenId()` times.
        unchecked {
            // With spot minting, the intermediate `result` can be temporarily negative,
            // and the computation must be unchecked.
            result = _currentIndex - _burnCounter - _startTokenId();
            if (_sequentialUpTo() != type(uint256).max) result += _spotMinted;
        }
    }

    /**
     * @dev Returns the total amount of tokens minted in the contract.
     */
    function _totalMinted() internal view virtual returns (uint256 result) {
        // Counter underflow is impossible as `_currentIndex` does not decrement,
        // and it is initialized to `_startTokenId()`.
        unchecked {
            result = _currentIndex - _startTokenId();
            if (_sequentialUpTo() != type(uint256).max) result += _spotMinted;
        }
    }

    /**
     * @dev Returns the total number of tokens burned.
     */
    function _totalBurned() internal view virtual returns (uint256) {
        return _burnCounter;
    }

    /**
     * @dev Returns the total number of tokens that are spot-minted.
     */
    function _totalSpotMinted() internal view virtual returns (uint256) {
        return _spotMinted;
    }

    // =============================================================
    //                    ADDRESS DATA OPERATIONS
    // =============================================================

    /**
     * @dev Returns the number of tokens in `owner`'s account.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        if (owner == address(0)) _revert(BalanceQueryForZeroAddress.selector);
        return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens minted by `owner`.
     */
    function _numberMinted(address owner) internal view returns (uint256) {
        return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the number of tokens burned by or on behalf of `owner`.
     */
    function _numberBurned(address owner) internal view returns (uint256) {
        return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY;
    }

    /**
     * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
     */
    function _getAux(address owner) internal view returns (uint64) {
        return uint64(_packedAddressData[owner] >> _BITPOS_AUX);
    }

    /**
     * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
     * If there are multiple variables, please pack them into a uint64.
     */
    function _setAux(address owner, uint64 aux) internal virtual {
        uint256 packed = _packedAddressData[owner];
        uint256 auxCasted;
        // Cast `aux` with assembly to avoid redundant masking.
        assembly {
            auxCasted := aux
        }
        packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX);
        _packedAddressData[owner] = packed;
    }

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        // The interface IDs are constants representing the first 4 bytes
        // of the XOR of all function selectors in the interface.
        // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165)
        // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`)
        return
            interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165.
            interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721.
            interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata.
    }

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

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

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        if (!_exists(tokenId)) _revert(URIQueryForNonexistentToken.selector);

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

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

    // =============================================================
    //                     OWNERSHIPS OPERATIONS
    // =============================================================

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        return address(uint160(_packedOwnershipOf(tokenId)));
    }

    /**
     * @dev Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around over time.
     */
    function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnershipOf(tokenId));
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct at `index`.
     */
    function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) {
        return _unpackedOwnership(_packedOwnerships[index]);
    }

    /**
     * @dev Returns whether the ownership slot at `index` is initialized.
     * An uninitialized slot does not necessarily mean that the slot has no owner.
     */
    function _ownershipIsInitialized(uint256 index) internal view virtual returns (bool) {
        return _packedOwnerships[index] != 0;
    }

    /**
     * @dev Initializes the ownership slot minted at `index` for efficiency purposes.
     */
    function _initializeOwnershipAt(uint256 index) internal virtual {
        if (_packedOwnerships[index] == 0) {
            _packedOwnerships[index] = _packedOwnershipOf(index);
        }
    }

    /**
     * @dev Returns the packed ownership data of `tokenId`.
     */
    function _packedOwnershipOf(uint256 tokenId) private view returns (uint256 packed) {
        if (_startTokenId() <= tokenId) {
            packed = _packedOwnerships[tokenId];

            if (tokenId > _sequentialUpTo()) {
                if (_packedOwnershipExists(packed)) return packed;
                _revert(OwnerQueryForNonexistentToken.selector);
            }

            // If the data at the starting slot does not exist, start the scan.
            if (packed == 0) {
                if (tokenId >= _currentIndex) _revert(OwnerQueryForNonexistentToken.selector);
                // Invariant:
                // There will always be an initialized ownership slot
                // (i.e. `ownership.addr != address(0) && ownership.burned == false`)
                // before an unintialized ownership slot
                // (i.e. `ownership.addr == address(0) && ownership.burned == false`)
                // Hence, `tokenId` will not underflow.
                //
                // We can directly compare the packed value.
                // If the address is zero, packed will be zero.
                for (;;) {
                    unchecked {
                        packed = _packedOwnerships[--tokenId];
                    }
                    if (packed == 0) continue;
                    if (packed & _BITMASK_BURNED == 0) return packed;
                    // Otherwise, the token is burned, and we must revert.
                    // This handles the case of batch burned tokens, where only the burned bit
                    // of the starting slot is set, and remaining slots are left uninitialized.
                    _revert(OwnerQueryForNonexistentToken.selector);
                }
            }
            // Otherwise, the data exists and we can skip the scan.
            // This is possible because we have already achieved the target condition.
            // This saves 2143 gas on transfers of initialized tokens.
            // If the token is not burned, return `packed`. Otherwise, revert.
            if (packed & _BITMASK_BURNED == 0) return packed;
        }
        _revert(OwnerQueryForNonexistentToken.selector);
    }

    /**
     * @dev Returns the unpacked `TokenOwnership` struct from `packed`.
     */
    function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) {
        ownership.addr = address(uint160(packed));
        ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP);
        ownership.burned = packed & _BITMASK_BURNED != 0;
        ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA);
    }

    /**
     * @dev Packs ownership data into a single uint256.
     */
    function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`.
            result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags))
        }
    }

    /**
     * @dev Returns the `nextInitialized` flag set if `quantity` equals 1.
     */
    function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) {
        // For branchless setting of the `nextInitialized` flag.
        assembly {
            // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`.
            result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1))
        }
    }

    // =============================================================
    //                      APPROVAL OPERATIONS
    // =============================================================

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account. See {ERC721A-_approve}.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     */
    function approve(address to, uint256 tokenId) public payable virtual override {
        _approve(to, tokenId, true);
    }

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        if (!_exists(tokenId)) _revert(ApprovalQueryForNonexistentToken.selector);

        return _tokenApprovals[tokenId].value;
    }

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom}
     * for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _operatorApprovals[_msgSenderERC721A()][operator] = approved;
        emit ApprovalForAll(_msgSenderERC721A(), operator, approved);
    }

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

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted. See {_mint}.
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool result) {
        if (_startTokenId() <= tokenId) {
            if (tokenId > _sequentialUpTo()) return _packedOwnershipExists(_packedOwnerships[tokenId]);

            if (tokenId < _currentIndex) {
                uint256 packed;
                while ((packed = _packedOwnerships[tokenId]) == 0) --tokenId;
                result = packed & _BITMASK_BURNED == 0;
            }
        }
    }

    /**
     * @dev Returns whether `packed` represents a token that exists.
     */
    function _packedOwnershipExists(uint256 packed) private pure returns (bool result) {
        assembly {
            // The following is equivalent to `owner != address(0) && burned == false`.
            // Symbolically tested.
            result := gt(and(packed, _BITMASK_ADDRESS), and(packed, _BITMASK_BURNED))
        }
    }

    /**
     * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`.
     */
    function _isSenderApprovedOrOwner(
        address approvedAddress,
        address owner,
        address msgSender
    ) private pure returns (bool result) {
        assembly {
            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
            owner := and(owner, _BITMASK_ADDRESS)
            // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean.
            msgSender := and(msgSender, _BITMASK_ADDRESS)
            // `msgSender == owner || msgSender == approvedAddress`.
            result := or(eq(msgSender, owner), eq(msgSender, approvedAddress))
        }
    }

    /**
     * @dev Returns the storage slot and value for the approved address of `tokenId`.
     */
    function _getApprovedSlotAndAddress(uint256 tokenId)
        private
        view
        returns (uint256 approvedAddressSlot, address approvedAddress)
    {
        TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId];
        // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`.
        assembly {
            approvedAddressSlot := tokenApproval.slot
            approvedAddress := sload(approvedAddressSlot)
        }
    }

    // =============================================================
    //                      TRANSFER OPERATIONS
    // =============================================================

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable virtual override {
        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);

        // Mask `from` to the lower 160 bits, in case the upper bits somehow aren't clean.
        from = address(uint160(uint256(uint160(from)) & _BITMASK_ADDRESS));

        if (address(uint160(prevOwnershipPacked)) != from) _revert(TransferFromIncorrectOwner.selector);

        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);

        // The nested ifs save around 20+ gas over a compound boolean condition.
        if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
            if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector);

        _beforeTokenTransfers(from, to, tokenId, 1);

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

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

            // Updates:
            // - `address` to the next owner.
            // - `startTimestamp` to the timestamp of transfering.
            // - `burned` to `false`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                to,
                _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
        uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;
        assembly {
            // Emit the `Transfer` event.
            log4(
                0, // Start of data (0, since no data).
                0, // End of data (0, since no data).
                _TRANSFER_EVENT_SIGNATURE, // Signature.
                from, // `from`.
                toMasked, // `to`.
                tokenId // `tokenId`.
            )
        }
        if (toMasked == 0) _revert(TransferToZeroAddress.selector);

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

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable virtual override {
        safeTransferFrom(from, to, tokenId, '');
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement
     * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public payable virtual override {
        transferFrom(from, to, tokenId);
        if (to.code.length != 0)
            if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
                _revert(TransferToNonERC721ReceiverImplementer.selector);
            }
    }

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

    /**
     * @dev Hook that is called after a set of serially-ordered token IDs
     * have been transferred. This includes minting.
     * And also called after one token has been burned.
     *
     * `startTokenId` - the first token ID to be transferred.
     * `quantity` - the amount to be transferred.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
     * transferred to `to`.
     * - When `from` is zero, `tokenId` has been minted for `to`.
     * - When `to` is zero, `tokenId` has been burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract.
     *
     * `from` - Previous owner of the given token ID.
     * `to` - Target address that will receive the token.
     * `tokenId` - Token ID to be transferred.
     * `_data` - Optional data to send along with the call.
     *
     * Returns whether the call correctly returned the expected magic value.
     */
    function _checkContractOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns (
            bytes4 retval
        ) {
            return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector;
        } catch (bytes memory reason) {
            if (reason.length == 0) {
                _revert(TransferToNonERC721ReceiverImplementer.selector);
            }
            assembly {
                revert(add(32, reason), mload(reason))
            }
        }
    }

    // =============================================================
    //                        MINT OPERATIONS
    // =============================================================

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _mint(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (quantity == 0) _revert(MintZeroQuantity.selector);

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

        // Overflows are incredibly unrealistic.
        // `balance` and `numberMinted` have a maximum limit of 2**64.
        // `tokenId` has a maximum limit of 2**256.
        unchecked {
            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
            );

            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
            uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;

            if (toMasked == 0) _revert(MintToZeroAddress.selector);

            uint256 end = startTokenId + quantity;
            uint256 tokenId = startTokenId;

            if (end - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector);

            do {
                assembly {
                    // Emit the `Transfer` event.
                    log4(
                        0, // Start of data (0, since no data).
                        0, // End of data (0, since no data).
                        _TRANSFER_EVENT_SIGNATURE, // Signature.
                        0, // `address(0)`.
                        toMasked, // `to`.
                        tokenId // `tokenId`.
                    )
                }
                // The `!=` check ensures that large values of `quantity`
                // that overflows uint256 will make the loop run out of gas.
            } while (++tokenId != end);

            _currentIndex = end;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * This function is intended for efficient minting only during contract creation.
     *
     * It emits only one {ConsecutiveTransfer} as defined in
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),
     * instead of a sequence of {Transfer} event(s).
     *
     * Calling this function outside of contract creation WILL make your contract
     * non-compliant with the ERC721 standard.
     * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309
     * {ConsecutiveTransfer} event is only permissible during contract creation.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {ConsecutiveTransfer} event.
     */
    function _mintERC2309(address to, uint256 quantity) internal virtual {
        uint256 startTokenId = _currentIndex;
        if (to == address(0)) _revert(MintToZeroAddress.selector);
        if (quantity == 0) _revert(MintZeroQuantity.selector);
        if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) _revert(MintERC2309QuantityExceedsLimit.selector);

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

        // Overflows are unrealistic due to the above check for `quantity` to be below the limit.
        unchecked {
            // Updates:
            // - `balance += quantity`.
            // - `numberMinted += quantity`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);

            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `quantity == 1`.
            _packedOwnerships[startTokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
            );

            if (startTokenId + quantity - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector);

            emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to);

            _currentIndex = startTokenId + quantity;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

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

        unchecked {
            if (to.code.length != 0) {
                uint256 end = _currentIndex;
                uint256 index = end - quantity;
                do {
                    if (!_checkContractOnERC721Received(address(0), to, index++, _data)) {
                        _revert(TransferToNonERC721ReceiverImplementer.selector);
                    }
                } while (index < end);
                // This prevents reentrancy to `_safeMint`.
                // It does not prevent reentrancy to `_safeMintSpot`.
                if (_currentIndex != end) revert();
            }
        }
    }

    /**
     * @dev Equivalent to `_safeMint(to, quantity, '')`.
     */
    function _safeMint(address to, uint256 quantity) internal virtual {
        _safeMint(to, quantity, '');
    }

    /**
     * @dev Mints a single token at `tokenId`.
     *
     * Note: A spot-minted `tokenId` that has been burned can be re-minted again.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` must be greater than `_sequentialUpTo()`.
     * - `tokenId` must not exist.
     *
     * Emits a {Transfer} event for each mint.
     */
    function _mintSpot(address to, uint256 tokenId) internal virtual {
        if (tokenId <= _sequentialUpTo()) _revert(SpotMintTokenIdTooSmall.selector);
        uint256 prevOwnershipPacked = _packedOwnerships[tokenId];
        if (_packedOwnershipExists(prevOwnershipPacked)) _revert(TokenAlreadyExists.selector);

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

        // Overflows are incredibly unrealistic.
        // The `numberMinted` for `to` is incremented by 1, and has a max limit of 2**64 - 1.
        // `_spotMinted` is incremented by 1, and has a max limit of 2**256 - 1.
        unchecked {
            // Updates:
            // - `address` to the owner.
            // - `startTimestamp` to the timestamp of minting.
            // - `burned` to `false`.
            // - `nextInitialized` to `true` (as `quantity == 1`).
            _packedOwnerships[tokenId] = _packOwnershipData(
                to,
                _nextInitializedFlag(1) | _nextExtraData(address(0), to, prevOwnershipPacked)
            );

            // Updates:
            // - `balance += 1`.
            // - `numberMinted += 1`.
            //
            // We can directly add to the `balance` and `numberMinted`.
            _packedAddressData[to] += (1 << _BITPOS_NUMBER_MINTED) | 1;

            // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
            uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;

            if (toMasked == 0) _revert(MintToZeroAddress.selector);

            assembly {
                // Emit the `Transfer` event.
                log4(
                    0, // Start of data (0, since no data).
                    0, // End of data (0, since no data).
                    _TRANSFER_EVENT_SIGNATURE, // Signature.
                    0, // `address(0)`.
                    toMasked, // `to`.
                    tokenId // `tokenId`.
                )
            }

            ++_spotMinted;
        }

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

    /**
     * @dev Safely mints a single token at `tokenId`.
     *
     * Note: A spot-minted `tokenId` that has been burned can be re-minted again.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}.
     * - `tokenId` must be greater than `_sequentialUpTo()`.
     * - `tokenId` must not exist.
     *
     * See {_mintSpot}.
     *
     * Emits a {Transfer} event.
     */
    function _safeMintSpot(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _mintSpot(to, tokenId);

        unchecked {
            if (to.code.length != 0) {
                uint256 currentSpotMinted = _spotMinted;
                if (!_checkContractOnERC721Received(address(0), to, tokenId, _data)) {
                    _revert(TransferToNonERC721ReceiverImplementer.selector);
                }
                // This prevents reentrancy to `_safeMintSpot`.
                // It does not prevent reentrancy to `_safeMint`.
                if (_spotMinted != currentSpotMinted) revert();
            }
        }
    }

    /**
     * @dev Equivalent to `_safeMintSpot(to, tokenId, '')`.
     */
    function _safeMintSpot(address to, uint256 tokenId) internal virtual {
        _safeMintSpot(to, tokenId, '');
    }

    // =============================================================
    //                       APPROVAL OPERATIONS
    // =============================================================

    /**
     * @dev Equivalent to `_approve(to, tokenId, false)`.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _approve(to, tokenId, false);
    }

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the
     * zero address clears previous approvals.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function _approve(
        address to,
        uint256 tokenId,
        bool approvalCheck
    ) internal virtual {
        address owner = ownerOf(tokenId);

        if (approvalCheck && _msgSenderERC721A() != owner)
            if (!isApprovedForAll(owner, _msgSenderERC721A())) {
                _revert(ApprovalCallerNotOwnerNorApproved.selector);
            }

        _tokenApprovals[tokenId].value = to;
        emit Approval(owner, to, tokenId);
    }

    // =============================================================
    //                        BURN OPERATIONS
    // =============================================================

    /**
     * @dev Equivalent to `_burn(tokenId, false)`.
     */
    function _burn(uint256 tokenId) internal virtual {
        _burn(tokenId, false);
    }

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

        address from = address(uint160(prevOwnershipPacked));

        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);

        if (approvalCheck) {
            // The nested ifs save around 20+ gas over a compound boolean condition.
            if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
                if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector);
        }

        _beforeTokenTransfers(from, address(0), tokenId, 1);

        // Clear approvals from the previous owner.
        assembly {
            if approvedAddress {
                // This is equivalent to `delete _tokenApprovals[tokenId]`.
                sstore(approvedAddressSlot, 0)
            }
        }

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
        unchecked {
            // Updates:
            // - `balance -= 1`.
            // - `numberBurned += 1`.
            //
            // We can directly decrement the balance, and increment the number burned.
            // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.
            _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1;

            // Updates:
            // - `address` to the last owner.
            // - `startTimestamp` to the timestamp of burning.
            // - `burned` to `true`.
            // - `nextInitialized` to `true`.
            _packedOwnerships[tokenId] = _packOwnershipData(
                from,
                (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked)
            );

            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
                uint256 nextTokenId = tokenId + 1;
                // If the next slot's address is zero and not burned (i.e. packed value is zero).
                if (_packedOwnerships[nextTokenId] == 0) {
                    // If the next slot is within bounds.
                    if (nextTokenId != _currentIndex) {
                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
                        _packedOwnerships[nextTokenId] = prevOwnershipPacked;
                    }
                }
            }
        }

        emit Transfer(from, address(0), tokenId);
        _afterTokenTransfers(from, address(0), tokenId, 1);

        // Overflow not possible, as `_burnCounter` cannot be exceed `_currentIndex + _spotMinted` times.
        unchecked {
            _burnCounter++;
        }
    }

    // =============================================================
    //                     EXTRA DATA OPERATIONS
    // =============================================================

    /**
     * @dev Directly sets the extra data for the ownership data `index`.
     */
    function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual {
        uint256 packed = _packedOwnerships[index];
        if (packed == 0) _revert(OwnershipNotInitializedForExtraData.selector);
        uint256 extraDataCasted;
        // Cast `extraData` with assembly to avoid redundant masking.
        assembly {
            extraDataCasted := extraData
        }
        packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA);
        _packedOwnerships[index] = packed;
    }

    /**
     * @dev Called during each token transfer to set the 24bit `extraData` field.
     * Intended to be overridden by the cosumer contract.
     *
     * `previousExtraData` - the value of `extraData` before transfer.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _extraData(
        address from,
        address to,
        uint24 previousExtraData
    ) internal view virtual returns (uint24) {}

    /**
     * @dev Returns the next extra data for the packed ownership data.
     * The returned result is shifted into position.
     */
    function _nextExtraData(
        address from,
        address to,
        uint256 prevOwnershipPacked
    ) private view returns (uint256) {
        uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA);
        return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA;
    }

    // =============================================================
    //                       OTHER OPERATIONS
    // =============================================================

    /**
     * @dev Returns the message sender (defaults to `msg.sender`).
     *
     * If you are writing GSN compatible contracts, you need to override this function.
     */
    function _msgSenderERC721A() internal view virtual returns (address) {
        return msg.sender;
    }

    /**
     * @dev Converts a uint256 to its ASCII string decimal representation.
     */
    function _toString(uint256 value) internal pure virtual returns (string memory str) {
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but
            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
            // We will need 1 word for the trailing zeros padding, 1 word for the length,
            // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.
            let m := add(mload(0x40), 0xa0)
            // Update the free memory pointer to allocate.
            mstore(0x40, m)
            // Assign the `str` to the end.
            str := sub(m, 0x20)
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end of the memory to calculate the length later.
            let end := str

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            // prettier-ignore
            for { let temp := value } 1 {} {
                str := sub(str, 1)
                // Write the character to the pointer.
                // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))
                // Keep dividing `temp` until zero.
                temp := div(temp, 10)
                // prettier-ignore
                if iszero(temp) { break }
            }

            let length := sub(end, str)
            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 0x20)
            // Store the length.
            mstore(str, length)
        }
    }

    /**
     * @dev For more efficient reverts.
     */
    function _revert(bytes4 errorSelector) internal pure {
        assembly {
            mstore(0x00, errorSelector)
            revert(0x00, 0x04)
        }
    }
}

// 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/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/access/Ownable2Step.sol


// OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.20;


/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * This extension of the {Ownable} contract includes a two-step mechanism to transfer
 * ownership, where the new owner must call {acceptOwnership} in order to replace the
 * old one. This can help prevent common mistakes, such as transfers of ownership to
 * incorrect accounts, or to contracts that are unable to interact with the
 * permission system.
 *
 * The initial owner is specified at deployment time in the constructor for `Ownable`. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

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

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

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     *
     * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() public virtual {
        address sender = _msgSender();
        if (pendingOwner() != sender) {
            revert OwnableUnauthorizedAccount(sender);
        }
        _transferOwnership(sender);
    }
}

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


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

pragma solidity ^0.8.20;

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

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

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

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

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

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

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


// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/Hashes.sol)

pragma solidity ^0.8.20;

/**
 * @dev Library of standard hash functions.
 *
 * _Available since v5.1._
 */
library Hashes {
    /**
     * @dev Commutative Keccak256 hash of a sorted pair of bytes32. Frequently used when working with merkle proofs.
     *
     * NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
     */
    function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) {
        return a < b ? efficientKeccak256(a, b) : efficientKeccak256(b, a);
    }

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

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


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

pragma solidity ^0.8.20;


/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The tree and the proofs can be generated using our
 * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 * You will find a quickstart guide in the readme.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the Merkle tree could be reinterpreted as a leaf value.
 * OpenZeppelin's JavaScript library generates Merkle trees that are safe
 * against this attack out of the box.
 *
 * IMPORTANT: Consider memory side-effects when using custom hashing functions
 * that access memory in an unsafe way.
 *
 * NOTE: This library supports proof verification for merkle trees built using
 * custom _commutative_ hashing functions (i.e. `H(a, b) == H(b, a)`). Proving
 * leaf inclusion in trees built using non-commutative hashing functions requires
 * additional logic that is not supported by this library.
 */
library MerkleProof {
    /**
     *@dev The multiproof provided is not valid.
     */
    error MerkleProofInvalidMultiproof();

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

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

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

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

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

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leaves & pre-images are assumed to be sorted.
     *
     * This version handles proofs in calldata with the default hashing function.
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     *
     * This version handles proofs in calldata with a custom hashing function.
     */
    function verifyCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32 leaf,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bool) {
        return processProofCalldata(proof, leaf, hasher) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leaves & pre-images are assumed to be sorted.
     *
     * This version handles proofs in calldata with a custom hashing function.
     */
    function processProofCalldata(
        bytes32[] calldata proof,
        bytes32 leaf,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = hasher(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * This version handles multiproofs in memory with the default hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
     * The `leaves` must be validated independently. See {processMultiProof}.
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

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

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

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

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

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * This version handles multiproofs in memory with a custom hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
     * The `leaves` must be validated independently. See {processMultiProof}.
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bool) {
        return processMultiProof(proof, proofFlags, leaves, hasher) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * This version handles multiproofs in memory with a custom hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
     * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
     * validating the leaves elsewhere.
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the Merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofFlagsLen = proofFlags.length;

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

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

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

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * This version handles multiproofs in calldata with the default hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
     * The `leaves` must be validated independently. See {processMultiProofCalldata}.
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * This version handles multiproofs in calldata with the default hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
     * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
     * validating the leaves elsewhere.
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the Merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofFlagsLen = proofFlags.length;

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

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

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

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * This version handles multiproofs in calldata with a custom hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
     * The `leaves` must be validated independently. See {processMultiProofCalldata}.
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves, hasher) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * This version handles multiproofs in calldata with a custom hashing function.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
     * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
     * validating the leaves elsewhere.
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves,
        function(bytes32, bytes32) view returns (bytes32) hasher
    ) internal view returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the Merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofFlagsLen = proofFlags.length;

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

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

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

// 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/interfaces/IERC2981.sol


// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC2981.sol)

pragma solidity >=0.6.2;


/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     *
     * NOTE: ERC-2981 allows setting the royalty to 100% of the price. In that case all the price would be sent to the
     * royalty receiver and 0 tokens to the seller. Contracts dealing with royalty should consider empty transfers.
     */
    function royaltyInfo(
        uint256 tokenId,
        uint256 salePrice
    ) external view returns (address receiver, uint256 royaltyAmount);
}

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


// OpenZeppelin Contracts (last updated v5.4.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 {
    /// @inheritdoc IERC165
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

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


// OpenZeppelin Contracts (last updated v5.4.0) (token/common/ERC2981.sol)

pragma solidity ^0.8.20;



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

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

    /**
     * @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).
     */
    error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);

    /**
     * @dev The default royalty receiver is invalid.
     */
    error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);

    /**
     * @dev The royalty set for a specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).
     */
    error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);

    /**
     * @dev The royalty receiver for `tokenId` is invalid.
     */
    error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);

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

    /// @inheritdoc IERC2981
    function royaltyInfo(
        uint256 tokenId,
        uint256 salePrice
    ) public view virtual returns (address receiver, uint256 amount) {
        RoyaltyInfo storage _royaltyInfo = _tokenRoyaltyInfo[tokenId];
        address royaltyReceiver = _royaltyInfo.receiver;
        uint96 royaltyFraction = _royaltyInfo.royaltyFraction;

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

        uint256 royaltyAmount = (salePrice * royaltyFraction) / _feeDenominator();

        return (royaltyReceiver, royaltyAmount);
    }

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

    /**
     * @dev Sets the royalty information that all ids in this contract will default to.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
        uint256 denominator = _feeDenominator();
        if (feeNumerator > denominator) {
            // Royalty fee will exceed the sale price
            revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);
        }
        if (receiver == address(0)) {
            revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));
        }

        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
    }

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

    /**
     * @dev Sets the royalty information for a specific token id, overriding the global default.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {
        uint256 denominator = _feeDenominator();
        if (feeNumerator > denominator) {
            // Royalty fee will exceed the sale price
            revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);
        }
        if (receiver == address(0)) {
            revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));
        }

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

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

// File: @openzeppelin/contracts/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.3.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 Return the 512-bit addition of two uint256.
     *
     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
     */
    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
        assembly ("memory-safe") {
            low := add(a, b)
            high := lt(low, a)
        }
    }

    /**
     * @dev Return the 512-bit multiplication of two uint256.
     *
     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
     */
    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
        // 512-bit multiply [high low] = 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 = high * 2²⁵⁶ + low.
        assembly ("memory-safe") {
            let mm := mulmod(a, b, not(0))
            low := mul(a, b)
            high := sub(sub(mm, low), lt(mm, low))
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            uint256 c = a + b;
            success = c >= a;
            result = c * SafeCast.toUint(success);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            uint256 c = a - b;
            success = c <= a;
            result = c * SafeCast.toUint(success);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            uint256 c = a * b;
            assembly ("memory-safe") {
                // Only true when the multiplication doesn't overflow
                // (c / a == b) || (a == 0)
                success := or(eq(div(c, a), b), iszero(a))
            }
            // equivalent to: success ? c : 0
            result = c * SafeCast.toUint(success);
        }
    }

    /**
     * @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 {
            success = b > 0;
            assembly ("memory-safe") {
                // The `DIV` opcode returns zero when the denominator is 0.
                result := div(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 {
            success = b > 0;
            assembly ("memory-safe") {
                // The `MOD` opcode returns zero when the denominator is 0.
                result := mod(a, b)
            }
        }
    }

    /**
     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
     */
    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
        (bool success, uint256 result) = tryAdd(a, b);
        return ternary(success, result, type(uint256).max);
    }

    /**
     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
     */
    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
        (, uint256 result) = trySub(a, b);
        return result;
    }

    /**
     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
     */
    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
        (bool success, uint256 result) = tryMul(a, b);
        return ternary(success, result, type(uint256).max);
    }

    /**
     * @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 {
            (uint256 high, uint256 low) = mul512(x, y);

            // Handle non-overflow cases, 256 by 256 division.
            if (high == 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 low / denominator;
            }

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

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

            // Make division exact by subtracting the remainder from [high low].
            uint256 remainder;
            assembly ("memory-safe") {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                high := sub(high, gt(remainder, low))
                low := sub(low, 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 ("memory-safe") {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [high low] by twos.
                low := div(low, 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 high into low.
            low |= high * 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 high
            // is no longer required.
            result = low * 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 Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
     */
    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
        unchecked {
            (uint256 high, uint256 low) = mul512(x, y);
            if (high >= 1 << n) {
                Panic.panic(Panic.UNDER_OVERFLOW);
            }
            return (high << (256 - n)) | (low >> n);
        }
    }

    /**
     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.
     */
    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 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 x) internal pure returns (uint256 r) {
        // If value has upper 128 bits set, log2 result is at least 128
        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
        // If upper 64 bits of 128-bit half set, add 64 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
        // If upper 32 bits of 64-bit half set, add 32 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
        // If upper 16 bits of 32-bit half set, add 16 to result
        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
        // If upper 8 bits of 16-bit half set, add 8 to result
        r |= SafeCast.toUint((x >> r) > 0xff) << 3;
        // If upper 4 bits of 8-bit half set, add 4 to result
        r |= SafeCast.toUint((x >> r) > 0xf) << 2;

        // Shifts value right by the current result and use it as an index into this lookup table:
        //
        // | x (4 bits) |  index  | table[index] = MSB position |
        // |------------|---------|-----------------------------|
        // |    0000    |    0    |        table[0] = 0         |
        // |    0001    |    1    |        table[1] = 0         |
        // |    0010    |    2    |        table[2] = 1         |
        // |    0011    |    3    |        table[3] = 1         |
        // |    0100    |    4    |        table[4] = 2         |
        // |    0101    |    5    |        table[5] = 2         |
        // |    0110    |    6    |        table[6] = 2         |
        // |    0111    |    7    |        table[7] = 2         |
        // |    1000    |    8    |        table[8] = 3         |
        // |    1001    |    9    |        table[9] = 3         |
        // |    1010    |   10    |        table[10] = 3        |
        // |    1011    |   11    |        table[11] = 3        |
        // |    1100    |   12    |        table[12] = 3        |
        // |    1101    |   13    |        table[13] = 3        |
        // |    1110    |   14    |        table[14] = 3        |
        // |    1111    |   15    |        table[15] = 3        |
        //
        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
        assembly ("memory-safe") {
            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
        }
    }

    /**
     * @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 x) internal pure returns (uint256 r) {
        // If value has upper 128 bits set, log2 result is at least 128
        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
        // If upper 64 bits of 128-bit half set, add 64 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
        // If upper 32 bits of 64-bit half set, add 32 to result
        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
        // If upper 16 bits of 32-bit half set, add 16 to result
        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
    }

    /**
     * @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/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.4.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;
    uint256 private constant SPECIAL_CHARS_LOOKUP =
        (1 << 0x08) | // backspace
            (1 << 0x09) | // tab
            (1 << 0x0a) | // newline
            (1 << 0x0c) | // form feed
            (1 << 0x0d) | // carriage return
            (1 << 0x22) | // double quote
            (1 << 0x5c); // backslash

    /**
     * @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(add(buffer, 0x20), 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-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 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-string-uint256-uint256} 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-string-uint256-uint256} 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-string} 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-string-uint256-uint256} 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 guarantees 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-string} 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-string} 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-string-uint256-uint256} 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 Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.
     *
     * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.
     *
     * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of
     * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode
     * characters that are not in this range, but other tooling may provide different results.
     */
    function escapeJSON(string memory input) internal pure returns (string memory) {
        bytes memory buffer = bytes(input);
        bytes memory output = new bytes(2 * buffer.length); // worst case scenario
        uint256 outputLength = 0;

        for (uint256 i; i < buffer.length; ++i) {
            bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));
            if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {
                output[outputLength++] = "\\";
                if (char == 0x08) output[outputLength++] = "b";
                else if (char == 0x09) output[outputLength++] = "t";
                else if (char == 0x0a) output[outputLength++] = "n";
                else if (char == 0x0c) output[outputLength++] = "f";
                else if (char == 0x0d) output[outputLength++] = "r";
                else if (char == 0x5c) output[outputLength++] = "\\";
                else if (char == 0x22) {
                    // solhint-disable-next-line quotes
                    output[outputLength++] = '"';
                }
            } else {
                output[outputLength++] = char;
            }
        }
        // write the actual length and deallocate unused memory
        assembly ("memory-safe") {
            mstore(output, outputLength)
            mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))
        }

        return string(output);
    }

    /**
     * @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(add(buffer, 0x20), offset))
        }
    }
}

// File: ShibutisNFTMinting.sol


pragma solidity 0.8.24;







contract Shibutis is ERC721A, ERC2981, Ownable2Step, ReentrancyGuard {
    error SaleClosed();
    error AllowlistOnly();
    error PublicOnly();
    error NotAllowlisted();
    error ZeroQuantity();
    error ExceedsMaxSupply();
    error ExceedsWalletLimit();
    error WrongPayment(uint256 required, uint256 sent);
    error ZeroAddress();
    error RoyaltyTooHigh();
    error WithdrawFailed();
    error NoBalance();
    error BaseURIUnset();
    error InvalidPrice();
    error InvalidMerkleRoot();
    error InvalidURI();

    event BaseURISet(string baseURI);
    event ContractURIUpdated(string newContractURI);
    event HiddenURISet(string newHiddenURI);
    event RevealToggled(bool revealed);
    event MintPriceSet(uint256 newPrice);
    event MaxPerWalletPublicSet(uint256 newLimit);
    event MerkleRootSet(bytes32 newRoot);
    event SalePhaseSet(uint8 newPhase);
    event Withdraw(address indexed to, uint256 amount);
    event Minted(address indexed to, uint256 quantity, uint8 phase);

    uint256 public constant MAX_SUPPLY = 6969;

    enum Phase {
        Closed,
        Allowlist,
        Public
    }

    Phase public salePhase = Phase.Closed;

    mapping(address => uint32) public presaleMinted;
    mapping(address => uint32) public publicMinted;

    uint256 public mintPrice = 0.0055 ether;
    uint256 public presalePrice = 0;

    uint256 public maxPerWalletPublic = 0;

    string private _baseTokenURI;
    bool public revealed = false;
    string private _hiddenURI;
    string private _contractURI;

    bytes32 public merkleRoot;

    constructor(
        address _initialOwner,
        address _royaltyReceiver,
        uint96 _royaltyFeeNumerator,
        string memory hiddenURI
    ) ERC721A("Shibutis", "SHIBU") Ownable(_initialOwner) {
        if (_initialOwner == address(0) || _royaltyReceiver == address(0))
            revert ZeroAddress();
        if (_royaltyFeeNumerator > 1000) revert RoyaltyTooHigh();
        _setDefaultRoyalty(_royaltyReceiver, _royaltyFeeNumerator);

        _hiddenURI = hiddenURI;
    }

    function whitelistMint(
        uint256 quantity,
        uint256 allowance,
        bytes32[] calldata proof
    ) external payable nonReentrant {
        if (salePhase != Phase.Allowlist) revert AllowlistOnly();
        if (quantity == 0) revert ZeroQuantity();

        if (_totalMinted() + quantity > MAX_SUPPLY) revert ExceedsMaxSupply();

        bytes32 leaf = keccak256(abi.encodePacked(msg.sender, allowance));
        if (!MerkleProof.verifyCalldata(proof, merkleRoot, leaf))
            revert NotAllowlisted();

        if (presaleMinted[msg.sender] + quantity > allowance)
            revert ExceedsWalletLimit();

        uint256 required = presalePrice * quantity;
        if (msg.value != required) revert WrongPayment(required, msg.value);

        presaleMinted[msg.sender] += uint32(quantity);

        _safeMint(msg.sender, quantity);

        emit Minted(msg.sender, quantity, uint8(Phase.Allowlist));
    }

    function publicMint(uint256 quantity) external payable nonReentrant {
        if (salePhase != Phase.Public) revert PublicOnly();
        if (quantity == 0) revert ZeroQuantity();

        if (_totalMinted() + quantity > MAX_SUPPLY) revert ExceedsMaxSupply();

        if (
            maxPerWalletPublic != 0 &&
            publicMinted[msg.sender] + quantity > maxPerWalletPublic
        ) revert ExceedsWalletLimit();

        uint256 required = mintPrice * quantity;
        if (msg.value != required) revert WrongPayment(required, msg.value);

        publicMinted[msg.sender] += uint32(quantity);
        _safeMint(msg.sender, quantity);

        emit Minted(msg.sender, quantity, uint8(Phase.Public));
    }

    function _startTokenId() internal pure override returns (uint256) {
        return 1;
    }

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

    function contractURI() public view returns (string memory) {
        return _contractURI;
    }

    function tokenURI(
        uint256 tokenId
    ) public view override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
        if (!revealed) return _hiddenURI;
        return
            string(
                abi.encodePacked(_baseURI(), Strings.toString(tokenId), ".json")
            );
    }

    function setBaseURI(string calldata newBase) external onlyOwner {
        if (bytes(newBase).length == 0) revert InvalidURI();
        _baseTokenURI = newBase;
        emit BaseURISet(newBase);
    }

    function setContractURI(string calldata newContractURI) external onlyOwner {
        if (bytes(newContractURI).length == 0) revert InvalidURI();
        _contractURI = newContractURI;
        emit ContractURIUpdated(newContractURI);
    }

    function setRevealed(bool _revealed) external onlyOwner {
        if (_revealed)
            if (bytes(_baseTokenURI).length == 0) revert BaseURIUnset();
        revealed = _revealed;
        emit RevealToggled(_revealed);
    }

    function setMintPrice(uint256 newPrice) external onlyOwner {
        if (newPrice == 0) revert InvalidPrice();
        mintPrice = newPrice;
        emit MintPriceSet(newPrice);
    }

    function setHiddenURI(string calldata newHiddenURI) external onlyOwner {
        if (bytes(newHiddenURI).length == 0) revert InvalidURI();
        _hiddenURI = newHiddenURI;
        emit HiddenURISet(newHiddenURI);
    }

    function setMaxPerWalletPublic(uint256 newLimit) external onlyOwner {
        maxPerWalletPublic = newLimit;
        emit MaxPerWalletPublicSet(newLimit);
    }

    function setMerkleRoot(bytes32 newRoot) external onlyOwner {
        if (newRoot == bytes32(0)) revert InvalidMerkleRoot();
        merkleRoot = newRoot;
        emit MerkleRootSet(newRoot);
    }

    function setSalePhase(Phase newPhase) external onlyOwner {
        salePhase = newPhase;
        emit SalePhaseSet(uint8(newPhase));
    }

    function setDefaultRoyalty(
        address receiver,
        uint96 feeNumerator
    ) external onlyOwner {
        if (feeNumerator > 1000) revert RoyaltyTooHigh();
        if (receiver == address(0)) revert ZeroAddress();
        _setDefaultRoyalty(receiver, feeNumerator);
    }

    function withdrawAmount(
        address payable to,
        uint256 amount
    ) external onlyOwner nonReentrant {
        if (to == address(0)) revert ZeroAddress();
        require(amount <= address(this).balance, "Amount too high");
        (bool ok, ) = to.call{value: amount}("");
        require(ok, "Transfer failed");
        emit Withdraw(to, amount);
    }

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_initialOwner","type":"address"},{"internalType":"address","name":"_royaltyReceiver","type":"address"},{"internalType":"uint96","name":"_royaltyFeeNumerator","type":"uint96"},{"internalType":"string","name":"hiddenURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AllowlistOnly","type":"error"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"BaseURIUnset","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[],"name":"ExceedsMaxSupply","type":"error"},{"inputs":[],"name":"ExceedsWalletLimit","type":"error"},{"inputs":[],"name":"InvalidMerkleRoot","type":"error"},{"inputs":[],"name":"InvalidPrice","type":"error"},{"inputs":[],"name":"InvalidURI","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"NoBalance","type":"error"},{"inputs":[],"name":"NotAllowlisted","type":"error"},{"inputs":[],"name":"NotCompatibleWithSpotMints","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"PublicOnly","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"RoyaltyTooHigh","type":"error"},{"inputs":[],"name":"SaleClosed","type":"error"},{"inputs":[],"name":"SequentialMintExceedsLimit","type":"error"},{"inputs":[],"name":"SequentialUpToTooSmall","type":"error"},{"inputs":[],"name":"SpotMintTokenIdTooSmall","type":"error"},{"inputs":[],"name":"TokenAlreadyExists","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"WithdrawFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"},{"internalType":"uint256","name":"sent","type":"uint256"}],"name":"WrongPayment","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroQuantity","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"baseURI","type":"string"}],"name":"BaseURISet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"newContractURI","type":"string"}],"name":"ContractURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"newHiddenURI","type":"string"}],"name":"HiddenURISet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"MaxPerWalletPublicSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"newRoot","type":"bytes32"}],"name":"MerkleRootSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"MintPriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"phase","type":"uint8"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"revealed","type":"bool"}],"name":"RevealToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"newPhase","type":"uint8"}],"name":"SalePhaseSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPerWalletPublic","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"presaleMinted","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presalePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"publicMinted","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"salePhase","outputs":[{"internalType":"enum Shibutis.Phase","name":"","type":"uint8"}],"stateMutability":"view","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":"newBase","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newContractURI","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newHiddenURI","type":"string"}],"name":"setHiddenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"setMaxPerWalletPublic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_revealed","type":"bool"}],"name":"setRevealed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Shibutis.Phase","name":"newPhase","type":"uint8"}],"name":"setSalePhase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"whitelistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawAmount","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040525f600e5f6101000a81548160ff021916908360028111156200002b576200002a620005fe565b5b021790555066138a388a43c0006011555f6012555f6013555f60155f6101000a81548160ff02191690831515021790555034801562000068575f80fd5b50604051620051f8380380620051f883398181016040528101906200008e919062000857565b836040518060400160405280600881526020017f53686962757469730000000000000000000000000000000000000000000000008152506040518060400160405280600581526020017f534849425500000000000000000000000000000000000000000000000000000081525081600290816200010c919062000b1c565b5080600390816200011e919062000b1c565b506200012f6200031a60201b60201c565b5f81905550620001446200031a60201b60201c565b620001546200032260201b60201c565b101562000174576200017363fed8210f60e01b6200034960201b60201c565b5b50505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620001e9575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620001e0919062000c11565b60405180910390fd5b620001fa816200035160201b60201c565b506001600d819055505f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806200026957505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b15620002a1576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8826bffffffffffffffffffffffff161115620002ec576040517fc2b03beb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620002fe83836200038960201b60201c565b80601690816200030f919062000b1c565b505050505062000ca0565b5f6001905090565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b805f5260045ffd5b600c5f6101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905562000386816200053260201b60201c565b50565b5f6200039a620005f560201b60201c565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff161115620004025781816040517f6f483d09000000000000000000000000000000000000000000000000000000008152600401620003f992919062000c75565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000475575f6040517fb6d9900a0000000000000000000000000000000000000000000000000000000081526004016200046c919062000c11565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff1681525060095f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f612710905090565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f62000667826200063c565b9050919050565b62000679816200065b565b811462000684575f80fd5b50565b5f8151905062000697816200066e565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b620006bf816200069d565b8114620006ca575f80fd5b50565b5f81519050620006dd81620006b4565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6200073382620006eb565b810181811067ffffffffffffffff82111715620007555762000754620006fb565b5b80604052505050565b5f620007696200062b565b905062000777828262000728565b919050565b5f67ffffffffffffffff821115620007995762000798620006fb565b5b620007a482620006eb565b9050602081019050919050565b5f5b83811015620007d0578082015181840152602081019050620007b3565b5f8484015250505050565b5f620007f1620007eb846200077c565b6200075e565b90508281526020810184848401111562000810576200080f620006e7565b5b6200081d848285620007b1565b509392505050565b5f82601f8301126200083c576200083b620006e3565b5b81516200084e848260208601620007db565b91505092915050565b5f805f806080858703121562000872576200087162000634565b5b5f620008818782880162000687565b9450506020620008948782880162000687565b9350506040620008a787828801620006cd565b925050606085015167ffffffffffffffff811115620008cb57620008ca62000638565b5b620008d98782880162000825565b91505092959194509250565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200093457607f821691505b6020821081036200094a5762000949620008ef565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620009ae7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000971565b620009ba868362000971565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f62000a04620009fe620009f884620009d2565b620009db565b620009d2565b9050919050565b5f819050919050565b62000a1f83620009e4565b62000a3762000a2e8262000a0b565b8484546200097d565b825550505050565b5f90565b62000a4d62000a3f565b62000a5a81848462000a14565b505050565b5b8181101562000a815762000a755f8262000a43565b60018101905062000a60565b5050565b601f82111562000ad05762000a9a8162000950565b62000aa58462000962565b8101602085101562000ab5578190505b62000acd62000ac48562000962565b83018262000a5f565b50505b505050565b5f82821c905092915050565b5f62000af25f198460080262000ad5565b1980831691505092915050565b5f62000b0c838362000ae1565b9150826002028217905092915050565b62000b2782620008e5565b67ffffffffffffffff81111562000b435762000b42620006fb565b5b62000b4f82546200091c565b62000b5c82828562000a85565b5f60209050601f83116001811462000b92575f841562000b7d578287015190505b62000b89858262000aff565b86555062000bf8565b601f19841662000ba28662000950565b5f5b8281101562000bcb5784890151825560018201915060208501945060208101905062000ba4565b8683101562000beb578489015162000be7601f89168262000ae1565b8355505b6001600288020188555050505b505050505050565b62000c0b816200065b565b82525050565b5f60208201905062000c265f83018462000c00565b92915050565b5f62000c4c62000c4662000c40846200069d565b620009db565b620009d2565b9050919050565b62000c5e8162000c2c565b82525050565b62000c6f81620009d2565b82525050565b5f60408201905062000c8a5f83018562000c53565b62000c99602083018462000c64565b9392505050565b61454a8062000cae5f395ff3fe60806040526004361061024f575f3560e01c806379ba509711610138578063bbaac02f116100b5578063e30c397811610079578063e30c39781461083c578063e4f2487a14610866578063e8a3d48514610890578063e985e9c5146108ba578063f2fde38b146108f6578063f4a0a5281461091e5761024f565b8063bbaac02f14610758578063bc660cac14610780578063c4be5b59146107bc578063c87b56dd146107d8578063e0a80853146108145761024f565b8063938e3d7b116100fc578063938e3d7b1461069857806395d89b41146106c0578063a22cb465146106ea578063b029a51414610712578063b88d4fde1461073c5761024f565b806379ba5097146105e05780637ad59431146105f65780637cb647591461061e5780638b533ea4146106465780638da5cb5b1461066e5761024f565b80632db11544116101d157806355f804b31161019557806355f804b3146104d85780636352211e146105005780636817c76c1461053c57806370a0823114610566578063715018a6146105a2578063736fe565146105b85761024f565b80632db11544146104225780632eb4a7ab1461043e57806332cb6b0c1461046857806342842e0e1461049257806351830227146104ae5761024f565b8063095ea7b311610218578063095ea7b3146103475780631015805b1461036357806318160ddd1461039f57806323b872dd146103c95780632a55205a146103e55761024f565b80620e7fa81461025357806301ffc9a71461027d57806304634d8d146102b957806306fdde03146102e1578063081812fc1461030b575b5f80fd5b34801561025e575f80fd5b50610267610946565b60405161027491906131e1565b60405180910390f35b348015610288575f80fd5b506102a3600480360381019061029e9190613260565b61094c565b6040516102b091906132a5565b60405180910390f35b3480156102c4575f80fd5b506102df60048036038101906102da9190613359565b61095d565b005b3480156102ec575f80fd5b506102f5610a22565b6040516103029190613421565b60405180910390f35b348015610316575f80fd5b50610331600480360381019061032c919061346b565b610ab2565b60405161033e91906134a5565b60405180910390f35b610361600480360381019061035c91906134be565b610b0b565b005b34801561036e575f80fd5b50610389600480360381019061038491906134fc565b610b1b565b6040516103969190613545565b60405180910390f35b3480156103aa575f80fd5b506103b3610b3b565b6040516103c091906131e1565b60405180910390f35b6103e360048036038101906103de919061355e565b610b86565b005b3480156103f0575f80fd5b5061040b600480360381019061040691906135ae565b610e31565b6040516104199291906135ec565b60405180910390f35b61043c6004803603810190610437919061346b565b610f53565b005b348015610449575f80fd5b5061045261123c565b60405161045f919061362b565b60405180910390f35b348015610473575f80fd5b5061047c611242565b60405161048991906131e1565b60405180910390f35b6104ac60048036038101906104a7919061355e565b611248565b005b3480156104b9575f80fd5b506104c2611267565b6040516104cf91906132a5565b60405180910390f35b3480156104e3575f80fd5b506104fe60048036038101906104f991906136a5565b611279565b005b34801561050b575f80fd5b506105266004803603810190610521919061346b565b61130c565b60405161053391906134a5565b60405180910390f35b348015610547575f80fd5b5061055061131d565b60405161055d91906131e1565b60405180910390f35b348015610571575f80fd5b5061058c600480360381019061058791906134fc565b611323565b60405161059991906131e1565b60405180910390f35b3480156105ad575f80fd5b506105b66113b7565b005b3480156105c3575f80fd5b506105de60048036038101906105d9919061372b565b6113ca565b005b3480156105eb575f80fd5b506105f4611585565b005b348015610601575f80fd5b5061061c6004803603810190610617919061378c565b611613565b005b348015610629575f80fd5b50610644600480360381019061063f91906137e1565b611690565b005b348015610651575f80fd5b5061066c6004803603810190610667919061346b565b611714565b005b348015610679575f80fd5b5061068261175d565b60405161068f91906134a5565b60405180910390f35b3480156106a3575f80fd5b506106be60048036038101906106b991906136a5565b611785565b005b3480156106cb575f80fd5b506106d4611818565b6040516106e19190613421565b60405180910390f35b3480156106f5575f80fd5b50610710600480360381019061070b9190613836565b6118a8565b005b34801561071d575f80fd5b506107266119ae565b60405161073391906131e1565b60405180910390f35b6107566004803603810190610751919061399c565b6119b4565b005b348015610763575f80fd5b5061077e600480360381019061077991906136a5565b611a05565b005b34801561078b575f80fd5b506107a660048036038101906107a191906134fc565b611a98565b6040516107b39190613545565b60405180910390f35b6107d660048036038101906107d19190613a71565b611ab8565b005b3480156107e3575f80fd5b506107fe60048036038101906107f9919061346b565b611e07565b60405161080b9190613421565b60405180910390f35b34801561081f575f80fd5b5061083a60048036038101906108359190613ae2565b611f2d565b005b348015610847575f80fd5b50610850611fd6565b60405161085d91906134a5565b60405180910390f35b348015610871575f80fd5b5061087a611ffe565b6040516108879190613b80565b60405180910390f35b34801561089b575f80fd5b506108a4612010565b6040516108b19190613421565b60405180910390f35b3480156108c5575f80fd5b506108e060048036038101906108db9190613b99565b6120a0565b6040516108ed91906132a5565b60405180910390f35b348015610901575f80fd5b5061091c600480360381019061091791906134fc565b61212e565b005b348015610929575f80fd5b50610944600480360381019061093f919061346b565b6121da565b005b60125481565b5f6109568261225b565b9050919050565b6109656122d4565b6103e8816bffffffffffffffffffffffff1611156109af576040517fc2b03beb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a14576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a1e8282612375565b5050565b606060028054610a3190613c04565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5d90613c04565b8015610aa85780601f10610a7f57610100808354040283529160200191610aa8565b820191905f5260205f20905b815481529060010190602001808311610a8b57829003601f168201915b5050505050905090565b5f610abc82612510565b610ad157610ad063cf4700e460e01b6125b3565b5b60065f8381526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610b17828260016125bb565b5050565b6010602052805f5260405f205f915054906101000a900463ffffffff1681565b5f610b446126e5565b6001545f54030390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610b766126ed565b14610b8357600854810190505b90565b5f610b9082612714565b905073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161693508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610c0557610c0463a114810060e01b6125b3565b5b5f80610c1084612823565b91509150610c268187610c21612846565b61284d565b610c5157610c3b86610c36612846565b6120a0565b610c5057610c4f6359c896be60e01b6125b3565b5b5b610c5e8686866001612890565b8015610c68575f82555b60055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600190039190508190555060055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815460010191905081905550610d3085610d0c888887612896565b7c0200000000000000000000000000000000000000000000000000000000176128bd565b60045f8681526020019081526020015f20819055505f7c0200000000000000000000000000000000000000000000000000000000841603610dac575f6001850190505f60045f8381526020019081526020015f205403610daa575f548114610da9578360045f8381526020019081526020015f20819055505b5b505b5f73ffffffffffffffffffffffffffffffffffffffff8673ffffffffffffffffffffffffffffffffffffffff161690508481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a45f8103610e1b57610e1a63ea553b3460e01b6125b3565b5b610e2887878760016128e7565b50505050505050565b5f805f600a5f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610f055760095f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915060095f0160149054906101000a90046bffffffffffffffffffffffff1690505b5f610f0e6128ed565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff1688610f369190613c61565b610f409190613ccf565b9050828195509550505050509250929050565b610f5b6128f6565b600280811115610f6e57610f6d613b0d565b5b600e5f9054906101000a900460ff166002811115610f8f57610f8e613b0d565b5b14610fc6576040517f47553b7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8103610fff576040517ff4f5b73300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b398161100b61293c565b6110159190613cff565b111561104d576040517fc30436e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f601354141580156110bd57506013548160105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900463ffffffff1663ffffffff166110bb9190613cff565b115b156110f4576040517f5107dbe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f816011546111039190613c61565b905080341461114b5780346040517f0dd32d1c000000000000000000000000000000000000000000000000000000008152600401611142929190613d32565b60405180910390fd5b8160105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282829054906101000a900463ffffffff166111a69190613d59565b92506101000a81548163ffffffff021916908363ffffffff1602179055506111ce3383612983565b3373ffffffffffffffffffffffffffffffffffffffff167fdcb23284f3935b5557998e99dcc286e29744c5000723d99eecd5d6f5694f6e118360028081111561121a57611219613b0d565b5b604051611228929190613dab565b60405180910390a2506112396129a0565b50565b60185481565b611b3981565b61126283838360405180602001604052805f8152506119b4565b505050565b60155f9054906101000a900460ff1681565b6112816122d4565b5f82829050036112bd576040517f3ba0191100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181601491826112ce929190613f79565b507ff9c7803e94e0d3c02900d8a90893a6d5e90dd04d32a4cfe825520f82bf9f32f68282604051611300929190614072565b60405180910390a15050565b5f61131682612714565b9050919050565b60115481565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361136857611367638f4eb60460e01b6125b3565b5b67ffffffffffffffff60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054169050919050565b6113bf6122d4565b6113c85f6129aa565b565b6113d26122d4565b6113da6128f6565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361143f576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47811115611482576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611479906140de565b60405180910390fd5b5f8273ffffffffffffffffffffffffffffffffffffffff16826040516114a790614129565b5f6040518083038185875af1925050503d805f81146114e1576040519150601f19603f3d011682016040523d82523d5f602084013e6114e6565b606091505b505090508061152a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161152190614187565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648360405161157091906131e1565b60405180910390a2506115816129a0565b5050565b5f61158e6129da565b90508073ffffffffffffffffffffffffffffffffffffffff166115af611fd6565b73ffffffffffffffffffffffffffffffffffffffff161461160757806040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016115fe91906134a5565b60405180910390fd5b611610816129aa565b50565b61161b6122d4565b80600e5f6101000a81548160ff0219169083600281111561163f5761163e613b0d565b5b02179055507f7b113c9b68e115832b8e4a4ad5a4d03d9b288f9105305adc0ddfc9a11bc68c4381600281111561167857611677613b0d565b5b60405161168591906141a5565b60405180910390a150565b6116986122d4565b5f801b81036116d3576040517f9dd854d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806018819055507f42cbc405e4dbf1b691e85b9a34b08ecfcf7a9ad9078bf4d645ccfa1fac11c10b81604051611709919061362b565b60405180910390a150565b61171c6122d4565b806013819055507fe4e809aaafc550a795e8ceb7b761a48dc15e5f6227a77ea95056cae1953070958160405161175291906131e1565b60405180910390a150565b5f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61178d6122d4565b5f82829050036117c9576040517f3ba0191100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181601791826117da929190613f79565b507f905d981207a7d0b6c62cc46ab0be2a076d0298e4a86d0ab79882dbd01ac37378828260405161180c929190614072565b60405180910390a15050565b60606003805461182790613c04565b80601f016020809104026020016040519081016040528092919081815260200182805461185390613c04565b801561189e5780601f106118755761010080835404028352916020019161189e565b820191905f5260205f20905b81548152906001019060200180831161188157829003601f168201915b5050505050905090565b8060075f6118b4612846565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661195d612846565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516119a291906132a5565b60405180910390a35050565b60135481565b6119bf848484610b86565b5f8373ffffffffffffffffffffffffffffffffffffffff163b146119ff576119e9848484846129e1565b6119fe576119fd63d1a57ed660e01b6125b3565b5b5b50505050565b611a0d6122d4565b5f8282905003611a49576040517f3ba0191100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160169182611a5a929190613f79565b507f77921c9d37eb9691e65b150b9a02c6d6142d44feabc36bac4dfd7ec550696b418282604051611a8c929190614072565b60405180910390a15050565b600f602052805f5260405f205f915054906101000a900463ffffffff1681565b611ac06128f6565b60016002811115611ad457611ad3613b0d565b5b600e5f9054906101000a900460ff166002811115611af557611af4613b0d565b5b14611b2c576040517ff091304f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8403611b65576040517ff4f5b73300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b3984611b7161293c565b611b7b9190613cff565b1115611bb3576040517fc30436e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f3384604051602001611bc7929190614223565b604051602081830303815290604052805190602001209050611bed838360185484612b0b565b611c23576040517f06fb10a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8385600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900463ffffffff1663ffffffff16611c829190613cff565b1115611cba576040517f5107dbe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f85601254611cc99190613c61565b9050803414611d115780346040517f0dd32d1c000000000000000000000000000000000000000000000000000000008152600401611d08929190613d32565b60405180910390fd5b85600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282829054906101000a900463ffffffff16611d6c9190613d59565b92506101000a81548163ffffffff021916908363ffffffff160217905550611d943387612983565b3373ffffffffffffffffffffffffffffffffffffffff167fdcb23284f3935b5557998e99dcc286e29744c5000723d99eecd5d6f5694f6e118760016002811115611de157611de0613b0d565b5b604051611def929190613dab565b60405180910390a25050611e016129a0565b50505050565b6060611e1282612510565b611e51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e48906142be565b60405180910390fd5b60155f9054906101000a900460ff16611ef45760168054611e7190613c04565b80601f0160208091040260200160405190810160405280929190818152602001828054611e9d90613c04565b8015611ee85780601f10611ebf57610100808354040283529160200191611ee8565b820191905f5260205f20905b815481529060010190602001808311611ecb57829003601f168201915b50505050509050611f28565b611efc612b23565b611f0583612bb3565b604051602001611f16929190614360565b60405160208183030381529060405290505b919050565b611f356122d4565b8015611f83575f60148054611f4990613c04565b905003611f82576040517fc56f153400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b8060155f6101000a81548160ff0219169083151502179055507f8d64ee099e0c2bcd3302c6eda442d7286c0545b908e1dbb1d2dba7ea6c26525981604051611fcb91906132a5565b60405180910390a150565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600e5f9054906101000a900460ff1681565b60606017805461201f90613c04565b80601f016020809104026020016040519081016040528092919081815260200182805461204b90613c04565b80156120965780601f1061206d57610100808354040283529160200191612096565b820191905f5260205f20905b81548152906001019060200180831161207957829003601f168201915b5050505050905090565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6121366122d4565b80600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff1661219561175d565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6121e26122d4565b5f810361221a576040517ebfc92100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806011819055507f680d48f3ac056f34ba048f33f9724cf2b4023626c5baa2b6bc554ec47fbfa1018160405161225091906131e1565b60405180910390a150565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806122cd57506122cc82612c7d565b5b9050919050565b6122dc6129da565b73ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612373576123376129da565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161236a91906134a5565b60405180910390fd5b565b5f61237e6128ed565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156123e35781816040517f6f483d090000000000000000000000000000000000000000000000000000000081526004016123da9291906143be565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612453575f6040517fb6d9900a00000000000000000000000000000000000000000000000000000000815260040161244a91906134a5565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff1681525060095f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f8161251a6126e5565b116125ad576125276126ed565b82111561254f5761254860045f8481526020019081526020015f2054612ce6565b90506125ae565b5f548210156125ac575f5b5f60045f8581526020019081526020015f205491508103612586578261257f906143e5565b925061255a565b5f7c01000000000000000000000000000000000000000000000000000000008216149150505b5b5b919050565b805f5260045ffd5b5f6125c58361130c565b905081801561260757508073ffffffffffffffffffffffffffffffffffffffff166125ee612846565b73ffffffffffffffffffffffffffffffffffffffff1614155b156126335761261d81612618612846565b6120a0565b6126325761263163cfb3b94260e01b6125b3565b5b5b8360065f8581526020019081526020015f205f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a450505050565b5f6001905090565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b5f8161271e6126e5565b1161280d5760045f8381526020019081526020015f2054905061273f6126ed565b8211156127645761274f81612ce6565b61281e5761276363df2d9b4260e01b6125b3565b5b5f81036127e5575f5482106127845761278363df2d9b4260e01b6125b3565b5b5b60045f836001900393508381526020019081526020015f205490505f8103156127e0575f7c01000000000000000000000000000000000000000000000000000000008216031561281e576127df63df2d9b4260e01b6125b3565b5b612785565b5f7c01000000000000000000000000000000000000000000000000000000008216031561281e575b61281d63df2d9b4260e01b6125b3565b5b919050565b5f805f60065f8581526020019081526020015f2090508092508254915050915091565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b5f8060e883901c905060e86128ac868684612d26565b62ffffff16901b9150509392505050565b5f73ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b5f612710905090565b6002600d5403612932576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600d81905550565b5f6129456126e5565b5f540390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6129736126ed565b1461298057600854810190505b90565b61299c828260405180602001604052805f815250612d2e565b5050565b6001600d81905550565b600c5f6101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556129d781612da4565b50565b5f33905090565b5f8373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612a06612846565b8786866040518563ffffffff1660e01b8152600401612a28949392919061445e565b6020604051808303815f875af1925050508015612a6357506040513d601f19601f82011682018060405250810190612a6091906144bc565b60015b612ab8573d805f8114612a91576040519150601f19603f3d011682016040523d82523d5f602084013e612a96565b606091505b505f815103612ab057612aaf63d1a57ed660e01b6125b3565b5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b5f82612b18868685612e67565b149050949350505050565b606060148054612b3290613c04565b80601f0160208091040260200160405190810160405280929190818152602001828054612b5e90613c04565b8015612ba95780601f10612b8057610100808354040283529160200191612ba9565b820191905f5260205f20905b815481529060010190602001808311612b8c57829003601f168201915b5050505050905090565b60605f6001612bc184612eb7565b0190505f8167ffffffffffffffff811115612bdf57612bde613878565b5b6040519080825280601f01601f191660200182016040528015612c115781602001600182028036833780820191505090505b5090505f82602083010190505b600115612c72578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612c6757612c66613ca2565b5b0494505f8503612c1e575b819350505050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f7c0100000000000000000000000000000000000000000000000000000000821673ffffffffffffffffffffffffffffffffffffffff8316119050919050565b5f9392505050565b612d388383613008565b5f8373ffffffffffffffffffffffffffffffffffffffff163b14612d9f575f805490505f83820390505b612d745f8683806001019450866129e1565b612d8957612d8863d1a57ed660e01b6125b3565b5b818110612d6257815f5414612d9c575f80fd5b50505b505050565b5f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f808290505f5b85859050811015612eab57612e9c82878784818110612e9057612e8f6144e7565b5b9050602002013561317c565b91508080600101915050612e6e565b50809150509392505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612f13577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612f0957612f08613ca2565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612f50576d04ee2d6d415b85acef81000000008381612f4657612f45613ca2565b5b0492506020810190505b662386f26fc100008310612f7f57662386f26fc100008381612f7557612f74613ca2565b5b0492506010810190505b6305f5e1008310612fa8576305f5e1008381612f9e57612f9d613ca2565b5b0492506008810190505b6127108310612fcd576127108381612fc357612fc2613ca2565b5b0492506004810190505b60648310612ff05760648381612fe657612fe5613ca2565b5b0492506002810190505b600a8310612fff576001810190505b80915050919050565b5f805490505f82036130255761302463b562e8dd60e01b6125b3565b5b6130315f848385612890565b61304f836130405f865f612896565b613049856131a6565b176128bd565b60045f8381526020019081526020015f2081905550600160406001901b17820260055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505f73ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161690505f8103613100576130ff632e07630060e01b6125b3565b5b5f83830190505f8390506131126126ed565b60018303111561312d5761312c6381647e3a60e01b6125b3565b5b5b80835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a481816001019150810361312e57815f819055505050506131775f8483856128e7565b505050565b5f8183106131935761318e82846131b5565b61319e565b61319d83836131b5565b5b905092915050565b5f6001821460e11b9050919050565b5f825f528160205260405f20905092915050565b5f819050919050565b6131db816131c9565b82525050565b5f6020820190506131f45f8301846131d2565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61323f8161320b565b8114613249575f80fd5b50565b5f8135905061325a81613236565b92915050565b5f6020828403121561327557613274613203565b5b5f6132828482850161324c565b91505092915050565b5f8115159050919050565b61329f8161328b565b82525050565b5f6020820190506132b85f830184613296565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6132e7826132be565b9050919050565b6132f7816132dd565b8114613301575f80fd5b50565b5f81359050613312816132ee565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b61333881613318565b8114613342575f80fd5b50565b5f813590506133538161332f565b92915050565b5f806040838503121561336f5761336e613203565b5b5f61337c85828601613304565b925050602061338d85828601613345565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156133ce5780820151818401526020810190506133b3565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6133f382613397565b6133fd81856133a1565b935061340d8185602086016133b1565b613416816133d9565b840191505092915050565b5f6020820190508181035f83015261343981846133e9565b905092915050565b61344a816131c9565b8114613454575f80fd5b50565b5f8135905061346581613441565b92915050565b5f602082840312156134805761347f613203565b5b5f61348d84828501613457565b91505092915050565b61349f816132dd565b82525050565b5f6020820190506134b85f830184613496565b92915050565b5f80604083850312156134d4576134d3613203565b5b5f6134e185828601613304565b92505060206134f285828601613457565b9150509250929050565b5f6020828403121561351157613510613203565b5b5f61351e84828501613304565b91505092915050565b5f63ffffffff82169050919050565b61353f81613527565b82525050565b5f6020820190506135585f830184613536565b92915050565b5f805f6060848603121561357557613574613203565b5b5f61358286828701613304565b935050602061359386828701613304565b92505060406135a486828701613457565b9150509250925092565b5f80604083850312156135c4576135c3613203565b5b5f6135d185828601613457565b92505060206135e285828601613457565b9150509250929050565b5f6040820190506135ff5f830185613496565b61360c60208301846131d2565b9392505050565b5f819050919050565b61362581613613565b82525050565b5f60208201905061363e5f83018461361c565b92915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f84011261366557613664613644565b5b8235905067ffffffffffffffff81111561368257613681613648565b5b60208301915083600182028301111561369e5761369d61364c565b5b9250929050565b5f80602083850312156136bb576136ba613203565b5b5f83013567ffffffffffffffff8111156136d8576136d7613207565b5b6136e485828601613650565b92509250509250929050565b5f6136fa826132be565b9050919050565b61370a816136f0565b8114613714575f80fd5b50565b5f8135905061372581613701565b92915050565b5f806040838503121561374157613740613203565b5b5f61374e85828601613717565b925050602061375f85828601613457565b9150509250929050565b60038110613775575f80fd5b50565b5f8135905061378681613769565b92915050565b5f602082840312156137a1576137a0613203565b5b5f6137ae84828501613778565b91505092915050565b6137c081613613565b81146137ca575f80fd5b50565b5f813590506137db816137b7565b92915050565b5f602082840312156137f6576137f5613203565b5b5f613803848285016137cd565b91505092915050565b6138158161328b565b811461381f575f80fd5b50565b5f813590506138308161380c565b92915050565b5f806040838503121561384c5761384b613203565b5b5f61385985828601613304565b925050602061386a85828601613822565b9150509250929050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6138ae826133d9565b810181811067ffffffffffffffff821117156138cd576138cc613878565b5b80604052505050565b5f6138df6131fa565b90506138eb82826138a5565b919050565b5f67ffffffffffffffff82111561390a57613909613878565b5b613913826133d9565b9050602081019050919050565b828183375f83830152505050565b5f61394061393b846138f0565b6138d6565b90508281526020810184848401111561395c5761395b613874565b5b613967848285613920565b509392505050565b5f82601f83011261398357613982613644565b5b813561399384826020860161392e565b91505092915050565b5f805f80608085870312156139b4576139b3613203565b5b5f6139c187828801613304565b94505060206139d287828801613304565b93505060406139e387828801613457565b925050606085013567ffffffffffffffff811115613a0457613a03613207565b5b613a108782880161396f565b91505092959194509250565b5f8083601f840112613a3157613a30613644565b5b8235905067ffffffffffffffff811115613a4e57613a4d613648565b5b602083019150836020820283011115613a6a57613a6961364c565b5b9250929050565b5f805f8060608587031215613a8957613a88613203565b5b5f613a9687828801613457565b9450506020613aa787828801613457565b935050604085013567ffffffffffffffff811115613ac857613ac7613207565b5b613ad487828801613a1c565b925092505092959194509250565b5f60208284031215613af757613af6613203565b5b5f613b0484828501613822565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110613b4b57613b4a613b0d565b5b50565b5f819050613b5b82613b3a565b919050565b5f613b6a82613b4e565b9050919050565b613b7a81613b60565b82525050565b5f602082019050613b935f830184613b71565b92915050565b5f8060408385031215613baf57613bae613203565b5b5f613bbc85828601613304565b9250506020613bcd85828601613304565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680613c1b57607f821691505b602082108103613c2e57613c2d613bd7565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f613c6b826131c9565b9150613c76836131c9565b9250828202613c84816131c9565b91508282048414831517613c9b57613c9a613c34565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613cd9826131c9565b9150613ce4836131c9565b925082613cf457613cf3613ca2565b5b828204905092915050565b5f613d09826131c9565b9150613d14836131c9565b9250828201905080821115613d2c57613d2b613c34565b5b92915050565b5f604082019050613d455f8301856131d2565b613d5260208301846131d2565b9392505050565b5f613d6382613527565b9150613d6e83613527565b9250828201905063ffffffff811115613d8a57613d89613c34565b5b92915050565b5f60ff82169050919050565b613da581613d90565b82525050565b5f604082019050613dbe5f8301856131d2565b613dcb6020830184613d9c565b9392505050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302613e387fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613dfd565b613e428683613dfd565b95508019841693508086168417925050509392505050565b5f819050919050565b5f613e7d613e78613e73846131c9565b613e5a565b6131c9565b9050919050565b5f819050919050565b613e9683613e63565b613eaa613ea282613e84565b848454613e09565b825550505050565b5f90565b613ebe613eb2565b613ec9818484613e8d565b505050565b5b81811015613eec57613ee15f82613eb6565b600181019050613ecf565b5050565b601f821115613f3157613f0281613ddc565b613f0b84613dee565b81016020851015613f1a578190505b613f2e613f2685613dee565b830182613ece565b50505b505050565b5f82821c905092915050565b5f613f515f1984600802613f36565b1980831691505092915050565b5f613f698383613f42565b9150826002028217905092915050565b613f838383613dd2565b67ffffffffffffffff811115613f9c57613f9b613878565b5b613fa68254613c04565b613fb1828285613ef0565b5f601f831160018114613fde575f8415613fcc578287013590505b613fd68582613f5e565b86555061403d565b601f198416613fec86613ddc565b5f5b8281101561401357848901358255600182019150602085019450602081019050613fee565b86831015614030578489013561402c601f891682613f42565b8355505b6001600288020188555050505b50505050505050565b5f61405183856133a1565b935061405e838584613920565b614067836133d9565b840190509392505050565b5f6020820190508181035f83015261408b818486614046565b90509392505050565b7f416d6f756e7420746f6f206869676800000000000000000000000000000000005f82015250565b5f6140c8600f836133a1565b91506140d382614094565b602082019050919050565b5f6020820190508181035f8301526140f5816140bc565b9050919050565b5f81905092915050565b50565b5f6141145f836140fc565b915061411f82614106565b5f82019050919050565b5f61413382614109565b9150819050919050565b7f5472616e73666572206661696c656400000000000000000000000000000000005f82015250565b5f614171600f836133a1565b915061417c8261413d565b602082019050919050565b5f6020820190508181035f83015261419e81614165565b9050919050565b5f6020820190506141b85f830184613d9c565b92915050565b5f8160601b9050919050565b5f6141d4826141be565b9050919050565b5f6141e5826141ca565b9050919050565b6141fd6141f8826132dd565b6141db565b82525050565b5f819050919050565b61421d614218826131c9565b614203565b82525050565b5f61422e82856141ec565b60148201915061423e828461420c565b6020820191508190509392505050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f5f8201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b5f6142a8602f836133a1565b91506142b38261424e565b604082019050919050565b5f6020820190508181035f8301526142d58161429c565b9050919050565b5f81905092915050565b5f6142f082613397565b6142fa81856142dc565b935061430a8185602086016133b1565b80840191505092915050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f61434a6005836142dc565b915061435582614316565b600582019050919050565b5f61436b82856142e6565b915061437782846142e6565b91506143828261433e565b91508190509392505050565b5f6143a86143a361439e84613318565b613e5a565b6131c9565b9050919050565b6143b88161438e565b82525050565b5f6040820190506143d15f8301856143af565b6143de60208301846131d2565b9392505050565b5f6143ef826131c9565b91505f820361440157614400613c34565b5b600182039050919050565b5f81519050919050565b5f82825260208201905092915050565b5f6144308261440c565b61443a8185614416565b935061444a8185602086016133b1565b614453816133d9565b840191505092915050565b5f6080820190506144715f830187613496565b61447e6020830186613496565b61448b60408301856131d2565b818103606083015261449d8184614426565b905095945050505050565b5f815190506144b681613236565b92915050565b5f602082840312156144d1576144d0613203565b5b5f6144de848285016144a8565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffdfea26469706673582212205ea9c01beec8443ebead36e345e8d8f886044de6987a2f203af4a7942cc204aa64736f6c634300081800330000000000000000000000003452bba88832705e50806e432c5e3a74b91910fc00000000000000000000000042af8f3f294740ce89b0865690ccf435e25796ef00000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000042697066733a2f2f6261666b7265696133787461367865786a7a61646b6c6f7373756a786a6c64706472646a76756677366c356875353237376b61707a753479677865000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x60806040526004361061024f575f3560e01c806379ba509711610138578063bbaac02f116100b5578063e30c397811610079578063e30c39781461083c578063e4f2487a14610866578063e8a3d48514610890578063e985e9c5146108ba578063f2fde38b146108f6578063f4a0a5281461091e5761024f565b8063bbaac02f14610758578063bc660cac14610780578063c4be5b59146107bc578063c87b56dd146107d8578063e0a80853146108145761024f565b8063938e3d7b116100fc578063938e3d7b1461069857806395d89b41146106c0578063a22cb465146106ea578063b029a51414610712578063b88d4fde1461073c5761024f565b806379ba5097146105e05780637ad59431146105f65780637cb647591461061e5780638b533ea4146106465780638da5cb5b1461066e5761024f565b80632db11544116101d157806355f804b31161019557806355f804b3146104d85780636352211e146105005780636817c76c1461053c57806370a0823114610566578063715018a6146105a2578063736fe565146105b85761024f565b80632db11544146104225780632eb4a7ab1461043e57806332cb6b0c1461046857806342842e0e1461049257806351830227146104ae5761024f565b8063095ea7b311610218578063095ea7b3146103475780631015805b1461036357806318160ddd1461039f57806323b872dd146103c95780632a55205a146103e55761024f565b80620e7fa81461025357806301ffc9a71461027d57806304634d8d146102b957806306fdde03146102e1578063081812fc1461030b575b5f80fd5b34801561025e575f80fd5b50610267610946565b60405161027491906131e1565b60405180910390f35b348015610288575f80fd5b506102a3600480360381019061029e9190613260565b61094c565b6040516102b091906132a5565b60405180910390f35b3480156102c4575f80fd5b506102df60048036038101906102da9190613359565b61095d565b005b3480156102ec575f80fd5b506102f5610a22565b6040516103029190613421565b60405180910390f35b348015610316575f80fd5b50610331600480360381019061032c919061346b565b610ab2565b60405161033e91906134a5565b60405180910390f35b610361600480360381019061035c91906134be565b610b0b565b005b34801561036e575f80fd5b50610389600480360381019061038491906134fc565b610b1b565b6040516103969190613545565b60405180910390f35b3480156103aa575f80fd5b506103b3610b3b565b6040516103c091906131e1565b60405180910390f35b6103e360048036038101906103de919061355e565b610b86565b005b3480156103f0575f80fd5b5061040b600480360381019061040691906135ae565b610e31565b6040516104199291906135ec565b60405180910390f35b61043c6004803603810190610437919061346b565b610f53565b005b348015610449575f80fd5b5061045261123c565b60405161045f919061362b565b60405180910390f35b348015610473575f80fd5b5061047c611242565b60405161048991906131e1565b60405180910390f35b6104ac60048036038101906104a7919061355e565b611248565b005b3480156104b9575f80fd5b506104c2611267565b6040516104cf91906132a5565b60405180910390f35b3480156104e3575f80fd5b506104fe60048036038101906104f991906136a5565b611279565b005b34801561050b575f80fd5b506105266004803603810190610521919061346b565b61130c565b60405161053391906134a5565b60405180910390f35b348015610547575f80fd5b5061055061131d565b60405161055d91906131e1565b60405180910390f35b348015610571575f80fd5b5061058c600480360381019061058791906134fc565b611323565b60405161059991906131e1565b60405180910390f35b3480156105ad575f80fd5b506105b66113b7565b005b3480156105c3575f80fd5b506105de60048036038101906105d9919061372b565b6113ca565b005b3480156105eb575f80fd5b506105f4611585565b005b348015610601575f80fd5b5061061c6004803603810190610617919061378c565b611613565b005b348015610629575f80fd5b50610644600480360381019061063f91906137e1565b611690565b005b348015610651575f80fd5b5061066c6004803603810190610667919061346b565b611714565b005b348015610679575f80fd5b5061068261175d565b60405161068f91906134a5565b60405180910390f35b3480156106a3575f80fd5b506106be60048036038101906106b991906136a5565b611785565b005b3480156106cb575f80fd5b506106d4611818565b6040516106e19190613421565b60405180910390f35b3480156106f5575f80fd5b50610710600480360381019061070b9190613836565b6118a8565b005b34801561071d575f80fd5b506107266119ae565b60405161073391906131e1565b60405180910390f35b6107566004803603810190610751919061399c565b6119b4565b005b348015610763575f80fd5b5061077e600480360381019061077991906136a5565b611a05565b005b34801561078b575f80fd5b506107a660048036038101906107a191906134fc565b611a98565b6040516107b39190613545565b60405180910390f35b6107d660048036038101906107d19190613a71565b611ab8565b005b3480156107e3575f80fd5b506107fe60048036038101906107f9919061346b565b611e07565b60405161080b9190613421565b60405180910390f35b34801561081f575f80fd5b5061083a60048036038101906108359190613ae2565b611f2d565b005b348015610847575f80fd5b50610850611fd6565b60405161085d91906134a5565b60405180910390f35b348015610871575f80fd5b5061087a611ffe565b6040516108879190613b80565b60405180910390f35b34801561089b575f80fd5b506108a4612010565b6040516108b19190613421565b60405180910390f35b3480156108c5575f80fd5b506108e060048036038101906108db9190613b99565b6120a0565b6040516108ed91906132a5565b60405180910390f35b348015610901575f80fd5b5061091c600480360381019061091791906134fc565b61212e565b005b348015610929575f80fd5b50610944600480360381019061093f919061346b565b6121da565b005b60125481565b5f6109568261225b565b9050919050565b6109656122d4565b6103e8816bffffffffffffffffffffffff1611156109af576040517fc2b03beb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a14576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a1e8282612375565b5050565b606060028054610a3190613c04565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5d90613c04565b8015610aa85780601f10610a7f57610100808354040283529160200191610aa8565b820191905f5260205f20905b815481529060010190602001808311610a8b57829003601f168201915b5050505050905090565b5f610abc82612510565b610ad157610ad063cf4700e460e01b6125b3565b5b60065f8381526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610b17828260016125bb565b5050565b6010602052805f5260405f205f915054906101000a900463ffffffff1681565b5f610b446126e5565b6001545f54030390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610b766126ed565b14610b8357600854810190505b90565b5f610b9082612714565b905073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161693508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610c0557610c0463a114810060e01b6125b3565b5b5f80610c1084612823565b91509150610c268187610c21612846565b61284d565b610c5157610c3b86610c36612846565b6120a0565b610c5057610c4f6359c896be60e01b6125b3565b5b5b610c5e8686866001612890565b8015610c68575f82555b60055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600190039190508190555060055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815460010191905081905550610d3085610d0c888887612896565b7c0200000000000000000000000000000000000000000000000000000000176128bd565b60045f8681526020019081526020015f20819055505f7c0200000000000000000000000000000000000000000000000000000000841603610dac575f6001850190505f60045f8381526020019081526020015f205403610daa575f548114610da9578360045f8381526020019081526020015f20819055505b5b505b5f73ffffffffffffffffffffffffffffffffffffffff8673ffffffffffffffffffffffffffffffffffffffff161690508481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a45f8103610e1b57610e1a63ea553b3460e01b6125b3565b5b610e2887878760016128e7565b50505050505050565b5f805f600a5f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610f055760095f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915060095f0160149054906101000a90046bffffffffffffffffffffffff1690505b5f610f0e6128ed565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff1688610f369190613c61565b610f409190613ccf565b9050828195509550505050509250929050565b610f5b6128f6565b600280811115610f6e57610f6d613b0d565b5b600e5f9054906101000a900460ff166002811115610f8f57610f8e613b0d565b5b14610fc6576040517f47553b7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8103610fff576040517ff4f5b73300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b398161100b61293c565b6110159190613cff565b111561104d576040517fc30436e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f601354141580156110bd57506013548160105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900463ffffffff1663ffffffff166110bb9190613cff565b115b156110f4576040517f5107dbe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f816011546111039190613c61565b905080341461114b5780346040517f0dd32d1c000000000000000000000000000000000000000000000000000000008152600401611142929190613d32565b60405180910390fd5b8160105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282829054906101000a900463ffffffff166111a69190613d59565b92506101000a81548163ffffffff021916908363ffffffff1602179055506111ce3383612983565b3373ffffffffffffffffffffffffffffffffffffffff167fdcb23284f3935b5557998e99dcc286e29744c5000723d99eecd5d6f5694f6e118360028081111561121a57611219613b0d565b5b604051611228929190613dab565b60405180910390a2506112396129a0565b50565b60185481565b611b3981565b61126283838360405180602001604052805f8152506119b4565b505050565b60155f9054906101000a900460ff1681565b6112816122d4565b5f82829050036112bd576040517f3ba0191100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181601491826112ce929190613f79565b507ff9c7803e94e0d3c02900d8a90893a6d5e90dd04d32a4cfe825520f82bf9f32f68282604051611300929190614072565b60405180910390a15050565b5f61131682612714565b9050919050565b60115481565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361136857611367638f4eb60460e01b6125b3565b5b67ffffffffffffffff60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054169050919050565b6113bf6122d4565b6113c85f6129aa565b565b6113d26122d4565b6113da6128f6565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361143f576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47811115611482576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611479906140de565b60405180910390fd5b5f8273ffffffffffffffffffffffffffffffffffffffff16826040516114a790614129565b5f6040518083038185875af1925050503d805f81146114e1576040519150601f19603f3d011682016040523d82523d5f602084013e6114e6565b606091505b505090508061152a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161152190614187565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648360405161157091906131e1565b60405180910390a2506115816129a0565b5050565b5f61158e6129da565b90508073ffffffffffffffffffffffffffffffffffffffff166115af611fd6565b73ffffffffffffffffffffffffffffffffffffffff161461160757806040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016115fe91906134a5565b60405180910390fd5b611610816129aa565b50565b61161b6122d4565b80600e5f6101000a81548160ff0219169083600281111561163f5761163e613b0d565b5b02179055507f7b113c9b68e115832b8e4a4ad5a4d03d9b288f9105305adc0ddfc9a11bc68c4381600281111561167857611677613b0d565b5b60405161168591906141a5565b60405180910390a150565b6116986122d4565b5f801b81036116d3576040517f9dd854d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806018819055507f42cbc405e4dbf1b691e85b9a34b08ecfcf7a9ad9078bf4d645ccfa1fac11c10b81604051611709919061362b565b60405180910390a150565b61171c6122d4565b806013819055507fe4e809aaafc550a795e8ceb7b761a48dc15e5f6227a77ea95056cae1953070958160405161175291906131e1565b60405180910390a150565b5f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61178d6122d4565b5f82829050036117c9576040517f3ba0191100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181601791826117da929190613f79565b507f905d981207a7d0b6c62cc46ab0be2a076d0298e4a86d0ab79882dbd01ac37378828260405161180c929190614072565b60405180910390a15050565b60606003805461182790613c04565b80601f016020809104026020016040519081016040528092919081815260200182805461185390613c04565b801561189e5780601f106118755761010080835404028352916020019161189e565b820191905f5260205f20905b81548152906001019060200180831161188157829003601f168201915b5050505050905090565b8060075f6118b4612846565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661195d612846565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516119a291906132a5565b60405180910390a35050565b60135481565b6119bf848484610b86565b5f8373ffffffffffffffffffffffffffffffffffffffff163b146119ff576119e9848484846129e1565b6119fe576119fd63d1a57ed660e01b6125b3565b5b5b50505050565b611a0d6122d4565b5f8282905003611a49576040517f3ba0191100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160169182611a5a929190613f79565b507f77921c9d37eb9691e65b150b9a02c6d6142d44feabc36bac4dfd7ec550696b418282604051611a8c929190614072565b60405180910390a15050565b600f602052805f5260405f205f915054906101000a900463ffffffff1681565b611ac06128f6565b60016002811115611ad457611ad3613b0d565b5b600e5f9054906101000a900460ff166002811115611af557611af4613b0d565b5b14611b2c576040517ff091304f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8403611b65576040517ff4f5b73300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b3984611b7161293c565b611b7b9190613cff565b1115611bb3576040517fc30436e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f3384604051602001611bc7929190614223565b604051602081830303815290604052805190602001209050611bed838360185484612b0b565b611c23576040517f06fb10a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8385600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900463ffffffff1663ffffffff16611c829190613cff565b1115611cba576040517f5107dbe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f85601254611cc99190613c61565b9050803414611d115780346040517f0dd32d1c000000000000000000000000000000000000000000000000000000008152600401611d08929190613d32565b60405180910390fd5b85600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282829054906101000a900463ffffffff16611d6c9190613d59565b92506101000a81548163ffffffff021916908363ffffffff160217905550611d943387612983565b3373ffffffffffffffffffffffffffffffffffffffff167fdcb23284f3935b5557998e99dcc286e29744c5000723d99eecd5d6f5694f6e118760016002811115611de157611de0613b0d565b5b604051611def929190613dab565b60405180910390a25050611e016129a0565b50505050565b6060611e1282612510565b611e51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e48906142be565b60405180910390fd5b60155f9054906101000a900460ff16611ef45760168054611e7190613c04565b80601f0160208091040260200160405190810160405280929190818152602001828054611e9d90613c04565b8015611ee85780601f10611ebf57610100808354040283529160200191611ee8565b820191905f5260205f20905b815481529060010190602001808311611ecb57829003601f168201915b50505050509050611f28565b611efc612b23565b611f0583612bb3565b604051602001611f16929190614360565b60405160208183030381529060405290505b919050565b611f356122d4565b8015611f83575f60148054611f4990613c04565b905003611f82576040517fc56f153400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b8060155f6101000a81548160ff0219169083151502179055507f8d64ee099e0c2bcd3302c6eda442d7286c0545b908e1dbb1d2dba7ea6c26525981604051611fcb91906132a5565b60405180910390a150565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600e5f9054906101000a900460ff1681565b60606017805461201f90613c04565b80601f016020809104026020016040519081016040528092919081815260200182805461204b90613c04565b80156120965780601f1061206d57610100808354040283529160200191612096565b820191905f5260205f20905b81548152906001019060200180831161207957829003601f168201915b5050505050905090565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6121366122d4565b80600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff1661219561175d565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6121e26122d4565b5f810361221a576040517ebfc92100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806011819055507f680d48f3ac056f34ba048f33f9724cf2b4023626c5baa2b6bc554ec47fbfa1018160405161225091906131e1565b60405180910390a150565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806122cd57506122cc82612c7d565b5b9050919050565b6122dc6129da565b73ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612373576123376129da565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161236a91906134a5565b60405180910390fd5b565b5f61237e6128ed565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156123e35781816040517f6f483d090000000000000000000000000000000000000000000000000000000081526004016123da9291906143be565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612453575f6040517fb6d9900a00000000000000000000000000000000000000000000000000000000815260040161244a91906134a5565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff1681525060095f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f8161251a6126e5565b116125ad576125276126ed565b82111561254f5761254860045f8481526020019081526020015f2054612ce6565b90506125ae565b5f548210156125ac575f5b5f60045f8581526020019081526020015f205491508103612586578261257f906143e5565b925061255a565b5f7c01000000000000000000000000000000000000000000000000000000008216149150505b5b5b919050565b805f5260045ffd5b5f6125c58361130c565b905081801561260757508073ffffffffffffffffffffffffffffffffffffffff166125ee612846565b73ffffffffffffffffffffffffffffffffffffffff1614155b156126335761261d81612618612846565b6120a0565b6126325761263163cfb3b94260e01b6125b3565b5b5b8360065f8581526020019081526020015f205f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a450505050565b5f6001905090565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b5f8161271e6126e5565b1161280d5760045f8381526020019081526020015f2054905061273f6126ed565b8211156127645761274f81612ce6565b61281e5761276363df2d9b4260e01b6125b3565b5b5f81036127e5575f5482106127845761278363df2d9b4260e01b6125b3565b5b5b60045f836001900393508381526020019081526020015f205490505f8103156127e0575f7c01000000000000000000000000000000000000000000000000000000008216031561281e576127df63df2d9b4260e01b6125b3565b5b612785565b5f7c01000000000000000000000000000000000000000000000000000000008216031561281e575b61281d63df2d9b4260e01b6125b3565b5b919050565b5f805f60065f8581526020019081526020015f2090508092508254915050915091565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b50505050565b5f8060e883901c905060e86128ac868684612d26565b62ffffff16901b9150509392505050565b5f73ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b50505050565b5f612710905090565b6002600d5403612932576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600d81905550565b5f6129456126e5565b5f540390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6129736126ed565b1461298057600854810190505b90565b61299c828260405180602001604052805f815250612d2e565b5050565b6001600d81905550565b600c5f6101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556129d781612da4565b50565b5f33905090565b5f8373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612a06612846565b8786866040518563ffffffff1660e01b8152600401612a28949392919061445e565b6020604051808303815f875af1925050508015612a6357506040513d601f19601f82011682018060405250810190612a6091906144bc565b60015b612ab8573d805f8114612a91576040519150601f19603f3d011682016040523d82523d5f602084013e612a96565b606091505b505f815103612ab057612aaf63d1a57ed660e01b6125b3565b5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b5f82612b18868685612e67565b149050949350505050565b606060148054612b3290613c04565b80601f0160208091040260200160405190810160405280929190818152602001828054612b5e90613c04565b8015612ba95780601f10612b8057610100808354040283529160200191612ba9565b820191905f5260205f20905b815481529060010190602001808311612b8c57829003601f168201915b5050505050905090565b60605f6001612bc184612eb7565b0190505f8167ffffffffffffffff811115612bdf57612bde613878565b5b6040519080825280601f01601f191660200182016040528015612c115781602001600182028036833780820191505090505b5090505f82602083010190505b600115612c72578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612c6757612c66613ca2565b5b0494505f8503612c1e575b819350505050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f7c0100000000000000000000000000000000000000000000000000000000821673ffffffffffffffffffffffffffffffffffffffff8316119050919050565b5f9392505050565b612d388383613008565b5f8373ffffffffffffffffffffffffffffffffffffffff163b14612d9f575f805490505f83820390505b612d745f8683806001019450866129e1565b612d8957612d8863d1a57ed660e01b6125b3565b5b818110612d6257815f5414612d9c575f80fd5b50505b505050565b5f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f808290505f5b85859050811015612eab57612e9c82878784818110612e9057612e8f6144e7565b5b9050602002013561317c565b91508080600101915050612e6e565b50809150509392505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612f13577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612f0957612f08613ca2565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612f50576d04ee2d6d415b85acef81000000008381612f4657612f45613ca2565b5b0492506020810190505b662386f26fc100008310612f7f57662386f26fc100008381612f7557612f74613ca2565b5b0492506010810190505b6305f5e1008310612fa8576305f5e1008381612f9e57612f9d613ca2565b5b0492506008810190505b6127108310612fcd576127108381612fc357612fc2613ca2565b5b0492506004810190505b60648310612ff05760648381612fe657612fe5613ca2565b5b0492506002810190505b600a8310612fff576001810190505b80915050919050565b5f805490505f82036130255761302463b562e8dd60e01b6125b3565b5b6130315f848385612890565b61304f836130405f865f612896565b613049856131a6565b176128bd565b60045f8381526020019081526020015f2081905550600160406001901b17820260055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505f73ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161690505f8103613100576130ff632e07630060e01b6125b3565b5b5f83830190505f8390506131126126ed565b60018303111561312d5761312c6381647e3a60e01b6125b3565b5b5b80835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a481816001019150810361312e57815f819055505050506131775f8483856128e7565b505050565b5f8183106131935761318e82846131b5565b61319e565b61319d83836131b5565b5b905092915050565b5f6001821460e11b9050919050565b5f825f528160205260405f20905092915050565b5f819050919050565b6131db816131c9565b82525050565b5f6020820190506131f45f8301846131d2565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61323f8161320b565b8114613249575f80fd5b50565b5f8135905061325a81613236565b92915050565b5f6020828403121561327557613274613203565b5b5f6132828482850161324c565b91505092915050565b5f8115159050919050565b61329f8161328b565b82525050565b5f6020820190506132b85f830184613296565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6132e7826132be565b9050919050565b6132f7816132dd565b8114613301575f80fd5b50565b5f81359050613312816132ee565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b61333881613318565b8114613342575f80fd5b50565b5f813590506133538161332f565b92915050565b5f806040838503121561336f5761336e613203565b5b5f61337c85828601613304565b925050602061338d85828601613345565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156133ce5780820151818401526020810190506133b3565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6133f382613397565b6133fd81856133a1565b935061340d8185602086016133b1565b613416816133d9565b840191505092915050565b5f6020820190508181035f83015261343981846133e9565b905092915050565b61344a816131c9565b8114613454575f80fd5b50565b5f8135905061346581613441565b92915050565b5f602082840312156134805761347f613203565b5b5f61348d84828501613457565b91505092915050565b61349f816132dd565b82525050565b5f6020820190506134b85f830184613496565b92915050565b5f80604083850312156134d4576134d3613203565b5b5f6134e185828601613304565b92505060206134f285828601613457565b9150509250929050565b5f6020828403121561351157613510613203565b5b5f61351e84828501613304565b91505092915050565b5f63ffffffff82169050919050565b61353f81613527565b82525050565b5f6020820190506135585f830184613536565b92915050565b5f805f6060848603121561357557613574613203565b5b5f61358286828701613304565b935050602061359386828701613304565b92505060406135a486828701613457565b9150509250925092565b5f80604083850312156135c4576135c3613203565b5b5f6135d185828601613457565b92505060206135e285828601613457565b9150509250929050565b5f6040820190506135ff5f830185613496565b61360c60208301846131d2565b9392505050565b5f819050919050565b61362581613613565b82525050565b5f60208201905061363e5f83018461361c565b92915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f84011261366557613664613644565b5b8235905067ffffffffffffffff81111561368257613681613648565b5b60208301915083600182028301111561369e5761369d61364c565b5b9250929050565b5f80602083850312156136bb576136ba613203565b5b5f83013567ffffffffffffffff8111156136d8576136d7613207565b5b6136e485828601613650565b92509250509250929050565b5f6136fa826132be565b9050919050565b61370a816136f0565b8114613714575f80fd5b50565b5f8135905061372581613701565b92915050565b5f806040838503121561374157613740613203565b5b5f61374e85828601613717565b925050602061375f85828601613457565b9150509250929050565b60038110613775575f80fd5b50565b5f8135905061378681613769565b92915050565b5f602082840312156137a1576137a0613203565b5b5f6137ae84828501613778565b91505092915050565b6137c081613613565b81146137ca575f80fd5b50565b5f813590506137db816137b7565b92915050565b5f602082840312156137f6576137f5613203565b5b5f613803848285016137cd565b91505092915050565b6138158161328b565b811461381f575f80fd5b50565b5f813590506138308161380c565b92915050565b5f806040838503121561384c5761384b613203565b5b5f61385985828601613304565b925050602061386a85828601613822565b9150509250929050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6138ae826133d9565b810181811067ffffffffffffffff821117156138cd576138cc613878565b5b80604052505050565b5f6138df6131fa565b90506138eb82826138a5565b919050565b5f67ffffffffffffffff82111561390a57613909613878565b5b613913826133d9565b9050602081019050919050565b828183375f83830152505050565b5f61394061393b846138f0565b6138d6565b90508281526020810184848401111561395c5761395b613874565b5b613967848285613920565b509392505050565b5f82601f83011261398357613982613644565b5b813561399384826020860161392e565b91505092915050565b5f805f80608085870312156139b4576139b3613203565b5b5f6139c187828801613304565b94505060206139d287828801613304565b93505060406139e387828801613457565b925050606085013567ffffffffffffffff811115613a0457613a03613207565b5b613a108782880161396f565b91505092959194509250565b5f8083601f840112613a3157613a30613644565b5b8235905067ffffffffffffffff811115613a4e57613a4d613648565b5b602083019150836020820283011115613a6a57613a6961364c565b5b9250929050565b5f805f8060608587031215613a8957613a88613203565b5b5f613a9687828801613457565b9450506020613aa787828801613457565b935050604085013567ffffffffffffffff811115613ac857613ac7613207565b5b613ad487828801613a1c565b925092505092959194509250565b5f60208284031215613af757613af6613203565b5b5f613b0484828501613822565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110613b4b57613b4a613b0d565b5b50565b5f819050613b5b82613b3a565b919050565b5f613b6a82613b4e565b9050919050565b613b7a81613b60565b82525050565b5f602082019050613b935f830184613b71565b92915050565b5f8060408385031215613baf57613bae613203565b5b5f613bbc85828601613304565b9250506020613bcd85828601613304565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680613c1b57607f821691505b602082108103613c2e57613c2d613bd7565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f613c6b826131c9565b9150613c76836131c9565b9250828202613c84816131c9565b91508282048414831517613c9b57613c9a613c34565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613cd9826131c9565b9150613ce4836131c9565b925082613cf457613cf3613ca2565b5b828204905092915050565b5f613d09826131c9565b9150613d14836131c9565b9250828201905080821115613d2c57613d2b613c34565b5b92915050565b5f604082019050613d455f8301856131d2565b613d5260208301846131d2565b9392505050565b5f613d6382613527565b9150613d6e83613527565b9250828201905063ffffffff811115613d8a57613d89613c34565b5b92915050565b5f60ff82169050919050565b613da581613d90565b82525050565b5f604082019050613dbe5f8301856131d2565b613dcb6020830184613d9c565b9392505050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302613e387fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613dfd565b613e428683613dfd565b95508019841693508086168417925050509392505050565b5f819050919050565b5f613e7d613e78613e73846131c9565b613e5a565b6131c9565b9050919050565b5f819050919050565b613e9683613e63565b613eaa613ea282613e84565b848454613e09565b825550505050565b5f90565b613ebe613eb2565b613ec9818484613e8d565b505050565b5b81811015613eec57613ee15f82613eb6565b600181019050613ecf565b5050565b601f821115613f3157613f0281613ddc565b613f0b84613dee565b81016020851015613f1a578190505b613f2e613f2685613dee565b830182613ece565b50505b505050565b5f82821c905092915050565b5f613f515f1984600802613f36565b1980831691505092915050565b5f613f698383613f42565b9150826002028217905092915050565b613f838383613dd2565b67ffffffffffffffff811115613f9c57613f9b613878565b5b613fa68254613c04565b613fb1828285613ef0565b5f601f831160018114613fde575f8415613fcc578287013590505b613fd68582613f5e565b86555061403d565b601f198416613fec86613ddc565b5f5b8281101561401357848901358255600182019150602085019450602081019050613fee565b86831015614030578489013561402c601f891682613f42565b8355505b6001600288020188555050505b50505050505050565b5f61405183856133a1565b935061405e838584613920565b614067836133d9565b840190509392505050565b5f6020820190508181035f83015261408b818486614046565b90509392505050565b7f416d6f756e7420746f6f206869676800000000000000000000000000000000005f82015250565b5f6140c8600f836133a1565b91506140d382614094565b602082019050919050565b5f6020820190508181035f8301526140f5816140bc565b9050919050565b5f81905092915050565b50565b5f6141145f836140fc565b915061411f82614106565b5f82019050919050565b5f61413382614109565b9150819050919050565b7f5472616e73666572206661696c656400000000000000000000000000000000005f82015250565b5f614171600f836133a1565b915061417c8261413d565b602082019050919050565b5f6020820190508181035f83015261419e81614165565b9050919050565b5f6020820190506141b85f830184613d9c565b92915050565b5f8160601b9050919050565b5f6141d4826141be565b9050919050565b5f6141e5826141ca565b9050919050565b6141fd6141f8826132dd565b6141db565b82525050565b5f819050919050565b61421d614218826131c9565b614203565b82525050565b5f61422e82856141ec565b60148201915061423e828461420c565b6020820191508190509392505050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f5f8201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b5f6142a8602f836133a1565b91506142b38261424e565b604082019050919050565b5f6020820190508181035f8301526142d58161429c565b9050919050565b5f81905092915050565b5f6142f082613397565b6142fa81856142dc565b935061430a8185602086016133b1565b80840191505092915050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f61434a6005836142dc565b915061435582614316565b600582019050919050565b5f61436b82856142e6565b915061437782846142e6565b91506143828261433e565b91508190509392505050565b5f6143a86143a361439e84613318565b613e5a565b6131c9565b9050919050565b6143b88161438e565b82525050565b5f6040820190506143d15f8301856143af565b6143de60208301846131d2565b9392505050565b5f6143ef826131c9565b91505f820361440157614400613c34565b5b600182039050919050565b5f81519050919050565b5f82825260208201905092915050565b5f6144308261440c565b61443a8185614416565b935061444a8185602086016133b1565b614453816133d9565b840191505092915050565b5f6080820190506144715f830187613496565b61447e6020830186613496565b61448b60408301856131d2565b818103606083015261449d8184614426565b905095945050505050565b5f815190506144b681613236565b92915050565b5f602082840312156144d1576144d0613203565b5b5f6144de848285016144a8565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffdfea26469706673582212205ea9c01beec8443ebead36e345e8d8f886044de6987a2f203af4a7942cc204aa64736f6c63430008180033

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

0000000000000000000000003452bba88832705e50806e432c5e3a74b91910fc00000000000000000000000042af8f3f294740ce89b0865690ccf435e25796ef00000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000042697066733a2f2f6261666b7265696133787461367865786a7a61646b6c6f7373756a786a6c64706472646a76756677366c356875353237376b61707a753479677865000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _initialOwner (address): 0x3452BBa88832705E50806E432c5e3a74b91910fc
Arg [1] : _royaltyReceiver (address): 0x42Af8F3F294740CE89B0865690cCF435e25796Ef
Arg [2] : _royaltyFeeNumerator (uint96): 500
Arg [3] : hiddenURI (string): ipfs://bafkreia3xta6xexjzadklossujxjldpdrdjvufw6l5hu5277kapzu4ygxe

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000003452bba88832705e50806e432c5e3a74b91910fc
Arg [1] : 00000000000000000000000042af8f3f294740ce89b0865690ccf435e25796ef
Arg [2] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000042
Arg [5] : 697066733a2f2f6261666b7265696133787461367865786a7a61646b6c6f7373
Arg [6] : 756a786a6c64706472646a76756677366c356875353237376b61707a75347967
Arg [7] : 7865000000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

198771:7055:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;200142:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;205644:179;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;204963:289;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;21523:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;28763:227;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;28480:124;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;200041:46;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;16725:573;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;33035:3523;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;102250:673;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;201869:732;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;200366:25;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;199811:41;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36654:193;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;200263:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;203306:203;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;22925:152;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;200096:39;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18449:242;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;64185:103;;;;;;;;;;;;;:::i;:::-;;205260:376;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;67313:235;;;;;;;;;;;;;:::i;:::-;;204814:141;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;204606:200;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;204435:163;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;63510:88;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;203517:242;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;21699:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;29330:234;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;200182:37;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37445:416;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;204203:224;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;199987:47;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;200908:953;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;202929:369;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;203767:233;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;66274:101;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;199941:37;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;202824:97;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;29721:164;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;66701:181;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;204008:187;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;200142:31;;;;:::o;205644:179::-;205755:4;205779:36;205803:11;205779:23;:36::i;:::-;205772:43;;205644:179;;;:::o;204963:289::-;63396:13;:11;:13::i;:::-;205103:4:::1;205088:12;:19;;;205084:48;;;205116:16;;;;;;;;;;;;;;205084:48;205167:1;205147:22;;:8;:22;;::::0;205143:48:::1;;205178:13;;;;;;;;;;;;;;205143:48;205202:42;205221:8;205231:12;205202:18;:42::i;:::-;204963:289:::0;;:::o;21523:100::-;21577:13;21610:5;21603:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21523:100;:::o;28763:227::-;28839:7;28864:16;28872:7;28864;:16::i;:::-;28859:73;;28882:50;28890:41;;;28882:7;:50::i;:::-;28859:73;28952:15;:24;28968:7;28952:24;;;;;;;;;;;:30;;;;;;;;;;;;28945:37;;28763:227;;;:::o;28480:124::-;28569:27;28578:2;28582:7;28591:4;28569:8;:27::i;:::-;28480:124;;:::o;200041:46::-;;;;;;;;;;;;;;;;;;;;;;:::o;16725:573::-;16786:14;17184:15;:13;:15::i;:::-;17169:12;;17153:13;;:28;:46;17144:55;;17239:17;17218;:15;:17::i;:::-;:38;17214:65;;17268:11;;17258:21;;;;17214:65;16725:573;:::o;33035:3523::-;33177:27;33207;33226:7;33207:18;:27::i;:::-;33177:57;;12667:14;33378:4;33362:22;;:41;33339:66;;33463:4;33422:45;;33438:19;33422:45;;;33418:95;;33469:44;33477:35;;;33469:7;:44::i;:::-;33418:95;33527:27;33556:23;33583:35;33610:7;33583:26;:35::i;:::-;33526:92;;;;33718:68;33743:15;33760:4;33766:19;:17;:19::i;:::-;33718:24;:68::i;:::-;33713:189;;33806:43;33823:4;33829:19;:17;:19::i;:::-;33806:16;:43::i;:::-;33801:101;;33851:51;33859:42;;;33851:7;:51::i;:::-;33801:101;33713:189;33915:43;33937:4;33943:2;33947:7;33956:1;33915:21;:43::i;:::-;34051:15;34048:160;;;34191:1;34170:19;34163:30;34048:160;34588:18;:24;34607:4;34588:24;;;;;;;;;;;;;;;;34586:26;;;;;;;;;;;;34657:18;:22;34676:2;34657:22;;;;;;;;;;;;;;;;34655:24;;;;;;;;;;;34979:146;35016:2;35065:45;35080:4;35086:2;35090:19;35065:14;:45::i;:::-;12265:8;35037:73;34979:18;:146::i;:::-;34950:17;:26;34968:7;34950:26;;;;;;;;;;;:175;;;;35296:1;12265:8;35245:19;:47;:52;35241:627;;35318:19;35350:1;35340:7;:11;35318:33;;35507:1;35473:17;:30;35491:11;35473:30;;;;;;;;;;;;:35;35469:384;;35611:13;;35596:11;:28;35592:242;;35791:19;35758:17;:30;35776:11;35758:30;;;;;;;;;;;:52;;;;35592:242;35469:384;35299:569;35241:627;35981:16;12667:14;36016:2;36000:20;;:39;35981:58;;36380:7;36344:8;36310:4;36252:25;36197:1;36140;36117:299;36453:1;36441:8;:13;36437:58;;36456:39;36464:30;;;36456:7;:39::i;:::-;36437:58;36508:42;36529:4;36535:2;36539:7;36548:1;36508:20;:42::i;:::-;33166:3392;;;;33035:3523;;;:::o;102250:673::-;102361:16;102379:14;102406:32;102441:17;:26;102459:7;102441:26;;;;;;;;;;;102406:61;;102478:23;102504:12;:21;;;;;;;;;;;;102478:47;;102536:22;102561:12;:28;;;;;;;;;;;;102536:53;;102633:1;102606:29;;:15;:29;;;102602:176;;102670:19;:28;;;;;;;;;;;;102652:46;;102731:19;:35;;;;;;;;;;;;102713:53;;102602:176;102790:21;102846:17;:15;:17::i;:::-;102814:49;;102827:15;102815:27;;:9;:27;;;;:::i;:::-;102814:49;;;;:::i;:::-;102790:73;;102884:15;102901:13;102876:39;;;;;;;;102250:673;;;;;:::o;201869:732::-;70144:21;:19;:21::i;:::-;201965:12:::1;201952:25:::0;::::1;;;;;;;:::i;:::-;;:9;;;;;;;;;;;:25;;;;;;;;:::i;:::-;;;201948:50;;201986:12;;;;;;;;;;;;;;201948:50;202025:1;202013:8;:13:::0;202009:40:::1;;202035:14;;;;;;;;;;;;;;202009:40;199848:4;202083:8;202066:14;:12;:14::i;:::-;:25;;;;:::i;:::-;:38;202062:69;;;202113:18;;;;;;;;;;;;;;202062:69;202184:1;202162:18;;:23;;:96;;;;;202240:18;;202229:8;202202:12;:24;202215:10;202202:24;;;;;;;;;;;;;;;;;;;;;;;;;:35;;;;;;:::i;:::-;:56;202162:96;202144:153;;;202277:20;;;;;;;;;;;;;;202144:153;202310:16;202341:8;202329:9;;:20;;;;:::i;:::-;202310:39;;202377:8;202364:9;:21;202360:67;;202407:8;202417:9;202394:33;;;;;;;;;;;;:::i;:::-;;;;;;;;202360:67;202475:8;202440:12;:24;202453:10;202440:24;;;;;;;;;;;;;;;;:44;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;202495:31;202505:10;202517:8;202495:9;:31::i;:::-;202551:10;202544:49;;;202563:8;202579:12;202573:19:::0;::::1;;;;;;;:::i;:::-;;202544:49;;;;;;;:::i;:::-;;;;;;;;201937:664;70188:20:::0;:18;:20::i;:::-;201869:732;:::o;200366:25::-;;;;:::o;199811:41::-;199848:4;199811:41;:::o;36654:193::-;36800:39;36817:4;36823:2;36827:7;36800:39;;;;;;;;;;;;:16;:39::i;:::-;36654:193;;;:::o;200263:28::-;;;;;;;;;;;;;:::o;203306:203::-;63396:13;:11;:13::i;:::-;203410:1:::1;203391:7;;203385:21;;:26:::0;203381:51:::1;;203420:12;;;;;;;;;;;;;;203381:51;203459:7;;203443:13;:23;;;;;;;:::i;:::-;;203482:19;203493:7;;203482:19;;;;;;;:::i;:::-;;;;;;;;203306:203:::0;;:::o;22925:152::-;22997:7;23040:27;23059:7;23040:18;:27::i;:::-;23017:52;;22925:152;;;:::o;200096:39::-;;;;:::o;18449:242::-;18521:7;18562:1;18545:19;;:5;:19;;;18541:69;;18566:44;18574:35;;;18566:7;:44::i;:::-;18541:69;11209:13;18628:18;:25;18647:5;18628:25;;;;;;;;;;;;;;;;:55;18621:62;;18449:242;;;:::o;64185:103::-;63396:13;:11;:13::i;:::-;64250:30:::1;64277:1;64250:18;:30::i;:::-;64185:103::o:0;205260:376::-;63396:13;:11;:13::i;:::-;70144:21:::1;:19;:21::i;:::-;205406:1:::2;205392:16;;:2;:16;;::::0;205388:42:::2;;205417:13;;;;;;;;;;;;;;205388:42;205459:21;205449:6;:31;;205441:59;;;;;;;;;;;;:::i;:::-;;;;;;;;;205512:7;205525:2;:7;;205540:6;205525:26;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;205511:40;;;205570:2;205562:30;;;;;;;;;;;;:::i;:::-;;;;;;;;;205617:2;205608:20;;;205621:6;205608:20;;;;;;:::i;:::-;;;;;;;;205377:259;70188:20:::1;:18;:20::i;:::-;205260:376:::0;;:::o;67313:235::-;67366:14;67383:12;:10;:12::i;:::-;67366:29;;67428:6;67410:24;;:14;:12;:14::i;:::-;:24;;;67406:98;;67485:6;67458:34;;;;;;;;;;;:::i;:::-;;;;;;;;67406:98;67514:26;67533:6;67514:18;:26::i;:::-;67355:193;67313:235::o;204814:141::-;63396:13;:11;:13::i;:::-;204894:8:::1;204882:9;;:20;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;204918:29;204937:8;204931:15;;;;;;;;:::i;:::-;;204918:29;;;;;;:::i;:::-;;;;;;;;204814:141:::0;:::o;204606:200::-;63396:13;:11;:13::i;:::-;204699:1:::1;204691:10:::0;::::1;204680:7;:21:::0;204676:53:::1;;204710:19;;;;;;;;;;;;;;204676:53;204753:7;204740:10;:20;;;;204776:22;204790:7;204776:22;;;;;;:::i;:::-;;;;;;;;204606:200:::0;:::o;204435:163::-;63396:13;:11;:13::i;:::-;204535:8:::1;204514:18;:29;;;;204559:31;204581:8;204559:31;;;;;;:::i;:::-;;;;;;;;204435:163:::0;:::o;63510:88::-;63557:7;63584:6;;;;;;;;;;;63577:13;;63510:88;:::o;203517:242::-;63396:13;:11;:13::i;:::-;203639:1:::1;203613:14;;203607:28;;:33:::0;203603:58:::1;;203649:12;;;;;;;;;;;;;;203603:58;203687:14;;203672:12;:29;;;;;;;:::i;:::-;;203717:34;203736:14;;203717:34;;;;;;;:::i;:::-;;;;;;;;203517:242:::0;;:::o;21699:104::-;21755:13;21788:7;21781:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21699:104;:::o;29330:234::-;29477:8;29425:18;:39;29444:19;:17;:19::i;:::-;29425:39;;;;;;;;;;;;;;;:49;29465:8;29425:49;;;;;;;;;;;;;;;;:60;;;;;;;;;;;;;;;;;;29537:8;29501:55;;29516:19;:17;:19::i;:::-;29501:55;;;29547:8;29501:55;;;;;;:::i;:::-;;;;;;;;29330:234;;:::o;200182:37::-;;;;:::o;37445:416::-;37620:31;37633:4;37639:2;37643:7;37620:12;:31::i;:::-;37684:1;37666:2;:14;;;:19;37662:192;;37705:56;37736:4;37742:2;37746:7;37755:5;37705:30;:56::i;:::-;37700:154;;37782:56;37790:47;;;37782:7;:56::i;:::-;37700:154;37662:192;37445:416;;;;:::o;204203:224::-;63396:13;:11;:13::i;:::-;204319:1:::1;204295:12;;204289:26;;:31:::0;204285:56:::1;;204329:12;;;;;;;;;;;;;;204285:56;204365:12;;204352:10;:25;;;;;;;:::i;:::-;;204393:26;204406:12;;204393:26;;;;;;;:::i;:::-;;;;;;;;204203:224:::0;;:::o;199987:47::-;;;;;;;;;;;;;;;;;;;;;;:::o;200908:953::-;70144:21;:19;:21::i;:::-;201086:15:::1;201073:28;;;;;;;;:::i;:::-;;:9;;;;;;;;;;;:28;;;;;;;;:::i;:::-;;;201069:56;;201110:15;;;;;;;;;;;;;;201069:56;201152:1;201140:8;:13:::0;201136:40:::1;;201162:14;;;;;;;;;;;;;;201136:40;199848:4;201210:8;201193:14;:12;:14::i;:::-;:25;;;;:::i;:::-;:38;201189:69;;;201240:18;;;;;;;;;;;;;;201189:69;201271:12;201313:10;201325:9;201296:39;;;;;;;;;:::i;:::-;;;;;;;;;;;;;201286:50;;;;;;201271:65;;201352:51;201379:5;;201386:10;;201398:4;201352:26;:51::i;:::-;201347:94;;201425:16;;;;;;;;;;;;;;201347:94;201497:9;201486:8;201458:13;:25;201472:10;201458:25;;;;;;;;;;;;;;;;;;;;;;;;;:36;;;;;;:::i;:::-;:48;201454:94;;;201528:20;;;;;;;;;;;;;;201454:94;201561:16;201595:8;201580:12;;:23;;;;:::i;:::-;201561:42;;201631:8;201618:9;:21;201614:67;;201661:8;201671:9;201648:33;;;;;;;;;;;;:::i;:::-;;;;;;;;201614:67;201730:8;201694:13;:25;201708:10;201694:25;;;;;;;;;;;;;;;;:45;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;201752:31;201762:10;201774:8;201752:9;:31::i;:::-;201808:10;201801:52;;;201820:8;201836:15;201830:22;;;;;;;;:::i;:::-;;201801:52;;;;;;;:::i;:::-;;;;;;;;201058:803;;70188:20:::0;:18;:20::i;:::-;200908:953;;;;:::o;202929:369::-;203010:13;203044:16;203052:7;203044;:16::i;:::-;203036:76;;;;;;;;;;;;:::i;:::-;;;;;;;;;203128:8;;;;;;;;;;;203123:32;;203145:10;203138:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;203123:32;203228:10;:8;:10::i;:::-;203240:25;203257:7;203240:16;:25::i;:::-;203211:64;;;;;;;;;:::i;:::-;;;;;;;;;;;;;203166:124;;202929:369;;;;:::o;203767:233::-;63396:13;:11;:13::i;:::-;203838:9:::1;203834:87;;;203897:1;203872:13;203866:27;;;;;:::i;:::-;;;:32:::0;203862:59:::1;;203907:14;;;;;;;;;;;;;;203862:59;203834:87;203943:9;203932:8;;:20;;;;;;;;;;;;;;;;;;203968:24;203982:9;203968:24;;;;;;:::i;:::-;;;;;;;;203767:233:::0;:::o;66274:101::-;66327:7;66354:13;;;;;;;;;;;66347:20;;66274:101;:::o;199941:37::-;;;;;;;;;;;;;:::o;202824:97::-;202868:13;202901:12;202894:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;202824:97;:::o;29721:164::-;29818:4;29842:18;:25;29861:5;29842:25;;;;;;;;;;;;;;;:35;29868:8;29842:35;;;;;;;;;;;;;;;;;;;;;;;;;29835:42;;29721:164;;;;:::o;66701:181::-;63396:13;:11;:13::i;:::-;66807:8:::1;66791:13;;:24;;;;;;;;;;;;;;;;;;66865:8;66831:43;;66856:7;:5;:7::i;:::-;66831:43;;;;;;;;;;;;66701:181:::0;:::o;204008:187::-;63396:13;:11;:13::i;:::-;204094:1:::1;204082:8;:13:::0;204078:40:::1;;204104:14;;;;;;;;;;;;;;204078:40;204141:8;204129:9;:20;;;;204165:22;204178:8;204165:22;;;;;;:::i;:::-;;;;;;;;204008:187:::0;:::o;101997:215::-;102099:4;102138:26;102123:41;;;:11;:41;;;;:81;;;;102168:36;102192:11;102168:23;:36::i;:::-;102123:81;102116:88;;101997:215;;;:::o;63676:165::-;63746:12;:10;:12::i;:::-;63736:22;;:6;;;;;;;;;;;:22;;;63732:102;;63809:12;:10;:12::i;:::-;63782:40;;;;;;;;;;;:::i;:::-;;;;;;;;63732:102;63676:165::o;103573:518::-;103668:19;103690:17;:15;:17::i;:::-;103668:39;;;;103737:11;103722:12;:26;;;103718:176;;;103856:12;103870:11;103827:55;;;;;;;;;;;;:::i;:::-;;;;;;;;103718:176;103928:1;103908:22;;:8;:22;;;103904:110;;103999:1;103954:48;;;;;;;;;;;:::i;:::-;;;;;;;;103904:110;104048:35;;;;;;;;104060:8;104048:35;;;;;;104070:12;104048:35;;;;;104026:19;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103657:434;103573:518;;:::o;30143:475::-;30208:11;30255:7;30236:15;:13;:15::i;:::-;:26;30232:379;;30293:17;:15;:17::i;:::-;30283:7;:27;30279:90;;;30319:50;30342:17;:26;30360:7;30342:26;;;;;;;;;;;;30319:22;:50::i;:::-;30312:57;;;;30279:90;30400:13;;30390:7;:23;30386:214;;;30434:14;30467:60;30515:1;30484:17;:26;30502:7;30484:26;;;;;;;;;;;;30475:35;;;30474:42;30467:60;;30518:9;;;;:::i;:::-;;;30467:60;;;30583:1;11985:8;30555:6;:24;:29;30546:38;;30415:185;30386:214;30232:379;30143:475;;;;:::o;60652:165::-;60753:13;60747:4;60740:27;60794:4;60788;60781:18;52067:474;52196:13;52212:16;52220:7;52212;:16::i;:::-;52196:32;;52245:13;:45;;;;;52285:5;52262:28;;:19;:17;:19::i;:::-;:28;;;;52245:45;52241:201;;;52310:44;52327:5;52334:19;:17;:19::i;:::-;52310:16;:44::i;:::-;52305:137;;52375:51;52383:42;;;52375:7;:51::i;:::-;52305:137;52241:201;52487:2;52454:15;:24;52470:7;52454:24;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;52525:7;52521:2;52505:28;;52514:5;52505:28;;;;;;;;;;;;52185:356;52067:474;;;:::o;202609:93::-;202666:7;202693:1;202686:8;;202609:93;:::o;16223:110::-;16281:7;16308:17;16301:24;;16223:110;:::o;24410:2213::-;24477:14;24527:7;24508:15;:13;:15::i;:::-;:26;24504:2054;;24560:17;:26;24578:7;24560:26;;;;;;;;;;;;24551:35;;24617:17;:15;:17::i;:::-;24607:7;:27;24603:183;;;24659:30;24682:6;24659:22;:30::i;:::-;24691:13;24655:49;24723:47;24731:38;;;24723:7;:47::i;:::-;24603:183;24897:1;24887:6;:11;24883:1292;;24934:13;;24923:7;:24;24919:77;;24949:47;24957:38;;;24949:7;:47::i;:::-;24919:77;25553:607;25631:17;:28;25649:9;;;;;;;25631:28;;;;;;;;;;;;25622:37;;25719:1;25709:6;:11;25705:25;25722:8;25705:25;25785:1;11985:8;25757:6;:24;:29;25753:48;25788:13;25753:48;26093:47;26101:38;;;26093:7;:47::i;:::-;25553:607;;;24883:1292;26530:1;11985:8;26502:6;:24;:29;26498:48;26533:13;26498:48;24504:2054;26568:47;26576:38;;;26568:7;:47::i;:::-;24410:2213;;;;:::o;31930:485::-;32032:27;32061:23;32102:38;32143:15;:24;32159:7;32143:24;;;;;;;;;;;32102:65;;32320:18;32297:41;;32377:19;32371:26;32352:45;;32282:126;31930:485;;;:::o;58633:105::-;58693:7;58720:10;58713:17;;58633:105;:::o;31158:659::-;31307:11;31472:16;31465:5;31461:28;31452:37;;31632:16;31621:9;31617:32;31604:45;;31782:15;31771:9;31768:30;31760:5;31749:9;31746:20;31743:56;31733:66;;31158:659;;;;;:::o;38523:159::-;;;;;:::o;57942:311::-;58077:7;58097:16;12389:3;58123:19;:41;;58097:68;;12389:3;58191:31;58202:4;58208:2;58212:9;58191:10;:31::i;:::-;58183:40;;:62;;58176:69;;;57942:311;;;;;:::o;27171:450::-;27251:14;27419:16;27412:5;27408:28;27399:37;;27596:5;27582:11;27557:23;27553:41;27550:52;27543:5;27540:63;27530:73;;27171:450;;;;:::o;39347:158::-;;;;;:::o;103205:97::-;103263:6;103289:5;103282:12;;103205:97;:::o;70224:315::-;69522:1;70353:7;;:18;70349:88;;70395:30;;;;;;;;;;;;;;70349:88;69522:1;70514:7;:17;;;;70224:315::o;17396:385::-;17451:14;17667:15;:13;:15::i;:::-;17651:13;;:31;17642:40;;17722:17;17701;:15;:17::i;:::-;:38;17697:65;;17751:11;;17741:21;;;;17697:65;17396:385;:::o;47261:112::-;47338:27;47348:2;47352:8;47338:27;;;;;;;;;;;;:9;:27::i;:::-;47261:112;;:::o;70547:212::-;69479:1;70730:7;:21;;;;70547:212::o;67072:156::-;67162:13;;67155:20;;;;;;;;;;;67186:34;67211:8;67186:24;:34::i;:::-;67072:156;:::o;61519:98::-;61572:7;61599:10;61592:17;;61519:98;:::o;39945:691::-;40108:4;40154:2;40129:45;;;40175:19;:17;:19::i;:::-;40196:4;40202:7;40211:5;40129:88;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;40125:504;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40429:1;40412:6;:13;:18;40408:115;;40451:56;40459:47;;;40451:7;:56::i;:::-;40408:115;40595:6;40589:13;40580:6;40576:2;40572:15;40565:38;40125:504;40298:54;;;40288:64;;;:6;:64;;;;40281:71;;;39945:691;;;;;;:::o;76908:174::-;77009:4;77070;77033:33;77054:5;;77061:4;77033:20;:33::i;:::-;:41;77026:48;;76908:174;;;;;;:::o;202710:106::-;202762:13;202795;202788:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;202710:106;:::o;180275:652::-;180331:13;180382:14;180419:1;180399:17;180410:5;180399:10;:17::i;:::-;:21;180382:38;;180435:20;180469:6;180458:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;180435:41;;180491:11;180591:6;180584:4;180576:6;180572:17;180568:30;180561:37;;180627:254;180634:4;180627:254;;;180659:5;;;;;;;;180765:10;180760:2;180753:5;180749:14;180744:32;180739:3;180731:46;180823:2;180814:11;;;;;;:::i;:::-;;;;;180857:1;180848:5;:10;180627:254;180844:21;180627:254;180902:6;180895:13;;;;;180275:652;;;:::o;99805:148::-;99881:4;99920:25;99905:40;;;:11;:40;;;;99898:47;;99805:148;;;:::o;30714:335::-;30784:11;31014:15;31006:6;31002:28;30983:16;30975:6;30971:29;30968:63;30958:73;;30714:335;;;:::o;57643:147::-;57780:6;57643:147;;;;;:::o;46390:787::-;46521:19;46527:2;46531:8;46521:5;:19::i;:::-;46600:1;46582:2;:14;;;:19;46578:581;;46622:11;46636:13;;46622:27;;46668:13;46690:8;46684:3;:14;46668:30;;46717:242;46748:62;46787:1;46791:2;46795:7;;;;;;46804:5;46748:30;:62::i;:::-;46743:176;;46839:56;46847:47;;;46839:7;:56::i;:::-;46743:176;46954:3;46946:5;:11;46717:242;;47130:3;47113:13;;:20;47109:34;;47135:8;;;47109:34;46603:556;;46578:581;46390:787;;;:::o;64823:191::-;64897:16;64916:6;;;;;;;;;;;64897:25;;64942:8;64933:6;;:17;;;;;;;;;;;;;;;;;;64997:8;64966:40;;64987:8;64966:40;;;;;;;;;;;;64886:128;64823:191;:::o;77495:324::-;77588:7;77608:20;77631:4;77608:27;;77651:9;77646:136;77670:5;;:12;;77666:1;:16;77646:136;;;77719:51;77747:12;77761:5;;77767:1;77761:8;;;;;;;:::i;:::-;;;;;;;;77719:27;:51::i;:::-;77704:66;;77684:3;;;;;;;77646:136;;;;77799:12;77792:19;;;77495:324;;;;;:::o;173286:948::-;173339:7;173359:14;173376:1;173359:18;;173426:8;173417:5;:17;173413:106;;173464:8;173455:17;;;;;;:::i;:::-;;;;;173501:2;173491:12;;;;173413:106;173546:8;173537:5;:17;173533:106;;173584:8;173575:17;;;;;;:::i;:::-;;;;;173621:2;173611:12;;;;173533:106;173666:8;173657:5;:17;173653:106;;173704:8;173695:17;;;;;;:::i;:::-;;;;;173741:2;173731:12;;;;173653:106;173786:7;173777:5;:16;173773:103;;173823:7;173814:16;;;;;;:::i;:::-;;;;;173859:1;173849:11;;;;173773:103;173903:7;173894:5;:16;173890:103;;173940:7;173931:16;;;;;;:::i;:::-;;;;;173976:1;173966:11;;;;173890:103;174020:7;174011:5;:16;174007:103;;174057:7;174048:16;;;;;;:::i;:::-;;;;;174093:1;174083:11;;;;174007:103;174137:7;174128:5;:16;174124:68;;174175:1;174165:11;;;;174124:68;174220:6;174213:13;;;173286:948;;;:::o;41098:2399::-;41171:20;41194:13;;41171:36;;41234:1;41222:8;:13;41218:53;;41237:34;41245:25;;;41237:7;:34::i;:::-;41218:53;41284:61;41314:1;41318:2;41322:12;41336:8;41284:21;:61::i;:::-;41818:139;41855:2;41909:33;41932:1;41936:2;41940:1;41909:14;:33::i;:::-;41876:30;41897:8;41876:20;:30::i;:::-;:66;41818:18;:139::i;:::-;41784:17;:31;41802:12;41784:31;;;;;;;;;;;:173;;;;42244:1;11347:2;42214:1;:26;;42213:32;42201:8;:45;42175:18;:22;42194:2;42175:22;;;;;;;;;;;;;;;;:71;;;;;;;;;;;42357:16;12667:14;42392:2;42376:20;;:39;42357:58;;42448:1;42436:8;:13;42432:54;;42451:35;42459:26;;;42451:7;:35::i;:::-;42432:54;42503:11;42532:8;42517:12;:23;42503:37;;42555:15;42573:12;42555:30;;42616:17;:15;:17::i;:::-;42612:1;42606:3;:7;:27;42602:77;;;42635:44;42643:35;;;42635:7;:44::i;:::-;42602:77;42696:676;43115:7;43071:8;43026:1;42960:25;42897:1;42832;42801:358;43367:3;43354:9;;;;;;:16;42696:676;;43404:3;43388:13;:19;;;;41533:1886;;;43429:60;43458:1;43462:2;43466:12;43480:8;43429:20;:60::i;:::-;41160:2337;41098:2399;;:::o;71614:169::-;71689:7;71720:1;71716;:5;:59;;71751:24;71770:1;71773;71751:18;:24::i;:::-;71716:59;;;71724:24;71743:1;71746;71724:18;:24::i;:::-;71716:59;71709:66;;71614:169;;;;:::o;27723:324::-;27793:14;28026:1;28016:8;28013:15;27987:24;27983:46;27973:56;;27723:324;;;:::o;71908:245::-;71981:13;72060:1;72054:4;72047:15;72089:1;72083:4;72076:15;72130:4;72124;72114:21;72105:30;;71908:245;;;;:::o;7:77:1:-;44:7;73:5;62:16;;7:77;;;:::o;90:118::-;177:24;195:5;177:24;:::i;:::-;172:3;165:37;90:118;;:::o;214:222::-;307:4;345:2;334:9;330:18;322:26;;358:71;426:1;415:9;411:17;402:6;358:71;:::i;:::-;214:222;;;;:::o;442:75::-;475:6;508:2;502:9;492:19;;442:75;:::o;523:117::-;632:1;629;622:12;646:117;755:1;752;745:12;769:149;805:7;845:66;838:5;834:78;823:89;;769:149;;;:::o;924:120::-;996:23;1013:5;996:23;:::i;:::-;989:5;986:34;976:62;;1034:1;1031;1024:12;976:62;924:120;:::o;1050:137::-;1095:5;1133:6;1120:20;1111:29;;1149:32;1175:5;1149:32;:::i;:::-;1050:137;;;;:::o;1193:327::-;1251:6;1300:2;1288:9;1279:7;1275:23;1271:32;1268:119;;;1306:79;;:::i;:::-;1268:119;1426:1;1451:52;1495:7;1486:6;1475:9;1471:22;1451:52;:::i;:::-;1441:62;;1397:116;1193:327;;;;:::o;1526:90::-;1560:7;1603:5;1596:13;1589:21;1578:32;;1526:90;;;:::o;1622:109::-;1703:21;1718:5;1703:21;:::i;:::-;1698:3;1691:34;1622:109;;:::o;1737:210::-;1824:4;1862:2;1851:9;1847:18;1839:26;;1875:65;1937:1;1926:9;1922:17;1913:6;1875:65;:::i;:::-;1737:210;;;;:::o;1953:126::-;1990:7;2030:42;2023:5;2019:54;2008:65;;1953:126;;;:::o;2085:96::-;2122:7;2151:24;2169:5;2151:24;:::i;:::-;2140:35;;2085:96;;;:::o;2187:122::-;2260:24;2278:5;2260:24;:::i;:::-;2253:5;2250:35;2240:63;;2299:1;2296;2289:12;2240:63;2187:122;:::o;2315:139::-;2361:5;2399:6;2386:20;2377:29;;2415:33;2442:5;2415:33;:::i;:::-;2315:139;;;;:::o;2460:109::-;2496:7;2536:26;2529:5;2525:38;2514:49;;2460:109;;;:::o;2575:120::-;2647:23;2664:5;2647:23;:::i;:::-;2640:5;2637:34;2627:62;;2685:1;2682;2675:12;2627:62;2575:120;:::o;2701:137::-;2746:5;2784:6;2771:20;2762:29;;2800:32;2826:5;2800:32;:::i;:::-;2701:137;;;;:::o;2844:472::-;2911:6;2919;2968:2;2956:9;2947:7;2943:23;2939:32;2936:119;;;2974:79;;:::i;:::-;2936:119;3094:1;3119:53;3164:7;3155:6;3144:9;3140:22;3119:53;:::i;:::-;3109:63;;3065:117;3221:2;3247:52;3291:7;3282:6;3271:9;3267:22;3247:52;:::i;:::-;3237:62;;3192:117;2844:472;;;;;:::o;3322:99::-;3374:6;3408:5;3402:12;3392:22;;3322:99;;;:::o;3427:169::-;3511:11;3545:6;3540:3;3533:19;3585:4;3580:3;3576:14;3561:29;;3427:169;;;;:::o;3602:246::-;3683:1;3693:113;3707:6;3704:1;3701:13;3693:113;;;3792:1;3787:3;3783:11;3777:18;3773:1;3768:3;3764:11;3757:39;3729:2;3726:1;3722:10;3717:15;;3693:113;;;3840:1;3831:6;3826:3;3822:16;3815:27;3664:184;3602:246;;;:::o;3854:102::-;3895:6;3946:2;3942:7;3937:2;3930:5;3926:14;3922:28;3912:38;;3854:102;;;:::o;3962:377::-;4050:3;4078:39;4111:5;4078:39;:::i;:::-;4133:71;4197:6;4192:3;4133:71;:::i;:::-;4126:78;;4213:65;4271:6;4266:3;4259:4;4252:5;4248:16;4213:65;:::i;:::-;4303:29;4325:6;4303:29;:::i;:::-;4298:3;4294:39;4287:46;;4054:285;3962:377;;;;:::o;4345:313::-;4458:4;4496:2;4485:9;4481:18;4473:26;;4545:9;4539:4;4535:20;4531:1;4520:9;4516:17;4509:47;4573:78;4646:4;4637:6;4573:78;:::i;:::-;4565:86;;4345:313;;;;:::o;4664:122::-;4737:24;4755:5;4737:24;:::i;:::-;4730:5;4727:35;4717:63;;4776:1;4773;4766:12;4717:63;4664:122;:::o;4792:139::-;4838:5;4876:6;4863:20;4854:29;;4892:33;4919:5;4892:33;:::i;:::-;4792:139;;;;:::o;4937:329::-;4996:6;5045:2;5033:9;5024:7;5020:23;5016:32;5013:119;;;5051:79;;:::i;:::-;5013:119;5171:1;5196:53;5241:7;5232:6;5221:9;5217:22;5196:53;:::i;:::-;5186:63;;5142:117;4937:329;;;;:::o;5272:118::-;5359:24;5377:5;5359:24;:::i;:::-;5354:3;5347:37;5272:118;;:::o;5396:222::-;5489:4;5527:2;5516:9;5512:18;5504:26;;5540:71;5608:1;5597:9;5593:17;5584:6;5540:71;:::i;:::-;5396:222;;;;:::o;5624:474::-;5692:6;5700;5749:2;5737:9;5728:7;5724:23;5720:32;5717:119;;;5755:79;;:::i;:::-;5717:119;5875:1;5900:53;5945:7;5936:6;5925:9;5921:22;5900:53;:::i;:::-;5890:63;;5846:117;6002:2;6028:53;6073:7;6064:6;6053:9;6049:22;6028:53;:::i;:::-;6018:63;;5973:118;5624:474;;;;;:::o;6104:329::-;6163:6;6212:2;6200:9;6191:7;6187:23;6183:32;6180:119;;;6218:79;;:::i;:::-;6180:119;6338:1;6363:53;6408:7;6399:6;6388:9;6384:22;6363:53;:::i;:::-;6353:63;;6309:117;6104:329;;;;:::o;6439:93::-;6475:7;6515:10;6508:5;6504:22;6493:33;;6439:93;;;:::o;6538:115::-;6623:23;6640:5;6623:23;:::i;:::-;6618:3;6611:36;6538:115;;:::o;6659:218::-;6750:4;6788:2;6777:9;6773:18;6765:26;;6801:69;6867:1;6856:9;6852:17;6843:6;6801:69;:::i;:::-;6659:218;;;;:::o;6883:619::-;6960:6;6968;6976;7025:2;7013:9;7004:7;7000:23;6996:32;6993:119;;;7031:79;;:::i;:::-;6993:119;7151:1;7176:53;7221:7;7212:6;7201:9;7197:22;7176:53;:::i;:::-;7166:63;;7122:117;7278:2;7304:53;7349:7;7340:6;7329:9;7325:22;7304:53;:::i;:::-;7294:63;;7249:118;7406:2;7432:53;7477:7;7468:6;7457:9;7453:22;7432:53;:::i;:::-;7422:63;;7377:118;6883:619;;;;;:::o;7508:474::-;7576:6;7584;7633:2;7621:9;7612:7;7608:23;7604:32;7601:119;;;7639:79;;:::i;:::-;7601:119;7759:1;7784:53;7829:7;7820:6;7809:9;7805:22;7784:53;:::i;:::-;7774:63;;7730:117;7886:2;7912:53;7957:7;7948:6;7937:9;7933:22;7912:53;:::i;:::-;7902:63;;7857:118;7508:474;;;;;:::o;7988:332::-;8109:4;8147:2;8136:9;8132:18;8124:26;;8160:71;8228:1;8217:9;8213:17;8204:6;8160:71;:::i;:::-;8241:72;8309:2;8298:9;8294:18;8285:6;8241:72;:::i;:::-;7988:332;;;;;:::o;8326:77::-;8363:7;8392:5;8381:16;;8326:77;;;:::o;8409:118::-;8496:24;8514:5;8496:24;:::i;:::-;8491:3;8484:37;8409:118;;:::o;8533:222::-;8626:4;8664:2;8653:9;8649:18;8641:26;;8677:71;8745:1;8734:9;8730:17;8721:6;8677:71;:::i;:::-;8533:222;;;;:::o;8761:117::-;8870:1;8867;8860:12;8884:117;8993:1;8990;8983:12;9007:117;9116:1;9113;9106:12;9144:553;9202:8;9212:6;9262:3;9255:4;9247:6;9243:17;9239:27;9229:122;;9270:79;;:::i;:::-;9229:122;9383:6;9370:20;9360:30;;9413:18;9405:6;9402:30;9399:117;;;9435:79;;:::i;:::-;9399:117;9549:4;9541:6;9537:17;9525:29;;9603:3;9595:4;9587:6;9583:17;9573:8;9569:32;9566:41;9563:128;;;9610:79;;:::i;:::-;9563:128;9144:553;;;;;:::o;9703:529::-;9774:6;9782;9831:2;9819:9;9810:7;9806:23;9802:32;9799:119;;;9837:79;;:::i;:::-;9799:119;9985:1;9974:9;9970:17;9957:31;10015:18;10007:6;10004:30;10001:117;;;10037:79;;:::i;:::-;10001:117;10150:65;10207:7;10198:6;10187:9;10183:22;10150:65;:::i;:::-;10132:83;;;;9928:297;9703:529;;;;;:::o;10238:104::-;10283:7;10312:24;10330:5;10312:24;:::i;:::-;10301:35;;10238:104;;;:::o;10348:138::-;10429:32;10455:5;10429:32;:::i;:::-;10422:5;10419:43;10409:71;;10476:1;10473;10466:12;10409:71;10348:138;:::o;10492:155::-;10546:5;10584:6;10571:20;10562:29;;10600:41;10635:5;10600:41;:::i;:::-;10492:155;;;;:::o;10653:490::-;10729:6;10737;10786:2;10774:9;10765:7;10761:23;10757:32;10754:119;;;10792:79;;:::i;:::-;10754:119;10912:1;10937:61;10990:7;10981:6;10970:9;10966:22;10937:61;:::i;:::-;10927:71;;10883:125;11047:2;11073:53;11118:7;11109:6;11098:9;11094:22;11073:53;:::i;:::-;11063:63;;11018:118;10653:490;;;;;:::o;11149:109::-;11232:1;11225:5;11222:12;11212:40;;11248:1;11245;11238:12;11212:40;11149:109;:::o;11264:159::-;11320:5;11358:6;11345:20;11336:29;;11374:43;11411:5;11374:43;:::i;:::-;11264:159;;;;:::o;11429:349::-;11498:6;11547:2;11535:9;11526:7;11522:23;11518:32;11515:119;;;11553:79;;:::i;:::-;11515:119;11673:1;11698:63;11753:7;11744:6;11733:9;11729:22;11698:63;:::i;:::-;11688:73;;11644:127;11429:349;;;;:::o;11784:122::-;11857:24;11875:5;11857:24;:::i;:::-;11850:5;11847:35;11837:63;;11896:1;11893;11886:12;11837:63;11784:122;:::o;11912:139::-;11958:5;11996:6;11983:20;11974:29;;12012:33;12039:5;12012:33;:::i;:::-;11912:139;;;;:::o;12057:329::-;12116:6;12165:2;12153:9;12144:7;12140:23;12136:32;12133:119;;;12171:79;;:::i;:::-;12133:119;12291:1;12316:53;12361:7;12352:6;12341:9;12337:22;12316:53;:::i;:::-;12306:63;;12262:117;12057:329;;;;:::o;12392:116::-;12462:21;12477:5;12462:21;:::i;:::-;12455:5;12452:32;12442:60;;12498:1;12495;12488:12;12442:60;12392:116;:::o;12514:133::-;12557:5;12595:6;12582:20;12573:29;;12611:30;12635:5;12611:30;:::i;:::-;12514:133;;;;:::o;12653:468::-;12718:6;12726;12775:2;12763:9;12754:7;12750:23;12746:32;12743:119;;;12781:79;;:::i;:::-;12743:119;12901:1;12926:53;12971:7;12962:6;12951:9;12947:22;12926:53;:::i;:::-;12916:63;;12872:117;13028:2;13054:50;13096:7;13087:6;13076:9;13072:22;13054:50;:::i;:::-;13044:60;;12999:115;12653:468;;;;;:::o;13127:117::-;13236:1;13233;13226:12;13250:180;13298:77;13295:1;13288:88;13395:4;13392:1;13385:15;13419:4;13416:1;13409:15;13436:281;13519:27;13541:4;13519:27;:::i;:::-;13511:6;13507:40;13649:6;13637:10;13634:22;13613:18;13601:10;13598:34;13595:62;13592:88;;;13660:18;;:::i;:::-;13592:88;13700:10;13696:2;13689:22;13479:238;13436:281;;:::o;13723:129::-;13757:6;13784:20;;:::i;:::-;13774:30;;13813:33;13841:4;13833:6;13813:33;:::i;:::-;13723:129;;;:::o;13858:307::-;13919:4;14009:18;14001:6;13998:30;13995:56;;;14031:18;;:::i;:::-;13995:56;14069:29;14091:6;14069:29;:::i;:::-;14061:37;;14153:4;14147;14143:15;14135:23;;13858:307;;;:::o;14171:146::-;14268:6;14263:3;14258;14245:30;14309:1;14300:6;14295:3;14291:16;14284:27;14171:146;;;:::o;14323:423::-;14400:5;14425:65;14441:48;14482:6;14441:48;:::i;:::-;14425:65;:::i;:::-;14416:74;;14513:6;14506:5;14499:21;14551:4;14544:5;14540:16;14589:3;14580:6;14575:3;14571:16;14568:25;14565:112;;;14596:79;;:::i;:::-;14565:112;14686:54;14733:6;14728:3;14723;14686:54;:::i;:::-;14406:340;14323:423;;;;;:::o;14765:338::-;14820:5;14869:3;14862:4;14854:6;14850:17;14846:27;14836:122;;14877:79;;:::i;:::-;14836:122;14994:6;14981:20;15019:78;15093:3;15085:6;15078:4;15070:6;15066:17;15019:78;:::i;:::-;15010:87;;14826:277;14765:338;;;;:::o;15109:943::-;15204:6;15212;15220;15228;15277:3;15265:9;15256:7;15252:23;15248:33;15245:120;;;15284:79;;:::i;:::-;15245:120;15404:1;15429:53;15474:7;15465:6;15454:9;15450:22;15429:53;:::i;:::-;15419:63;;15375:117;15531:2;15557:53;15602:7;15593:6;15582:9;15578:22;15557:53;:::i;:::-;15547:63;;15502:118;15659:2;15685:53;15730:7;15721:6;15710:9;15706:22;15685:53;:::i;:::-;15675:63;;15630:118;15815:2;15804:9;15800:18;15787:32;15846:18;15838:6;15835:30;15832:117;;;15868:79;;:::i;:::-;15832:117;15973:62;16027:7;16018:6;16007:9;16003:22;15973:62;:::i;:::-;15963:72;;15758:287;15109:943;;;;;;;:::o;16075:568::-;16148:8;16158:6;16208:3;16201:4;16193:6;16189:17;16185:27;16175:122;;16216:79;;:::i;:::-;16175:122;16329:6;16316:20;16306:30;;16359:18;16351:6;16348:30;16345:117;;;16381:79;;:::i;:::-;16345:117;16495:4;16487:6;16483:17;16471:29;;16549:3;16541:4;16533:6;16529:17;16519:8;16515:32;16512:41;16509:128;;;16556:79;;:::i;:::-;16509:128;16075:568;;;;;:::o;16649:849::-;16753:6;16761;16769;16777;16826:2;16814:9;16805:7;16801:23;16797:32;16794:119;;;16832:79;;:::i;:::-;16794:119;16952:1;16977:53;17022:7;17013:6;17002:9;16998:22;16977:53;:::i;:::-;16967:63;;16923:117;17079:2;17105:53;17150:7;17141:6;17130:9;17126:22;17105:53;:::i;:::-;17095:63;;17050:118;17235:2;17224:9;17220:18;17207:32;17266:18;17258:6;17255:30;17252:117;;;17288:79;;:::i;:::-;17252:117;17401:80;17473:7;17464:6;17453:9;17449:22;17401:80;:::i;:::-;17383:98;;;;17178:313;16649:849;;;;;;;:::o;17504:323::-;17560:6;17609:2;17597:9;17588:7;17584:23;17580:32;17577:119;;;17615:79;;:::i;:::-;17577:119;17735:1;17760:50;17802:7;17793:6;17782:9;17778:22;17760:50;:::i;:::-;17750:60;;17706:114;17504:323;;;;:::o;17833:180::-;17881:77;17878:1;17871:88;17978:4;17975:1;17968:15;18002:4;17999:1;17992:15;18019:115;18102:1;18095:5;18092:12;18082:46;;18108:18;;:::i;:::-;18082:46;18019:115;:::o;18140:131::-;18187:7;18216:5;18205:16;;18222:43;18259:5;18222:43;:::i;:::-;18140:131;;;:::o;18277:::-;18335:9;18368:34;18396:5;18368:34;:::i;:::-;18355:47;;18277:131;;;:::o;18414:147::-;18509:45;18548:5;18509:45;:::i;:::-;18504:3;18497:58;18414:147;;:::o;18567:238::-;18668:4;18706:2;18695:9;18691:18;18683:26;;18719:79;18795:1;18784:9;18780:17;18771:6;18719:79;:::i;:::-;18567:238;;;;:::o;18811:474::-;18879:6;18887;18936:2;18924:9;18915:7;18911:23;18907:32;18904:119;;;18942:79;;:::i;:::-;18904:119;19062:1;19087:53;19132:7;19123:6;19112:9;19108:22;19087:53;:::i;:::-;19077:63;;19033:117;19189:2;19215:53;19260:7;19251:6;19240:9;19236:22;19215:53;:::i;:::-;19205:63;;19160:118;18811:474;;;;;:::o;19291:180::-;19339:77;19336:1;19329:88;19436:4;19433:1;19426:15;19460:4;19457:1;19450:15;19477:320;19521:6;19558:1;19552:4;19548:12;19538:22;;19605:1;19599:4;19595:12;19626:18;19616:81;;19682:4;19674:6;19670:17;19660:27;;19616:81;19744:2;19736:6;19733:14;19713:18;19710:38;19707:84;;19763:18;;:::i;:::-;19707:84;19528:269;19477:320;;;:::o;19803:180::-;19851:77;19848:1;19841:88;19948:4;19945:1;19938:15;19972:4;19969:1;19962:15;19989:410;20029:7;20052:20;20070:1;20052:20;:::i;:::-;20047:25;;20086:20;20104:1;20086:20;:::i;:::-;20081:25;;20141:1;20138;20134:9;20163:30;20181:11;20163:30;:::i;:::-;20152:41;;20342:1;20333:7;20329:15;20326:1;20323:22;20303:1;20296:9;20276:83;20253:139;;20372:18;;:::i;:::-;20253:139;20037:362;19989:410;;;;:::o;20405:180::-;20453:77;20450:1;20443:88;20550:4;20547:1;20540:15;20574:4;20571:1;20564:15;20591:185;20631:1;20648:20;20666:1;20648:20;:::i;:::-;20643:25;;20682:20;20700:1;20682:20;:::i;:::-;20677:25;;20721:1;20711:35;;20726:18;;:::i;:::-;20711:35;20768:1;20765;20761:9;20756:14;;20591:185;;;;:::o;20782:191::-;20822:3;20841:20;20859:1;20841:20;:::i;:::-;20836:25;;20875:20;20893:1;20875:20;:::i;:::-;20870:25;;20918:1;20915;20911:9;20904:16;;20939:3;20936:1;20933:10;20930:36;;;20946:18;;:::i;:::-;20930:36;20782:191;;;;:::o;20979:332::-;21100:4;21138:2;21127:9;21123:18;21115:26;;21151:71;21219:1;21208:9;21204:17;21195:6;21151:71;:::i;:::-;21232:72;21300:2;21289:9;21285:18;21276:6;21232:72;:::i;:::-;20979:332;;;;;:::o;21317:197::-;21356:3;21375:19;21392:1;21375:19;:::i;:::-;21370:24;;21408:19;21425:1;21408:19;:::i;:::-;21403:24;;21450:1;21447;21443:9;21436:16;;21473:10;21468:3;21465:19;21462:45;;;21487:18;;:::i;:::-;21462:45;21317:197;;;;:::o;21520:86::-;21555:7;21595:4;21588:5;21584:16;21573:27;;21520:86;;;:::o;21612:112::-;21695:22;21711:5;21695:22;:::i;:::-;21690:3;21683:35;21612:112;;:::o;21730:324::-;21847:4;21885:2;21874:9;21870:18;21862:26;;21898:71;21966:1;21955:9;21951:17;21942:6;21898:71;:::i;:::-;21979:68;22043:2;22032:9;22028:18;22019:6;21979:68;:::i;:::-;21730:324;;;;;:::o;22060:97::-;22119:6;22147:3;22137:13;;22060:97;;;;:::o;22163:141::-;22212:4;22235:3;22227:11;;22258:3;22255:1;22248:14;22292:4;22289:1;22279:18;22271:26;;22163:141;;;:::o;22310:93::-;22347:6;22394:2;22389;22382:5;22378:14;22374:23;22364:33;;22310:93;;;:::o;22409:107::-;22453:8;22503:5;22497:4;22493:16;22472:37;;22409:107;;;;:::o;22522:393::-;22591:6;22641:1;22629:10;22625:18;22664:97;22694:66;22683:9;22664:97;:::i;:::-;22782:39;22812:8;22801:9;22782:39;:::i;:::-;22770:51;;22854:4;22850:9;22843:5;22839:21;22830:30;;22903:4;22893:8;22889:19;22882:5;22879:30;22869:40;;22598:317;;22522:393;;;;;:::o;22921:60::-;22949:3;22970:5;22963:12;;22921:60;;;:::o;22987:142::-;23037:9;23070:53;23088:34;23097:24;23115:5;23097:24;:::i;:::-;23088:34;:::i;:::-;23070:53;:::i;:::-;23057:66;;22987:142;;;:::o;23135:75::-;23178:3;23199:5;23192:12;;23135:75;;;:::o;23216:269::-;23326:39;23357:7;23326:39;:::i;:::-;23387:91;23436:41;23460:16;23436:41;:::i;:::-;23428:6;23421:4;23415:11;23387:91;:::i;:::-;23381:4;23374:105;23292:193;23216:269;;;:::o;23491:73::-;23536:3;23491:73;:::o;23570:189::-;23647:32;;:::i;:::-;23688:65;23746:6;23738;23732:4;23688:65;:::i;:::-;23623:136;23570:189;;:::o;23765:186::-;23825:120;23842:3;23835:5;23832:14;23825:120;;;23896:39;23933:1;23926:5;23896:39;:::i;:::-;23869:1;23862:5;23858:13;23849:22;;23825:120;;;23765:186;;:::o;23957:543::-;24058:2;24053:3;24050:11;24047:446;;;24092:38;24124:5;24092:38;:::i;:::-;24176:29;24194:10;24176:29;:::i;:::-;24166:8;24162:44;24359:2;24347:10;24344:18;24341:49;;;24380:8;24365:23;;24341:49;24403:80;24459:22;24477:3;24459:22;:::i;:::-;24449:8;24445:37;24432:11;24403:80;:::i;:::-;24062:431;;24047:446;23957:543;;;:::o;24506:117::-;24560:8;24610:5;24604:4;24600:16;24579:37;;24506:117;;;;:::o;24629:169::-;24673:6;24706:51;24754:1;24750:6;24742:5;24739:1;24735:13;24706:51;:::i;:::-;24702:56;24787:4;24781;24777:15;24767:25;;24680:118;24629:169;;;;:::o;24803:295::-;24879:4;25025:29;25050:3;25044:4;25025:29;:::i;:::-;25017:37;;25087:3;25084:1;25080:11;25074:4;25071:21;25063:29;;24803:295;;;;:::o;25103:1403::-;25227:44;25267:3;25262;25227:44;:::i;:::-;25336:18;25328:6;25325:30;25322:56;;;25358:18;;:::i;:::-;25322:56;25402:38;25434:4;25428:11;25402:38;:::i;:::-;25487:67;25547:6;25539;25533:4;25487:67;:::i;:::-;25581:1;25610:2;25602:6;25599:14;25627:1;25622:632;;;;26298:1;26315:6;26312:84;;;26371:9;26366:3;26362:19;26349:33;26340:42;;26312:84;26422:67;26482:6;26475:5;26422:67;:::i;:::-;26416:4;26409:81;26271:229;25592:908;;25622:632;25674:4;25670:9;25662:6;25658:22;25708:37;25740:4;25708:37;:::i;:::-;25767:1;25781:215;25795:7;25792:1;25789:14;25781:215;;;25881:9;25876:3;25872:19;25859:33;25851:6;25844:49;25932:1;25924:6;25920:14;25910:24;;25979:2;25968:9;25964:18;25951:31;;25818:4;25815:1;25811:12;25806:17;;25781:215;;;26024:6;26015:7;26012:19;26009:186;;;26089:9;26084:3;26080:19;26067:33;26132:48;26174:4;26166:6;26162:17;26151:9;26132:48;:::i;:::-;26124:6;26117:64;26032:163;26009:186;26241:1;26237;26229:6;26225:14;26221:22;26215:4;26208:36;25629:625;;;25592:908;;25202:1304;;;25103:1403;;;:::o;26536:317::-;26634:3;26655:71;26719:6;26714:3;26655:71;:::i;:::-;26648:78;;26736:56;26785:6;26780:3;26773:5;26736:56;:::i;:::-;26817:29;26839:6;26817:29;:::i;:::-;26812:3;26808:39;26801:46;;26536:317;;;;;:::o;26859:333::-;26982:4;27020:2;27009:9;27005:18;26997:26;;27069:9;27063:4;27059:20;27055:1;27044:9;27040:17;27033:47;27097:88;27180:4;27171:6;27163;27097:88;:::i;:::-;27089:96;;26859:333;;;;;:::o;27198:165::-;27338:17;27334:1;27326:6;27322:14;27315:41;27198:165;:::o;27369:366::-;27511:3;27532:67;27596:2;27591:3;27532:67;:::i;:::-;27525:74;;27608:93;27697:3;27608:93;:::i;:::-;27726:2;27721:3;27717:12;27710:19;;27369:366;;;:::o;27741:419::-;27907:4;27945:2;27934:9;27930:18;27922:26;;27994:9;27988:4;27984:20;27980:1;27969:9;27965:17;27958:47;28022:131;28148:4;28022:131;:::i;:::-;28014:139;;27741:419;;;:::o;28166:147::-;28267:11;28304:3;28289:18;;28166:147;;;;:::o;28319:114::-;;:::o;28439:398::-;28598:3;28619:83;28700:1;28695:3;28619:83;:::i;:::-;28612:90;;28711:93;28800:3;28711:93;:::i;:::-;28829:1;28824:3;28820:11;28813:18;;28439:398;;;:::o;28843:379::-;29027:3;29049:147;29192:3;29049:147;:::i;:::-;29042:154;;29213:3;29206:10;;28843:379;;;:::o;29228:165::-;29368:17;29364:1;29356:6;29352:14;29345:41;29228:165;:::o;29399:366::-;29541:3;29562:67;29626:2;29621:3;29562:67;:::i;:::-;29555:74;;29638:93;29727:3;29638:93;:::i;:::-;29756:2;29751:3;29747:12;29740:19;;29399:366;;;:::o;29771:419::-;29937:4;29975:2;29964:9;29960:18;29952:26;;30024:9;30018:4;30014:20;30010:1;29999:9;29995:17;29988:47;30052:131;30178:4;30052:131;:::i;:::-;30044:139;;29771:419;;;:::o;30196:214::-;30285:4;30323:2;30312:9;30308:18;30300:26;;30336:67;30400:1;30389:9;30385:17;30376:6;30336:67;:::i;:::-;30196:214;;;;:::o;30416:94::-;30449:8;30497:5;30493:2;30489:14;30468:35;;30416:94;;;:::o;30516:::-;30555:7;30584:20;30598:5;30584:20;:::i;:::-;30573:31;;30516:94;;;:::o;30616:100::-;30655:7;30684:26;30704:5;30684:26;:::i;:::-;30673:37;;30616:100;;;:::o;30722:157::-;30827:45;30847:24;30865:5;30847:24;:::i;:::-;30827:45;:::i;:::-;30822:3;30815:58;30722:157;;:::o;30885:79::-;30924:7;30953:5;30942:16;;30885:79;;;:::o;30970:157::-;31075:45;31095:24;31113:5;31095:24;:::i;:::-;31075:45;:::i;:::-;31070:3;31063:58;30970:157;;:::o;31133:397::-;31273:3;31288:75;31359:3;31350:6;31288:75;:::i;:::-;31388:2;31383:3;31379:12;31372:19;;31401:75;31472:3;31463:6;31401:75;:::i;:::-;31501:2;31496:3;31492:12;31485:19;;31521:3;31514:10;;31133:397;;;;;:::o;31536:234::-;31676:34;31672:1;31664:6;31660:14;31653:58;31745:17;31740:2;31732:6;31728:15;31721:42;31536:234;:::o;31776:366::-;31918:3;31939:67;32003:2;31998:3;31939:67;:::i;:::-;31932:74;;32015:93;32104:3;32015:93;:::i;:::-;32133:2;32128:3;32124:12;32117:19;;31776:366;;;:::o;32148:419::-;32314:4;32352:2;32341:9;32337:18;32329:26;;32401:9;32395:4;32391:20;32387:1;32376:9;32372:17;32365:47;32429:131;32555:4;32429:131;:::i;:::-;32421:139;;32148:419;;;:::o;32573:148::-;32675:11;32712:3;32697:18;;32573:148;;;;:::o;32727:390::-;32833:3;32861:39;32894:5;32861:39;:::i;:::-;32916:89;32998:6;32993:3;32916:89;:::i;:::-;32909:96;;33014:65;33072:6;33067:3;33060:4;33053:5;33049:16;33014:65;:::i;:::-;33104:6;33099:3;33095:16;33088:23;;32837:280;32727:390;;;;:::o;33123:155::-;33263:7;33259:1;33251:6;33247:14;33240:31;33123:155;:::o;33284:400::-;33444:3;33465:84;33547:1;33542:3;33465:84;:::i;:::-;33458:91;;33558:93;33647:3;33558:93;:::i;:::-;33676:1;33671:3;33667:11;33660:18;;33284:400;;;:::o;33690:701::-;33971:3;33993:95;34084:3;34075:6;33993:95;:::i;:::-;33986:102;;34105:95;34196:3;34187:6;34105:95;:::i;:::-;34098:102;;34217:148;34361:3;34217:148;:::i;:::-;34210:155;;34382:3;34375:10;;33690:701;;;;;:::o;34397:140::-;34446:9;34479:52;34497:33;34506:23;34523:5;34506:23;:::i;:::-;34497:33;:::i;:::-;34479:52;:::i;:::-;34466:65;;34397:140;;;:::o;34543:129::-;34629:36;34659:5;34629:36;:::i;:::-;34624:3;34617:49;34543:129;;:::o;34678:330::-;34798:4;34836:2;34825:9;34821:18;34813:26;;34849:70;34916:1;34905:9;34901:17;34892:6;34849:70;:::i;:::-;34929:72;34997:2;34986:9;34982:18;34973:6;34929:72;:::i;:::-;34678:330;;;;;:::o;35014:171::-;35053:3;35076:24;35094:5;35076:24;:::i;:::-;35067:33;;35122:4;35115:5;35112:15;35109:41;;35130:18;;:::i;:::-;35109:41;35177:1;35170:5;35166:13;35159:20;;35014:171;;;:::o;35191:98::-;35242:6;35276:5;35270:12;35260:22;;35191:98;;;:::o;35295:168::-;35378:11;35412:6;35407:3;35400:19;35452:4;35447:3;35443:14;35428:29;;35295:168;;;;:::o;35469:373::-;35555:3;35583:38;35615:5;35583:38;:::i;:::-;35637:70;35700:6;35695:3;35637:70;:::i;:::-;35630:77;;35716:65;35774:6;35769:3;35762:4;35755:5;35751:16;35716:65;:::i;:::-;35806:29;35828:6;35806:29;:::i;:::-;35801:3;35797:39;35790:46;;35559:283;35469:373;;;;:::o;35848:640::-;36043:4;36081:3;36070:9;36066:19;36058:27;;36095:71;36163:1;36152:9;36148:17;36139:6;36095:71;:::i;:::-;36176:72;36244:2;36233:9;36229:18;36220:6;36176:72;:::i;:::-;36258;36326:2;36315:9;36311:18;36302:6;36258:72;:::i;:::-;36377:9;36371:4;36367:20;36362:2;36351:9;36347:18;36340:48;36405:76;36476:4;36467:6;36405:76;:::i;:::-;36397:84;;35848:640;;;;;;;:::o;36494:141::-;36550:5;36581:6;36575:13;36566:22;;36597:32;36623:5;36597:32;:::i;:::-;36494:141;;;;:::o;36641:349::-;36710:6;36759:2;36747:9;36738:7;36734:23;36730:32;36727:119;;;36765:79;;:::i;:::-;36727:119;36885:1;36910:63;36965:7;36956:6;36945:9;36941:22;36910:63;:::i;:::-;36900:73;;36856:127;36641:349;;;;:::o;36996:180::-;37044:77;37041:1;37034:88;37141:4;37138:1;37131:15;37165:4;37162:1;37155:15

Swarm Source

ipfs://5ea9c01beec8443ebead36e345e8d8f886044de6987a2f203af4a7942cc204aa
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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