ETH Price: $2,807.66 (-5.11%)
 

Overview

Max Total Supply

251,778 BASEBUILDER

Holders

251,778

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Filtered by Token Holder
oxraji.base.eth
Balance
1 BASEBUILDER
0xe030eAb5D0727BC78b5248403052Fe8f6616d7f9
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
Builder

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at basescan.org on 2024-04-23
*/

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13 ^0.8.4;

// lib/solady/src/auth/Ownable.sol

/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The caller is not authorized to call the function.
    error Unauthorized();

    /// @dev The `newOwner` cannot be the zero address.
    error NewOwnerIsZeroAddress();

    /// @dev The `pendingOwner` does not have a valid handover request.
    error NoHandoverRequest();

    /// @dev Cannot double-initialize.
    error AlreadyInitialized();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership is transferred from `oldOwner` to `newOwner`.
    /// This event is intentionally kept the same as OpenZeppelin's Ownable to be
    /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
    /// despite it not being as lightweight as a single argument event.
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    /// @dev An ownership handover to `pendingOwner` has been requested.
    event OwnershipHandoverRequested(address indexed pendingOwner);

    /// @dev The ownership handover to `pendingOwner` has been canceled.
    event OwnershipHandoverCanceled(address indexed pendingOwner);

    /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
    uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
        0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;

    /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
        0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;

    /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
        0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The owner slot is given by:
    /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
    /// It is intentionally chosen to be a high value
    /// to avoid collision with lower slots.
    /// The choice of manual storage layout is to enable compatibility
    /// with both regular and upgradeable contracts.
    bytes32 internal constant _OWNER_SLOT =
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;

    /// The ownership handover slot of `newOwner` is given by:
    /// ```
    ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
    ///     let handoverSlot := keccak256(0x00, 0x20)
    /// ```
    /// It stores the expiry timestamp of the two-step ownership handover.
    uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
    function _guardInitializeOwner() internal pure virtual returns (bool guard) {}

    /// @dev Initializes the owner directly without authorization guard.
    /// This function must be called upon initialization,
    /// regardless of whether the contract is upgradeable or not.
    /// This is to enable generalization to both regular and upgradeable contracts,
    /// and to save gas in case the initial owner is not the caller.
    /// For performance reasons, this function will not check if there
    /// is an existing owner.
    function _initializeOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                if sload(ownerSlot) {
                    mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
                    revert(0x1c, 0x04)
                }
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(_OWNER_SLOT, newOwner)
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        }
    }

    /// @dev Sets the owner directly without authorization guard.
    function _setOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, newOwner)
            }
        }
    }

    /// @dev Throws if the sender is not the owner.
    function _checkOwner() internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // If the caller is not the stored owner, revert.
            if iszero(eq(caller(), sload(_OWNER_SLOT))) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns how long a two-step ownership handover is valid for in seconds.
    /// Override to return a different value if needed.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
        return 48 * 3600;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Allows the owner to transfer the ownership to `newOwner`.
    function transferOwnership(address newOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(shl(96, newOwner)) {
                mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
                revert(0x1c, 0x04)
            }
        }
        _setOwner(newOwner);
    }

    /// @dev Allows the owner to renounce their ownership.
    function renounceOwnership() public payable virtual onlyOwner {
        _setOwner(address(0));
    }

    /// @dev Request a two-step ownership handover to the caller.
    /// The request will automatically expire in 48 hours (172800 seconds) by default.
    function requestOwnershipHandover() public payable virtual {
        unchecked {
            uint256 expires = block.timestamp + _ownershipHandoverValidFor();
            /// @solidity memory-safe-assembly
            assembly {
                // Compute and set the handover slot to `expires`.
                mstore(0x0c, _HANDOVER_SLOT_SEED)
                mstore(0x00, caller())
                sstore(keccak256(0x0c, 0x20), expires)
                // Emit the {OwnershipHandoverRequested} event.
                log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
            }
        }
    }

    /// @dev Cancels the two-step ownership handover to the caller, if any.
    function cancelOwnershipHandover() public payable virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x20), 0)
            // Emit the {OwnershipHandoverCanceled} event.
            log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
        }
    }

    /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
    /// Reverts if there is no existing ownership handover requested by `pendingOwner`.
    function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            let handoverSlot := keccak256(0x0c, 0x20)
            // If the handover does not exist, or has expired.
            if gt(timestamp(), sload(handoverSlot)) {
                mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
                revert(0x1c, 0x04)
            }
            // Set the handover slot to 0.
            sstore(handoverSlot, 0)
        }
        _setOwner(pendingOwner);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   PUBLIC READ FUNCTIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of the contract.
    function owner() public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_OWNER_SLOT)
        }
    }

    /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
    function ownershipHandoverExpiresAt(address pendingOwner)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the handover slot.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            // Load the handover slot.
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Marks a function as only callable by the owner.
    modifier onlyOwner() virtual {
        _checkOwner();
        _;
    }
}

// lib/solady/src/tokens/ERC721.sol

/// @notice Simple ERC721 implementation with storage hitchhiking.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC721.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721/ERC721.sol)
///
/// @dev Note:
/// - The ERC721 standard allows for self-approvals.
///   For performance, this implementation WILL NOT revert for such actions.
///   Please add any checks with overrides if desired.
/// - For performance, methods are made payable where permitted by the ERC721 standard.
/// - The `safeTransfer` functions use the identity precompile (0x4)
///   to copy memory internally.
///
/// If you are overriding:
/// - NEVER violate the ERC721 invariant:
///   the balance of an owner MUST always be equal to their number of ownership slots.
///   The transfer functions do not have an underflow guard for user token balances.
/// - Make sure all variables written to storage are properly cleaned
//    (e.g. the bool value for `isApprovedForAll` MUST be either 1 or 0 under the hood).
/// - Check that the overridden function is actually used in the function you want to
///   change the behavior of. Much of the code has been manually inlined for performance.
abstract contract ERC721 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev An account can hold up to 4294967295 tokens.
    uint256 internal constant _MAX_ACCOUNT_BALANCE = 0xffffffff;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Only the token owner or an approved account can manage the token.
    error NotOwnerNorApproved();

    /// @dev The token does not exist.
    error TokenDoesNotExist();

    /// @dev The token already exists.
    error TokenAlreadyExists();

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

    /// @dev Cannot mint or transfer to the zero address.
    error TransferToZeroAddress();

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

    /// @dev The recipient's balance has overflowed.
    error AccountBalanceOverflow();

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

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

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

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

    /// @dev Emitted when `owner` enables or disables `operator` to manage all of their tokens.
    event ApprovalForAll(address indexed owner, address indexed operator, bool isApproved);

    /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
    uint256 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`.
    uint256 private constant _APPROVAL_EVENT_SIGNATURE =
        0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;

    /// @dev `keccak256(bytes("ApprovalForAll(address,address,bool)"))`.
    uint256 private constant _APPROVAL_FOR_ALL_EVENT_SIGNATURE =
        0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership data slot of `id` is given by:
    /// ```
    ///     mstore(0x00, id)
    ///     mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
    ///     let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
    /// ```
    /// Bits Layout:
    /// - [0..159]   `addr`
    /// - [160..255] `extraData`
    ///
    /// The approved address slot is given by: `add(1, ownershipSlot)`.
    ///
    /// See: https://notes.ethereum.org/%40vbuterin/verkle_tree_eip
    ///
    /// The balance slot of `owner` is given by:
    /// ```
    ///     mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let balanceSlot := keccak256(0x0c, 0x1c)
    /// ```
    /// Bits Layout:
    /// - [0..31]   `balance`
    /// - [32..255] `aux`
    ///
    /// The `operator` approval slot of `owner` is given by:
    /// ```
    ///     mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator))
    ///     mstore(0x00, owner)
    ///     let operatorApprovalSlot := keccak256(0x0c, 0x30)
    /// ```
    uint256 private constant _ERC721_MASTER_SLOT_SEED = 0x7d8825530a5a2e7a << 192;

    /// @dev Pre-shifted and pre-masked constant.
    uint256 private constant _ERC721_MASTER_SLOT_SEED_MASKED = 0x0a5a2e7a00000000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC721 METADATA                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

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

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

    /// @dev Returns the Uniform Resource Identifier (URI) for token `id`.
    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           ERC721                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function ownerOf(uint256 id) public view virtual returns (address result) {
        result = _ownerOf(id);
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(result) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns the number of tokens owned by `owner`.
    ///
    /// Requirements:
    /// - `owner` must not be the zero address.
    function balanceOf(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Revert if the `owner` is the zero address.
            if iszero(owner) {
                mstore(0x00, 0x8f4eb604) // `BalanceQueryForZeroAddress()`.
                revert(0x1c, 0x04)
            }
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            result := and(sload(keccak256(0x0c, 0x1c)), _MAX_ACCOUNT_BALANCE)
        }
    }

    /// @dev Returns the account approved to manage token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function getApproved(uint256 id) public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            if iszero(shl(96, sload(ownershipSlot))) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            result := sload(add(1, ownershipSlot))
        }
    }

    /// @dev Sets `account` as the approved account to manage token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    /// - The caller must be the owner of the token,
    ///   or an approved operator for the token owner.
    ///
    /// Emits an {Approval} event.
    function approve(address account, uint256 id) public payable virtual {
        _approve(msg.sender, account, id);
    }

    /// @dev Returns whether `operator` is approved to manage the tokens of `owner`.
    function isApprovedForAll(address owner, address operator)
        public
        view
        virtual
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, operator)
            mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x30))
        }
    }

    /// @dev Sets whether `operator` is approved to manage the tokens of the caller.
    ///
    /// Emits an {ApprovalForAll} event.
    function setApprovalForAll(address operator, bool isApproved) public virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Convert to 0 or 1.
            isApproved := iszero(iszero(isApproved))
            // Update the `isApproved` for (`msg.sender`, `operator`).
            mstore(0x1c, operator)
            mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x30), isApproved)
            // Emit the {ApprovalForAll} event.
            mstore(0x00, isApproved)
            // forgefmt: disable-next-item
            log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), shr(96, shl(96, operator)))
        }
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function transferFrom(address from, address to, uint256 id) public payable virtual {
        _beforeTokenTransfer(from, to, id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            from := and(bitmaskAddress, from)
            to := and(bitmaskAddress, to)
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, caller()))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            let owner := and(bitmaskAddress, ownershipPacked)
            // Revert if the token does not exist, or if `from` is not the owner.
            if iszero(mul(owner, eq(owner, from))) {
                // `TokenDoesNotExist()`, `TransferFromIncorrectOwner()`.
                mstore(shl(2, iszero(owner)), 0xceea21b6a1148100)
                revert(0x1c, 0x04)
            }
            // Load, check, and update the token approval.
            {
                mstore(0x00, from)
                let approvedAddress := sload(add(1, ownershipSlot))
                // Revert if the caller is not the owner, nor approved.
                if iszero(or(eq(caller(), from), eq(caller(), approvedAddress))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
                // Delete the approved address if any.
                if approvedAddress { sstore(add(1, ownershipSlot), 0) }
            }
            // Update with the new owner.
            sstore(ownershipSlot, xor(ownershipPacked, xor(from, to)))
            // Decrement the balance of `from`.
            {
                let fromBalanceSlot := keccak256(0x0c, 0x1c)
                sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1))
            }
            // Increment the balance of `to`.
            {
                mstore(0x00, to)
                let toBalanceSlot := keccak256(0x0c, 0x1c)
                let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)
                // Revert if `to` is the zero address, or if the account balance overflows.
                if iszero(mul(to, and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {
                    // `TransferToZeroAddress()`, `AccountBalanceOverflow()`.
                    mstore(shl(2, iszero(to)), 0xea553b3401336cea)
                    revert(0x1c, 0x04)
                }
                sstore(toBalanceSlot, toBalanceSlotPacked)
            }
            // Emit the {Transfer} event.
            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)
        }
        _afterTokenTransfer(from, to, id);
    }

    /// @dev Equivalent to `safeTransferFrom(from, to, id, "")`.
    function safeTransferFrom(address from, address to, uint256 id) public payable virtual {
        transferFrom(from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    /// - 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 id, bytes calldata data)
        public
        payable
        virtual
    {
        transferFrom(from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /// @dev Returns true if this contract implements the interface defined by `interfaceId`.
    /// See: https://eips.ethereum.org/EIPS/eip-165
    /// This function call must use less than 30000 gas.
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            let s := shr(224, interfaceId)
            // ERC165: 0x01ffc9a7, ERC721: 0x80ac58cd, ERC721Metadata: 0x5b5e139f.
            result := or(or(eq(s, 0x01ffc9a7), eq(s, 0x80ac58cd)), eq(s, 0x5b5e139f))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL QUERY FUNCTIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns if token `id` exists.
    function _exists(uint256 id) internal view virtual returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := iszero(iszero(shl(96, sload(add(id, add(id, keccak256(0x00, 0x20)))))))
        }
    }

    /// @dev Returns the owner of token `id`.
    /// Returns the zero address instead of reverting if the token does not exist.
    function _ownerOf(uint256 id) internal view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := shr(96, shl(96, sload(add(id, add(id, keccak256(0x00, 0x20))))))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*            INTERNAL DATA HITCHHIKING FUNCTIONS             */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // For performance, no events are emitted for the hitchhiking setters.
    // Please emit your own events if required.

    /// @dev Returns the auxiliary data for `owner`.
    /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data.
    /// Auxiliary data can be set for any address, even if it does not have any tokens.
    function _getAux(address owner) internal view virtual returns (uint224 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            result := shr(32, sload(keccak256(0x0c, 0x1c)))
        }
    }

    /// @dev Set the auxiliary data for `owner` to `value`.
    /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data.
    /// Auxiliary data can be set for any address, even if it does not have any tokens.
    function _setAux(address owner, uint224 value) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            let balanceSlot := keccak256(0x0c, 0x1c)
            let packed := sload(balanceSlot)
            sstore(balanceSlot, xor(packed, shl(32, xor(value, shr(32, packed)))))
        }
    }

    /// @dev Returns the extra data for token `id`.
    /// Minting, transferring, burning a token will not change the extra data.
    /// The extra data can be set on a non-existent token.
    function _getExtraData(uint256 id) internal view virtual returns (uint96 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := shr(160, sload(add(id, add(id, keccak256(0x00, 0x20)))))
        }
    }

    /// @dev Sets the extra data for token `id` to `value`.
    /// Minting, transferring, burning a token will not change the extra data.
    /// The extra data can be set on a non-existent token.
    function _setExtraData(uint256 id, uint96 value) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let packed := sload(ownershipSlot)
            sstore(ownershipSlot, xor(packed, shl(160, xor(value, shr(160, packed)))))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL MINT FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Mints token `id` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must not exist.
    /// - `to` cannot be the zero address.
    ///
    /// Emits a {Transfer} event.
    function _mint(address to, uint256 id) internal virtual {
        _beforeTokenTransfer(address(0), to, id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            to := shr(96, shl(96, to))
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            // Revert if the token already exists.
            if shl(96, ownershipPacked) {
                mstore(0x00, 0xc991cbb1) // `TokenAlreadyExists()`.
                revert(0x1c, 0x04)
            }
            // Update with the owner.
            sstore(ownershipSlot, or(ownershipPacked, to))
            // Increment the balance of the owner.
            {
                mstore(0x00, to)
                let balanceSlot := keccak256(0x0c, 0x1c)
                let balanceSlotPacked := add(sload(balanceSlot), 1)
                // Revert if `to` is the zero address, or if the account balance overflows.
                if iszero(mul(to, and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {
                    // `TransferToZeroAddress()`, `AccountBalanceOverflow()`.
                    mstore(shl(2, iszero(to)), 0xea553b3401336cea)
                    revert(0x1c, 0x04)
                }
                sstore(balanceSlot, balanceSlotPacked)
            }
            // Emit the {Transfer} event.
            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, 0, to, id)
        }
        _afterTokenTransfer(address(0), to, id);
    }

    /// @dev Mints token `id` to `to`, and updates the extra data for token `id` to `value`.
    /// Does NOT check if token `id` already exists (assumes `id` is auto-incrementing).
    ///
    /// Requirements:
    ///
    /// - `to` cannot be the zero address.
    ///
    /// Emits a {Transfer} event.
    function _mintAndSetExtraDataUnchecked(address to, uint256 id, uint96 value) internal virtual {
        _beforeTokenTransfer(address(0), to, id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            to := shr(96, shl(96, to))
            // Update with the owner and extra data.
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            sstore(add(id, add(id, keccak256(0x00, 0x20))), or(shl(160, value), to))
            // Increment the balance of the owner.
            {
                mstore(0x00, to)
                let balanceSlot := keccak256(0x0c, 0x1c)
                let balanceSlotPacked := add(sload(balanceSlot), 1)
                // Revert if `to` is the zero address, or if the account balance overflows.
                if iszero(mul(to, and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {
                    // `TransferToZeroAddress()`, `AccountBalanceOverflow()`.
                    mstore(shl(2, iszero(to)), 0xea553b3401336cea)
                    revert(0x1c, 0x04)
                }
                sstore(balanceSlot, balanceSlotPacked)
            }
            // Emit the {Transfer} event.
            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, 0, to, id)
        }
        _afterTokenTransfer(address(0), to, id);
    }

    /// @dev Equivalent to `_safeMint(to, id, "")`.
    function _safeMint(address to, uint256 id) internal virtual {
        _safeMint(to, id, "");
    }

    /// @dev Mints token `id` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must not exist.
    /// - `to` cannot be the zero address.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function _safeMint(address to, uint256 id, bytes memory data) internal virtual {
        _mint(to, id);
        if (_hasCode(to)) _checkOnERC721Received(address(0), to, id, data);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL BURN FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `_burn(address(0), id)`.
    function _burn(uint256 id) internal virtual {
        _burn(address(0), id);
    }

    /// @dev Destroys token `id`, using `by`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function _burn(address by, uint256 id) internal virtual {
        address owner = ownerOf(id);
        _beforeTokenTransfer(owner, address(0), id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            by := shr(96, shl(96, by))
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            // Reload the owner in case it is changed in `_beforeTokenTransfer`.
            owner := shr(96, shl(96, ownershipPacked))
            // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            // Load and check the token approval.
            {
                mstore(0x00, owner)
                let approvedAddress := sload(add(1, ownershipSlot))
                // If `by` is not the zero address, do the authorization check.
                // Revert if the `by` is not the owner, nor approved.
                if iszero(or(iszero(by), or(eq(by, owner), eq(by, approvedAddress)))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
                // Delete the approved address if any.
                if approvedAddress { sstore(add(1, ownershipSlot), 0) }
            }
            // Clear the owner.
            sstore(ownershipSlot, xor(ownershipPacked, owner))
            // Decrement the balance of `owner`.
            {
                let balanceSlot := keccak256(0x0c, 0x1c)
                sstore(balanceSlot, sub(sload(balanceSlot), 1))
            }
            // Emit the {Transfer} event.
            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, owner, 0, id)
        }
        _afterTokenTransfer(owner, address(0), id);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL APPROVAL FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `account` is the owner of token `id`, or is approved to manage it.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function _isApprovedOrOwner(address account, uint256 id)
        internal
        view
        virtual
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            // Clear the upper 96 bits.
            account := shr(96, shl(96, account))
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, account))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let owner := shr(96, shl(96, sload(ownershipSlot)))
            // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            // Check if `account` is the `owner`.
            if iszero(eq(account, owner)) {
                mstore(0x00, owner)
                // Check if `account` is approved to manage the token.
                if iszero(sload(keccak256(0x0c, 0x30))) {
                    result := eq(account, sload(add(1, ownershipSlot)))
                }
            }
        }
    }

    /// @dev Returns the account approved to manage token `id`.
    /// Returns the zero address instead of reverting if the token does not exist.
    function _getApproved(uint256 id) internal view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := sload(add(1, add(id, add(id, keccak256(0x00, 0x20)))))
        }
    }

    /// @dev Equivalent to `_approve(address(0), account, id)`.
    function _approve(address account, uint256 id) internal virtual {
        _approve(address(0), account, id);
    }

    /// @dev Sets `account` as the approved account to manage token `id`, using `by`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    /// - If `by` is not the zero address, `by` must be the owner
    ///   or an approved operator for the token owner.
    ///
    /// Emits a {Approval} event.
    function _approve(address by, address account, uint256 id) internal virtual {
        assembly {
            // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            account := and(bitmaskAddress, account)
            by := and(bitmaskAddress, by)
            // Load the owner of the token.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let owner := and(bitmaskAddress, sload(ownershipSlot))
            // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            // If `by` is not the zero address, do the authorization check.
            // Revert if `by` is not the owner, nor approved.
            if iszero(or(iszero(by), eq(by, owner))) {
                mstore(0x00, owner)
                if iszero(sload(keccak256(0x0c, 0x30))) {
                    mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                    revert(0x1c, 0x04)
                }
            }
            // Sets `account` as the approved account to manage `id`.
            sstore(add(1, ownershipSlot), account)
            // Emit the {Approval} event.
            log4(codesize(), 0x00, _APPROVAL_EVENT_SIGNATURE, owner, account, id)
        }
    }

    /// @dev Approve or remove the `operator` as an operator for `by`,
    /// without authorization checks.
    ///
    /// Emits an {ApprovalForAll} event.
    function _setApprovalForAll(address by, address operator, bool isApproved) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            by := shr(96, shl(96, by))
            operator := shr(96, shl(96, operator))
            // Convert to 0 or 1.
            isApproved := iszero(iszero(isApproved))
            // Update the `isApproved` for (`by`, `operator`).
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator))
            mstore(0x00, by)
            sstore(keccak256(0x0c, 0x30), isApproved)
            // Emit the {ApprovalForAll} event.
            mstore(0x00, isApproved)
            log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, by, operator)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL TRANSFER FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `_transfer(address(0), from, to, id)`.
    function _transfer(address from, address to, uint256 id) internal virtual {
        _transfer(address(0), from, to, id);
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function _transfer(address by, address from, address to, uint256 id) internal virtual {
        _beforeTokenTransfer(from, to, id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            from := and(bitmaskAddress, from)
            to := and(bitmaskAddress, to)
            by := and(bitmaskAddress, by)
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            let owner := and(bitmaskAddress, ownershipPacked)
            // Revert if the token does not exist, or if `from` is not the owner.
            if iszero(mul(owner, eq(owner, from))) {
                // `TokenDoesNotExist()`, `TransferFromIncorrectOwner()`.
                mstore(shl(2, iszero(owner)), 0xceea21b6a1148100)
                revert(0x1c, 0x04)
            }
            // Load, check, and update the token approval.
            {
                mstore(0x00, from)
                let approvedAddress := sload(add(1, ownershipSlot))
                // If `by` is not the zero address, do the authorization check.
                // Revert if the `by` is not the owner, nor approved.
                if iszero(or(iszero(by), or(eq(by, from), eq(by, approvedAddress)))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
                // Delete the approved address if any.
                if approvedAddress { sstore(add(1, ownershipSlot), 0) }
            }
            // Update with the new owner.
            sstore(ownershipSlot, xor(ownershipPacked, xor(from, to)))
            // Decrement the balance of `from`.
            {
                let fromBalanceSlot := keccak256(0x0c, 0x1c)
                sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1))
            }
            // Increment the balance of `to`.
            {
                mstore(0x00, to)
                let toBalanceSlot := keccak256(0x0c, 0x1c)
                let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)
                // Revert if `to` is the zero address, or if the account balance overflows.
                if iszero(mul(to, and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {
                    // `TransferToZeroAddress()`, `AccountBalanceOverflow()`.
                    mstore(shl(2, iszero(to)), 0xea553b3401336cea)
                    revert(0x1c, 0x04)
                }
                sstore(toBalanceSlot, toBalanceSlotPacked)
            }
            // Emit the {Transfer} event.
            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)
        }
        _afterTokenTransfer(from, to, id);
    }

    /// @dev Equivalent to `_safeTransfer(from, to, id, "")`.
    function _safeTransfer(address from, address to, uint256 id) internal virtual {
        _safeTransfer(from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function _safeTransfer(address from, address to, uint256 id, bytes memory data)
        internal
        virtual
    {
        _transfer(address(0), from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /// @dev Equivalent to `_safeTransfer(by, from, to, id, "")`.
    function _safeTransfer(address by, address from, address to, uint256 id) internal virtual {
        _safeTransfer(by, from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function _safeTransfer(address by, address from, address to, uint256 id, bytes memory data)
        internal
        virtual
    {
        _transfer(by, from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    HOOKS FOR OVERRIDING                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Hook that is called before any token transfers, including minting and burning.
    function _beforeTokenTransfer(address from, address to, uint256 id) internal virtual {}

    /// @dev Hook that is called after any token transfers, including minting and burning.
    function _afterTokenTransfer(address from, address to, uint256 id) internal virtual {}

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns if `a` has bytecode of non-zero length.
    function _hasCode(address a) private view returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := extcodesize(a) // Can handle dirty upper bits.
        }
    }

    /// @dev Perform a call to invoke {IERC721Receiver-onERC721Received} on `to`.
    /// Reverts if the target does not support the function correctly.
    function _checkOnERC721Received(address from, address to, uint256 id, bytes memory data)
        private
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Prepare the calldata.
            let m := mload(0x40)
            let onERC721ReceivedSelector := 0x150b7a02
            mstore(m, onERC721ReceivedSelector)
            mstore(add(m, 0x20), caller()) // The `operator`, which is always `msg.sender`.
            mstore(add(m, 0x40), shr(96, shl(96, from)))
            mstore(add(m, 0x60), id)
            mstore(add(m, 0x80), 0x80)
            let n := mload(data)
            mstore(add(m, 0xa0), n)
            if n { pop(staticcall(gas(), 4, add(data, 0x20), n, add(m, 0xc0), n)) }
            // Revert if the call reverts.
            if iszero(call(gas(), to, 0, add(m, 0x1c), add(n, 0xa4), m, 0x20)) {
                if returndatasize() {
                    // Bubble up the revert if the call reverts.
                    returndatacopy(m, 0x00, returndatasize())
                    revert(m, returndatasize())
                }
            }
            // Load the returndata and compare it.
            if iszero(eq(mload(m), shl(224, onERC721ReceivedSelector))) {
                mstore(0x00, 0xd1a57ed6) // `TransferToNonERC721ReceiverImplementer()`.
                revert(0x1c, 0x04)
            }
        }
    }
}

// lib/solady/src/utils/LibString.sol

/// @notice Library for converting numbers into strings and other string operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
///
/// @dev Note:
/// For performance and bytecode compactness, most of the string operations are restricted to
/// byte strings (7-bit ASCII), except where otherwise specified.
/// Usage of byte string operations on charsets with runes spanning two or more bytes
/// can lead to undefined behavior.
library LibString {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The length of the output is too small to contain all the hex digits.
    error HexLengthInsufficient();

    /// @dev The length of the string is more than 32 bytes.
    error TooBigForSmallString();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The constant returned when the `search` is not found in the string.
    uint256 internal constant NOT_FOUND = type(uint256).max;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     DECIMAL OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the base 10 decimal representation of `value`.
    function toString(uint256 value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        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.
            str := add(mload(0x40), 0x80)
            // Update the free memory pointer to allocate.
            mstore(0x40, add(str, 0x20))
            // Zeroize the slot after the string.
            mstore(str, 0)

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

            let w := not(0) // Tsk.
            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for { let temp := value } 1 {} {
                str := add(str, w) // `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)
                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 Returns the base 10 decimal representation of `value`.
    function toString(int256 value) internal pure returns (string memory str) {
        if (value >= 0) {
            return toString(uint256(value));
        }
        unchecked {
            str = toString(~uint256(value) + 1);
        }
        /// @solidity memory-safe-assembly
        assembly {
            // We still have some spare memory space on the left,
            // as we have allocated 3 words (96 bytes) for up to 78 digits.
            let length := mload(str) // Load the string length.
            mstore(str, 0x2d) // Store the '-' character.
            str := sub(str, 1) // Move back the string pointer by a byte.
            mstore(str, add(length, 1)) // Update the string length.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   HEXADECIMAL OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the hexadecimal representation of `value`,
    /// left-padded to an input length of `length` bytes.
    /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
    /// giving a total length of `length * 2 + 2` bytes.
    /// Reverts if `length` is too small for the output to contain all the digits.
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value, length);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`,
    /// left-padded to an input length of `length` bytes.
    /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
    /// giving a total length of `length * 2` bytes.
    /// Reverts if `length` is too small for the output to contain all the digits.
    function toHexStringNoPrefix(uint256 value, uint256 length)
        internal
        pure
        returns (string memory str)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes
            // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length.
            // We add 0x20 to the total and round down to a multiple of 0x20.
            // (0x20 + 0x20 + 0x02 + 0x20) = 0x62.
            str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f)))
            // Allocate the memory.
            mstore(0x40, add(str, 0x20))
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end to calculate the length later.
            let end := str
            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            let start := sub(str, add(length, length))
            let w := not(1) // Tsk.
            let temp := value
            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for {} 1 {} {
                str := add(str, w) // `sub(str, 2)`.
                mstore8(add(str, 1), mload(and(temp, 15)))
                mstore8(str, mload(and(shr(4, temp), 15)))
                temp := shr(8, temp)
                if iszero(xor(str, start)) { break }
            }

            if temp {
                mstore(0x00, 0x2194895a) // `HexLengthInsufficient()`.
                revert(0x1c, 0x04)
            }

            // Compute the string's length.
            let strLength := sub(end, str)
            // Move the pointer and write the length.
            str := sub(str, 0x20)
            mstore(str, strLength)
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
    /// As address are 20 bytes long, the output will left-padded to have
    /// a length of `20 * 2 + 2` bytes.
    function toHexString(uint256 value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x".
    /// The output excludes leading "0" from the `toHexString` output.
    /// `0x00: "0x0", 0x01: "0x1", 0x12: "0x12", 0x123: "0x123"`.
    function toMinimalHexString(uint256 value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present.
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(add(str, o), 0x3078) // Write the "0x" prefix, accounting for leading zero.
            str := sub(add(str, o), 2) // Move the pointer, accounting for leading zero.
            mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output excludes leading "0" from the `toHexStringNoPrefix` output.
    /// `0x00: "0", 0x01: "1", 0x12: "12", 0x123: "123"`.
    function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present.
            let strLength := mload(str) // Get the length.
            str := add(str, o) // Move the pointer, accounting for leading zero.
            mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is encoded using 2 hexadecimal digits per byte.
    /// As address are 20 bytes long, the output will left-padded to have
    /// a length of `20 * 2` bytes.
    function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
            // 0x02 bytes for the prefix, and 0x40 bytes for the digits.
            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0.
            str := add(mload(0x40), 0x80)
            // Allocate the memory.
            mstore(0x40, add(str, 0x20))
            // Zeroize the slot after the string.
            mstore(str, 0)

            // Cache the end to calculate the length later.
            let end := str
            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            let w := not(1) // Tsk.
            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for { let temp := value } 1 {} {
                str := add(str, w) // `sub(str, 2)`.
                mstore8(add(str, 1), mload(and(temp, 15)))
                mstore8(str, mload(and(shr(4, temp), 15)))
                temp := shr(8, temp)
                if iszero(temp) { break }
            }

            // Compute the string's length.
            let strLength := sub(end, str)
            // Move the pointer and write the length.
            str := sub(str, 0x20)
            mstore(str, strLength)
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte,
    /// and the alphabets are capitalized conditionally according to
    /// https://eips.ethereum.org/EIPS/eip-55
    function toHexStringChecksummed(address value) internal pure returns (string memory str) {
        str = toHexString(value);
        /// @solidity memory-safe-assembly
        assembly {
            let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...`
            let o := add(str, 0x22)
            let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... `
            let t := shl(240, 136) // `0b10001000 << 240`
            for { let i := 0 } 1 {} {
                mstore(add(i, i), mul(t, byte(i, hashed)))
                i := add(i, 1)
                if eq(i, 20) { break }
            }
            mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))
            o := add(o, 0x20)
            mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
    function toHexString(address value) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(value);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hexadecimal representation of `value`.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexStringNoPrefix(address value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            str := mload(0x40)

            // Allocate the memory.
            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
            // 0x02 bytes for the prefix, and 0x28 bytes for the digits.
            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80.
            mstore(0x40, add(str, 0x80))

            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            str := add(str, 2)
            mstore(str, 40)

            let o := add(str, 0x20)
            mstore(add(o, 40), 0)

            value := shl(96, value)

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            for { let i := 0 } 1 {} {
                let p := add(o, add(i, i))
                let temp := byte(i, value)
                mstore8(add(p, 1), mload(and(temp, 15)))
                mstore8(p, mload(shr(4, temp)))
                i := add(i, 1)
                if eq(i, 20) { break }
            }
        }
    }

    /// @dev Returns the hex encoded string from the raw bytes.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexString(bytes memory raw) internal pure returns (string memory str) {
        str = toHexStringNoPrefix(raw);
        /// @solidity memory-safe-assembly
        assembly {
            let strLength := add(mload(str), 2) // Compute the length.
            mstore(str, 0x3078) // Write the "0x" prefix.
            str := sub(str, 2) // Move the pointer.
            mstore(str, strLength) // Write the length.
        }
    }

    /// @dev Returns the hex encoded string from the raw bytes.
    /// The output is encoded using 2 hexadecimal digits per byte.
    function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            let length := mload(raw)
            str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix.
            mstore(str, add(length, length)) // Store the length of the output.

            // Store "0123456789abcdef" in scratch space.
            mstore(0x0f, 0x30313233343536373839616263646566)

            let o := add(str, 0x20)
            let end := add(raw, length)

            for {} iszero(eq(raw, end)) {} {
                raw := add(raw, 1)
                mstore8(add(o, 1), mload(and(mload(raw), 15)))
                mstore8(o, mload(and(shr(4, mload(raw)), 15)))
                o := add(o, 2)
            }
            mstore(o, 0) // Zeroize the slot after the string.
            mstore(0x40, add(o, 0x20)) // Allocate the memory.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   RUNE STRING OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the number of UTF characters in the string.
    function runeCount(string memory s) internal pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            if mload(s) {
                mstore(0x00, div(not(0), 255))
                mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506)
                let o := add(s, 0x20)
                let end := add(o, mload(s))
                for { result := 1 } 1 { result := add(result, 1) } {
                    o := add(o, byte(0, mload(shr(250, mload(o)))))
                    if iszero(lt(o, end)) { break }
                }
            }
        }
    }

    /// @dev Returns if this string is a 7-bit ASCII string.
    /// (i.e. all characters codes are in [0..127])
    function is7BitASCII(string memory s) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            let mask := shl(7, div(not(0), 255))
            result := 1
            let n := mload(s)
            if n {
                let o := add(s, 0x20)
                let end := add(o, n)
                let last := mload(end)
                mstore(end, 0)
                for {} 1 {} {
                    if and(mask, mload(o)) {
                        result := 0
                        break
                    }
                    o := add(o, 0x20)
                    if iszero(lt(o, end)) { break }
                }
                mstore(end, last)
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   BYTE STRING OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // For performance and bytecode compactness, byte string operations are restricted
    // to 7-bit ASCII strings. All offsets are byte offsets, not UTF character offsets.
    // Usage of byte string operations on charsets with runes spanning two or more bytes
    // can lead to undefined behavior.

    /// @dev Returns `subject` all occurrences of `search` replaced with `replacement`.
    function replace(string memory subject, string memory search, string memory replacement)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            let searchLength := mload(search)
            let replacementLength := mload(replacement)

            subject := add(subject, 0x20)
            search := add(search, 0x20)
            replacement := add(replacement, 0x20)
            result := add(mload(0x40), 0x20)

            let subjectEnd := add(subject, subjectLength)
            if iszero(gt(searchLength, subjectLength)) {
                let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1)
                let h := 0
                if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }
                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
                let s := mload(search)
                for {} 1 {} {
                    let t := mload(subject)
                    // Whether the first `searchLength % 32` bytes of
                    // `subject` and `search` matches.
                    if iszero(shr(m, xor(t, s))) {
                        if h {
                            if iszero(eq(keccak256(subject, searchLength), h)) {
                                mstore(result, t)
                                result := add(result, 1)
                                subject := add(subject, 1)
                                if iszero(lt(subject, subjectSearchEnd)) { break }
                                continue
                            }
                        }
                        // Copy the `replacement` one word at a time.
                        for { let o := 0 } 1 {} {
                            mstore(add(result, o), mload(add(replacement, o)))
                            o := add(o, 0x20)
                            if iszero(lt(o, replacementLength)) { break }
                        }
                        result := add(result, replacementLength)
                        subject := add(subject, searchLength)
                        if searchLength {
                            if iszero(lt(subject, subjectSearchEnd)) { break }
                            continue
                        }
                    }
                    mstore(result, t)
                    result := add(result, 1)
                    subject := add(subject, 1)
                    if iszero(lt(subject, subjectSearchEnd)) { break }
                }
            }

            let resultRemainder := result
            result := add(mload(0x40), 0x20)
            let k := add(sub(resultRemainder, result), sub(subjectEnd, subject))
            // Copy the rest of the string one word at a time.
            for {} lt(subject, subjectEnd) {} {
                mstore(resultRemainder, mload(subject))
                resultRemainder := add(resultRemainder, 0x20)
                subject := add(subject, 0x20)
            }
            result := sub(result, 0x20)
            let last := add(add(result, 0x20), k) // Zeroize the slot after the string.
            mstore(last, 0)
            mstore(0x40, add(last, 0x20)) // Allocate the memory.
            mstore(result, k) // Store the length.
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from left to right, starting from `from`.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function indexOf(string memory subject, string memory search, uint256 from)
        internal
        pure
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for { let subjectLength := mload(subject) } 1 {} {
                if iszero(mload(search)) {
                    if iszero(gt(from, subjectLength)) {
                        result := from
                        break
                    }
                    result := subjectLength
                    break
                }
                let searchLength := mload(search)
                let subjectStart := add(subject, 0x20)

                result := not(0) // Initialize to `NOT_FOUND`.

                subject := add(subjectStart, from)
                let end := add(sub(add(subjectStart, subjectLength), searchLength), 1)

                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
                let s := mload(add(search, 0x20))

                if iszero(and(lt(subject, end), lt(from, subjectLength))) { break }

                if iszero(lt(searchLength, 0x20)) {
                    for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
                        if iszero(shr(m, xor(mload(subject), s))) {
                            if eq(keccak256(subject, searchLength), h) {
                                result := sub(subject, subjectStart)
                                break
                            }
                        }
                        subject := add(subject, 1)
                        if iszero(lt(subject, end)) { break }
                    }
                    break
                }
                for {} 1 {} {
                    if iszero(shr(m, xor(mload(subject), s))) {
                        result := sub(subject, subjectStart)
                        break
                    }
                    subject := add(subject, 1)
                    if iszero(lt(subject, end)) { break }
                }
                break
            }
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from left to right.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function indexOf(string memory subject, string memory search)
        internal
        pure
        returns (uint256 result)
    {
        result = indexOf(subject, search, 0);
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from right to left, starting from `from`.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function lastIndexOf(string memory subject, string memory search, uint256 from)
        internal
        pure
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for {} 1 {} {
                result := not(0) // Initialize to `NOT_FOUND`.
                let searchLength := mload(search)
                if gt(searchLength, mload(subject)) { break }
                let w := result

                let fromMax := sub(mload(subject), searchLength)
                if iszero(gt(fromMax, from)) { from := fromMax }

                let end := add(add(subject, 0x20), w)
                subject := add(add(subject, 0x20), from)
                if iszero(gt(subject, end)) { break }
                // As this function is not too often used,
                // we shall simply use keccak256 for smaller bytecode size.
                for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
                    if eq(keccak256(subject, searchLength), h) {
                        result := sub(subject, add(end, 1))
                        break
                    }
                    subject := add(subject, w) // `sub(subject, 1)`.
                    if iszero(gt(subject, end)) { break }
                }
                break
            }
        }
    }

    /// @dev Returns the byte index of the first location of `search` in `subject`,
    /// searching from right to left.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
    function lastIndexOf(string memory subject, string memory search)
        internal
        pure
        returns (uint256 result)
    {
        result = lastIndexOf(subject, search, uint256(int256(-1)));
    }

    /// @dev Returns true if `search` is found in `subject`, false otherwise.
    function contains(string memory subject, string memory search) internal pure returns (bool) {
        return indexOf(subject, search) != NOT_FOUND;
    }

    /// @dev Returns whether `subject` starts with `search`.
    function startsWith(string memory subject, string memory search)
        internal
        pure
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let searchLength := mload(search)
            // Just using keccak256 directly is actually cheaper.
            // forgefmt: disable-next-item
            result := and(
                iszero(gt(searchLength, mload(subject))),
                eq(
                    keccak256(add(subject, 0x20), searchLength),
                    keccak256(add(search, 0x20), searchLength)
                )
            )
        }
    }

    /// @dev Returns whether `subject` ends with `search`.
    function endsWith(string memory subject, string memory search)
        internal
        pure
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let searchLength := mload(search)
            let subjectLength := mload(subject)
            // Whether `search` is not longer than `subject`.
            let withinRange := iszero(gt(searchLength, subjectLength))
            // Just using keccak256 directly is actually cheaper.
            // forgefmt: disable-next-item
            result := and(
                withinRange,
                eq(
                    keccak256(
                        // `subject + 0x20 + max(subjectLength - searchLength, 0)`.
                        add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))),
                        searchLength
                    ),
                    keccak256(add(search, 0x20), searchLength)
                )
            )
        }
    }

    /// @dev Returns `subject` repeated `times`.
    function repeat(string memory subject, uint256 times)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            if iszero(or(iszero(times), iszero(subjectLength))) {
                subject := add(subject, 0x20)
                result := mload(0x40)
                let output := add(result, 0x20)
                for {} 1 {} {
                    // Copy the `subject` one word at a time.
                    for { let o := 0 } 1 {} {
                        mstore(add(output, o), mload(add(subject, o)))
                        o := add(o, 0x20)
                        if iszero(lt(o, subjectLength)) { break }
                    }
                    output := add(output, subjectLength)
                    times := sub(times, 1)
                    if iszero(times) { break }
                }
                mstore(output, 0) // Zeroize the slot after the string.
                let resultLength := sub(output, add(result, 0x20))
                mstore(result, resultLength) // Store the length.
                // Allocate the memory.
                mstore(0x40, add(result, add(resultLength, 0x20)))
            }
        }
    }

    /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function slice(string memory subject, uint256 start, uint256 end)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            if iszero(gt(subjectLength, end)) { end := subjectLength }
            if iszero(gt(subjectLength, start)) { start := subjectLength }
            if lt(start, end) {
                result := mload(0x40)
                let resultLength := sub(end, start)
                mstore(result, resultLength)
                subject := add(subject, start)
                let w := not(0x1f)
                // Copy the `subject` one word at a time, backwards.
                for { let o := and(add(resultLength, 0x1f), w) } 1 {} {
                    mstore(add(result, o), mload(add(subject, o)))
                    o := add(o, w) // `sub(o, 0x20)`.
                    if iszero(o) { break }
                }
                // Zeroize the slot after the string.
                mstore(add(add(result, 0x20), resultLength), 0)
                // Allocate memory for the length and the bytes,
                // rounded up to a multiple of 32.
                mstore(0x40, add(result, and(add(resultLength, 0x3f), w)))
            }
        }
    }

    /// @dev Returns a copy of `subject` sliced from `start` to the end of the string.
    /// `start` is a byte offset.
    function slice(string memory subject, uint256 start)
        internal
        pure
        returns (string memory result)
    {
        result = slice(subject, start, uint256(int256(-1)));
    }

    /// @dev Returns all the indices of `search` in `subject`.
    /// The indices are byte offsets.
    function indicesOf(string memory subject, string memory search)
        internal
        pure
        returns (uint256[] memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let subjectLength := mload(subject)
            let searchLength := mload(search)

            if iszero(gt(searchLength, subjectLength)) {
                subject := add(subject, 0x20)
                search := add(search, 0x20)
                result := add(mload(0x40), 0x20)

                let subjectStart := subject
                let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1)
                let h := 0
                if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }
                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
                let s := mload(search)
                for {} 1 {} {
                    let t := mload(subject)
                    // Whether the first `searchLength % 32` bytes of
                    // `subject` and `search` matches.
                    if iszero(shr(m, xor(t, s))) {
                        if h {
                            if iszero(eq(keccak256(subject, searchLength), h)) {
                                subject := add(subject, 1)
                                if iszero(lt(subject, subjectSearchEnd)) { break }
                                continue
                            }
                        }
                        // Append to `result`.
                        mstore(result, sub(subject, subjectStart))
                        result := add(result, 0x20)
                        // Advance `subject` by `searchLength`.
                        subject := add(subject, searchLength)
                        if searchLength {
                            if iszero(lt(subject, subjectSearchEnd)) { break }
                            continue
                        }
                    }
                    subject := add(subject, 1)
                    if iszero(lt(subject, subjectSearchEnd)) { break }
                }
                let resultEnd := result
                // Assign `result` to the free memory pointer.
                result := mload(0x40)
                // Store the length of `result`.
                mstore(result, shr(5, sub(resultEnd, add(result, 0x20))))
                // Allocate memory for result.
                // We allocate one more word, so this array can be recycled for {split}.
                mstore(0x40, add(resultEnd, 0x20))
            }
        }
    }

    /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string.
    function split(string memory subject, string memory delimiter)
        internal
        pure
        returns (string[] memory result)
    {
        uint256[] memory indices = indicesOf(subject, delimiter);
        /// @solidity memory-safe-assembly
        assembly {
            let w := not(0x1f)
            let indexPtr := add(indices, 0x20)
            let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1)))
            mstore(add(indicesEnd, w), mload(subject))
            mstore(indices, add(mload(indices), 1))
            let prevIndex := 0
            for {} 1 {} {
                let index := mload(indexPtr)
                mstore(indexPtr, 0x60)
                if iszero(eq(index, prevIndex)) {
                    let element := mload(0x40)
                    let elementLength := sub(index, prevIndex)
                    mstore(element, elementLength)
                    // Copy the `subject` one word at a time, backwards.
                    for { let o := and(add(elementLength, 0x1f), w) } 1 {} {
                        mstore(add(element, o), mload(add(add(subject, prevIndex), o)))
                        o := add(o, w) // `sub(o, 0x20)`.
                        if iszero(o) { break }
                    }
                    // Zeroize the slot after the string.
                    mstore(add(add(element, 0x20), elementLength), 0)
                    // Allocate memory for the length and the bytes,
                    // rounded up to a multiple of 32.
                    mstore(0x40, add(element, and(add(elementLength, 0x3f), w)))
                    // Store the `element` into the array.
                    mstore(indexPtr, element)
                }
                prevIndex := add(index, mload(delimiter))
                indexPtr := add(indexPtr, 0x20)
                if iszero(lt(indexPtr, indicesEnd)) { break }
            }
            result := indices
            if iszero(mload(delimiter)) {
                result := add(indices, 0x20)
                mstore(result, sub(mload(indices), 2))
            }
        }
    }

    /// @dev Returns a concatenated string of `a` and `b`.
    /// Cheaper than `string.concat()` and does not de-align the free memory pointer.
    function concat(string memory a, string memory b)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let w := not(0x1f)
            result := mload(0x40)
            let aLength := mload(a)
            // Copy `a` one word at a time, backwards.
            for { let o := and(add(aLength, 0x20), w) } 1 {} {
                mstore(add(result, o), mload(add(a, o)))
                o := add(o, w) // `sub(o, 0x20)`.
                if iszero(o) { break }
            }
            let bLength := mload(b)
            let output := add(result, aLength)
            // Copy `b` one word at a time, backwards.
            for { let o := and(add(bLength, 0x20), w) } 1 {} {
                mstore(add(output, o), mload(add(b, o)))
                o := add(o, w) // `sub(o, 0x20)`.
                if iszero(o) { break }
            }
            let totalLength := add(aLength, bLength)
            let last := add(add(result, 0x20), totalLength)
            // Zeroize the slot after the string.
            mstore(last, 0)
            // Stores the length.
            mstore(result, totalLength)
            // Allocate memory for the length and the bytes,
            // rounded up to a multiple of 32.
            mstore(0x40, and(add(last, 0x1f), w))
        }
    }

    /// @dev Returns a copy of the string in either lowercase or UPPERCASE.
    /// WARNING! This function is only compatible with 7-bit ASCII strings.
    function toCase(string memory subject, bool toUpper)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let length := mload(subject)
            if length {
                result := add(mload(0x40), 0x20)
                subject := add(subject, 1)
                let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff)
                let w := not(0)
                for { let o := length } 1 {} {
                    o := add(o, w)
                    let b := and(0xff, mload(add(subject, o)))
                    mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20)))
                    if iszero(o) { break }
                }
                result := mload(0x40)
                mstore(result, length) // Store the length.
                let last := add(add(result, 0x20), length)
                mstore(last, 0) // Zeroize the slot after the string.
                mstore(0x40, add(last, 0x20)) // Allocate the memory.
            }
        }
    }

    /// @dev Returns a string from a small bytes32 string.
    /// `s` must be null-terminated, or behavior will be undefined.
    function fromSmallString(bytes32 s) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let n := 0
            for {} byte(n, s) { n := add(n, 1) } {} // Scan for '\0'.
            mstore(result, n)
            let o := add(result, 0x20)
            mstore(o, s)
            mstore(add(o, n), 0)
            mstore(0x40, add(result, 0x40))
        }
    }

    /// @dev Returns the small string, with all bytes after the first null byte zeroized.
    function normalizeSmallString(bytes32 s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            for {} byte(result, s) { result := add(result, 1) } {} // Scan for '\0'.
            mstore(0x00, s)
            mstore(result, 0x00)
            result := mload(0x00)
        }
    }

    /// @dev Returns the string as a normalized null-terminated small string.
    function toSmallString(string memory s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(s)
            if iszero(lt(result, 33)) {
                mstore(0x00, 0xec92f9a3) // `TooBigForSmallString()`.
                revert(0x1c, 0x04)
            }
            result := shl(shl(3, sub(32, result)), mload(add(s, result)))
        }
    }

    /// @dev Returns a lowercased copy of the string.
    /// WARNING! This function is only compatible with 7-bit ASCII strings.
    function lower(string memory subject) internal pure returns (string memory result) {
        result = toCase(subject, false);
    }

    /// @dev Returns an UPPERCASED copy of the string.
    /// WARNING! This function is only compatible with 7-bit ASCII strings.
    function upper(string memory subject) internal pure returns (string memory result) {
        result = toCase(subject, true);
    }

    /// @dev Escapes the string to be used within HTML tags.
    function escapeHTML(string memory s) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            let end := add(s, mload(s))
            result := add(mload(0x40), 0x20)
            // Store the bytes of the packed offsets and strides into the scratch space.
            // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6.
            mstore(0x1f, 0x900094)
            mstore(0x08, 0xc0000000a6ab)
            // Store "&quot;&amp;&#39;&lt;&gt;" into the scratch space.
            mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b))
            for {} iszero(eq(s, end)) {} {
                s := add(s, 1)
                let c := and(mload(s), 0xff)
                // Not in `["\"","'","&","<",">"]`.
                if iszero(and(shl(c, 1), 0x500000c400000000)) {
                    mstore8(result, c)
                    result := add(result, 1)
                    continue
                }
                let t := shr(248, mload(c))
                mstore(result, mload(and(t, 0x1f)))
                result := add(result, shr(5, t))
            }
            let last := result
            mstore(last, 0) // Zeroize the slot after the string.
            result := mload(0x40)
            mstore(result, sub(last, add(result, 0x20))) // Store the length.
            mstore(0x40, add(last, 0x20)) // Allocate the memory.
        }
    }

    /// @dev Escapes the string to be used within double-quotes in a JSON.
    /// If `addDoubleQuotes` is true, the result will be enclosed in double-quotes.
    function escapeJSON(string memory s, bool addDoubleQuotes)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let end := add(s, mload(s))
            result := add(mload(0x40), 0x20)
            if addDoubleQuotes {
                mstore8(result, 34)
                result := add(1, result)
            }
            // Store "\\u0000" in scratch space.
            // Store "0123456789abcdef" in scratch space.
            // Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`.
            // into the scratch space.
            mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672)
            // Bitmask for detecting `["\"","\\"]`.
            let e := or(shl(0x22, 1), shl(0x5c, 1))
            for {} iszero(eq(s, end)) {} {
                s := add(s, 1)
                let c := and(mload(s), 0xff)
                if iszero(lt(c, 0x20)) {
                    if iszero(and(shl(c, 1), e)) {
                        // Not in `["\"","\\"]`.
                        mstore8(result, c)
                        result := add(result, 1)
                        continue
                    }
                    mstore8(result, 0x5c) // "\\".
                    mstore8(add(result, 1), c)
                    result := add(result, 2)
                    continue
                }
                if iszero(and(shl(c, 1), 0x3700)) {
                    // Not in `["\b","\t","\n","\f","\d"]`.
                    mstore8(0x1d, mload(shr(4, c))) // Hex value.
                    mstore8(0x1e, mload(and(c, 15))) // Hex value.
                    mstore(result, mload(0x19)) // "\\u00XX".
                    result := add(result, 6)
                    continue
                }
                mstore8(result, 0x5c) // "\\".
                mstore8(add(result, 1), mload(add(c, 8)))
                result := add(result, 2)
            }
            if addDoubleQuotes {
                mstore8(result, 34)
                result := add(1, result)
            }
            let last := result
            mstore(last, 0) // Zeroize the slot after the string.
            result := mload(0x40)
            mstore(result, sub(last, add(result, 0x20))) // Store the length.
            mstore(0x40, add(last, 0x20)) // Allocate the memory.
        }
    }

    /// @dev Escapes the string to be used within double-quotes in a JSON.
    function escapeJSON(string memory s) internal pure returns (string memory result) {
        result = escapeJSON(s, false);
    }

    /// @dev Returns whether `a` equals `b`.
    function eq(string memory a, string memory b) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b)))
        }
    }

    /// @dev Returns whether `a` equals `b`, where `b` is a null-terminated small string.
    function eqs(string memory a, bytes32 b) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            // These should be evaluated on compile time, as far as possible.
            let m := not(shl(7, div(not(iszero(b)), 255))) // `0x7f7f ...`.
            let x := not(or(m, or(b, add(m, and(b, m)))))
            let r := shl(7, iszero(iszero(shr(128, x))))
            r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x))))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            // forgefmt: disable-next-item
            result := gt(eq(mload(a), add(iszero(x), xor(31, shr(3, r)))),
                xor(shr(add(8, r), b), shr(add(8, r), mload(add(a, 0x20)))))
        }
    }

    /// @dev Packs a single string with its length into a single word.
    /// Returns `bytes32(0)` if the length is zero or greater than 31.
    function packOne(string memory a) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // We don't need to zero right pad the string,
            // since this is our own custom non-standard packing scheme.
            result :=
                mul(
                    // Load the length and the bytes.
                    mload(add(a, 0x1f)),
                    // `length != 0 && length < 32`. Abuses underflow.
                    // Assumes that the length is valid and within the block gas limit.
                    lt(sub(mload(a), 1), 0x1f)
                )
        }
    }

    /// @dev Unpacks a string packed using {packOne}.
    /// Returns the empty string if `packed` is `bytes32(0)`.
    /// If `packed` is not an output of {packOne}, the output behavior is undefined.
    function unpackOne(bytes32 packed) internal pure returns (string memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Grab the free memory pointer.
            result := mload(0x40)
            // Allocate 2 words (1 for the length, 1 for the bytes).
            mstore(0x40, add(result, 0x40))
            // Zeroize the length slot.
            mstore(result, 0)
            // Store the length and bytes.
            mstore(add(result, 0x1f), packed)
            // Right pad with zeroes.
            mstore(add(add(result, 0x20), mload(result)), 0)
        }
    }

    /// @dev Packs two strings with their lengths into a single word.
    /// Returns `bytes32(0)` if combined length is zero or greater than 30.
    function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let aLength := mload(a)
            // We don't need to zero right pad the strings,
            // since this is our own custom non-standard packing scheme.
            result :=
                mul(
                    // Load the length and the bytes of `a` and `b`.
                    or(
                        shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))),
                        mload(sub(add(b, 0x1e), aLength))
                    ),
                    // `totalLength != 0 && totalLength < 31`. Abuses underflow.
                    // Assumes that the lengths are valid and within the block gas limit.
                    lt(sub(add(aLength, mload(b)), 1), 0x1e)
                )
        }
    }

    /// @dev Unpacks strings packed using {packTwo}.
    /// Returns the empty strings if `packed` is `bytes32(0)`.
    /// If `packed` is not an output of {packTwo}, the output behavior is undefined.
    function unpackTwo(bytes32 packed)
        internal
        pure
        returns (string memory resultA, string memory resultB)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Grab the free memory pointer.
            resultA := mload(0x40)
            resultB := add(resultA, 0x40)
            // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words.
            mstore(0x40, add(resultB, 0x40))
            // Zeroize the length slots.
            mstore(resultA, 0)
            mstore(resultB, 0)
            // Store the lengths and bytes.
            mstore(add(resultA, 0x1f), packed)
            mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA))))
            // Right pad with zeroes.
            mstore(add(add(resultA, 0x20), mload(resultA)), 0)
            mstore(add(add(resultB, 0x20), mload(resultB)), 0)
        }
    }

    /// @dev Directly returns `a` without copying.
    function directReturn(string memory a) internal pure {
        assembly {
            // Assumes that the string does not start from the scratch space.
            let retStart := sub(a, 0x20)
            let retSize := add(mload(a), 0x40)
            // Right pad with zeroes. Just in case the string is produced
            // by a method that doesn't zero right pad.
            mstore(add(retStart, retSize), 0)
            // Store the return offset.
            mstore(retStart, 0x20)
            // End the transaction, returning the string.
            return(retStart, retSize)
        }
    }
}

// lib/solady/src/utils/MerkleProofLib.sol

/// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol)
library MerkleProofLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*            MERKLE PROOF VERIFICATION OPERATIONS            */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf)
        internal
        pure
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if mload(proof) {
                // Initialize `offset` to the offset of `proof` elements in memory.
                let offset := add(proof, 0x20)
                // Left shift by 5 is equivalent to multiplying by 0x20.
                let end := add(offset, shl(5, mload(proof)))
                // Iterate over proof elements to compute root hash.
                for {} 1 {} {
                    // Slot of `leaf` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(leaf, mload(offset)))
                    // Store elements to hash contiguously in scratch space.
                    // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
                    mstore(scratch, leaf)
                    mstore(xor(scratch, 0x20), mload(offset))
                    // Reuse `leaf` to store the hash to reduce stack operations.
                    leaf := keccak256(0x00, 0x40)
                    offset := add(offset, 0x20)
                    if iszero(lt(offset, end)) { break }
                }
            }
            isValid := eq(leaf, root)
        }
    }

    /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf)
        internal
        pure
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if proof.length {
                // Left shift by 5 is equivalent to multiplying by 0x20.
                let end := add(proof.offset, shl(5, proof.length))
                // Initialize `offset` to the offset of `proof` in the calldata.
                let offset := proof.offset
                // Iterate over proof elements to compute root hash.
                for {} 1 {} {
                    // Slot of `leaf` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(leaf, calldataload(offset)))
                    // Store elements to hash contiguously in scratch space.
                    // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
                    mstore(scratch, leaf)
                    mstore(xor(scratch, 0x20), calldataload(offset))
                    // Reuse `leaf` to store the hash to reduce stack operations.
                    leaf := keccak256(0x00, 0x40)
                    offset := add(offset, 0x20)
                    if iszero(lt(offset, end)) { break }
                }
            }
            isValid := eq(leaf, root)
        }
    }

    /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
    /// given `proof` and `flags`.
    ///
    /// Note:
    /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
    ///   will always return false.
    /// - The sum of the lengths of `proof` and `leaves` must never overflow.
    /// - Any non-zero word in the `flags` array is treated as true.
    /// - The memory offset of `proof` must be non-zero
    ///   (i.e. `proof` is not pointing to the scratch space).
    function verifyMultiProof(
        bytes32[] memory proof,
        bytes32 root,
        bytes32[] memory leaves,
        bool[] memory flags
    ) internal pure returns (bool isValid) {
        // Rebuilds the root by consuming and producing values on a queue.
        // The queue starts with the `leaves` array, and goes into a `hashes` array.
        // After the process, the last element on the queue is verified
        // to be equal to the `root`.
        //
        // The `flags` array denotes whether the sibling
        // should be popped from the queue (`flag == true`), or
        // should be popped from the `proof` (`flag == false`).
        /// @solidity memory-safe-assembly
        assembly {
            // Cache the lengths of the arrays.
            let leavesLength := mload(leaves)
            let proofLength := mload(proof)
            let flagsLength := mload(flags)

            // Advance the pointers of the arrays to point to the data.
            leaves := add(0x20, leaves)
            proof := add(0x20, proof)
            flags := add(0x20, flags)

            // If the number of flags is correct.
            for {} eq(add(leavesLength, proofLength), add(flagsLength, 1)) {} {
                // For the case where `proof.length + leaves.length == 1`.
                if iszero(flagsLength) {
                    // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
                    isValid := eq(mload(xor(leaves, mul(xor(proof, leaves), proofLength))), root)
                    break
                }

                // The required final proof offset if `flagsLength` is not zero, otherwise zero.
                let proofEnd := add(proof, shl(5, proofLength))
                // We can use the free memory space for the queue.
                // We don't need to allocate, since the queue is temporary.
                let hashesFront := mload(0x40)
                // Copy the leaves into the hashes.
                // Sometimes, a little memory expansion costs less than branching.
                // Should cost less, even with a high free memory offset of 0x7d00.
                leavesLength := shl(5, leavesLength)
                for { let i := 0 } iszero(eq(i, leavesLength)) { i := add(i, 0x20) } {
                    mstore(add(hashesFront, i), mload(add(leaves, i)))
                }
                // Compute the back of the hashes.
                let hashesBack := add(hashesFront, leavesLength)
                // This is the end of the memory for the queue.
                // We recycle `flagsLength` to save on stack variables (sometimes save gas).
                flagsLength := add(hashesBack, shl(5, flagsLength))

                for {} 1 {} {
                    // Pop from `hashes`.
                    let a := mload(hashesFront)
                    // Pop from `hashes`.
                    let b := mload(add(hashesFront, 0x20))
                    hashesFront := add(hashesFront, 0x40)

                    // If the flag is false, load the next proof,
                    // else, pops from the queue.
                    if iszero(mload(flags)) {
                        // Loads the next proof.
                        b := mload(proof)
                        proof := add(proof, 0x20)
                        // Unpop from `hashes`.
                        hashesFront := sub(hashesFront, 0x20)
                    }

                    // Advance to the next flag.
                    flags := add(flags, 0x20)

                    // Slot of `a` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(a, b))
                    // Hash the scratch space and push the result onto the queue.
                    mstore(scratch, a)
                    mstore(xor(scratch, 0x20), b)
                    mstore(hashesBack, keccak256(0x00, 0x40))
                    hashesBack := add(hashesBack, 0x20)
                    if iszero(lt(hashesBack, flagsLength)) { break }
                }
                isValid :=
                    and(
                        // Checks if the last value in the queue is same as the root.
                        eq(mload(sub(hashesBack, 0x20)), root),
                        // And whether all the proofs are used, if required.
                        eq(proofEnd, proof)
                    )
                break
            }
        }
    }

    /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
    /// given `proof` and `flags`.
    ///
    /// Note:
    /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
    ///   will always return false.
    /// - Any non-zero word in the `flags` array is treated as true.
    /// - The calldata offset of `proof` must be non-zero
    ///   (i.e. `proof` is from a regular Solidity function with a 4-byte selector).
    function verifyMultiProofCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32[] calldata leaves,
        bool[] calldata flags
    ) internal pure returns (bool isValid) {
        // Rebuilds the root by consuming and producing values on a queue.
        // The queue starts with the `leaves` array, and goes into a `hashes` array.
        // After the process, the last element on the queue is verified
        // to be equal to the `root`.
        //
        // The `flags` array denotes whether the sibling
        // should be popped from the queue (`flag == true`), or
        // should be popped from the `proof` (`flag == false`).
        /// @solidity memory-safe-assembly
        assembly {
            // If the number of flags is correct.
            for {} eq(add(leaves.length, proof.length), add(flags.length, 1)) {} {
                // For the case where `proof.length + leaves.length == 1`.
                if iszero(flags.length) {
                    // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
                    // forgefmt: disable-next-item
                    isValid := eq(
                        calldataload(
                            xor(leaves.offset, mul(xor(proof.offset, leaves.offset), proof.length))
                        ),
                        root
                    )
                    break
                }

                // The required final proof offset if `flagsLength` is not zero, otherwise zero.
                let proofEnd := add(proof.offset, shl(5, proof.length))
                // We can use the free memory space for the queue.
                // We don't need to allocate, since the queue is temporary.
                let hashesFront := mload(0x40)
                // Copy the leaves into the hashes.
                // Sometimes, a little memory expansion costs less than branching.
                // Should cost less, even with a high free memory offset of 0x7d00.
                calldatacopy(hashesFront, leaves.offset, shl(5, leaves.length))
                // Compute the back of the hashes.
                let hashesBack := add(hashesFront, shl(5, leaves.length))
                // This is the end of the memory for the queue.
                // We recycle `flagsLength` to save on stack variables (sometimes save gas).
                flags.length := add(hashesBack, shl(5, flags.length))

                // We don't need to make a copy of `proof.offset` or `flags.offset`,
                // as they are pass-by-value (this trick may not always save gas).

                for {} 1 {} {
                    // Pop from `hashes`.
                    let a := mload(hashesFront)
                    // Pop from `hashes`.
                    let b := mload(add(hashesFront, 0x20))
                    hashesFront := add(hashesFront, 0x40)

                    // If the flag is false, load the next proof,
                    // else, pops from the queue.
                    if iszero(calldataload(flags.offset)) {
                        // Loads the next proof.
                        b := calldataload(proof.offset)
                        proof.offset := add(proof.offset, 0x20)
                        // Unpop from `hashes`.
                        hashesFront := sub(hashesFront, 0x20)
                    }

                    // Advance to the next flag offset.
                    flags.offset := add(flags.offset, 0x20)

                    // Slot of `a` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(a, b))
                    // Hash the scratch space and push the result onto the queue.
                    mstore(scratch, a)
                    mstore(xor(scratch, 0x20), b)
                    mstore(hashesBack, keccak256(0x00, 0x40))
                    hashesBack := add(hashesBack, 0x20)
                    if iszero(lt(hashesBack, flags.length)) { break }
                }
                isValid :=
                    and(
                        // Checks if the last value in the queue is same as the root.
                        eq(mload(sub(hashesBack, 0x20)), root),
                        // And whether all the proofs are used, if required.
                        eq(proofEnd, proof.offset)
                    )
                break
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes32 array.
    function emptyProof() internal pure returns (bytes32[] calldata proof) {
        /// @solidity memory-safe-assembly
        assembly {
            proof.length := 0
        }
    }

    /// @dev Returns an empty calldata bytes32 array.
    function emptyLeaves() internal pure returns (bytes32[] calldata leaves) {
        /// @solidity memory-safe-assembly
        assembly {
            leaves.length := 0
        }
    }

    /// @dev Returns an empty calldata bool array.
    function emptyFlags() internal pure returns (bool[] calldata flags) {
        /// @solidity memory-safe-assembly
        assembly {
            flags.length := 0
        }
    }
}

// lib/solady/src/utils/ReentrancyGuard.sol

/// @notice Reentrancy guard mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Unauthorized reentrant call.
    error Reentrancy();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to: `uint72(bytes9(keccak256("_REENTRANCY_GUARD_SLOT")))`.
    /// 9 bytes is large enough to avoid collisions with lower slots,
    /// but not too large to result in excessive bytecode bloat.
    uint256 private constant _REENTRANCY_GUARD_SLOT = 0x929eee149b4bd21268;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      REENTRANCY GUARD                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Guards a function from reentrancy.
    modifier nonReentrant() virtual {
        /// @solidity memory-safe-assembly
        assembly {
            if eq(sload(_REENTRANCY_GUARD_SLOT), address()) {
                mstore(0x00, 0xab143c06) // `Reentrancy()`.
                revert(0x1c, 0x04)
            }
            sstore(_REENTRANCY_GUARD_SLOT, address())
        }
        _;
        /// @solidity memory-safe-assembly
        assembly {
            sstore(_REENTRANCY_GUARD_SLOT, codesize())
        }
    }

    /// @dev Guards a view function from read-only reentrancy.
    modifier nonReadReentrant() virtual {
        /// @solidity memory-safe-assembly
        assembly {
            if eq(sload(_REENTRANCY_GUARD_SLOT), address()) {
                mstore(0x00, 0xab143c06) // `Reentrancy()`.
                revert(0x1c, 0x04)
            }
        }
        _;
    }
}

// src/Builder.sol

/*
                    
                             ..',;::cccccc::;;,...                              
                       ..;coxk0KKKXXKKKKKKKKKK00Okdoc,..                        
                    ':ok0XXXXXXXXXXKKKKKKKKKKKKKKK0000Oxl;.                     
                .,lkKXXXXXXXXXXXXXXKKKKKKKKKKKKKKK00000000Odc'.                 
              .ckKNXNXXXXXXXXXXXXXXKKKKKKKKKKKKKKK00000000000Od:.               
            ,o0NNNNNNNNXXXXXXXXXXXXKKKKKKKKKKKKKK00000000000000Okl'             
          'dKNNNNNNNNNNXXXXXXXXXXXXKKKKKKKKKKKKKK0000000000000OOOOkl'           
        .oKNNNNNNNNNNNNNXXXXXXXXXXXKKKKKKKKKKKKK0000000000000OOOOOOOkc.         
       ;ONNNNNNNNNNNNNNNNNXXXXXXXXXXKKKKKKKKKKK0000000000000OOOOOOOOOOd,        
     .lKWNNNNNNNNNNNNNNNNNXXXXXXXXXXXKKKKKKKKK000000000000OOOOOOOOOOOOOk:.      
    .dXWWWNWNNNNNNNNNNNNNNNNXXXXXXXXXKKKKKKKKK0000000000OOOOOOOOOOOOOOOOkc.     
   .dNWWWWWWWWWNNNNNNNNNNNNNNXXXXXXXXKKKKKKKK000000000OOOOOOOOOOOOOOOOOOOkc.    
  .oNWWWWWWWWWWWWWNNNNNNNNNNNNXXXXXXXKKKKKKK000000000OOOOOOOOOOOOOOOOOkkkkkc.   
  :XWWWWWWWWWWWWWWWWNNNNNNNNNNNXXXXXXKKKKKKK0000000OOOOOOOOOOOOOOOOOkkkkkkkx:.  
 'OWWWWWWWWWWWWWWWWWWWWWNNNNNNNNXXXXXKKKKKK000000OOOOOOOOOOOOOOkkkkkkkkkkkkkd.  
.lNWWWWWWWWWWWWWWWWWWWWWWWWNNNNNNNXXXXKKKKK00000OOOOOOOOOOOkkkkkkkkkkkkkkkkkx:  
cOWMMWWWWWWWWWWWWWWWWWWWWWWWWNNNNNNXXXKKKK0000OOOOOOOOOkkkkkkkkkkkkkkkkkkkkkko. 
dXMMMMMMMMMMMMMWWWWWWWWWWWWWWWWWWNNNNXKKK000OOOOOOkkkkkkkkkkkkkkkkkkkkkkkkkkkd' 
dXMMMMMMMMMMMMMMMMMMMMMMMMWWWWWWWWWNNNXK00OOOOkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkx; 
ok00000000000000000000000   BASE IS FOR BUILDERS    kkkkkkkkkkxxxkkkkxxxxxxxxx; 
::;;;;;;;;;;;;;;;;;;;;;;;;;::::::::::clodddxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; 
;,;;;;;;;;;;;;;;;;;;;;;;;;;::::::::cccllloooodddddddxxxxxxxxxxxxxxxxxxxxxxxxxo. 
'';;;;;;;;;;;;;;;;;;;;;::::::::::cccccllllooooodddddddddxxxxxxxxxxxxxxxxxxxxxc. 
..,;;;;;;;;;;;;;;;::::::::::::::cccccllllllooooodddddddddddddxxxxxxxxxxxxxxxd,  
  .;;;;;;;;;;:::::::::::::::::ccccccclllllloooooooddddddddddddddddxxxxxxxxxxc.  
   ';;;;;;:::::::::::::::::::ccccccccllllllooooooooodddddddddddddddddxxxxxxl'   
   .,::::::::::::::::::::::cccccccccclllllllooooooooooddddddddddddddddddddo'    
    .,:::::::::::::::::::ccccccccccclllllllloooooooooooddddddddddddddddddo'     
     .,:::::::::::::::::ccccccccccccllllllllloooooooooooodddddddddddddddl'      
      .';:::::::::::::cccccccccccccllllllllllloooooooooooooddddddddddddc.       
        .;::::::::::cccccccccccccccllllllllllloooooooooooooodddddddddl,.        
         .';:::::::ccccccccccccccccllllllllllllooooooooooooooddddddo:.          
           .';::::cccccccccccccccccllllllllllllooooozenoooooooodoo:.            
             .';:ccccccccccccccccclllllllllllllloooiluvuoooooool;.              
                .,::ccccccccccccccllllllllllllllooooooooooool:'.                
                   .';:ccccccccccllllllllllllllllloooooolc;'.                   
                      ..';:cccccllllllllllllllllloolc:,'.                       
                          ....',,;:::cccccc:::;,,'...                           
                                       .                
*/

contract Builder is ERC721, Ownable, ReentrancyGuard {
    using LibString for uint256;

    error AlreadyClaimed(address minter);
    error DoesNotAcceptEther();
    error InvalidProof();
    error NonexistentToken(uint256 tokenId);
    error TransferDisabled();

    uint256 private lastId;
    string public baseURI;
    bytes32 public merkleRoot;
    mapping(address => bool) public hasClaimed;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          INIT                              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    constructor(address _owner, string memory _baseURI, bytes32 _root) {
        _initializeOwner(_owner);
        baseURI = _baseURI;
        merkleRoot = _root;
    }

    receive() external payable {
        revert DoesNotAcceptEther();
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          MODIFIERS                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    modifier hasNotClaimed() {
        if (hasClaimed[msg.sender]) revert AlreadyClaimed(msg.sender);
        _;
    }

    modifier isValidMerkleProof(bytes32[] calldata proof) {
        if (!MerkleProofLib.verifyCalldata(proof, merkleRoot, keccak256(abi.encodePacked(msg.sender)))) {
            revert InvalidProof();
        }        
        _;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC721 METADATA                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the token collection name.
    function name() public pure override returns (string memory) {
        return "Base Builder NFT";
    }

    /// @dev Returns the token collection symbol.
    function symbol() public pure override returns (string memory) {
        return "BASEBUILDER";
    }

    /// @dev Returns the Uniform Resource Identifier (URI) for token `id`.
    ///
    /// @param id uint256 ID of the token to query.
    function tokenURI(uint256 id) public view override returns (string memory) {
        if (!_exists(id)) revert NonexistentToken(id);

        return baseURI;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      EXTERNAL                              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function mint(bytes32[] calldata proof) external nonReentrant hasNotClaimed isValidMerkleProof(proof) {
        hasClaimed[msg.sender] = true;
        lastId++;
        _safeMint(msg.sender, lastId);
    }

    function transferFrom(address, address, uint256) public payable override {
        revert TransferDisabled();
    }

    function safeTransferFrom(address, address, uint256) public payable override {
        revert TransferDisabled();
    }

    function safeTransferFrom(address, address, uint256, bytes calldata) public payable override {
        revert TransferDisabled();
    }

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

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      RESTRICTED                            */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function setBaseURI(string memory _baseURI) external onlyOwner {
        baseURI = _baseURI;
    }

    function setMerkleRoot(bytes32 _root) external onlyOwner {
        merkleRoot = _root;
    }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"string","name":"_baseURI","type":"string"},{"internalType":"bytes32","name":"_root","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccountBalanceOverflow","type":"error"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"AlreadyClaimed","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"DoesNotAcceptEther","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NonexistentToken","type":"error"},{"inputs":[],"name":"NotOwnerNorApproved","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"TokenAlreadyExists","type":"error"},{"inputs":[],"name":"TokenDoesNotExist","type":"error"},{"inputs":[],"name":"TransferDisabled","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","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":"isApproved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"isApproved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_root","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561000f575f80fd5b506040516122f83803806122f883398181016040528101906100319190610319565b6100408361005f60201b60201c565b816001908161004f9190610592565b5080600281905550505050610661565b61006d61013b60201b60201c565b156100e5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278054156100a757630dc149f05f526004601cfd5b8160601b60601c9150811560ff1b82178155815f7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a350610138565b8060601b60601c9050807fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392755805f7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a35b50565b5f90565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61017982610150565b9050919050565b6101898161016f565b8114610193575f80fd5b50565b5f815190506101a481610180565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6101f8826101b2565b810181811067ffffffffffffffff82111715610217576102166101c2565b5b80604052505050565b5f61022961013f565b905061023582826101ef565b919050565b5f67ffffffffffffffff821115610254576102536101c2565b5b61025d826101b2565b9050602081019050919050565b8281835e5f83830152505050565b5f61028a6102858461023a565b610220565b9050828152602081018484840111156102a6576102a56101ae565b5b6102b184828561026a565b509392505050565b5f82601f8301126102cd576102cc6101aa565b5b81516102dd848260208601610278565b91505092915050565b5f819050919050565b6102f8816102e6565b8114610302575f80fd5b50565b5f81519050610313816102ef565b92915050565b5f805f606084860312156103305761032f610148565b5b5f61033d86828701610196565b935050602084015167ffffffffffffffff81111561035e5761035d61014c565b5b61036a868287016102b9565b925050604061037b86828701610305565b9150509250925092565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806103d357607f821691505b6020821081036103e6576103e561038f565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026104487fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261040d565b610452868361040d565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f61049661049161048c8461046a565b610473565b61046a565b9050919050565b5f819050919050565b6104af8361047c565b6104c36104bb8261049d565b848454610419565b825550505050565b5f90565b6104d76104cb565b6104e28184846104a6565b505050565b5b81811015610505576104fa5f826104cf565b6001810190506104e8565b5050565b601f82111561054a5761051b816103ec565b610524846103fe565b81016020851015610533578190505b61054761053f856103fe565b8301826104e7565b50505b505050565b5f82821c905092915050565b5f61056a5f198460080261054f565b1980831691505092915050565b5f610582838361055b565b9150826002028217905092915050565b61059b82610385565b67ffffffffffffffff8111156105b4576105b36101c2565b5b6105be82546103bc565b6105c9828285610509565b5f60209050601f8311600181146105fa575f84156105e8578287015190505b6105f28582610577565b865550610659565b601f198416610608866103ec565b5f5b8281101561062f5784890151825560018201915060208501945060208101905061060a565b8683101561064c5784890151610648601f89168261055b565b8355505b6001600288020188555050505b505050505050565b611c8a8061066e5f395ff3fe60806040526004361061019f575f3560e01c806370a08231116100eb578063b77a147b11610089578063e985e9c511610063578063e985e9c51461056c578063f04e283e146105a8578063f2fde38b146105c4578063fee81cf4146105e0576101d6565b8063b77a147b146104ec578063b88d4fde14610514578063c87b56dd14610530576101d6565b80637cb64759116100c55780637cb64759146104485780638da5cb5b1461047057806395d89b411461049a578063a22cb465146104c4576101d6565b806370a08231146103c6578063715018a61461040257806373b2e80e1461040c576101d6565b8063256929621161015857806354d1f13d1161013257806354d1f13d1461032e57806355f804b3146103385780636352211e146103605780636c0360eb1461039c576101d6565b806325692962146102de5780632eb4a7ab146102e857806342842e0e14610312576101d6565b806301ffc9a7146101da57806306fdde0314610216578063081812fc14610240578063095ea7b31461027c57806318160ddd1461029857806323b872dd146102c2576101d6565b366101d6576040517f38ea61ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80fd5b3480156101e5575f80fd5b5061020060048036038101906101fb91906111e9565b61061c565b60405161020d919061122e565b60405180910390f35b348015610221575f80fd5b5061022a610640565b60405161023791906112b7565b60405180910390f35b34801561024b575f80fd5b506102666004803603810190610261919061130a565b61067d565b6040516102739190611374565b60405180910390f35b610296600480360381019061029191906113b7565b6106d0565b005b3480156102a3575f80fd5b506102ac6106df565b6040516102b99190611404565b60405180910390f35b6102dc60048036038101906102d7919061141d565b6106e7565b005b6102e6610719565b005b3480156102f3575f80fd5b506102fc61076a565b6040516103099190611485565b60405180910390f35b61032c6004803603810190610327919061141d565b610770565b005b6103366107a2565b005b348015610343575f80fd5b5061035e600480360381019061035991906115ca565b6107db565b005b34801561036b575f80fd5b506103866004803603810190610381919061130a565b6107f6565b6040516103939190611374565b60405180910390f35b3480156103a7575f80fd5b506103b0610819565b6040516103bd91906112b7565b60405180910390f35b3480156103d1575f80fd5b506103ec60048036038101906103e79190611611565b6108a5565b6040516103f99190611404565b60405180910390f35b61040a6108f2565b005b348015610417575f80fd5b50610432600480360381019061042d9190611611565b610905565b60405161043f919061122e565b60405180910390f35b348015610453575f80fd5b5061046e60048036038101906104699190611666565b610922565b005b34801561047b575f80fd5b50610484610934565b6040516104919190611374565b60405180910390f35b3480156104a5575f80fd5b506104ae61095c565b6040516104bb91906112b7565b60405180910390f35b3480156104cf575f80fd5b506104ea60048036038101906104e591906116bb565b610999565b005b3480156104f7575f80fd5b50610512600480360381019061050d9190611756565b6109ec565b005b61052e600480360381019061052991906117f6565b610b96565b005b34801561053b575f80fd5b506105566004803603810190610551919061130a565b610bc8565b60405161056391906112b7565b60405180910390f35b348015610577575f80fd5b50610592600480360381019061058d919061187a565b610ca4565b60405161059f919061122e565b60405180910390f35b6105c260048036038101906105bd9190611611565b610cc6565b005b6105de60048036038101906105d99190611611565b610d04565b005b3480156105eb575f80fd5b5061060660048036038101906106019190611611565b610d2d565b6040516106139190611404565b60405180910390f35b5f8160e01c635b5e139f81146380ac58cd82146301ffc9a783141717915050919050565b60606040518060400160405280601081526020017f42617365204275696c646572204e465400000000000000000000000000000000815250905090565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f2082018201805460601b6106c35763ceea21b65f526004601cfd5b8060010154915050919050565b6106db338383610d46565b5050565b5f8054905090565b6040517fa24e573d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610722610df6565b67ffffffffffffffff164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a250565b60025481565b6040517fa24e573d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2565b6107e3610e00565b80600190816107f29190611ab2565b5050565b5f61080082610e37565b9050806108145763ceea21b65f526004601cfd5b919050565b60018054610826906118e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610852906118e5565b801561089d5780601f106108745761010080835404028352916020019161089d565b820191905f5260205f20905b81548152906001019060200180831161088057829003601f168201915b505050505081565b5f816108b857638f4eb6045f526004601cfd5b7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f5263ffffffff601c600c2054169050919050565b6108fa610e00565b6109035f610e75565b565b6003602052805f5260405f205f915054906101000a900460ff1681565b61092a610e00565b8060028190555050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392754905090565b60606040518060400160405280600b81526020017f424153454255494c444552000000000000000000000000000000000000000000815250905090565b801515905081601c52670a5a2e7a00000000600852335f52806030600c2055805f528160601b60601c337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160205fa35050565b3068929eee149b4bd212685403610a0a5763ab143c065f526004601cfd5b3068929eee149b4bd212685560035f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1615610aa257336040517f2058b6db000000000000000000000000000000000000000000000000000000008152600401610a999190611374565b60405180910390fd5b8181610ad8828260025433604051602001610abd9190611bc6565b60405160208183030381529060405280519060200120610f3b565b610b0e576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160035f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f80815480929190610b7490611c0d565b9190505550610b84335f54610f91565b50503868929eee149b4bd21268555050565b6040517fa24e573d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610bd382610fae565b610c1457816040517f2f4163e7000000000000000000000000000000000000000000000000000000008152600401610c0b9190611404565b60405180910390fd5b60018054610c21906118e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4d906118e5565b8015610c985780601f10610c6f57610100808354040283529160200191610c98565b820191905f5260205f20905b815481529060010190602001808311610c7b57829003601f168201915b50505050509050919050565b5f81601c52670a5a2e7a00000000600852825f526030600c2054905092915050565b610cce610e00565b63389a75e1600c52805f526020600c208054421115610cf457636f5e88185f526004601cfd5b5f815550610d0181610e75565b50565b610d0c610e00565b8060601b610d2157637448fbae5f526004601cfd5b610d2a81610e75565b50565b5f63389a75e1600c52815f526020600c20549050919050565b5f1960601c82811692508381169350815f52837f7d8825530a5a2e7a00000000000000000000000000000000000000000000000017601c5260205f20820182018054821680610d9c5763ceea21b65f526004601cfd5b808614861517610dc157805f526030600c2054610dc057634b6e7f185f526004601cfd5b5b8482600101558385827f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f38a4505050505050565b5f6202a300905090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314610e35576382b429005f526004601cfd5b565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b60601c9050919050565b610e7d610feb565b15610ee2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278160601b60601c91508181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3811560ff1b8217815550610f38565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278160601b60601c91508181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3818155505b50565b5f8315610f84578360051b8501855b600115610f81578035841160051b8481528135602082185260405f209450602082019150828210610f7b5750610f81565b50610f4a565b50505b8282149050949350505050565b610faa828260405180602001604052805f815250610fef565b5050565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b15159050919050565b5f90565b610ff98383611019565b611002836110e5565b15611014576110135f8484846110ef565b5b505050565b6110245f8383611179565b8160601b60601c9150805f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f208101810180548060601b156110745763c991cbb15f526004601cfd5b8381178255835f52601c600c20600181540163ffffffff811686026110a85767ea553b3401336cea861560021b526004601cfd5b808255505082845f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f38a450506110e15f838361117e565b5050565b5f813b9050919050565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a08401528015611136578060c08401826020870160045afa505b60208360a48301601c86015f8a5af1611158573d15611157573d5f843e3d83fd5b5b8160e01b8351146111705763d1a57ed65f526004601cfd5b50505050505050565b505050565b505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6111c881611194565b81146111d2575f80fd5b50565b5f813590506111e3816111bf565b92915050565b5f602082840312156111fe576111fd61118c565b5b5f61120b848285016111d5565b91505092915050565b5f8115159050919050565b61122881611214565b82525050565b5f6020820190506112415f83018461121f565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61128982611247565b6112938185611251565b93506112a3818560208601611261565b6112ac8161126f565b840191505092915050565b5f6020820190508181035f8301526112cf818461127f565b905092915050565b5f819050919050565b6112e9816112d7565b81146112f3575f80fd5b50565b5f81359050611304816112e0565b92915050565b5f6020828403121561131f5761131e61118c565b5b5f61132c848285016112f6565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61135e82611335565b9050919050565b61136e81611354565b82525050565b5f6020820190506113875f830184611365565b92915050565b61139681611354565b81146113a0575f80fd5b50565b5f813590506113b18161138d565b92915050565b5f80604083850312156113cd576113cc61118c565b5b5f6113da858286016113a3565b92505060206113eb858286016112f6565b9150509250929050565b6113fe816112d7565b82525050565b5f6020820190506114175f8301846113f5565b92915050565b5f805f606084860312156114345761143361118c565b5b5f611441868287016113a3565b9350506020611452868287016113a3565b9250506040611463868287016112f6565b9150509250925092565b5f819050919050565b61147f8161146d565b82525050565b5f6020820190506114985f830184611476565b92915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6114dc8261126f565b810181811067ffffffffffffffff821117156114fb576114fa6114a6565b5b80604052505050565b5f61150d611183565b905061151982826114d3565b919050565b5f67ffffffffffffffff821115611538576115376114a6565b5b6115418261126f565b9050602081019050919050565b828183375f83830152505050565b5f61156e6115698461151e565b611504565b90508281526020810184848401111561158a576115896114a2565b5b61159584828561154e565b509392505050565b5f82601f8301126115b1576115b061149e565b5b81356115c184826020860161155c565b91505092915050565b5f602082840312156115df576115de61118c565b5b5f82013567ffffffffffffffff8111156115fc576115fb611190565b5b6116088482850161159d565b91505092915050565b5f602082840312156116265761162561118c565b5b5f611633848285016113a3565b91505092915050565b6116458161146d565b811461164f575f80fd5b50565b5f813590506116608161163c565b92915050565b5f6020828403121561167b5761167a61118c565b5b5f61168884828501611652565b91505092915050565b61169a81611214565b81146116a4575f80fd5b50565b5f813590506116b581611691565b92915050565b5f80604083850312156116d1576116d061118c565b5b5f6116de858286016113a3565b92505060206116ef858286016116a7565b9150509250929050565b5f80fd5b5f80fd5b5f8083601f8401126117165761171561149e565b5b8235905067ffffffffffffffff811115611733576117326116f9565b5b60208301915083602082028301111561174f5761174e6116fd565b5b9250929050565b5f806020838503121561176c5761176b61118c565b5b5f83013567ffffffffffffffff81111561178957611788611190565b5b61179585828601611701565b92509250509250929050565b5f8083601f8401126117b6576117b561149e565b5b8235905067ffffffffffffffff8111156117d3576117d26116f9565b5b6020830191508360018202830111156117ef576117ee6116fd565b5b9250929050565b5f805f805f6080868803121561180f5761180e61118c565b5b5f61181c888289016113a3565b955050602061182d888289016113a3565b945050604061183e888289016112f6565b935050606086013567ffffffffffffffff81111561185f5761185e611190565b5b61186b888289016117a1565b92509250509295509295909350565b5f80604083850312156118905761188f61118c565b5b5f61189d858286016113a3565b92505060206118ae858286016113a3565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806118fc57607f821691505b60208210810361190f5761190e6118b8565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026119717fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611936565b61197b8683611936565b95508019841693508086168417925050509392505050565b5f819050919050565b5f6119b66119b16119ac846112d7565b611993565b6112d7565b9050919050565b5f819050919050565b6119cf8361199c565b6119e36119db826119bd565b848454611942565b825550505050565b5f90565b6119f76119eb565b611a028184846119c6565b505050565b5b81811015611a2557611a1a5f826119ef565b600181019050611a08565b5050565b601f821115611a6a57611a3b81611915565b611a4484611927565b81016020851015611a53578190505b611a67611a5f85611927565b830182611a07565b50505b505050565b5f82821c905092915050565b5f611a8a5f1984600802611a6f565b1980831691505092915050565b5f611aa28383611a7b565b9150826002028217905092915050565b611abb82611247565b67ffffffffffffffff811115611ad457611ad36114a6565b5b611ade82546118e5565b611ae9828285611a29565b5f60209050601f831160018114611b1a575f8415611b08578287015190505b611b128582611a97565b865550611b79565b601f198416611b2886611915565b5f5b82811015611b4f57848901518255600182019150602085019450602081019050611b2a565b86831015611b6c5784890151611b68601f891682611a7b565b8355505b6001600288020188555050505b505050505050565b5f8160601b9050919050565b5f611b9782611b81565b9050919050565b5f611ba882611b8d565b9050919050565b611bc0611bbb82611354565b611b9e565b82525050565b5f611bd18284611baf565b60148201915081905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611c17826112d7565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611c4957611c48611be0565b5b60018201905091905056fea264697066735822122077425466c2d79db1fc8da310f717f43aa7fd014b71d764ed674ff6b63683956264736f6c63430008190033000000000000000000000000fd4f24676ed4588928213f37b126b53c07186f450000000000000000000000000000000000000000000000000000000000000060420d11a2781ec05cbfcf2338f411716bac0acbba3d50076157706ffbdd59705f000000000000000000000000000000000000000000000000000000000000002268747470733a2f2f626173652e6f72672f6e6674732f6275696c6465722e6a736f6e000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x60806040526004361061019f575f3560e01c806370a08231116100eb578063b77a147b11610089578063e985e9c511610063578063e985e9c51461056c578063f04e283e146105a8578063f2fde38b146105c4578063fee81cf4146105e0576101d6565b8063b77a147b146104ec578063b88d4fde14610514578063c87b56dd14610530576101d6565b80637cb64759116100c55780637cb64759146104485780638da5cb5b1461047057806395d89b411461049a578063a22cb465146104c4576101d6565b806370a08231146103c6578063715018a61461040257806373b2e80e1461040c576101d6565b8063256929621161015857806354d1f13d1161013257806354d1f13d1461032e57806355f804b3146103385780636352211e146103605780636c0360eb1461039c576101d6565b806325692962146102de5780632eb4a7ab146102e857806342842e0e14610312576101d6565b806301ffc9a7146101da57806306fdde0314610216578063081812fc14610240578063095ea7b31461027c57806318160ddd1461029857806323b872dd146102c2576101d6565b366101d6576040517f38ea61ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80fd5b3480156101e5575f80fd5b5061020060048036038101906101fb91906111e9565b61061c565b60405161020d919061122e565b60405180910390f35b348015610221575f80fd5b5061022a610640565b60405161023791906112b7565b60405180910390f35b34801561024b575f80fd5b506102666004803603810190610261919061130a565b61067d565b6040516102739190611374565b60405180910390f35b610296600480360381019061029191906113b7565b6106d0565b005b3480156102a3575f80fd5b506102ac6106df565b6040516102b99190611404565b60405180910390f35b6102dc60048036038101906102d7919061141d565b6106e7565b005b6102e6610719565b005b3480156102f3575f80fd5b506102fc61076a565b6040516103099190611485565b60405180910390f35b61032c6004803603810190610327919061141d565b610770565b005b6103366107a2565b005b348015610343575f80fd5b5061035e600480360381019061035991906115ca565b6107db565b005b34801561036b575f80fd5b506103866004803603810190610381919061130a565b6107f6565b6040516103939190611374565b60405180910390f35b3480156103a7575f80fd5b506103b0610819565b6040516103bd91906112b7565b60405180910390f35b3480156103d1575f80fd5b506103ec60048036038101906103e79190611611565b6108a5565b6040516103f99190611404565b60405180910390f35b61040a6108f2565b005b348015610417575f80fd5b50610432600480360381019061042d9190611611565b610905565b60405161043f919061122e565b60405180910390f35b348015610453575f80fd5b5061046e60048036038101906104699190611666565b610922565b005b34801561047b575f80fd5b50610484610934565b6040516104919190611374565b60405180910390f35b3480156104a5575f80fd5b506104ae61095c565b6040516104bb91906112b7565b60405180910390f35b3480156104cf575f80fd5b506104ea60048036038101906104e591906116bb565b610999565b005b3480156104f7575f80fd5b50610512600480360381019061050d9190611756565b6109ec565b005b61052e600480360381019061052991906117f6565b610b96565b005b34801561053b575f80fd5b506105566004803603810190610551919061130a565b610bc8565b60405161056391906112b7565b60405180910390f35b348015610577575f80fd5b50610592600480360381019061058d919061187a565b610ca4565b60405161059f919061122e565b60405180910390f35b6105c260048036038101906105bd9190611611565b610cc6565b005b6105de60048036038101906105d99190611611565b610d04565b005b3480156105eb575f80fd5b5061060660048036038101906106019190611611565b610d2d565b6040516106139190611404565b60405180910390f35b5f8160e01c635b5e139f81146380ac58cd82146301ffc9a783141717915050919050565b60606040518060400160405280601081526020017f42617365204275696c646572204e465400000000000000000000000000000000815250905090565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f2082018201805460601b6106c35763ceea21b65f526004601cfd5b8060010154915050919050565b6106db338383610d46565b5050565b5f8054905090565b6040517fa24e573d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610722610df6565b67ffffffffffffffff164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a250565b60025481565b6040517fa24e573d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2565b6107e3610e00565b80600190816107f29190611ab2565b5050565b5f61080082610e37565b9050806108145763ceea21b65f526004601cfd5b919050565b60018054610826906118e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610852906118e5565b801561089d5780601f106108745761010080835404028352916020019161089d565b820191905f5260205f20905b81548152906001019060200180831161088057829003601f168201915b505050505081565b5f816108b857638f4eb6045f526004601cfd5b7f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c52815f5263ffffffff601c600c2054169050919050565b6108fa610e00565b6109035f610e75565b565b6003602052805f5260405f205f915054906101000a900460ff1681565b61092a610e00565b8060028190555050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392754905090565b60606040518060400160405280600b81526020017f424153454255494c444552000000000000000000000000000000000000000000815250905090565b801515905081601c52670a5a2e7a00000000600852335f52806030600c2055805f528160601b60601c337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160205fa35050565b3068929eee149b4bd212685403610a0a5763ab143c065f526004601cfd5b3068929eee149b4bd212685560035f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1615610aa257336040517f2058b6db000000000000000000000000000000000000000000000000000000008152600401610a999190611374565b60405180910390fd5b8181610ad8828260025433604051602001610abd9190611bc6565b60405160208183030381529060405280519060200120610f3b565b610b0e576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160035f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505f80815480929190610b7490611c0d565b9190505550610b84335f54610f91565b50503868929eee149b4bd21268555050565b6040517fa24e573d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060610bd382610fae565b610c1457816040517f2f4163e7000000000000000000000000000000000000000000000000000000008152600401610c0b9190611404565b60405180910390fd5b60018054610c21906118e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4d906118e5565b8015610c985780601f10610c6f57610100808354040283529160200191610c98565b820191905f5260205f20905b815481529060010190602001808311610c7b57829003601f168201915b50505050509050919050565b5f81601c52670a5a2e7a00000000600852825f526030600c2054905092915050565b610cce610e00565b63389a75e1600c52805f526020600c208054421115610cf457636f5e88185f526004601cfd5b5f815550610d0181610e75565b50565b610d0c610e00565b8060601b610d2157637448fbae5f526004601cfd5b610d2a81610e75565b50565b5f63389a75e1600c52815f526020600c20549050919050565b5f1960601c82811692508381169350815f52837f7d8825530a5a2e7a00000000000000000000000000000000000000000000000017601c5260205f20820182018054821680610d9c5763ceea21b65f526004601cfd5b808614861517610dc157805f526030600c2054610dc057634b6e7f185f526004601cfd5b5b8482600101558385827f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f38a4505050505050565b5f6202a300905090565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314610e35576382b429005f526004601cfd5b565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b60601c9050919050565b610e7d610feb565b15610ee2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278160601b60601c91508181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3811560ff1b8217815550610f38565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739278160601b60601c91508181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3818155505b50565b5f8315610f84578360051b8501855b600115610f81578035841160051b8481528135602082185260405f209450602082019150828210610f7b5750610f81565b50610f4a565b50505b8282149050949350505050565b610faa828260405180602001604052805f815250610fef565b5050565b5f815f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f20820182015460601b15159050919050565b5f90565b610ff98383611019565b611002836110e5565b15611014576110135f8484846110ef565b5b505050565b6110245f8383611179565b8160601b60601c9150805f527f7d8825530a5a2e7a000000000000000000000000000000000000000000000000601c5260205f208101810180548060601b156110745763c991cbb15f526004601cfd5b8381178255835f52601c600c20600181540163ffffffff811686026110a85767ea553b3401336cea861560021b526004601cfd5b808255505082845f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f38a450506110e15f838361117e565b5050565b5f813b9050919050565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a08401528015611136578060c08401826020870160045afa505b60208360a48301601c86015f8a5af1611158573d15611157573d5f843e3d83fd5b5b8160e01b8351146111705763d1a57ed65f526004601cfd5b50505050505050565b505050565b505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6111c881611194565b81146111d2575f80fd5b50565b5f813590506111e3816111bf565b92915050565b5f602082840312156111fe576111fd61118c565b5b5f61120b848285016111d5565b91505092915050565b5f8115159050919050565b61122881611214565b82525050565b5f6020820190506112415f83018461121f565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61128982611247565b6112938185611251565b93506112a3818560208601611261565b6112ac8161126f565b840191505092915050565b5f6020820190508181035f8301526112cf818461127f565b905092915050565b5f819050919050565b6112e9816112d7565b81146112f3575f80fd5b50565b5f81359050611304816112e0565b92915050565b5f6020828403121561131f5761131e61118c565b5b5f61132c848285016112f6565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61135e82611335565b9050919050565b61136e81611354565b82525050565b5f6020820190506113875f830184611365565b92915050565b61139681611354565b81146113a0575f80fd5b50565b5f813590506113b18161138d565b92915050565b5f80604083850312156113cd576113cc61118c565b5b5f6113da858286016113a3565b92505060206113eb858286016112f6565b9150509250929050565b6113fe816112d7565b82525050565b5f6020820190506114175f8301846113f5565b92915050565b5f805f606084860312156114345761143361118c565b5b5f611441868287016113a3565b9350506020611452868287016113a3565b9250506040611463868287016112f6565b9150509250925092565b5f819050919050565b61147f8161146d565b82525050565b5f6020820190506114985f830184611476565b92915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6114dc8261126f565b810181811067ffffffffffffffff821117156114fb576114fa6114a6565b5b80604052505050565b5f61150d611183565b905061151982826114d3565b919050565b5f67ffffffffffffffff821115611538576115376114a6565b5b6115418261126f565b9050602081019050919050565b828183375f83830152505050565b5f61156e6115698461151e565b611504565b90508281526020810184848401111561158a576115896114a2565b5b61159584828561154e565b509392505050565b5f82601f8301126115b1576115b061149e565b5b81356115c184826020860161155c565b91505092915050565b5f602082840312156115df576115de61118c565b5b5f82013567ffffffffffffffff8111156115fc576115fb611190565b5b6116088482850161159d565b91505092915050565b5f602082840312156116265761162561118c565b5b5f611633848285016113a3565b91505092915050565b6116458161146d565b811461164f575f80fd5b50565b5f813590506116608161163c565b92915050565b5f6020828403121561167b5761167a61118c565b5b5f61168884828501611652565b91505092915050565b61169a81611214565b81146116a4575f80fd5b50565b5f813590506116b581611691565b92915050565b5f80604083850312156116d1576116d061118c565b5b5f6116de858286016113a3565b92505060206116ef858286016116a7565b9150509250929050565b5f80fd5b5f80fd5b5f8083601f8401126117165761171561149e565b5b8235905067ffffffffffffffff811115611733576117326116f9565b5b60208301915083602082028301111561174f5761174e6116fd565b5b9250929050565b5f806020838503121561176c5761176b61118c565b5b5f83013567ffffffffffffffff81111561178957611788611190565b5b61179585828601611701565b92509250509250929050565b5f8083601f8401126117b6576117b561149e565b5b8235905067ffffffffffffffff8111156117d3576117d26116f9565b5b6020830191508360018202830111156117ef576117ee6116fd565b5b9250929050565b5f805f805f6080868803121561180f5761180e61118c565b5b5f61181c888289016113a3565b955050602061182d888289016113a3565b945050604061183e888289016112f6565b935050606086013567ffffffffffffffff81111561185f5761185e611190565b5b61186b888289016117a1565b92509250509295509295909350565b5f80604083850312156118905761188f61118c565b5b5f61189d858286016113a3565b92505060206118ae858286016113a3565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806118fc57607f821691505b60208210810361190f5761190e6118b8565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026119717fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611936565b61197b8683611936565b95508019841693508086168417925050509392505050565b5f819050919050565b5f6119b66119b16119ac846112d7565b611993565b6112d7565b9050919050565b5f819050919050565b6119cf8361199c565b6119e36119db826119bd565b848454611942565b825550505050565b5f90565b6119f76119eb565b611a028184846119c6565b505050565b5b81811015611a2557611a1a5f826119ef565b600181019050611a08565b5050565b601f821115611a6a57611a3b81611915565b611a4484611927565b81016020851015611a53578190505b611a67611a5f85611927565b830182611a07565b50505b505050565b5f82821c905092915050565b5f611a8a5f1984600802611a6f565b1980831691505092915050565b5f611aa28383611a7b565b9150826002028217905092915050565b611abb82611247565b67ffffffffffffffff811115611ad457611ad36114a6565b5b611ade82546118e5565b611ae9828285611a29565b5f60209050601f831160018114611b1a575f8415611b08578287015190505b611b128582611a97565b865550611b79565b601f198416611b2886611915565b5f5b82811015611b4f57848901518255600182019150602085019450602081019050611b2a565b86831015611b6c5784890151611b68601f891682611a7b565b8355505b6001600288020188555050505b505050505050565b5f8160601b9050919050565b5f611b9782611b81565b9050919050565b5f611ba882611b8d565b9050919050565b611bc0611bbb82611354565b611b9e565b82525050565b5f611bd18284611baf565b60148201915081905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611c17826112d7565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611c4957611c48611be0565b5b60018201905091905056fea264697066735822122077425466c2d79db1fc8da310f717f43aa7fd014b71d764ed674ff6b63683956264736f6c63430008190033

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

000000000000000000000000fd4f24676ed4588928213f37b126b53c07186f450000000000000000000000000000000000000000000000000000000000000060420d11a2781ec05cbfcf2338f411716bac0acbba3d50076157706ffbdd59705f000000000000000000000000000000000000000000000000000000000000002268747470733a2f2f626173652e6f72672f6e6674732f6275696c6465722e6a736f6e000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _owner (address): 0xFd4F24676eD4588928213F37B126B53c07186F45
Arg [1] : _baseURI (string): https://base.org/nfts/builder.json
Arg [2] : _root (bytes32): 0x420d11a2781ec05cbfcf2338f411716bac0acbba3d50076157706ffbdd59705f

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000fd4f24676ed4588928213f37b126b53c07186f45
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 420d11a2781ec05cbfcf2338f411716bac0acbba3d50076157706ffbdd59705f
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000022
Arg [4] : 68747470733a2f2f626173652e6f72672f6e6674732f6275696c6465722e6a73
Arg [5] : 6f6e000000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

127462:4030:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;128388:20;;;;;;;;;;;;;;127462:4030;;;;28068:387;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;129416:105;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;21141:544;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;21989:121;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;130905:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;130506:117;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9265:630;;;:::i;:::-;;127797:25;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;130631:121;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9980:466;;;:::i;:::-;;131287:100;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;19966:341;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;127769:21;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;20457:545;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;9000:102;;;:::i;:::-;;127829:42;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;131395:94;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;11705:187;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;129580:102;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;22754:741;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;130289:209;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;130760:137;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;129828:166;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;22204:405;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;10637:724;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;8574:358;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;11998:449;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;28068:387;28144:11;28254;28249:3;28245:21;28425:10;28422:1;28419:17;28405:10;28402:1;28399:17;28386:10;28383:1;28380:17;28377:40;28374:63;28364:73;;28221:227;28068:387;;;:::o;129416:105::-;129462:13;129488:25;;;;;;;;;;;;;;;;;;;129416:105;:::o;21141:544::-;21203:14;21311:2;21305:4;21298:16;21341:24;21335:4;21328:38;21433:4;21427;21417:21;21413:2;21409:30;21405:2;21401:39;21478:13;21472:20;21468:2;21464:29;21454:161;;21527:10;21521:4;21514:24;21595:4;21589;21582:18;21454:161;21652:13;21649:1;21645:21;21639:28;21629:38;;21283:395;21141:544;;;:::o;21989:121::-;22069:33;22078:10;22090:7;22099:2;22069:8;:33::i;:::-;21989:121;;:::o;130905:87::-;130951:7;130978:6;;130971:13;;130905:87;:::o;130506:117::-;130597:18;;;;;;;;;;;;;;9265:630;9360:15;9396:28;:26;:28::i;:::-;9378:46;;:15;:46;9360:64;;9596:19;9590:4;9583:33;9647:8;9641:4;9634:22;9704:7;9697:4;9691;9681:21;9674:38;9853:8;9806:45;9803:1;9800;9795:67;9496:381;9265:630::o;127797:25::-;;;;:::o;130631:121::-;130726:18;;;;;;;;;;;;;;9980:466;10186:19;10180:4;10173:33;10233:8;10227:4;10220:22;10286:1;10279:4;10273;10263:21;10256:32;10419:8;10373:44;10370:1;10367;10362:66;9980:466::o;131287:100::-;12844:13;:11;:13::i;:::-;131371:8:::1;131361:7;:18;;;;;;:::i;:::-;;131287:100:::0;:::o;19966:341::-;20024:14;20060:12;20069:2;20060:8;:12::i;:::-;20051:21;;20161:6;20151:138;;20201:10;20195:4;20188:24;20269:4;20263;20256:18;20151:138;19966:341;;;:::o;127769:21::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;20457:545::-;20520:14;20684:5;20674:146;;20723:10;20717:4;20710:24;20800:4;20794;20787:18;20674:146;20847:24;20841:4;20834:38;20899:5;20893:4;20886:19;20963:20;20955:4;20949;20939:21;20933:28;20929:55;20919:65;;20457:545;;;:::o;9000:102::-;12844:13;:11;:13::i;:::-;9073:21:::1;9091:1;9073:9;:21::i;:::-;9000:102::o:0;127829:42::-;;;;;;;;;;;;;;;;;;;;;;:::o;131395:94::-;12844:13;:11;:13::i;:::-;131476:5:::1;131463:10;:18;;;;131395:94:::0;:::o;11705:187::-;11751:14;11862:11;11856:18;11846:28;;11705:187;:::o;129580:102::-;129628:13;129654:20;;;;;;;;;;;;;;;;;;;129580:102;:::o;22754:741::-;22973:10;22966:18;22959:26;22945:40;;23084:8;23078:4;23071:22;23120:31;23114:4;23107:45;23179:8;23173:4;23166:22;23232:10;23225:4;23219;23209:21;23202:41;23319:10;23313:4;23306:24;23466:8;23462:2;23458:17;23454:2;23450:26;23440:8;23405:33;23399:4;23393;23388:89;22754:741;;:::o;130289:209::-;123509:9;123484:22;123478:29;123475:44;123472:161;;123552:10;123546:4;123539:24;123613:4;123607;123600:18;123472:161;123678:9;123654:22;123647:41;128751:10:::1;:22;128762:10;128751:22;;;;;;;;;;;;;;;;;;;;;;;;;128747:61;;;128797:10;128782:26;;;;;;;;;;;:::i;:::-;;;;;;;;128747:61;130384:5:::2;;128906:89;128936:5;;128943:10;;128982;128965:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;128955:39;;;;;;128906:29;:89::i;:::-;128901:144;;129019:14;;;;;;;;;;;;;;128901:144;130427:4:::3;130402:10;:22;130413:10;130402:22;;;;;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;130442:6;::::0;:8:::3;;;;;;;;;:::i;:::-;;;;;;130461:29;130471:10;130483:6;;130461:9;:29::i;:::-;128819:1:::2;;123820:10:::0;123796:22;123789:42;130289:209;;:::o;130760:137::-;130871:18;;;;;;;;;;;;;;129828:166;129888:13;129919:11;129927:2;129919:7;:11::i;:::-;129914:45;;129956:2;129939:20;;;;;;;;;;;:::i;:::-;;;;;;;;129914:45;129979:7;129972:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;129828:166;;;:::o;22204:405::-;22328:11;22438:8;22432:4;22425:22;22474:31;22468:4;22461:45;22533:5;22527:4;22520:19;22585:4;22579;22569:21;22563:28;22553:38;;22204:405;;;;:::o;10637:724::-;12844:13;:11;:13::i;:::-;10875:19:::1;10869:4;10862:33;10922:12;10916:4;10909:26;10985:4;10979;10969:21;11093:12;11087:19;11074:11;11071:36;11068:160;;;11140:10;11134:4;11127:24;11208:4;11202;11195:18;11068:160;11307:1;11293:12;11286:23;10791:529;11330:23;11340:12;11330:9;:23::i;:::-;10637:724:::0;:::o;8574:358::-;12844:13;:11;:13::i;:::-;8749:8:::1;8745:2;8741:17;8731:153;;8792:10;8786:4;8779:24;8864:4;8858;8851:18;8731:153;8905:19;8915:8;8905:9;:19::i;:::-;8574:358:::0;:::o;11998:449::-;12121:14;12277:19;12271:4;12264:33;12324:12;12318:4;12311:26;12423:4;12417;12407:21;12401:28;12391:38;;11998:449;;;:::o;42571:1472::-;42757:1;42753:6;42749:2;42745:15;42805:7;42789:14;42785:28;42774:39;;42853:2;42837:14;42833:23;42827:29;;42928:2;42922:4;42915:16;42987:2;42961:24;42958:32;42952:4;42945:46;43058:4;43052;43042:21;43038:2;43034:30;43030:2;43026:39;43118:13;43112:20;43096:14;43092:41;43209:5;43199:137;;43248:10;43242:4;43235:24;43316:4;43310;43303:18;43199:137;43522:5;43518:2;43515:13;43510:2;43503:10;43500:29;43490:286;;43563:5;43557:4;43550:19;43619:4;43613;43603:21;43597:28;43587:174;;43663:10;43657:4;43650:24;43737:4;43731;43724:18;43587:174;43490:286;43891:7;43875:13;43872:1;43868:21;43861:38;44022:2;44013:7;44006:5;43979:25;43973:4;43961:10;43956:69;42667:1369;;;42571:1472;;;:::o;8095:112::-;8164:6;8190:9;8183:16;;8095:112;:::o;7495:364::-;7711:11;7705:18;7695:8;7692:32;7682:159;;7758:10;7752:4;7745:24;7821:4;7815;7808:18;7682:159;7495:364::o;29266:330::-;29327:14;29435:2;29429:4;29422:16;29465:24;29459:4;29452:38;29568:4;29562;29552:21;29548:2;29544:30;29540:2;29536:39;29530:46;29526:2;29522:55;29518:2;29514:64;29504:74;;29266:330;;;:::o;6321:1113::-;6390:23;:21;:23::i;:::-;6386:1041;;;6523:11;6625:8;6621:2;6617:17;6613:2;6609:26;6597:38;;6781:8;6769:9;6763:16;6723:38;6720:1;6717;6712:78;6896:8;6889:16;6884:3;6880:26;6870:8;6867:40;6856:9;6849:59;6487:436;6386:1041;;;7048:11;7150:8;7146:2;7142:17;7138:2;7134:26;7122:38;;7306:8;7294:9;7288:16;7248:38;7245:1;7242;7237:78;7392:8;7381:9;7374:27;7012:404;6386:1041;6321:1113;:::o;109283:1436::-;109411:12;109512;109509:1153;;;109654:12;109651:1;109647:20;109633:12;109629:39;109782:12;109882:765;109889:1;109882:765;;;110091:6;110078:20;110072:4;110069:30;110066:1;110062:38;110312:4;110303:7;110296:21;110379:6;110366:20;110359:4;110350:7;110346:18;110339:48;110516:4;110510;110500:21;110492:29;;110565:4;110557:6;110553:17;110543:27;;110613:3;110605:6;110602:15;110592:36;;110621:5;;;110592:36;109894:753;109882:765;;;109525:1137;;109509:1153;110696:4;110690;110687:14;110676:25;;109283:1436;;;;;;:::o;36368:100::-;36439:21;36449:2;36453;36439:21;;;;;;;;;;;;:9;:21::i;:::-;36368:100;;:::o;28794:333::-;28854:11;28959:2;28953:4;28946:16;28989:24;28983:4;28976:38;29098:4;29092;29082:21;29078:2;29074:30;29070:2;29066:39;29060:46;29056:2;29052:55;29045:63;29038:71;29028:81;;28794:333;;;:::o;4485:78::-;4549:10;4485:78;:::o;36833:188::-;36923:13;36929:2;36933;36923:5;:13::i;:::-;36951:12;36960:2;36951:8;:12::i;:::-;36947:66;;;36965:48;36996:1;37000:2;37004;37008:4;36965:22;:48::i;:::-;36947:66;36833:188;;;:::o;32918:1688::-;32985:40;33014:1;33018:2;33022;32985:20;:40::i;:::-;33167:2;33163;33159:11;33155:2;33151:20;33145:26;;33239:2;33233:4;33226:16;33269:24;33263:4;33256:38;33361:4;33355;33345:21;33341:2;33337:30;33333:2;33329:39;33411:13;33405:20;33502:15;33498:2;33494:24;33491:149;;;33551:10;33545:4;33538:24;33620:4;33614;33607:18;33491:149;33735:2;33718:15;33715:23;33700:13;33693:46;33837:2;33831:4;33824:16;33893:4;33887;33877:21;33965:1;33951:11;33945:18;33941:26;34119:20;34100:17;34096:44;34092:2;34088:53;34078:272;;34272:18;34266:2;34259:10;34256:1;34252:18;34245:46;34326:4;34320;34313:18;34078:272;34388:17;34375:11;34368:38;33805:616;;34535:2;34531;34528:1;34501:25;34495:4;34483:10;34478:60;33089:1460;;34559:39;34587:1;34591:2;34595;34559:19;:39::i;:::-;32918:1688;;:::o;51951:217::-;52002:11;52116:1;52104:14;52094:24;;51951:217;;;:::o;52331:1400::-;52574:4;52568:11;52625:10;52659:24;52656:1;52649:35;52719:8;52712:4;52709:1;52705:12;52698:30;52828:4;52824:2;52820:13;52816:2;52812:22;52805:4;52802:1;52798:12;52791:44;52870:2;52863:4;52860:1;52856:12;52849:24;52908:4;52901;52898:1;52894:12;52887:26;52942:4;52936:11;52982:1;52975:4;52972:1;52968:12;52961:23;53001:1;52998:71;;;53064:1;53057:4;53054:1;53050:12;53047:1;53040:4;53034;53030:15;53027:1;53020:5;53009:57;53005:62;52998:71;53187:4;53184:1;53177:4;53174:1;53170:12;53163:4;53160:1;53156:12;53153:1;53149:2;53142:5;53137:55;53127:319;;53216:16;53213:218;;;53346:16;53340:4;53337:1;53322:41;53395:16;53392:1;53385:27;53213:218;53127:319;53544:24;53539:3;53535:34;53531:1;53525:8;53522:48;53512:201;;53604:10;53598:4;53591:24;53693:4;53687;53680:18;53512:201;52506:1218;;;52331:1400;;;;:::o;51321:87::-;;;;:::o;51508:86::-;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:139::-;1887:6;1882:3;1877;1871:23;1928:1;1919:6;1914:3;1910:16;1903:27;1798:139;;;:::o;1943:102::-;1984:6;2035:2;2031:7;2026:2;2019:5;2015:14;2011:28;2001:38;;1943:102;;;:::o;2051:377::-;2139:3;2167:39;2200:5;2167:39;:::i;:::-;2222:71;2286:6;2281:3;2222:71;:::i;:::-;2215:78;;2302:65;2360:6;2355:3;2348:4;2341:5;2337:16;2302:65;:::i;:::-;2392:29;2414:6;2392:29;:::i;:::-;2387:3;2383:39;2376:46;;2143:285;2051:377;;;;:::o;2434:313::-;2547:4;2585:2;2574:9;2570:18;2562:26;;2634:9;2628:4;2624:20;2620:1;2609:9;2605:17;2598:47;2662:78;2735:4;2726:6;2662:78;:::i;:::-;2654:86;;2434:313;;;;:::o;2753:77::-;2790:7;2819:5;2808:16;;2753:77;;;:::o;2836:122::-;2909:24;2927:5;2909:24;:::i;:::-;2902:5;2899:35;2889:63;;2948:1;2945;2938:12;2889:63;2836:122;:::o;2964:139::-;3010:5;3048:6;3035:20;3026:29;;3064:33;3091:5;3064:33;:::i;:::-;2964:139;;;;:::o;3109:329::-;3168:6;3217:2;3205:9;3196:7;3192:23;3188:32;3185:119;;;3223:79;;:::i;:::-;3185:119;3343:1;3368:53;3413:7;3404:6;3393:9;3389:22;3368:53;:::i;:::-;3358:63;;3314:117;3109:329;;;;:::o;3444:126::-;3481:7;3521:42;3514:5;3510:54;3499:65;;3444:126;;;:::o;3576:96::-;3613:7;3642:24;3660:5;3642:24;:::i;:::-;3631:35;;3576:96;;;:::o;3678:118::-;3765:24;3783:5;3765:24;:::i;:::-;3760:3;3753:37;3678:118;;:::o;3802:222::-;3895:4;3933:2;3922:9;3918:18;3910:26;;3946:71;4014:1;4003:9;3999:17;3990:6;3946:71;:::i;:::-;3802:222;;;;:::o;4030:122::-;4103:24;4121:5;4103:24;:::i;:::-;4096:5;4093:35;4083:63;;4142:1;4139;4132:12;4083:63;4030:122;:::o;4158:139::-;4204:5;4242:6;4229:20;4220:29;;4258:33;4285:5;4258:33;:::i;:::-;4158:139;;;;:::o;4303:474::-;4371:6;4379;4428:2;4416:9;4407:7;4403:23;4399:32;4396:119;;;4434:79;;:::i;:::-;4396:119;4554:1;4579:53;4624:7;4615:6;4604:9;4600:22;4579:53;:::i;:::-;4569:63;;4525:117;4681:2;4707:53;4752:7;4743:6;4732:9;4728:22;4707:53;:::i;:::-;4697:63;;4652:118;4303:474;;;;;:::o;4783:118::-;4870:24;4888:5;4870:24;:::i;:::-;4865:3;4858:37;4783:118;;:::o;4907:222::-;5000:4;5038:2;5027:9;5023:18;5015:26;;5051:71;5119:1;5108:9;5104:17;5095:6;5051:71;:::i;:::-;4907:222;;;;:::o;5135:619::-;5212:6;5220;5228;5277:2;5265:9;5256:7;5252:23;5248:32;5245:119;;;5283:79;;:::i;:::-;5245:119;5403:1;5428:53;5473:7;5464:6;5453:9;5449:22;5428:53;:::i;:::-;5418:63;;5374:117;5530:2;5556:53;5601:7;5592:6;5581:9;5577:22;5556:53;:::i;:::-;5546:63;;5501:118;5658:2;5684:53;5729:7;5720:6;5709:9;5705:22;5684:53;:::i;:::-;5674:63;;5629:118;5135:619;;;;;:::o;5760:77::-;5797:7;5826:5;5815:16;;5760:77;;;:::o;5843:118::-;5930:24;5948:5;5930:24;:::i;:::-;5925:3;5918:37;5843:118;;:::o;5967:222::-;6060:4;6098:2;6087:9;6083:18;6075:26;;6111:71;6179:1;6168:9;6164:17;6155:6;6111:71;:::i;:::-;5967:222;;;;:::o;6195:117::-;6304:1;6301;6294:12;6318:117;6427:1;6424;6417:12;6441:180;6489:77;6486:1;6479:88;6586:4;6583:1;6576:15;6610:4;6607:1;6600:15;6627:281;6710:27;6732:4;6710:27;:::i;:::-;6702:6;6698:40;6840:6;6828:10;6825:22;6804:18;6792:10;6789:34;6786:62;6783:88;;;6851:18;;:::i;:::-;6783:88;6891:10;6887:2;6880:22;6670:238;6627:281;;:::o;6914:129::-;6948:6;6975:20;;:::i;:::-;6965:30;;7004:33;7032:4;7024:6;7004:33;:::i;:::-;6914:129;;;:::o;7049:308::-;7111:4;7201:18;7193:6;7190:30;7187:56;;;7223:18;;:::i;:::-;7187:56;7261:29;7283:6;7261:29;:::i;:::-;7253:37;;7345:4;7339;7335:15;7327:23;;7049:308;;;:::o;7363:148::-;7461:6;7456:3;7451;7438:30;7502:1;7493:6;7488:3;7484:16;7477:27;7363:148;;;:::o;7517:425::-;7595:5;7620:66;7636:49;7678:6;7636:49;:::i;:::-;7620:66;:::i;:::-;7611:75;;7709:6;7702:5;7695:21;7747:4;7740:5;7736:16;7785:3;7776:6;7771:3;7767:16;7764:25;7761:112;;;7792:79;;:::i;:::-;7761:112;7882:54;7929:6;7924:3;7919;7882:54;:::i;:::-;7601:341;7517:425;;;;;:::o;7962:340::-;8018:5;8067:3;8060:4;8052:6;8048:17;8044:27;8034:122;;8075:79;;:::i;:::-;8034:122;8192:6;8179:20;8217:79;8292:3;8284:6;8277:4;8269:6;8265:17;8217:79;:::i;:::-;8208:88;;8024:278;7962:340;;;;:::o;8308:509::-;8377:6;8426:2;8414:9;8405:7;8401:23;8397:32;8394:119;;;8432:79;;:::i;:::-;8394:119;8580:1;8569:9;8565:17;8552:31;8610:18;8602:6;8599:30;8596:117;;;8632:79;;:::i;:::-;8596:117;8737:63;8792:7;8783:6;8772:9;8768:22;8737:63;:::i;:::-;8727:73;;8523:287;8308:509;;;;:::o;8823:329::-;8882:6;8931:2;8919:9;8910:7;8906:23;8902:32;8899:119;;;8937:79;;:::i;:::-;8899:119;9057:1;9082:53;9127:7;9118:6;9107:9;9103:22;9082:53;:::i;:::-;9072:63;;9028:117;8823:329;;;;:::o;9158:122::-;9231:24;9249:5;9231:24;:::i;:::-;9224:5;9221:35;9211:63;;9270:1;9267;9260:12;9211:63;9158:122;:::o;9286:139::-;9332:5;9370:6;9357:20;9348:29;;9386:33;9413:5;9386:33;:::i;:::-;9286:139;;;;:::o;9431:329::-;9490:6;9539:2;9527:9;9518:7;9514:23;9510:32;9507:119;;;9545:79;;:::i;:::-;9507:119;9665:1;9690:53;9735:7;9726:6;9715:9;9711:22;9690:53;:::i;:::-;9680:63;;9636:117;9431:329;;;;:::o;9766:116::-;9836:21;9851:5;9836:21;:::i;:::-;9829:5;9826:32;9816:60;;9872:1;9869;9862:12;9816:60;9766:116;:::o;9888:133::-;9931:5;9969:6;9956:20;9947:29;;9985:30;10009:5;9985:30;:::i;:::-;9888:133;;;;:::o;10027:468::-;10092:6;10100;10149:2;10137:9;10128:7;10124:23;10120:32;10117:119;;;10155:79;;:::i;:::-;10117:119;10275:1;10300:53;10345:7;10336:6;10325:9;10321:22;10300:53;:::i;:::-;10290:63;;10246:117;10402:2;10428:50;10470:7;10461:6;10450:9;10446:22;10428:50;:::i;:::-;10418:60;;10373:115;10027:468;;;;;:::o;10501:117::-;10610:1;10607;10600:12;10624:117;10733:1;10730;10723:12;10764:568;10837:8;10847:6;10897:3;10890:4;10882:6;10878:17;10874:27;10864:122;;10905:79;;:::i;:::-;10864:122;11018:6;11005:20;10995:30;;11048:18;11040:6;11037:30;11034:117;;;11070:79;;:::i;:::-;11034:117;11184:4;11176:6;11172:17;11160:29;;11238:3;11230:4;11222:6;11218:17;11208:8;11204:32;11201:41;11198:128;;;11245:79;;:::i;:::-;11198:128;10764:568;;;;;:::o;11338:559::-;11424:6;11432;11481:2;11469:9;11460:7;11456:23;11452:32;11449:119;;;11487:79;;:::i;:::-;11449:119;11635:1;11624:9;11620:17;11607:31;11665:18;11657:6;11654:30;11651:117;;;11687:79;;:::i;:::-;11651:117;11800:80;11872:7;11863:6;11852:9;11848:22;11800:80;:::i;:::-;11782:98;;;;11578:312;11338:559;;;;;:::o;11916:552::-;11973:8;11983:6;12033:3;12026:4;12018:6;12014:17;12010:27;12000:122;;12041:79;;:::i;:::-;12000:122;12154:6;12141:20;12131:30;;12184:18;12176:6;12173:30;12170:117;;;12206:79;;:::i;:::-;12170:117;12320:4;12312:6;12308:17;12296:29;;12374:3;12366:4;12358:6;12354:17;12344:8;12340:32;12337:41;12334:128;;;12381:79;;:::i;:::-;12334:128;11916:552;;;;;:::o;12474:963::-;12571:6;12579;12587;12595;12603;12652:3;12640:9;12631:7;12627:23;12623:33;12620:120;;;12659:79;;:::i;:::-;12620:120;12779:1;12804:53;12849:7;12840:6;12829:9;12825:22;12804:53;:::i;:::-;12794:63;;12750:117;12906:2;12932:53;12977:7;12968:6;12957:9;12953:22;12932:53;:::i;:::-;12922:63;;12877:118;13034:2;13060:53;13105:7;13096:6;13085:9;13081:22;13060:53;:::i;:::-;13050:63;;13005:118;13190:2;13179:9;13175:18;13162:32;13221:18;13213:6;13210:30;13207:117;;;13243:79;;:::i;:::-;13207:117;13356:64;13412:7;13403:6;13392:9;13388:22;13356:64;:::i;:::-;13338:82;;;;13133:297;12474:963;;;;;;;;:::o;13443:474::-;13511:6;13519;13568:2;13556:9;13547:7;13543:23;13539:32;13536:119;;;13574:79;;:::i;:::-;13536:119;13694:1;13719:53;13764:7;13755:6;13744:9;13740:22;13719:53;:::i;:::-;13709:63;;13665:117;13821:2;13847:53;13892:7;13883:6;13872:9;13868:22;13847:53;:::i;:::-;13837:63;;13792:118;13443:474;;;;;:::o;13923:180::-;13971:77;13968:1;13961:88;14068:4;14065:1;14058:15;14092:4;14089:1;14082:15;14109:320;14153:6;14190:1;14184:4;14180:12;14170:22;;14237:1;14231:4;14227:12;14258:18;14248:81;;14314:4;14306:6;14302:17;14292:27;;14248:81;14376:2;14368:6;14365:14;14345:18;14342:38;14339:84;;14395:18;;:::i;:::-;14339:84;14160:269;14109:320;;;:::o;14435:141::-;14484:4;14507:3;14499:11;;14530:3;14527:1;14520:14;14564:4;14561:1;14551:18;14543:26;;14435:141;;;:::o;14582:93::-;14619:6;14666:2;14661;14654:5;14650:14;14646:23;14636:33;;14582:93;;;:::o;14681:107::-;14725:8;14775:5;14769:4;14765:16;14744:37;;14681:107;;;;:::o;14794:393::-;14863:6;14913:1;14901:10;14897:18;14936:97;14966:66;14955:9;14936:97;:::i;:::-;15054:39;15084:8;15073:9;15054:39;:::i;:::-;15042:51;;15126:4;15122:9;15115:5;15111:21;15102:30;;15175:4;15165:8;15161:19;15154:5;15151:30;15141:40;;14870:317;;14794:393;;;;;:::o;15193:60::-;15221:3;15242:5;15235:12;;15193:60;;;:::o;15259:142::-;15309:9;15342:53;15360:34;15369:24;15387:5;15369:24;:::i;:::-;15360:34;:::i;:::-;15342:53;:::i;:::-;15329:66;;15259:142;;;:::o;15407:75::-;15450:3;15471:5;15464:12;;15407:75;;;:::o;15488:269::-;15598:39;15629:7;15598:39;:::i;:::-;15659:91;15708:41;15732:16;15708:41;:::i;:::-;15700:6;15693:4;15687:11;15659:91;:::i;:::-;15653:4;15646:105;15564:193;15488:269;;;:::o;15763:73::-;15808:3;15763:73;:::o;15842:189::-;15919:32;;:::i;:::-;15960:65;16018:6;16010;16004:4;15960:65;:::i;:::-;15895:136;15842:189;;:::o;16037:186::-;16097:120;16114:3;16107:5;16104:14;16097:120;;;16168:39;16205:1;16198:5;16168:39;:::i;:::-;16141:1;16134:5;16130:13;16121:22;;16097:120;;;16037:186;;:::o;16229:543::-;16330:2;16325:3;16322:11;16319:446;;;16364:38;16396:5;16364:38;:::i;:::-;16448:29;16466:10;16448:29;:::i;:::-;16438:8;16434:44;16631:2;16619:10;16616:18;16613:49;;;16652:8;16637:23;;16613:49;16675:80;16731:22;16749:3;16731:22;:::i;:::-;16721:8;16717:37;16704:11;16675:80;:::i;:::-;16334:431;;16319:446;16229:543;;;:::o;16778:117::-;16832:8;16882:5;16876:4;16872:16;16851:37;;16778:117;;;;:::o;16901:169::-;16945:6;16978:51;17026:1;17022:6;17014:5;17011:1;17007:13;16978:51;:::i;:::-;16974:56;17059:4;17053;17049:15;17039:25;;16952:118;16901:169;;;;:::o;17075:295::-;17151:4;17297:29;17322:3;17316:4;17297:29;:::i;:::-;17289:37;;17359:3;17356:1;17352:11;17346:4;17343:21;17335:29;;17075:295;;;;:::o;17375:1395::-;17492:37;17525:3;17492:37;:::i;:::-;17594:18;17586:6;17583:30;17580:56;;;17616:18;;:::i;:::-;17580:56;17660:38;17692:4;17686:11;17660:38;:::i;:::-;17745:67;17805:6;17797;17791:4;17745:67;:::i;:::-;17839:1;17863:4;17850:17;;17895:2;17887:6;17884:14;17912:1;17907:618;;;;18569:1;18586:6;18583:77;;;18635:9;18630:3;18626:19;18620:26;18611:35;;18583:77;18686:67;18746:6;18739:5;18686:67;:::i;:::-;18680:4;18673:81;18542:222;17877:887;;17907:618;17959:4;17955:9;17947:6;17943:22;17993:37;18025:4;17993:37;:::i;:::-;18052:1;18066:208;18080:7;18077:1;18074:14;18066:208;;;18159:9;18154:3;18150:19;18144:26;18136:6;18129:42;18210:1;18202:6;18198:14;18188:24;;18257:2;18246:9;18242:18;18229:31;;18103:4;18100:1;18096:12;18091:17;;18066:208;;;18302:6;18293:7;18290:19;18287:179;;;18360:9;18355:3;18351:19;18345:26;18403:48;18445:4;18437:6;18433:17;18422:9;18403:48;:::i;:::-;18395:6;18388:64;18310:156;18287:179;18512:1;18508;18500:6;18496:14;18492:22;18486:4;18479:36;17914:611;;;17877:887;;17467:1303;;;17375:1395;;:::o;18776:94::-;18809:8;18857:5;18853:2;18849:14;18828:35;;18776:94;;;:::o;18876:::-;18915:7;18944:20;18958:5;18944:20;:::i;:::-;18933:31;;18876:94;;;:::o;18976:100::-;19015:7;19044:26;19064:5;19044:26;:::i;:::-;19033:37;;18976:100;;;:::o;19082:157::-;19187:45;19207:24;19225:5;19207:24;:::i;:::-;19187:45;:::i;:::-;19182:3;19175:58;19082:157;;:::o;19245:256::-;19357:3;19372:75;19443:3;19434:6;19372:75;:::i;:::-;19472:2;19467:3;19463:12;19456:19;;19492:3;19485:10;;19245:256;;;;:::o;19507:180::-;19555:77;19552:1;19545:88;19652:4;19649:1;19642:15;19676:4;19673:1;19666:15;19693:233;19732:3;19755:24;19773:5;19755:24;:::i;:::-;19746:33;;19801:66;19794:5;19791:77;19788:103;;19871:18;;:::i;:::-;19788:103;19918:1;19911:5;19907:13;19900:20;;19693:233;;;:::o

Swarm Source

ipfs://77425466c2d79db1fc8da310f717f43aa7fd014b71d764ed674ff6b636839562
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.