creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/MajesticBeetlez.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n\n\n\n\n\n// \n// ███╗   ███╗ █████╗      ██╗███████╗███████╗████████╗██╗ ██████╗    ██████╗ ███████╗███████╗████████╗██╗     ███████╗███████╗\n// ████╗ ████║██╔══██╗     ██║██╔════╝██╔════╝╚══██╔══╝██║██╔════╝    ██╔══██╗██╔════╝██╔════╝╚══██╔══╝██║     ██╔════╝╚══███╔╝\n// ██╔████╔██║███████║     ██║█████╗  ███████╗   ██║   ██║██║         ██████╔╝█████╗  █████╗     ██║   ██║     █████╗    ███╔╝ \n// ██║╚██╔╝██║██╔══██║██   ██║██╔══╝  ╚════██║   ██║   ██║██║         ██╔══██╗██╔══╝  ██╔══╝     ██║   ██║     ██╔══╝   ███╔╝  \n// ██║ ╚═╝ ██║██║  ██║╚█████╔╝███████╗███████║   ██║   ██║╚██████╗    ██████╔╝███████╗███████╗   ██║   ███████╗███████╗███████╗\n// ╚═╝     ╚═╝╚═╝  ╚═╝ ╚════╝ ╚══════╝╚══════╝   ╚═╝   ╚═╝ ╚═════╝    ╚═════╝ ╚══════╝╚══════╝   ╚═╝   ╚══════╝╚══════╝╚══════╝\n//                                                                                                                             \n// Majestic Beetlez - generated with HeyMint.xyz Launchpad - https://nft-launchpad.heymint.xyz\n// \n\n\n\n\n\n\n\n\nimport {StorageSlot} from \"@openzeppelin/contracts/utils/StorageSlot.sol\";\nimport {IAddressRelay} from \"./interfaces/IAddressRelay.sol\";\nimport {BaseConfig} from \"./libraries/HeyMintStorage.sol\";\n\ncontract MajesticBeetlez {\n    bytes32 internal constant _IMPLEMENTATION_SLOT =\n        0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n    bytes32 internal constant _ADDRESS_RELAY_SLOT =\n        keccak256(\"heymint.launchpad.addressRelay\");\n\n    /**\n     * @notice Initializes the child contract with the base implementation address and the configuration settings\n     * @param _name The name of the NFT\n     * @param _symbol The symbol of the NFT\n     * @param _baseConfig Base configuration settings\n     */\n    constructor(\n        string memory _name,\n        string memory _symbol,\n        address _addressRelay,\n        address _implementation,\n        BaseConfig memory _baseConfig\n    ) {\n        StorageSlot\n            .getAddressSlot(_IMPLEMENTATION_SLOT)\n            .value = _implementation;\n        StorageSlot.getAddressSlot(_ADDRESS_RELAY_SLOT).value = _addressRelay;\n        IAddressRelay addressRelay = IAddressRelay(\n            StorageSlot.getAddressSlot(_ADDRESS_RELAY_SLOT).value\n        );\n        address implContract = addressRelay.fallbackImplAddress();\n        (bool success, ) = implContract.delegatecall(\n            abi.encodeWithSelector(0xfdd7fbcc, _name, _symbol, _baseConfig)\n        );\n        require(success);\n    }\n\n    /**\n     * @dev Delegates the current call to nftImplementation\n     *\n     * This function does not return to its internal call site - it will return directly to the external caller.\n     */\n    fallback() external payable {\n        IAddressRelay addressRelay = IAddressRelay(\n            StorageSlot.getAddressSlot(_ADDRESS_RELAY_SLOT).value\n        );\n        address implContract = addressRelay.getImplAddress(msg.sig);\n\n        assembly {\n            calldatacopy(0, 0, calldatasize())\n            let result := delegatecall(\n                gas(),\n                implContract,\n                0,\n                calldatasize(),\n                0,\n                0\n            )\n            returndatacopy(0, 0, returndatasize())\n            switch result\n            case 0 {\n                revert(0, returndatasize())\n            }\n            default {\n                return(0, returndatasize())\n            }\n        }\n    }\n\n    receive() external payable {}\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/interfaces/IERC2981Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Interface for the NFT Royalty Standard.\n *\n * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal\n * support for royalty payments across all NFT marketplaces and ecosystem participants.\n *\n * _Available since v4.5._\n */\ninterface IERC2981Upgradeable is IERC165Upgradeable {\n    /**\n     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of\n     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.\n     */\n    function royaltyInfo(uint256 tokenId, uint256 salePrice)\n        external\n        view\n        returns (address receiver, uint256 royaltyAmount);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized < type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    function __Pausable_init() internal onlyInitializing {\n        __Pausable_init_unchained();\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        require(!paused(), \"Pausable: paused\");\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        require(paused(), \"Pausable: not paused\");\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../StringsUpgradeable.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV // Deprecated in v4.8\n    }\n\n    function _throwError(RecoverError error) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert(\"ECDSA: invalid signature\");\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert(\"ECDSA: invalid signature length\");\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert(\"ECDSA: invalid signature 's' value\");\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature` or error string. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            /// @solidity memory-safe-assembly\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength);\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, signature);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address, RecoverError) {\n        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n        uint8 v = uint8((uint256(vs) >> 255) + 27);\n        return tryRecover(hash, v, r, s);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     *\n     * _Available since v4.2._\n     */\n    function recover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address, RecoverError) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature);\n        }\n\n        return (signer, RecoverError.NoError);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n        // 32 is the length in bytes of hash,\n        // enforced by the type signature above\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from `s`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", StringsUpgradeable.toString(s.length), s));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Typed Data, created from a\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\n     * to the one signed with the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n     * JSON-RPC method as part of EIP-712.\n     *\n     * See {recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProofUpgradeable {\n    /**\n     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n     * defined by `root`. For this, a `proof` must be provided, containing\n     * sibling hashes on the branch from the leaf to the root of the tree. Each\n     * pair of leaves and each pair of pre-images are assumed to be sorted.\n     */\n    function verify(\n        bytes32[] memory proof,\n        bytes32 root,\n        bytes32 leaf\n    ) internal pure returns (bool) {\n        return processProof(proof, leaf) == root;\n    }\n\n    /**\n     * @dev Calldata version of {verify}\n     *\n     * _Available since v4.7._\n     */\n    function verifyCalldata(\n        bytes32[] calldata proof,\n        bytes32 root,\n        bytes32 leaf\n    ) internal pure returns (bool) {\n        return processProofCalldata(proof, leaf) == root;\n    }\n\n    /**\n     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n     * hash matches the root of the tree. When processing the proof, the pairs\n     * of leafs & pre-images are assumed to be sorted.\n     *\n     * _Available since v4.4._\n     */\n    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n        bytes32 computedHash = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            computedHash = _hashPair(computedHash, proof[i]);\n        }\n        return computedHash;\n    }\n\n    /**\n     * @dev Calldata version of {processProof}\n     *\n     * _Available since v4.7._\n     */\n    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n        bytes32 computedHash = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            computedHash = _hashPair(computedHash, proof[i]);\n        }\n        return computedHash;\n    }\n\n    /**\n     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n     *\n     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n     *\n     * _Available since v4.7._\n     */\n    function multiProofVerify(\n        bytes32[] memory proof,\n        bool[] memory proofFlags,\n        bytes32 root,\n        bytes32[] memory leaves\n    ) internal pure returns (bool) {\n        return processMultiProof(proof, proofFlags, leaves) == root;\n    }\n\n    /**\n     * @dev Calldata version of {multiProofVerify}\n     *\n     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n     *\n     * _Available since v4.7._\n     */\n    function multiProofVerifyCalldata(\n        bytes32[] calldata proof,\n        bool[] calldata proofFlags,\n        bytes32 root,\n        bytes32[] memory leaves\n    ) internal pure returns (bool) {\n        return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n    }\n\n    /**\n     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n     * respectively.\n     *\n     * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n     *\n     * _Available since v4.7._\n     */\n    function processMultiProof(\n        bytes32[] memory proof,\n        bool[] memory proofFlags,\n        bytes32[] memory leaves\n    ) internal pure returns (bytes32 merkleRoot) {\n        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\n        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n        // the merkle tree.\n        uint256 leavesLen = leaves.length;\n        uint256 totalHashes = proofFlags.length;\n\n        // Check proof validity.\n        require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n        // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n        bytes32[] memory hashes = new bytes32[](totalHashes);\n        uint256 leafPos = 0;\n        uint256 hashPos = 0;\n        uint256 proofPos = 0;\n        // At each step, we compute the next hash using two values:\n        // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n        //   get the next hash.\n        // - depending on the flag, either another value for the \"main queue\" (merging branches) or an element from the\n        //   `proof` array.\n        for (uint256 i = 0; i < totalHashes; i++) {\n            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\n            hashes[i] = _hashPair(a, b);\n        }\n\n        if (totalHashes > 0) {\n            return hashes[totalHashes - 1];\n        } else if (leavesLen > 0) {\n            return leaves[0];\n        } else {\n            return proof[0];\n        }\n    }\n\n    /**\n     * @dev Calldata version of {processMultiProof}.\n     *\n     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n     *\n     * _Available since v4.7._\n     */\n    function processMultiProofCalldata(\n        bytes32[] calldata proof,\n        bool[] calldata proofFlags,\n        bytes32[] memory leaves\n    ) internal pure returns (bytes32 merkleRoot) {\n        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\n        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n        // the merkle tree.\n        uint256 leavesLen = leaves.length;\n        uint256 totalHashes = proofFlags.length;\n\n        // Check proof validity.\n        require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n        // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n        bytes32[] memory hashes = new bytes32[](totalHashes);\n        uint256 leafPos = 0;\n        uint256 hashPos = 0;\n        uint256 proofPos = 0;\n        // At each step, we compute the next hash using two values:\n        // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n        //   get the next hash.\n        // - depending on the flag, either another value for the \"main queue\" (merging branches) or an element from the\n        //   `proof` array.\n        for (uint256 i = 0; i < totalHashes; i++) {\n            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\n            hashes[i] = _hashPair(a, b);\n        }\n\n        if (totalHashes > 0) {\n            return hashes[totalHashes - 1];\n        } else if (leavesLen > 0) {\n            return leaves[0];\n        } else {\n            return proof[0];\n        }\n    }\n\n    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n    }\n\n    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, a)\n            mstore(0x20, b)\n            value := keccak256(0x00, 0x40)\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1);\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator,\n        Rounding rounding\n    ) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10**64) {\n                value /= 10**64;\n                result += 64;\n            }\n            if (value >= 10**32) {\n                value /= 10**32;\n                result += 32;\n            }\n            if (value >= 10**16) {\n                value /= 10**16;\n                result += 16;\n            }\n            if (value >= 10**8) {\n                value /= 10**8;\n                result += 8;\n            }\n            if (value >= 10**4) {\n                value /= 10**4;\n                result += 4;\n            }\n            if (value >= 10**2) {\n                value /= 10**2;\n                result += 2;\n            }\n            if (value >= 10**1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = MathUpgradeable.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, MathUpgradeable.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n}\n"
      },
      "@openzeppelin/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "@openzeppelin/contracts/interfaces/IERC2981.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Interface for the NFT Royalty Standard.\n *\n * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal\n * support for royalty payments across all NFT marketplaces and ecosystem participants.\n *\n * _Available since v4.5._\n */\ninterface IERC2981 is IERC165 {\n    /**\n     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of\n     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.\n     */\n    function royaltyInfo(uint256 tokenId, uint256 salePrice)\n        external\n        view\n        returns (address receiver, uint256 royaltyAmount);\n}\n"
      },
      "@openzeppelin/contracts/security/Pausable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    constructor() {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        require(!paused(), \"Pausable: paused\");\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        require(paused(), \"Pausable: not paused\");\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"
      },
      "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    constructor() {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/common/ERC2981.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/IERC2981.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.\n *\n * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for\n * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.\n *\n * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the\n * fee is specified in basis points by default.\n *\n * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See\n * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to\n * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.\n *\n * _Available since v4.5._\n */\nabstract contract ERC2981 is IERC2981, ERC165 {\n    struct RoyaltyInfo {\n        address receiver;\n        uint96 royaltyFraction;\n    }\n\n    RoyaltyInfo private _defaultRoyaltyInfo;\n    mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @inheritdoc IERC2981\n     */\n    function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) {\n        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];\n\n        if (royalty.receiver == address(0)) {\n            royalty = _defaultRoyaltyInfo;\n        }\n\n        uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();\n\n        return (royalty.receiver, royaltyAmount);\n    }\n\n    /**\n     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a\n     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an\n     * override.\n     */\n    function _feeDenominator() internal pure virtual returns (uint96) {\n        return 10000;\n    }\n\n    /**\n     * @dev Sets the royalty information that all ids in this contract will default to.\n     *\n     * Requirements:\n     *\n     * - `receiver` cannot be the zero address.\n     * - `feeNumerator` cannot be greater than the fee denominator.\n     */\n    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {\n        require(feeNumerator <= _feeDenominator(), \"ERC2981: royalty fee will exceed salePrice\");\n        require(receiver != address(0), \"ERC2981: invalid receiver\");\n\n        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);\n    }\n\n    /**\n     * @dev Removes default royalty information.\n     */\n    function _deleteDefaultRoyalty() internal virtual {\n        delete _defaultRoyaltyInfo;\n    }\n\n    /**\n     * @dev Sets the royalty information for a specific token id, overriding the global default.\n     *\n     * Requirements:\n     *\n     * - `receiver` cannot be the zero address.\n     * - `feeNumerator` cannot be greater than the fee denominator.\n     */\n    function _setTokenRoyalty(\n        uint256 tokenId,\n        address receiver,\n        uint96 feeNumerator\n    ) internal virtual {\n        require(feeNumerator <= _feeDenominator(), \"ERC2981: royalty fee will exceed salePrice\");\n        require(receiver != address(0), \"ERC2981: Invalid parameters\");\n\n        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);\n    }\n\n    /**\n     * @dev Resets royalty information for the token id back to the global default.\n     */\n    function _resetTokenRoyalty(uint256 tokenId) internal virtual {\n        delete _tokenRoyaltyInfo[tokenId];\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC1155/ERC1155.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n    using Address for address;\n\n    // Mapping from token ID to account balances\n    mapping(uint256 => mapping(address => uint256)) private _balances;\n\n    // Mapping from account to operator approvals\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n    // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n    string private _uri;\n\n    /**\n     * @dev See {_setURI}.\n     */\n    constructor(string memory uri_) {\n        _setURI(uri_);\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n        return\n            interfaceId == type(IERC1155).interfaceId ||\n            interfaceId == type(IERC1155MetadataURI).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC1155MetadataURI-uri}.\n     *\n     * This implementation returns the same URI for *all* token types. It relies\n     * on the token type ID substitution mechanism\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n     *\n     * Clients calling this function must replace the `\\{id\\}` substring with the\n     * actual token type ID.\n     */\n    function uri(uint256) public view virtual override returns (string memory) {\n        return _uri;\n    }\n\n    /**\n     * @dev See {IERC1155-balanceOf}.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n        require(account != address(0), \"ERC1155: address zero is not a valid owner\");\n        return _balances[id][account];\n    }\n\n    /**\n     * @dev See {IERC1155-balanceOfBatch}.\n     *\n     * Requirements:\n     *\n     * - `accounts` and `ids` must have the same length.\n     */\n    function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\n        public\n        view\n        virtual\n        override\n        returns (uint256[] memory)\n    {\n        require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n        uint256[] memory batchBalances = new uint256[](accounts.length);\n\n        for (uint256 i = 0; i < accounts.length; ++i) {\n            batchBalances[i] = balanceOf(accounts[i], ids[i]);\n        }\n\n        return batchBalances;\n    }\n\n    /**\n     * @dev See {IERC1155-setApprovalForAll}.\n     */\n    function setApprovalForAll(address operator, bool approved) public virtual override {\n        _setApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /**\n     * @dev See {IERC1155-isApprovedForAll}.\n     */\n    function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n        return _operatorApprovals[account][operator];\n    }\n\n    /**\n     * @dev See {IERC1155-safeTransferFrom}.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) public virtual override {\n        require(\n            from == _msgSender() || isApprovedForAll(from, _msgSender()),\n            \"ERC1155: caller is not token owner or approved\"\n        );\n        _safeTransferFrom(from, to, id, amount, data);\n    }\n\n    /**\n     * @dev See {IERC1155-safeBatchTransferFrom}.\n     */\n    function safeBatchTransferFrom(\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) public virtual override {\n        require(\n            from == _msgSender() || isApprovedForAll(from, _msgSender()),\n            \"ERC1155: caller is not token owner or approved\"\n        );\n        _safeBatchTransferFrom(from, to, ids, amounts, data);\n    }\n\n    /**\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n     *\n     * Emits a {TransferSingle} event.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n     * acceptance magic value.\n     */\n    function _safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) internal virtual {\n        require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n        address operator = _msgSender();\n        uint256[] memory ids = _asSingletonArray(id);\n        uint256[] memory amounts = _asSingletonArray(amount);\n\n        _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n        uint256 fromBalance = _balances[id][from];\n        require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n        unchecked {\n            _balances[id][from] = fromBalance - amount;\n        }\n        _balances[id][to] += amount;\n\n        emit TransferSingle(operator, from, to, id, amount);\n\n        _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n    }\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\n     *\n     * Emits a {TransferBatch} event.\n     *\n     * Requirements:\n     *\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n     * acceptance magic value.\n     */\n    function _safeBatchTransferFrom(\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal virtual {\n        require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n        require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n        address operator = _msgSender();\n\n        _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n        for (uint256 i = 0; i < ids.length; ++i) {\n            uint256 id = ids[i];\n            uint256 amount = amounts[i];\n\n            uint256 fromBalance = _balances[id][from];\n            require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n            unchecked {\n                _balances[id][from] = fromBalance - amount;\n            }\n            _balances[id][to] += amount;\n        }\n\n        emit TransferBatch(operator, from, to, ids, amounts);\n\n        _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n        _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n    }\n\n    /**\n     * @dev Sets a new URI for all token types, by relying on the token type ID\n     * substitution mechanism\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n     *\n     * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n     * URI or any of the amounts in the JSON file at said URI will be replaced by\n     * clients with the token type ID.\n     *\n     * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n     * interpreted by clients as\n     * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n     * for token type ID 0x4cce0.\n     *\n     * See {uri}.\n     *\n     * Because these URIs cannot be meaningfully represented by the {URI} event,\n     * this function emits no events.\n     */\n    function _setURI(string memory newuri) internal virtual {\n        _uri = newuri;\n    }\n\n    /**\n     * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\n     *\n     * Emits a {TransferSingle} event.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n     * acceptance magic value.\n     */\n    function _mint(\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) internal virtual {\n        require(to != address(0), \"ERC1155: mint to the zero address\");\n\n        address operator = _msgSender();\n        uint256[] memory ids = _asSingletonArray(id);\n        uint256[] memory amounts = _asSingletonArray(amount);\n\n        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n        _balances[id][to] += amount;\n        emit TransferSingle(operator, address(0), to, id, amount);\n\n        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n        _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\n    }\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n     *\n     * Emits a {TransferBatch} event.\n     *\n     * Requirements:\n     *\n     * - `ids` and `amounts` must have the same length.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n     * acceptance magic value.\n     */\n    function _mintBatch(\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal virtual {\n        require(to != address(0), \"ERC1155: mint to the zero address\");\n        require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n        address operator = _msgSender();\n\n        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n        for (uint256 i = 0; i < ids.length; i++) {\n            _balances[ids[i]][to] += amounts[i];\n        }\n\n        emit TransferBatch(operator, address(0), to, ids, amounts);\n\n        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n        _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens of token type `id` from `from`\n     *\n     * Emits a {TransferSingle} event.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `from` must have at least `amount` tokens of token type `id`.\n     */\n    function _burn(\n        address from,\n        uint256 id,\n        uint256 amount\n    ) internal virtual {\n        require(from != address(0), \"ERC1155: burn from the zero address\");\n\n        address operator = _msgSender();\n        uint256[] memory ids = _asSingletonArray(id);\n        uint256[] memory amounts = _asSingletonArray(amount);\n\n        _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n        uint256 fromBalance = _balances[id][from];\n        require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n        unchecked {\n            _balances[id][from] = fromBalance - amount;\n        }\n\n        emit TransferSingle(operator, from, address(0), id, amount);\n\n        _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n    }\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n     *\n     * Emits a {TransferBatch} event.\n     *\n     * Requirements:\n     *\n     * - `ids` and `amounts` must have the same length.\n     */\n    function _burnBatch(\n        address from,\n        uint256[] memory ids,\n        uint256[] memory amounts\n    ) internal virtual {\n        require(from != address(0), \"ERC1155: burn from the zero address\");\n        require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n        address operator = _msgSender();\n\n        _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n        for (uint256 i = 0; i < ids.length; i++) {\n            uint256 id = ids[i];\n            uint256 amount = amounts[i];\n\n            uint256 fromBalance = _balances[id][from];\n            require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n            unchecked {\n                _balances[id][from] = fromBalance - amount;\n            }\n        }\n\n        emit TransferBatch(operator, from, address(0), ids, amounts);\n\n        _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n    }\n\n    /**\n     * @dev Approve `operator` to operate on all of `owner` tokens\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function _setApprovalForAll(\n        address owner,\n        address operator,\n        bool approved\n    ) internal virtual {\n        require(owner != operator, \"ERC1155: setting approval status for self\");\n        _operatorApprovals[owner][operator] = approved;\n        emit ApprovalForAll(owner, operator, approved);\n    }\n\n    /**\n     * @dev Hook that is called before any token transfer. This includes minting\n     * and burning, as well as batched variants.\n     *\n     * The same hook is called on both single and batched variants. For single\n     * transfers, the length of the `ids` and `amounts` arrays will be 1.\n     *\n     * Calling conditions (for each `id` and `amount` pair):\n     *\n     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * of token type `id` will be  transferred to `to`.\n     * - When `from` is zero, `amount` tokens of token type `id` will be minted\n     * for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n     * will be burned.\n     * - `from` and `to` are never both zero.\n     * - `ids` and `amounts` have the same, non-zero length.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address operator,\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any token transfer. This includes minting\n     * and burning, as well as batched variants.\n     *\n     * The same hook is called on both single and batched variants. For single\n     * transfers, the length of the `id` and `amount` arrays will be 1.\n     *\n     * Calling conditions (for each `id` and `amount` pair):\n     *\n     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * of token type `id` will be  transferred to `to`.\n     * - When `from` is zero, `amount` tokens of token type `id` will be minted\n     * for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n     * will be burned.\n     * - `from` and `to` are never both zero.\n     * - `ids` and `amounts` have the same, non-zero length.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(\n        address operator,\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal virtual {}\n\n    function _doSafeTransferAcceptanceCheck(\n        address operator,\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) private {\n        if (to.isContract()) {\n            try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n                if (response != IERC1155Receiver.onERC1155Received.selector) {\n                    revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n                }\n            } catch Error(string memory reason) {\n                revert(reason);\n            } catch {\n                revert(\"ERC1155: transfer to non-ERC1155Receiver implementer\");\n            }\n        }\n    }\n\n    function _doSafeBatchTransferAcceptanceCheck(\n        address operator,\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) private {\n        if (to.isContract()) {\n            try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\n                bytes4 response\n            ) {\n                if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\n                    revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n                }\n            } catch Error(string memory reason) {\n                revert(reason);\n            } catch {\n                revert(\"ERC1155: transfer to non-ERC1155Receiver implementer\");\n            }\n        }\n    }\n\n    function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n        uint256[] memory array = new uint256[](1);\n        array[0] = element;\n\n        return array;\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\n\n/**\n * @dev Extension of ERC1155 that adds tracking of total supply per id.\n *\n * Useful for scenarios where Fungible and Non-fungible tokens have to be\n * clearly identified. Note: While a totalSupply of 1 might mean the\n * corresponding is an NFT, there is no guarantees that no other token with the\n * same id are not going to be minted.\n */\nabstract contract ERC1155Supply is ERC1155 {\n    mapping(uint256 => uint256) private _totalSupply;\n\n    /**\n     * @dev Total amount of tokens in with a given id.\n     */\n    function totalSupply(uint256 id) public view virtual returns (uint256) {\n        return _totalSupply[id];\n    }\n\n    /**\n     * @dev Indicates whether any token exist with a given id, or not.\n     */\n    function exists(uint256 id) public view virtual returns (bool) {\n        return ERC1155Supply.totalSupply(id) > 0;\n    }\n\n    /**\n     * @dev See {ERC1155-_beforeTokenTransfer}.\n     */\n    function _beforeTokenTransfer(\n        address operator,\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal virtual override {\n        super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n        if (from == address(0)) {\n            for (uint256 i = 0; i < ids.length; ++i) {\n                _totalSupply[ids[i]] += amounts[i];\n            }\n        }\n\n        if (to == address(0)) {\n            for (uint256 i = 0; i < ids.length; ++i) {\n                uint256 id = ids[i];\n                uint256 amount = amounts[i];\n                uint256 supply = _totalSupply[id];\n                require(supply >= amount, \"ERC1155: burn amount exceeds totalSupply\");\n                unchecked {\n                    _totalSupply[id] = supply - amount;\n                }\n            }\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n    /**\n     * @dev Returns the URI for token type `id`.\n     *\n     * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n     * clients with the actual token type ID.\n     */\n    function uri(uint256 id) external view returns (string memory);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n    /**\n     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n     */\n    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n    /**\n     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n     * transfers.\n     */\n    event TransferBatch(\n        address indexed operator,\n        address indexed from,\n        address indexed to,\n        uint256[] ids,\n        uint256[] values\n    );\n\n    /**\n     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n     * `approved`.\n     */\n    event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n    /**\n     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n     *\n     * If an {URI} event was emitted for `id`, the standard\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n     * returned by {IERC1155MetadataURI-uri}.\n     */\n    event URI(string value, uint256 indexed id);\n\n    /**\n     * @dev Returns the amount of tokens of token type `id` owned by `account`.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function balanceOf(address account, uint256 id) external view returns (uint256);\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n     *\n     * Requirements:\n     *\n     * - `accounts` and `ids` must have the same length.\n     */\n    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n        external\n        view\n        returns (uint256[] memory);\n\n    /**\n     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n     *\n     * Emits an {ApprovalForAll} event.\n     *\n     * Requirements:\n     *\n     * - `operator` cannot be the caller.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n     *\n     * See {setApprovalForAll}.\n     */\n    function isApprovedForAll(address account, address operator) external view returns (bool);\n\n    /**\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n     *\n     * Emits a {TransferSingle} event.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n     * acceptance magic value.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes calldata data\n    ) external;\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n     *\n     * Emits a {TransferBatch} event.\n     *\n     * Requirements:\n     *\n     * - `ids` and `amounts` must have the same length.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n     * acceptance magic value.\n     */\n    function safeBatchTransferFrom(\n        address from,\n        address to,\n        uint256[] calldata ids,\n        uint256[] calldata amounts,\n        bytes calldata data\n    ) external;\n}\n"
      },
      "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n    /**\n     * @dev Handles the receipt of a single ERC1155 token type. This function is\n     * called at the end of a `safeTransferFrom` after the balance has been updated.\n     *\n     * NOTE: To accept the transfer, this must return\n     * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n     * (i.e. 0xf23a6e61, or its own function selector).\n     *\n     * @param operator The address which initiated the transfer (i.e. msg.sender)\n     * @param from The address which previously owned the token\n     * @param id The ID of the token being transferred\n     * @param value The amount of tokens being transferred\n     * @param data Additional data with no specified format\n     * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n     */\n    function onERC1155Received(\n        address operator,\n        address from,\n        uint256 id,\n        uint256 value,\n        bytes calldata data\n    ) external returns (bytes4);\n\n    /**\n     * @dev Handles the receipt of a multiple ERC1155 token types. This function\n     * is called at the end of a `safeBatchTransferFrom` after the balances have\n     * been updated.\n     *\n     * NOTE: To accept the transfer(s), this must return\n     * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n     * (i.e. 0xbc197c81, or its own function selector).\n     *\n     * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n     * @param from The address which previously owned the token\n     * @param ids An array containing ids of each token being transferred (order and length must match values array)\n     * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n     * @param data Additional data with no specified format\n     * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n     */\n    function onERC1155BatchReceived(\n        address operator,\n        address from,\n        uint256[] calldata ids,\n        uint256[] calldata values,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC721/ERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.2) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n    using Address for address;\n    using Strings for uint256;\n\n    // Token name\n    string private _name;\n\n    // Token symbol\n    string private _symbol;\n\n    // Mapping from token ID to owner address\n    mapping(uint256 => address) private _owners;\n\n    // Mapping owner address to token count\n    mapping(address => uint256) private _balances;\n\n    // Mapping from token ID to approved address\n    mapping(uint256 => address) private _tokenApprovals;\n\n    // Mapping from owner to operator approvals\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n    /**\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n        return\n            interfaceId == type(IERC721).interfaceId ||\n            interfaceId == type(IERC721Metadata).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC721-balanceOf}.\n     */\n    function balanceOf(address owner) public view virtual override returns (uint256) {\n        require(owner != address(0), \"ERC721: address zero is not a valid owner\");\n        return _balances[owner];\n    }\n\n    /**\n     * @dev See {IERC721-ownerOf}.\n     */\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n        address owner = _ownerOf(tokenId);\n        require(owner != address(0), \"ERC721: invalid token ID\");\n        return owner;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-name}.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-symbol}.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-tokenURI}.\n     */\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n        _requireMinted(tokenId);\n\n        string memory baseURI = _baseURI();\n        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n    }\n\n    /**\n     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n     * by default, can be overridden in child contracts.\n     */\n    function _baseURI() internal view virtual returns (string memory) {\n        return \"\";\n    }\n\n    /**\n     * @dev See {IERC721-approve}.\n     */\n    function approve(address to, uint256 tokenId) public virtual override {\n        address owner = ERC721.ownerOf(tokenId);\n        require(to != owner, \"ERC721: approval to current owner\");\n\n        require(\n            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n            \"ERC721: approve caller is not token owner or approved for all\"\n        );\n\n        _approve(to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-getApproved}.\n     */\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\n        _requireMinted(tokenId);\n\n        return _tokenApprovals[tokenId];\n    }\n\n    /**\n     * @dev See {IERC721-setApprovalForAll}.\n     */\n    function setApprovalForAll(address operator, bool approved) public virtual override {\n        _setApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /**\n     * @dev See {IERC721-isApprovedForAll}.\n     */\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n        return _operatorApprovals[owner][operator];\n    }\n\n    /**\n     * @dev See {IERC721-transferFrom}.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) public virtual override {\n        //solhint-disable-next-line max-line-length\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n\n        _transfer(from, to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) public virtual override {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) public virtual override {\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n        _safeTransfer(from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * `data` is additional data, it has no specified format and it is sent in call to `to`.\n     *\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeTransfer(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal virtual {\n        _transfer(from, to, tokenId);\n        require(_checkOnERC721Received(from, to, tokenId, data), \"ERC721: transfer to non ERC721Receiver implementer\");\n    }\n\n    /**\n     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n     */\n    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n        return _owners[tokenId];\n    }\n\n    /**\n     * @dev Returns whether `tokenId` exists.\n     *\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n     *\n     * Tokens start existing when they are minted (`_mint`),\n     * and stop existing when they are burned (`_burn`).\n     */\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\n        return _ownerOf(tokenId) != address(0);\n    }\n\n    /**\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n        address owner = ERC721.ownerOf(tokenId);\n        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n    }\n\n    /**\n     * @dev Safely mints `tokenId` and transfers it to `to`.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeMint(address to, uint256 tokenId) internal virtual {\n        _safeMint(to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeMint(\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal virtual {\n        _mint(to, tokenId);\n        require(\n            _checkOnERC721Received(address(0), to, tokenId, data),\n            \"ERC721: transfer to non ERC721Receiver implementer\"\n        );\n    }\n\n    /**\n     * @dev Mints `tokenId` and transfers it to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - `to` cannot be the zero address.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _mint(address to, uint256 tokenId) internal virtual {\n        require(to != address(0), \"ERC721: mint to the zero address\");\n        require(!_exists(tokenId), \"ERC721: token already minted\");\n\n        _beforeTokenTransfer(address(0), to, tokenId, 1);\n\n        // Check that tokenId was not minted by `_beforeTokenTransfer` hook\n        require(!_exists(tokenId), \"ERC721: token already minted\");\n\n        unchecked {\n            // Will not overflow unless all 2**256 token ids are minted to the same owner.\n            // Given that tokens are minted one by one, it is impossible in practice that\n            // this ever happens. Might change if we allow batch minting.\n            // The ERC fails to describe this case.\n            _balances[to] += 1;\n        }\n\n        _owners[tokenId] = to;\n\n        emit Transfer(address(0), to, tokenId);\n\n        _afterTokenTransfer(address(0), to, tokenId, 1);\n    }\n\n    /**\n     * @dev Destroys `tokenId`.\n     * The approval is cleared when the token is burned.\n     * This is an internal function that does not check if the sender is authorized to operate on the token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _burn(uint256 tokenId) internal virtual {\n        address owner = ERC721.ownerOf(tokenId);\n\n        _beforeTokenTransfer(owner, address(0), tokenId, 1);\n\n        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\n        owner = ERC721.ownerOf(tokenId);\n\n        // Clear approvals\n        delete _tokenApprovals[tokenId];\n\n        unchecked {\n            // Cannot overflow, as that would require more tokens to be burned/transferred\n            // out than the owner initially received through minting and transferring in.\n            _balances[owner] -= 1;\n        }\n        delete _owners[tokenId];\n\n        emit Transfer(owner, address(0), tokenId);\n\n        _afterTokenTransfer(owner, address(0), tokenId, 1);\n    }\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _transfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {\n        require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n        require(to != address(0), \"ERC721: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, tokenId, 1);\n\n        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\n        require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n\n        // Clear approvals from the previous owner\n        delete _tokenApprovals[tokenId];\n\n        unchecked {\n            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\n            // `from`'s balance is the number of token held, which is at least one before the current\n            // transfer.\n            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\n            // all 2**256 token ids to be minted, which in practice is impossible.\n            _balances[from] -= 1;\n            _balances[to] += 1;\n        }\n        _owners[tokenId] = to;\n\n        emit Transfer(from, to, tokenId);\n\n        _afterTokenTransfer(from, to, tokenId, 1);\n    }\n\n    /**\n     * @dev Approve `to` to operate on `tokenId`\n     *\n     * Emits an {Approval} event.\n     */\n    function _approve(address to, uint256 tokenId) internal virtual {\n        _tokenApprovals[tokenId] = to;\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n    }\n\n    /**\n     * @dev Approve `operator` to operate on all of `owner` tokens\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function _setApprovalForAll(\n        address owner,\n        address operator,\n        bool approved\n    ) internal virtual {\n        require(owner != operator, \"ERC721: approve to caller\");\n        _operatorApprovals[owner][operator] = approved;\n        emit ApprovalForAll(owner, operator, approved);\n    }\n\n    /**\n     * @dev Reverts if the `tokenId` has not been minted yet.\n     */\n    function _requireMinted(uint256 tokenId) internal view virtual {\n        require(_exists(tokenId), \"ERC721: invalid token ID\");\n    }\n\n    /**\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n     * The call is not executed if the target address is not a contract.\n     *\n     * @param from address representing the previous owner of the given token ID\n     * @param to target address that will receive the tokens\n     * @param tokenId uint256 ID of the token to be transferred\n     * @param data bytes optional data to send along with the call\n     * @return bool whether the call correctly returned the expected magic value\n     */\n    function _checkOnERC721Received(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) private returns (bool) {\n        if (to.isContract()) {\n            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n                return retval == IERC721Receiver.onERC721Received.selector;\n            } catch (bytes memory reason) {\n                if (reason.length == 0) {\n                    revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n                } else {\n                    /// @solidity memory-safe-assembly\n                    assembly {\n                        revert(add(32, reason), mload(reason))\n                    }\n                }\n            }\n        } else {\n            return true;\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\n     * - When `from` is zero, the tokens will be minted for `to`.\n     * - When `to` is zero, ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     * - `batchSize` is non-zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 firstTokenId,\n        uint256 batchSize\n    ) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\n     * - When `from` is zero, the tokens were minted for `to`.\n     * - When `to` is zero, ``from``'s tokens were burned.\n     * - `from` and `to` are never both zero.\n     * - `batchSize` is non-zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 firstTokenId,\n        uint256 batchSize\n    ) internal virtual {}\n\n    /**\n     * @dev Unsafe write access to the balances, used by extensions that \"mint\" tokens using an {ownerOf} override.\n     *\n     * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant\n     * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such\n     * that `ownerOf(tokenId)` is `a`.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function __unsafe_increaseBalance(address account, uint256 amount) internal {\n        _balances[account] += amount;\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC721.sol\";\nimport \"./IERC721Enumerable.sol\";\n\n/**\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\n * enumerability of all the token ids in the contract as well as all token ids owned by each\n * account.\n */\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\n    // Mapping from owner to list of owned token IDs\n    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\n\n    // Mapping from token ID to index of the owner tokens list\n    mapping(uint256 => uint256) private _ownedTokensIndex;\n\n    // Array with all token ids, used for enumeration\n    uint256[] private _allTokens;\n\n    // Mapping from token id to position in the allTokens array\n    mapping(uint256 => uint256) private _allTokensIndex;\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\n        return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\n     */\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\n        require(index < ERC721.balanceOf(owner), \"ERC721Enumerable: owner index out of bounds\");\n        return _ownedTokens[owner][index];\n    }\n\n    /**\n     * @dev See {IERC721Enumerable-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _allTokens.length;\n    }\n\n    /**\n     * @dev See {IERC721Enumerable-tokenByIndex}.\n     */\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\n        require(index < ERC721Enumerable.totalSupply(), \"ERC721Enumerable: global index out of bounds\");\n        return _allTokens[index];\n    }\n\n    /**\n     * @dev See {ERC721-_beforeTokenTransfer}.\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 firstTokenId,\n        uint256 batchSize\n    ) internal virtual override {\n        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);\n\n        if (batchSize > 1) {\n            // Will only trigger during construction. Batch transferring (minting) is not available afterwards.\n            revert(\"ERC721Enumerable: consecutive transfers not supported\");\n        }\n\n        uint256 tokenId = firstTokenId;\n\n        if (from == address(0)) {\n            _addTokenToAllTokensEnumeration(tokenId);\n        } else if (from != to) {\n            _removeTokenFromOwnerEnumeration(from, tokenId);\n        }\n        if (to == address(0)) {\n            _removeTokenFromAllTokensEnumeration(tokenId);\n        } else if (to != from) {\n            _addTokenToOwnerEnumeration(to, tokenId);\n        }\n    }\n\n    /**\n     * @dev Private function to add a token to this extension's ownership-tracking data structures.\n     * @param to address representing the new owner of the given token ID\n     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n     */\n    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\n        uint256 length = ERC721.balanceOf(to);\n        _ownedTokens[to][length] = tokenId;\n        _ownedTokensIndex[tokenId] = length;\n    }\n\n    /**\n     * @dev Private function to add a token to this extension's token tracking data structures.\n     * @param tokenId uint256 ID of the token to be added to the tokens list\n     */\n    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\n        _allTokensIndex[tokenId] = _allTokens.length;\n        _allTokens.push(tokenId);\n    }\n\n    /**\n     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n     * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n     * @param from address representing the previous owner of the given token ID\n     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n     */\n    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\n        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\n        // then delete the last slot (swap and pop).\n\n        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\n        uint256 tokenIndex = _ownedTokensIndex[tokenId];\n\n        // When the token to delete is the last token, the swap operation is unnecessary\n        if (tokenIndex != lastTokenIndex) {\n            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\n\n            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n        }\n\n        // This also deletes the contents at the last position of the array\n        delete _ownedTokensIndex[tokenId];\n        delete _ownedTokens[from][lastTokenIndex];\n    }\n\n    /**\n     * @dev Private function to remove a token from this extension's token tracking data structures.\n     * This has O(1) time complexity, but alters the order of the _allTokens array.\n     * @param tokenId uint256 ID of the token to be removed from the tokens list\n     */\n    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\n        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\n        // then delete the last slot (swap and pop).\n\n        uint256 lastTokenIndex = _allTokens.length - 1;\n        uint256 tokenIndex = _allTokensIndex[tokenId];\n\n        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\n        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\n        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\n        uint256 lastTokenId = _allTokens[lastTokenIndex];\n\n        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n\n        // This also deletes the contents at the last position of the array\n        delete _allTokensIndex[tokenId];\n        _allTokens.pop();\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n    /**\n     * @dev Returns the total amount of tokens stored by the contract.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n     */\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\n\n    /**\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n     * Use along with {totalSupply} to enumerate all tokens.\n     */\n    function tokenByIndex(uint256 index) external view returns (uint256);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC721/IERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes calldata data\n    ) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool _approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Counters.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n    struct Counter {\n        // This variable should never be directly accessed by users of the library: interactions must be restricted to\n        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n        // this feature: see https://github.com/ethereum/solidity/issues/4637\n        uint256 _value; // default: 0\n    }\n\n    function current(Counter storage counter) internal view returns (uint256) {\n        return counter._value;\n    }\n\n    function increment(Counter storage counter) internal {\n        unchecked {\n            counter._value += 1;\n        }\n    }\n\n    function decrement(Counter storage counter) internal {\n        uint256 value = counter._value;\n        require(value > 0, \"Counter: decrement overflow\");\n        unchecked {\n            counter._value = value - 1;\n        }\n    }\n\n    function reset(Counter storage counter) internal {\n        counter._value = 0;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV // Deprecated in v4.8\n    }\n\n    function _throwError(RecoverError error) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert(\"ECDSA: invalid signature\");\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert(\"ECDSA: invalid signature length\");\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert(\"ECDSA: invalid signature 's' value\");\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature` or error string. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            /// @solidity memory-safe-assembly\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength);\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, signature);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address, RecoverError) {\n        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n        uint8 v = uint8((uint256(vs) >> 255) + 27);\n        return tryRecover(hash, v, r, s);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     *\n     * _Available since v4.2._\n     */\n    function recover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address, RecoverError) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature);\n        }\n\n        return (signer, RecoverError.NoError);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n        // 32 is the length in bytes of hash,\n        // enforced by the type signature above\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from `s`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Typed Data, created from a\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\n     * to the one signed with the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n     * JSON-RPC method as part of EIP-712.\n     *\n     * See {recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/introspection/ERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1);\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator,\n        Rounding rounding\n    ) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10**64) {\n                value /= 10**64;\n                result += 64;\n            }\n            if (value >= 10**32) {\n                value /= 10**32;\n                result += 32;\n            }\n            if (value >= 10**16) {\n                value /= 10**16;\n                result += 16;\n            }\n            if (value >= 10**8) {\n                value /= 10**8;\n                result += 8;\n            }\n            if (value >= 10**4) {\n                value /= 10**4;\n                result += 4;\n            }\n            if (value >= 10**2) {\n                value /= 10**2;\n                result += 2;\n            }\n            if (value >= 10**1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/StorageSlot.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Strings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n}\n"
      },
      "contracts/AddressRelay.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {IAddressRelay, Implementation} from \"./interfaces/IAddressRelay.sol\";\nimport {IERC165} from \"./interfaces/IERC165.sol\";\nimport {IERC173} from \"./interfaces/IERC173.sol\";\n\n/**\n * @author Created by HeyMint Launchpad https://join.heymint.xyz\n * @notice This contract contains the base logic for ERC-721A tokens deployed with HeyMint\n */\ncontract AddressRelay is IAddressRelay, Ownable {\n    mapping(bytes4 => address) public selectorToImplAddress;\n    mapping(bytes4 => bool) public supportedInterfaces;\n    bytes4[] selectors;\n    address[] implAddresses;\n    address public fallbackImplAddress;\n    bool public relayFrozen;\n\n    constructor() {\n        supportedInterfaces[0x01ffc9a7] = true; // IERC165\n        supportedInterfaces[0x7f5828d0] = true; // IERC173\n        supportedInterfaces[0x80ac58cd] = true; // IERC721\n        supportedInterfaces[0x5b5e139f] = true; // IERC721Metadata\n        supportedInterfaces[0x2a55205a] = true; // IERC2981\n        supportedInterfaces[0xad092b5c] = true; // IERC4907\n    }\n\n    /**\n     * @notice Permanently freezes the relay so no more selectors can be added or removed\n     */\n    function freezeRelay() external onlyOwner {\n        relayFrozen = true;\n    }\n\n    /**\n     * @notice Adds or updates selectors and their implementation addresses\n     * @param _selectors The selectors to add or update\n     * @param _implAddress The implementation address the selectors will point to\n     */\n    function addOrUpdateSelectors(\n        bytes4[] memory _selectors,\n        address _implAddress\n    ) external onlyOwner {\n        require(!relayFrozen, \"RELAY_FROZEN\");\n        for (uint256 i = 0; i < _selectors.length; i++) {\n            bytes4 selector = _selectors[i];\n            selectorToImplAddress[selector] = _implAddress;\n            selectors.push(selector);\n        }\n        bool implAddressExists = false;\n        for (uint256 i = 0; i < implAddresses.length; i++) {\n            if (implAddresses[i] == _implAddress) {\n                implAddressExists = true;\n                break;\n            }\n        }\n        if (!implAddressExists) {\n            implAddresses.push(_implAddress);\n        }\n    }\n\n    /**\n     * @notice Removes selectors\n     * @param _selectors The selectors to remove\n     */\n    function removeSelectors(bytes4[] memory _selectors) external onlyOwner {\n        require(!relayFrozen, \"RELAY_FROZEN\");\n        for (uint256 i = 0; i < _selectors.length; i++) {\n            bytes4 selector = _selectors[i];\n            delete selectorToImplAddress[selector];\n            for (uint256 j = 0; j < selectors.length; j++) {\n                if (selectors[j] == selector) {\n                    // this just sets the value to 0, but doesn't remove it from the array\n                    delete selectors[j];\n                    break;\n                }\n            }\n        }\n    }\n\n    /**\n     * @notice Removes an implementation address and all the selectors that point to it\n     * @param _implAddress The implementation address to remove\n     */\n    function removeImplAddressAndAllSelectors(\n        address _implAddress\n    ) external onlyOwner {\n        require(!relayFrozen, \"RELAY_FROZEN\");\n        for (uint256 i = 0; i < implAddresses.length; i++) {\n            if (implAddresses[i] == _implAddress) {\n                // this just sets the value to 0, but doesn't remove it from the array\n                delete implAddresses[i];\n                break;\n            }\n        }\n        for (uint256 i = 0; i < selectors.length; i++) {\n            if (selectorToImplAddress[selectors[i]] == _implAddress) {\n                delete selectorToImplAddress[selectors[i]];\n                delete selectors[i];\n            }\n        }\n    }\n\n    /**\n     * @notice Returns the implementation address for a given function selector\n     * @param _functionSelector The function selector to get the implementation address for\n     */\n    function getImplAddress(\n        bytes4 _functionSelector\n    ) external view returns (address) {\n        address implAddress = selectorToImplAddress[_functionSelector];\n        if (implAddress == address(0)) {\n            implAddress = fallbackImplAddress;\n        }\n        require(implAddress != address(0), \"Function does not exist\");\n        return implAddress;\n    }\n\n    /**\n     * @notice Returns the implementation address for a given function selector. Throws an error if function does not exist.\n     * @param _functionSelector The function selector to get the implementation address for\n     */\n    function getImplAddressNoFallback(\n        bytes4 _functionSelector\n    ) external view returns (address) {\n        address implAddress = selectorToImplAddress[_functionSelector];\n        require(implAddress != address(0), \"Function does not exist\");\n        return implAddress;\n    }\n\n    /**\n     * @notice Returns all the implementation addresses and the selectors they support\n     * @return impls_ An array of Implementation structs\n     */\n    function getAllImplAddressesAndSelectors()\n        external\n        view\n        returns (Implementation[] memory)\n    {\n        uint256 trueImplAddressCount = 0;\n        uint256 implAddressesLength = implAddresses.length;\n        for (uint256 i = 0; i < implAddressesLength; i++) {\n            if (implAddresses[i] != address(0)) {\n                trueImplAddressCount++;\n            }\n        }\n        Implementation[] memory impls = new Implementation[](\n            trueImplAddressCount\n        );\n        uint256 implIndex = 0;\n        for (uint256 i = 0; i < implAddressesLength; i++) {\n            if (implAddresses[i] == address(0)) {\n                continue;\n            }\n            address implAddress = implAddresses[i];\n            bytes4[] memory selectors_;\n            uint256 selectorCount = 0;\n            uint256 selectorsLength = selectors.length;\n            for (uint256 j = 0; j < selectorsLength; j++) {\n                if (selectorToImplAddress[selectors[j]] == implAddress) {\n                    selectorCount++;\n                }\n            }\n            selectors_ = new bytes4[](selectorCount);\n            uint256 selectorIndex = 0;\n            for (uint256 j = 0; j < selectorsLength; j++) {\n                if (selectorToImplAddress[selectors[j]] == implAddress) {\n                    selectors_[selectorIndex] = selectors[j];\n                    selectorIndex++;\n                }\n            }\n            impls[implIndex] = Implementation(implAddress, selectors_);\n            implIndex++;\n        }\n        return impls;\n    }\n\n    /**\n     * @notice Return all the function selectors associated with an implementation address\n     * @param _implAddress The implementation address to get the selectors for\n     */\n    function getSelectorsForImplAddress(\n        address _implAddress\n    ) external view returns (bytes4[] memory) {\n        uint256 selectorCount = 0;\n        uint256 selectorsLength = selectors.length;\n        for (uint256 i = 0; i < selectorsLength; i++) {\n            if (selectorToImplAddress[selectors[i]] == _implAddress) {\n                selectorCount++;\n            }\n        }\n        bytes4[] memory selectorArr = new bytes4[](selectorCount);\n        uint256 selectorIndex = 0;\n        for (uint256 i = 0; i < selectorsLength; i++) {\n            if (selectorToImplAddress[selectors[i]] == _implAddress) {\n                selectorArr[selectorIndex] = selectors[i];\n                selectorIndex++;\n            }\n        }\n        return selectorArr;\n    }\n\n    /**\n     * @notice Sets the fallback implementation address to use when a function selector is not found\n     * @param _fallbackAddress The fallback implementation address\n     */\n    function setFallbackImplAddress(\n        address _fallbackAddress\n    ) external onlyOwner {\n        require(!relayFrozen, \"RELAY_FROZEN\");\n        fallbackImplAddress = _fallbackAddress;\n    }\n\n    /**\n     * @notice Updates the supported interfaces\n     * @param _interfaceId The interface ID to update\n     * @param _supported Whether the interface is supported or not\n     */\n    function updateSupportedInterfaces(\n        bytes4 _interfaceId,\n        bool _supported\n    ) external onlyOwner {\n        supportedInterfaces[_interfaceId] = _supported;\n    }\n\n    /**\n     * @notice Returns whether the interface is supported or not\n     * @param _interfaceId The interface ID to check\n     */\n    function supportsInterface(\n        bytes4 _interfaceId\n    ) external view returns (bool) {\n        return supportedInterfaces[_interfaceId];\n    }\n}\n"
      },
      "contracts/implementations/HeyMintERC721ABase.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {HeyMintERC721AUpgradeable} from \"./HeyMintERC721AUpgradeable.sol\";\nimport {BaseConfig, HeyMintStorage} from \"../libraries/HeyMintStorage.sol\";\nimport {ERC721AUpgradeable, IERC721AUpgradeable} from \"erc721a-upgradeable/contracts/ERC721AUpgradeable.sol\";\n\nimport {ECDSAUpgradeable} from \"@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol\";\nimport {IERC2981Upgradeable, IERC165Upgradeable} from \"@openzeppelin/contracts-upgradeable/interfaces/IERC2981Upgradeable.sol\";\n\ncontract HeyMintERC721ABase is HeyMintERC721AUpgradeable, IERC2981Upgradeable {\n    using HeyMintStorage for HeyMintStorage.State;\n    using ECDSAUpgradeable for bytes32;\n\n    // Default subscription address to use to enable royalty enforcement on certain exchanges like OpenSea\n    address public constant CORI_SUBSCRIPTION_ADDRESS =\n        0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6;\n    // Default subscription address to use as a placeholder for no royalty enforcement\n    address public constant EMPTY_SUBSCRIPTION_ADDRESS =\n        0x511af84166215d528ABf8bA6437ec4BEcF31934B;\n\n    /**\n     * @notice Initializes a new child deposit contract\n     * @param _name The name of the token\n     * @param _symbol The symbol of the token\n     * @param _config Base configuration settings\n     */\n    function initialize(\n        string memory _name,\n        string memory _symbol,\n        BaseConfig memory _config\n    ) public initializerERC721A initializer {\n        __ERC721A_init(_name, _symbol);\n        __Ownable_init();\n        __ReentrancyGuard_init();\n        __OperatorFilterer_init(\n            _config.enforceRoyalties == true\n                ? CORI_SUBSCRIPTION_ADDRESS\n                : EMPTY_SUBSCRIPTION_ADDRESS,\n            true\n        );\n\n        HeyMintStorage.state().cfg = _config;\n\n        // If public sale start time is set but end time is not, set default end time\n        if (_config.publicSaleStartTime > 0 && _config.publicSaleEndTime == 0) {\n            HeyMintStorage.state().cfg.publicSaleEndTime =\n                _config.publicSaleStartTime +\n                520 weeks;\n        }\n\n        // If public sale end time is set but not start time, set default start time\n        if (_config.publicSaleEndTime > 0 && _config.publicSaleStartTime == 0) {\n            HeyMintStorage.state().cfg.publicSaleStartTime = uint32(\n                block.timestamp\n            );\n        }\n\n        // If presale start time is set but end time is not, set default end time\n        if (_config.presaleStartTime > 0 && _config.presaleEndTime == 0) {\n            HeyMintStorage.state().cfg.presaleEndTime =\n                _config.presaleStartTime +\n                520 weeks;\n        }\n\n        // If presale end time is set but not start time, set default start time\n        if (_config.presaleEndTime > 0 && _config.presaleStartTime == 0) {\n            HeyMintStorage.state().cfg.presaleStartTime = uint32(\n                block.timestamp\n            );\n        }\n    }\n\n    // ============ BASE FUNCTIONALITY ============\n\n    function pause() external onlyOwner {\n        _pause();\n    }\n\n    function unpause() external onlyOwner {\n        _unpause();\n    }\n\n    /**\n     * @notice Returns true if the contract implements the interface defined by interfaceId\n     * @param interfaceId The interface identifier, as specified in ERC-165\n     */\n    function supportsInterface(\n        bytes4 interfaceId\n    )\n        public\n        view\n        virtual\n        override(HeyMintERC721AUpgradeable, IERC165Upgradeable)\n        returns (bool)\n    {\n        return HeyMintERC721AUpgradeable.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @notice Reduce the max supply of tokens\n     * @param _newMaxSupply The new maximum supply of tokens available to mint\n     */\n    function reduceMaxSupply(uint16 _newMaxSupply) external onlyOwner {\n        BaseConfig storage cfg = HeyMintStorage.state().cfg;\n        require(_newMaxSupply < cfg.maxSupply, \"NEW_MAX_SUPPLY_TOO_HIGH\");\n        require(\n            _newMaxSupply >= totalSupply(),\n            \"SUPPLY_LOWER_THAN_MINTED_TOKENS\"\n        );\n        cfg.maxSupply = _newMaxSupply;\n    }\n\n    // ============ METADATA ============\n\n    /**\n     * @notice Returns the base URI for all tokens. If the base URI is not set, it will be generated based on the project ID\n     */\n    function _baseURI() internal view virtual override returns (string memory) {\n        return HeyMintStorage.state().cfg.uriBase;\n    }\n\n    /**\n     * @notice Overrides the default ERC721 tokenURI function to look for specific token URIs when present\n     * @param tokenId The token ID to query\n     */\n    function tokenURI(\n        uint256 tokenId\n    )\n        public\n        view\n        virtual\n        override(ERC721AUpgradeable, IERC721AUpgradeable)\n        returns (string memory)\n    {\n        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        string memory specificTokenURI = state.data.tokenURIs[tokenId];\n        if (bytes(specificTokenURI).length != 0) return specificTokenURI;\n        string memory baseURI = _baseURI();\n        if (bytes(baseURI).length == 0) return \"\";\n        uint256 burnTokenId = state.data.tokenIdToBurnTokenId[tokenId];\n        uint256 tokenURITokenId = state.advCfg.useBurnTokenIdForMetadata &&\n            burnTokenId != 0\n            ? burnTokenId\n            : tokenId;\n        return string(abi.encodePacked(baseURI, _toString(tokenURITokenId)));\n    }\n\n    /**\n     * @notice Update the base token URI\n     * @param _newBaseURI The new base URI to use\n     */\n    function setBaseURI(string calldata _newBaseURI) external onlyOwner {\n        require(!HeyMintStorage.state().advCfg.metadataFrozen, \"NOT_ACTIVE\");\n        HeyMintStorage.state().cfg.uriBase = _newBaseURI;\n    }\n\n    /**\n     * @notice Freeze metadata so it can never be changed again\n     */\n    function freezeMetadata() external onlyOwner {\n        HeyMintStorage.state().advCfg.metadataFrozen = true;\n    }\n\n    // ============ ERC-2981 ROYALTY ============\n\n    /**\n     * @notice Basic gas saving implementation of ERC-2981 royaltyInfo function with receiver set to the contract owner\n     * @param _salePrice The sale price used to determine the royalty amount\n     */\n    function royaltyInfo(\n        uint256,\n        uint256 _salePrice\n    ) external view override returns (address, uint256) {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        address payoutAddress = state.advCfg.royaltyPayoutAddress !=\n            address(0x0)\n            ? state.advCfg.royaltyPayoutAddress\n            : owner();\n        if (payoutAddress == address(0x0)) {\n            return (payoutAddress, 0);\n        }\n        return (payoutAddress, (_salePrice * state.cfg.royaltyBps) / 10000);\n    }\n\n    // ============ PAYOUT ============\n\n    /**\n     * @notice Withdraws all funds held within contract\n     */\n    function withdraw() external nonReentrant onlyOwner {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        if (state.cfg.fundingEndsAt > 0) {\n            require(\n                state.data.fundingTargetReached,\n                \"FUNDING_TARGET_NOT_REACHED\"\n            );\n        }\n        if (state.advCfg.refundEndsAt > 0) {\n            require(!refundGuaranteeActive(), \"REFUND_GUARANTEE_STILL_ACTIVE\");\n        }\n        uint256 balance = address(this).balance;\n        if (state.advCfg.payoutAddresses.length == 0) {\n            (bool success, ) = payable(owner()).call{value: balance}(\"\");\n            require(success, \"TRANSFER_FAILED\");\n        } else {\n            for (uint256 i = 0; i < state.advCfg.payoutAddresses.length; i++) {\n                uint256 amount = (balance * state.advCfg.payoutBasisPoints[i]) /\n                    10000;\n                (bool success, ) = HeyMintStorage\n                    .state()\n                    .advCfg\n                    .payoutAddresses[i]\n                    .call{value: amount}(\"\");\n                require(success, \"TRANSFER_FAILED\");\n            }\n        }\n    }\n\n    // ============ PUBLIC SALE ============\n\n    /**\n     * @notice To be updated by contract owner to allow public sale minting\n     */\n    function setPublicSaleState(bool _saleActiveState) external onlyOwner {\n        HeyMintStorage.state().cfg.publicSaleActive = _saleActiveState;\n    }\n\n    /**\n     * @notice Update the public mint price\n     * @param _publicPrice The new public mint price to use\n     */\n    function setPublicPrice(uint32 _publicPrice) external onlyOwner {\n        HeyMintStorage.state().cfg.publicPrice = _publicPrice;\n    }\n\n    /**\n     * @notice Set the maximum mints allowed per a given address in the public sale\n     * @param _mintsAllowed The new maximum mints allowed per address\n     */\n    function setPublicMintsAllowedPerAddress(\n        uint8 _mintsAllowed\n    ) external onlyOwner {\n        HeyMintStorage.state().cfg.publicMintsAllowedPerAddress = _mintsAllowed;\n    }\n\n    /**\n     * @notice Set the maximum mints allowed per a given transaction in the public sale\n     * @param _mintsAllowed The new maximum mints allowed per transaction\n     */\n    function setPublicMintsAllowedPerTransaction(\n        uint8 _mintsAllowed\n    ) external onlyOwner {\n        HeyMintStorage\n            .state()\n            .cfg\n            .publicMintsAllowedPerTransaction = _mintsAllowed;\n    }\n\n    /**\n     * @notice Update the start time for public mint\n     * @param _publicSaleStartTime The new start time for public mint\n     */\n    function setPublicSaleStartTime(\n        uint32 _publicSaleStartTime\n    ) external onlyOwner {\n        HeyMintStorage.state().cfg.publicSaleStartTime = _publicSaleStartTime;\n    }\n\n    /**\n     * @notice Update the end time for public mint\n     * @param _publicSaleEndTime The new end time for public mint\n     */\n    function setPublicSaleEndTime(\n        uint32 _publicSaleEndTime\n    ) external onlyOwner {\n        require(_publicSaleEndTime > block.timestamp, \"TIME_IN_PAST\");\n        HeyMintStorage.state().cfg.publicSaleEndTime = _publicSaleEndTime;\n    }\n\n    /**\n     * @notice Update whether or not to use the automatic public sale times\n     * @param _usePublicSaleTimes Whether or not to use the automatic public sale times\n     */\n    function setUsePublicSaleTimes(\n        bool _usePublicSaleTimes\n    ) external onlyOwner {\n        HeyMintStorage.state().cfg.usePublicSaleTimes = _usePublicSaleTimes;\n    }\n\n    // ============ REFUND ============\n\n    /**\n     * Will return true if token holders can still return their tokens for a refund\n     */\n    function refundGuaranteeActive() public view returns (bool) {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        return block.timestamp < state.advCfg.refundEndsAt;\n    }\n}\n"
      },
      "contracts/implementations/HeyMintERC721AExtensionA.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {HeyMintERC721AUpgradeable} from \"./HeyMintERC721AUpgradeable.sol\";\nimport {BaseConfig, AdvancedConfig, BurnToken, HeyMintStorage} from \"../libraries/HeyMintStorage.sol\";\n\ncontract HeyMintERC721AExtensionA is HeyMintERC721AUpgradeable {\n    using HeyMintStorage for HeyMintStorage.State;\n\n    event Stake(uint256 indexed tokenId);\n    event Unstake(uint256 indexed tokenId);\n    event Loan(address from, address to, uint256 tokenId);\n    event LoanRetrieved(address from, address to, uint256 tokenId);\n\n    // ============ BASE FUNCTIONALITY ============\n\n    /**\n     * @notice Returns all storage variables for the contract\n     */\n    function getSettings()\n        external\n        view\n        returns (\n            BaseConfig memory,\n            AdvancedConfig memory,\n            BurnToken[] memory,\n            bool,\n            bool,\n            bool,\n            uint256\n        )\n    {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        return (\n            state.cfg,\n            state.advCfg,\n            state.burnTokens,\n            state.data.advancedConfigInitialized,\n            state.data.fundingTargetReached,\n            state.data.fundingSuccessDetermined,\n            state.data.currentLoanTotal\n        );\n    }\n\n    /**\n     * @notice Updates the address configuration for the contract\n     */\n    function updateBaseConfig(\n        BaseConfig memory _baseConfig\n    ) external onlyOwner {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(\n            _baseConfig.projectId == state.cfg.projectId,\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        require(\n            _baseConfig.maxSupply <= state.cfg.maxSupply,\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        require(\n            _baseConfig.presaleMaxSupply <= state.cfg.presaleMaxSupply,\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        require(\n            _baseConfig.fundingEndsAt == state.cfg.fundingEndsAt,\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        require(\n            _baseConfig.fundingTarget == state.cfg.fundingTarget,\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        require(\n            _baseConfig.heyMintFeeActive == state.cfg.heyMintFeeActive,\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        require(\n            _baseConfig.affiliateBasisPoints == state.cfg.affiliateBasisPoints,\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        require(\n            _baseConfig.presaleAffiliateMintEnabled ==\n                state.cfg.presaleAffiliateMintEnabled,\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        require(\n            _baseConfig.publicSaleAffiliateMintEnabled ==\n                state.cfg.publicSaleAffiliateMintEnabled,\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        if (state.advCfg.metadataFrozen) {\n            require(\n                keccak256(abi.encode(_baseConfig.uriBase)) ==\n                    keccak256(abi.encode(state.cfg.uriBase)),\n                \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n            );\n        }\n        state.cfg = _baseConfig;\n    }\n\n    /**\n     * @notice Updates the advanced configuration for the contract\n     */\n    function updateAdvancedConfig(\n        AdvancedConfig memory _advancedConfig\n    ) external onlyOwner {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        if (state.advCfg.metadataFrozen) {\n            require(\n                _advancedConfig.metadataFrozen,\n                \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n            );\n        }\n        if (state.advCfg.soulbindAdminTransfersPermanentlyDisabled) {\n            require(\n                _advancedConfig.soulbindAdminTransfersPermanentlyDisabled,\n                \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n            );\n        }\n        if (state.advCfg.refundEndsAt > 0) {\n            require(\n                _advancedConfig.refundPrice == state.advCfg.refundPrice,\n                \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n            );\n            require(\n                _advancedConfig.refundEndsAt >= state.advCfg.refundEndsAt,\n                \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n            );\n        } else if (\n            _advancedConfig.refundEndsAt > 0 || _advancedConfig.refundPrice > 0\n        ) {\n            require(\n                _advancedConfig.refundPrice > 0,\n                \"REFUND_PRICE_MUST_BE_SET\"\n            );\n            require(\n                _advancedConfig.refundEndsAt > 0,\n                \"REFUND_DURATION_MUST_BE_SET\"\n            );\n        }\n        if (!state.data.advancedConfigInitialized) {\n            state.data.advancedConfigInitialized = true;\n        }\n        uint256 payoutAddressesLength = _advancedConfig.payoutAddresses.length;\n        uint256 payoutBasisPointsLength = _advancedConfig\n            .payoutBasisPoints\n            .length;\n        if (state.advCfg.payoutAddressesFrozen) {\n            require(\n                _advancedConfig.payoutAddressesFrozen,\n                \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n            );\n            require(\n                payoutAddressesLength == state.advCfg.payoutAddresses.length,\n                \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n            );\n            require(\n                payoutBasisPointsLength ==\n                    state.advCfg.payoutBasisPoints.length,\n                \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n            );\n            for (uint256 i = 0; i < payoutAddressesLength; i++) {\n                require(\n                    _advancedConfig.payoutAddresses[i] ==\n                        state.advCfg.payoutAddresses[i],\n                    \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n                );\n                require(\n                    _advancedConfig.payoutBasisPoints[i] ==\n                        state.advCfg.payoutBasisPoints[i],\n                    \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n                );\n            }\n        } else if (payoutAddressesLength > 0) {\n            require(\n                payoutAddressesLength == payoutBasisPointsLength,\n                \"ARRAY_LENGTHS_MUST_MATCH\"\n            );\n            uint256 totalBasisPoints = 0;\n            for (uint256 i = 0; i < payoutBasisPointsLength; i++) {\n                totalBasisPoints += _advancedConfig.payoutBasisPoints[i];\n            }\n            require(totalBasisPoints == 10000, \"BASIS_POINTS_MUST_EQUAL_10000\");\n        }\n        require(\n            (state.advCfg.subscriptionPeriod == 0 ||\n                _advancedConfig.subscriptionPeriod ==\n                state.advCfg.subscriptionPeriod),\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        require(\n            (state.advCfg.subscriptionPrice == 0 ||\n                _advancedConfig.subscriptionPrice ==\n                state.advCfg.subscriptionPrice),\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        require(\n            state.advCfg.subscriptionErc20Address == address(0) ||\n                _advancedConfig.subscriptionErc20Address ==\n                state.advCfg.subscriptionErc20Address,\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        state.advCfg = _advancedConfig;\n    }\n}\n"
      },
      "contracts/implementations/HeyMintERC721AExtensionB.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {HeyMintERC721AUpgradeable} from \"./HeyMintERC721AUpgradeable.sol\";\nimport {HeyMintStorage, BaseConfig} from \"../libraries/HeyMintStorage.sol\";\nimport {ECDSAUpgradeable} from \"@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol\";\n\ncontract HeyMintERC721AExtensionB is HeyMintERC721AUpgradeable {\n    using HeyMintStorage for HeyMintStorage.State;\n    using ECDSAUpgradeable for bytes32;\n\n    event HeyMintAffiliatePaid(address to, uint256 numTokens, uint256 value);\n\n    // ============ PRESALE ============\n\n    /**\n     * @notice Returns the presale price in wei. Presale price is stored with 5 decimals (1 = 0.00001 ETH), so total 5 + 13 == 18 decimals\n     */\n    function presalePriceInWei() public view returns (uint256) {\n        return uint256(HeyMintStorage.state().cfg.presalePrice) * 10 ** 13;\n    }\n\n    /**\n     * @notice To be updated by contract owner to allow presale minting\n     * @param _saleActiveState The new presale activ\n     .e state\n     */\n    function setPresaleState(bool _saleActiveState) external onlyOwner {\n        HeyMintStorage.state().cfg.presaleActive = _saleActiveState;\n    }\n\n    /**\n     * @notice Update the presale mint price\n     * @param _presalePrice The new presale mint price to use\n     */\n    function setPresalePrice(uint32 _presalePrice) external onlyOwner {\n        HeyMintStorage.state().cfg.presalePrice = _presalePrice;\n    }\n\n    /**\n     * @notice Reduce the max supply of tokens available to mint in the presale\n     * @param _newPresaleMaxSupply The new maximum supply of presale tokens available to mint\n     */\n    function reducePresaleMaxSupply(\n        uint16 _newPresaleMaxSupply\n    ) external onlyOwner {\n        BaseConfig storage cfg = HeyMintStorage.state().cfg;\n        require(\n            _newPresaleMaxSupply < cfg.presaleMaxSupply,\n            \"NEW_MAX_SUPPLY_TOO_HIGH\"\n        );\n        cfg.presaleMaxSupply = _newPresaleMaxSupply;\n    }\n\n    /**\n     * @notice Set the maximum mints allowed per a given address in the presale\n     * @param _mintsAllowed The new maximum mints allowed per address in the presale\n     */\n    function setPresaleMintsAllowedPerAddress(\n        uint8 _mintsAllowed\n    ) external onlyOwner {\n        HeyMintStorage\n            .state()\n            .cfg\n            .presaleMintsAllowedPerAddress = _mintsAllowed;\n    }\n\n    /**\n     * @notice Set the maximum mints allowed per a given transaction in the presale\n     * @param _mintsAllowed The new maximum mints allowed per transaction in the presale\n     */\n    function setPresaleMintsAllowedPerTransaction(\n        uint8 _mintsAllowed\n    ) external onlyOwner {\n        HeyMintStorage\n            .state()\n            .cfg\n            .presaleMintsAllowedPerTransaction = _mintsAllowed;\n    }\n\n    /**\n     * @notice Set the signer address used to verify presale minting\n     * @param _presaleSignerAddress The new signer address to use\n     */\n    function setPresaleSignerAddress(\n        address _presaleSignerAddress\n    ) external onlyOwner {\n        HeyMintStorage.state().cfg.presaleSignerAddress = _presaleSignerAddress;\n    }\n\n    /**\n     * @notice Update the start time for presale mint\n     */\n    function setPresaleStartTime(uint32 _presaleStartTime) external onlyOwner {\n        HeyMintStorage.state().cfg.presaleStartTime = _presaleStartTime;\n    }\n\n    /**\n     * @notice Update the end time for presale mint\n     */\n    function setPresaleEndTime(uint32 _presaleEndTime) external onlyOwner {\n        require(_presaleEndTime > block.timestamp, \"TIME_IN_PAST\");\n        HeyMintStorage.state().cfg.presaleEndTime = _presaleEndTime;\n    }\n\n    /**\n     * @notice Update whether or not to use the automatic presale times\n     */\n    function setUsePresaleTimes(bool _usePresaleTimes) external onlyOwner {\n        HeyMintStorage.state().cfg.usePresaleTimes = _usePresaleTimes;\n    }\n\n    /**\n     * @notice Returns if presale times are active. If required config settings are not set, returns true.\n     */\n    function presaleTimeIsActive() public view returns (bool) {\n        BaseConfig storage cfg = HeyMintStorage.state().cfg;\n        if (\n            cfg.usePresaleTimes == false ||\n            cfg.presaleStartTime == 0 ||\n            cfg.presaleEndTime == 0\n        ) {\n            return true;\n        }\n        return\n            block.timestamp >= cfg.presaleStartTime &&\n            block.timestamp <= cfg.presaleEndTime;\n    }\n\n    /**\n     * @notice Allow for allowlist minting of tokens\n     * @param _messageHash The hash of the message containing msg.sender & _maximumAllowedMints to verify\n     * @param _signature The signature of the messageHash to verify\n     * @param _numTokens The number of tokens to mint\n     * @param _maximumAllowedMints The maximum number of tokens that can be minted by the caller\n     */\n    function _presaleMint(\n        bytes32 _messageHash,\n        bytes calldata _signature,\n        uint256 _numTokens,\n        uint256 _maximumAllowedMints\n    ) internal {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        BaseConfig storage cfg = state.cfg;\n        require(cfg.presaleActive, \"NOT_ACTIVE\");\n        require(presaleTimeIsActive(), \"NOT_ACTIVE\");\n        uint256 qtyAlreadyMinted = _numberMinted(msg.sender);\n        require(\n            cfg.presaleMintsAllowedPerAddress == 0 ||\n                qtyAlreadyMinted + _numTokens <=\n                cfg.presaleMintsAllowedPerAddress,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        require(\n            cfg.presaleMintsAllowedPerTransaction == 0 ||\n                _numTokens <= cfg.presaleMintsAllowedPerTransaction,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        require(\n            qtyAlreadyMinted + _numTokens <= _maximumAllowedMints,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        require(\n            cfg.presaleMaxSupply == 0 ||\n                totalSupply() + _numTokens <= cfg.presaleMaxSupply,\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        require(\n            totalSupply() + _numTokens <= cfg.maxSupply,\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        uint256 presalePrice = presalePriceInWei();\n        if (cfg.heyMintFeeActive) {\n            uint256 heymintFee = _numTokens * heymintFeePerToken();\n            require(\n                msg.value == presalePrice * _numTokens + heymintFee,\n                \"INVALID_PRICE_PAID\"\n            );\n            (bool success, ) = heymintPayoutAddress.call{value: heymintFee}(\"\");\n            require(success, \"TRANSFER_FAILED\");\n        } else {\n            require(\n                msg.value == presalePrice * _numTokens,\n                \"INVALID_PRICE_PAID\"\n            );\n        }\n        require(\n            keccak256(abi.encode(msg.sender, _maximumAllowedMints)) ==\n                _messageHash,\n            \"MESSAGE_INVALID\"\n        );\n        require(\n            verifySignerAddress(_messageHash, _signature),\n            \"INVALID_SIGNATURE\"\n        );\n\n        if (cfg.fundingEndsAt > 0) {\n            uint256 firstTokenIdToMint = _nextTokenId();\n            for (uint256 i = 0; i < _numTokens; i++) {\n                HeyMintStorage.state().data.pricePaid[\n                    firstTokenIdToMint + i\n                ] = presalePrice;\n            }\n        }\n\n        _safeMint(msg.sender, _numTokens);\n\n        if (totalSupply() >= cfg.presaleMaxSupply) {\n            cfg.presaleActive = false;\n        }\n    }\n\n    /**\n     * @notice Allow for allowlist minting of tokens\n     * @param _messageHash The hash of the message containing msg.sender & _maximumAllowedMints to verify\n     * @param _signature The signature of the messageHash to verify\n     * @param _numTokens The number of tokens to mint\n     * @param _maximumAllowedMints The maximum number of tokens that can be minted by the caller\n     */\n    function presaleMint(\n        bytes32 _messageHash,\n        bytes calldata _signature,\n        uint256 _numTokens,\n        uint256 _maximumAllowedMints\n    ) external payable nonReentrant {\n        _presaleMint(\n            _messageHash,\n            _signature,\n            _numTokens,\n            _maximumAllowedMints\n        );\n    }\n\n    function _creditCardPresaleMint(\n        bytes32 _messageHash,\n        bytes calldata _signature,\n        uint256 _numTokens,\n        address _to,\n        bytes32 _emailAddress,\n        uint256 _maximumAllowedMints\n    ) internal {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(\n            isSenderAuthorizedForCreditCardMint(),\n            \"NOT_AUTHORIZED_ADDRESS\"\n        );\n        require(state.cfg.presaleActive, \"NOT_ACTIVE\");\n        require(presaleTimeIsActive(), \"NOT_ACTIVE\");\n        uint256 qtyAlreadyMinted = state.data.tokensMintedByEmailAddress[\n            _emailAddress\n        ];\n        require(\n            state.cfg.presaleMintsAllowedPerAddress == 0 ||\n                qtyAlreadyMinted + _numTokens <=\n                state.cfg.presaleMintsAllowedPerAddress,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        require(\n            state.cfg.presaleMintsAllowedPerTransaction == 0 ||\n                _numTokens <= state.cfg.presaleMintsAllowedPerTransaction,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        require(\n            qtyAlreadyMinted + _numTokens <= _maximumAllowedMints,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        // We are minting by verified email address, but still double check the _to address to prevent abuse.\n        require(\n            _numberMinted(_to) + _numTokens <=\n                state.cfg.presaleMintsAllowedPerAddress &&\n                _numberMinted(_to) + _numTokens <= _maximumAllowedMints,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        require(\n            state.cfg.presaleMaxSupply == 0 ||\n                totalSupply() + _numTokens <= state.cfg.presaleMaxSupply,\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        require(\n            totalSupply() + _numTokens <= state.cfg.maxSupply,\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        uint256 presalePrice = presalePriceInWei();\n        if (state.cfg.heyMintFeeActive) {\n            uint256 heymintFee = _numTokens * heymintFeePerToken();\n            require(\n                msg.value == presalePrice * _numTokens + heymintFee,\n                \"INVALID_PRICE_PAID\"\n            );\n            (bool success, ) = heymintPayoutAddress.call{value: heymintFee}(\"\");\n            require(success, \"TRANSFER_FAILED\");\n        } else {\n            require(\n                msg.value == presalePrice * _numTokens,\n                \"INVALID_PRICE_PAID\"\n            );\n        }\n        require(\n            keccak256(abi.encode(_emailAddress, _maximumAllowedMints)) ==\n                _messageHash,\n            \"MESSAGE_INVALID\"\n        );\n        require(\n            verifySignerAddress(_messageHash, _signature),\n            \"INVALID_SIGNATURE\"\n        );\n\n        if (state.cfg.fundingEndsAt > 0) {\n            uint256 firstTokenIdToMint = _nextTokenId();\n            for (uint256 i = 0; i < _numTokens; i++) {\n                HeyMintStorage.state().data.pricePaid[\n                    firstTokenIdToMint + i\n                ] = presalePrice;\n            }\n        }\n\n        state.data.tokensMintedByEmailAddress[_emailAddress] += _numTokens;\n\n        _safeMint(_to, _numTokens);\n\n        if (totalSupply() >= state.cfg.presaleMaxSupply) {\n            state.cfg.presaleActive = false;\n        }\n    }\n\n    /**\n     * @notice Allow for allowlist minting of tokens via credit card\n     * @param _messageHash The hash of the message containing the _emailAddress hash & _maximumAllowedMints to verify\n     * @param _signature The signature of the messageHash to verify\n     * @param _numTokens The number of tokens to mint\n     * @param _to The address to mint the tokens to\n     * @param _emailAddress keccak256 hash of the email address allowed to mint\n     * @param _maximumAllowedMints The maximum number of tokens that can be minted by the caller\n     */\n    function creditCardPresaleMint(\n        bytes32 _messageHash,\n        bytes calldata _signature,\n        uint256 _numTokens,\n        address _to,\n        bytes32 _emailAddress,\n        uint256 _maximumAllowedMints\n    ) external payable nonReentrant {\n        _creditCardPresaleMint(\n            _messageHash,\n            _signature,\n            _numTokens,\n            _to,\n            _emailAddress,\n            _maximumAllowedMints\n        );\n    }\n\n    /**\n     * @notice Allow for allowlist minting of tokens via credit card, including affiliate payments\n     * @param _affPaymentAddress The address to receive affiliate fees\n     * @param _affMessageHash The hash of the affiliate message containing the affiliate payment address & projectId\n     * @param _affSignature The signature for the affiliate payment message to verify\n     * @param _messageHash The hash of the message containing the _emailAddress hash and _maximumAllowedMints to verify\n     * @param _signature The signature of the messageHash to verify\n     * @param _numTokens The number of tokens to mint\n     * @param _to The address to mint the tokens to\n     * @param _emailAddress keccak256 hash of the email address allowed to mint\n     * @param _maximumAllowedMints The maximum number of tokens that can be minted by the caller\n     */\n    function affiliateCreditCardPresaleMint(\n        address _affPaymentAddress,\n        bytes32 _affMessageHash,\n        bytes calldata _affSignature,\n        bytes32 _messageHash,\n        bytes calldata _signature,\n        uint256 _numTokens,\n        address _to,\n        bytes32 _emailAddress,\n        uint256 _maximumAllowedMints\n    ) external payable nonReentrant {\n        require(isPresaleAffiliateMintActive(), \"NOT_ACTIVE\");\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(\n            keccak256(abi.encode(state.cfg.projectId, _affPaymentAddress)) ==\n                _affMessageHash,\n            \"MESSAGE_INVALID\"\n        );\n        require(\n            verifySignerAddress(_affMessageHash, _affSignature),\n            \"INVALID_SIGNATURE\"\n        );\n        _creditCardPresaleMint(\n            _messageHash,\n            _signature,\n            _numTokens,\n            _to,\n            _emailAddress,\n            _maximumAllowedMints\n        );\n        uint256 affFee = (_numTokens *\n            presalePriceInWei() *\n            state.cfg.affiliateBasisPoints) / 10000;\n        (bool ok, ) = _affPaymentAddress.call{value: affFee}(\"\");\n        require(ok, \"TRANSFER_FAILED\");\n        emit HeyMintAffiliatePaid(_affPaymentAddress, _numTokens, affFee);\n    }\n\n    /**\n     * @notice Checks if the presale affiliate minting is currently active.\n     * @return A boolean indicating whether presale affiliate minting is active.\n     */\n    function isPresaleAffiliateMintActive() public view returns (bool) {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        return (state.cfg.presaleSignerAddress != address(0) &&\n            state.cfg.presaleAffiliateMintEnabled &&\n            state.cfg.presaleActive &&\n            state.cfg.presalePrice > 0 &&\n            state.cfg.affiliateBasisPoints > 0 &&\n            (!state.cfg.usePresaleTimes ||\n                block.timestamp >= state.cfg.presaleStartTime) &&\n            (!state.cfg.usePresaleTimes ||\n                block.timestamp < state.cfg.presaleEndTime));\n    }\n\n    /**\n     * @notice Allows for allowlist minting of tokens using an affiliate.\n     * @param _affPaymentAddress The address to receive affiliate fees\n     * @param _affMessageHash The hash of the affiliate message containing the affiliate payment address & projectId\n     * @param _affSignature The signature for the affiliate payment message to verify\n     * @param _messageHash The hash of the message containing msg.sender & _maximumAllowedMints to verify\n     * @param _signature The signature of the messageHash to verify\n     * @param _numTokens The number of tokens to mint\n     * @param _maximumAllowedMints The maximum number of tokens that can be minted by the caller\n     */\n    function affiliatePresaleMint(\n        address _affPaymentAddress,\n        bytes32 _affMessageHash,\n        bytes calldata _affSignature,\n        bytes32 _messageHash,\n        bytes calldata _signature,\n        uint256 _numTokens,\n        uint256 _maximumAllowedMints\n    ) external payable nonReentrant {\n        require(isPresaleAffiliateMintActive(), \"NOT_ACTIVE\");\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(\n            keccak256(abi.encode(state.cfg.projectId, _affPaymentAddress)) ==\n                _affMessageHash,\n            \"MESSAGE_INVALID\"\n        );\n        require(\n            verifySignerAddress(_affMessageHash, _affSignature),\n            \"INVALID_SIGNATURE\"\n        );\n        _presaleMint(\n            _messageHash,\n            _signature,\n            _numTokens,\n            _maximumAllowedMints\n        );\n        uint256 affFee = (_numTokens *\n            presalePriceInWei() *\n            state.cfg.affiliateBasisPoints) / 10000;\n        (bool ok, ) = _affPaymentAddress.call{value: affFee}(\"\");\n        require(ok, \"TRANSFER_FAILED\");\n        emit HeyMintAffiliatePaid(_affPaymentAddress, _numTokens, affFee);\n    }\n}\n"
      },
      "contracts/implementations/HeyMintERC721AExtensionC.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {HeyMintERC721AUpgradeable} from \"./HeyMintERC721AUpgradeable.sol\";\nimport {AdvancedConfig, Data, BaseConfig, HeyMintStorage} from \"../libraries/HeyMintStorage.sol\";\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\n\ncontract HeyMintERC721AExtensionC is HeyMintERC721AUpgradeable {\n    using HeyMintStorage for HeyMintStorage.State;\n\n    event Stake(uint256 indexed tokenId);\n    event Unstake(uint256 indexed tokenId);\n    event HeyMintAffiliatePaid(address to, uint256 numTokens, uint256 value);\n\n    // ============ BASE FUNCTIONALITY ============\n\n    /**\n     * @notice Update the specific token URI for a set of tokens\n     * @param _tokenIds The token IDs to update\n     * @param _newURIs The new URIs to use\n     */\n    function setTokenURIs(\n        uint256[] calldata _tokenIds,\n        string[] calldata _newURIs\n    ) external onlyOwner {\n        require(!HeyMintStorage.state().advCfg.metadataFrozen, \"NOT_ACTIVE\");\n        uint256 tokenIdsLength = _tokenIds.length;\n        require(tokenIdsLength == _newURIs.length);\n        for (uint256 i = 0; i < tokenIdsLength; i++) {\n            HeyMintStorage.state().data.tokenURIs[_tokenIds[i]] = _newURIs[i];\n        }\n    }\n\n    function baseTokenURI() external view returns (string memory) {\n        return HeyMintStorage.state().cfg.uriBase;\n    }\n\n    // ============ CREDIT CARD PAYMENT ============\n\n    /**\n     * @notice Returns if public sale times are active. If required config settings are not set, returns true.\n     */\n    function _publicSaleTimeIsActive() internal view returns (bool) {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        if (\n            state.cfg.usePublicSaleTimes == false ||\n            state.cfg.publicSaleStartTime == 0 ||\n            state.cfg.publicSaleEndTime == 0\n        ) {\n            return true;\n        }\n        return\n            block.timestamp >= state.cfg.publicSaleStartTime &&\n            block.timestamp <= state.cfg.publicSaleEndTime;\n    }\n\n    /**\n     * @notice Checks if the public sale affiliate minting is currently active.\n     * @return A boolean indicating whether public sale affiliate minting is active.\n     */\n    function isPublicAffiliateMintActive() public view returns (bool) {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        return (state.cfg.presaleSignerAddress != address(0) &&\n            state.cfg.publicSaleAffiliateMintEnabled &&\n            state.cfg.publicSaleActive &&\n            state.cfg.publicPrice > 0 &&\n            state.cfg.affiliateBasisPoints > 0 &&\n            (!state.cfg.usePublicSaleTimes ||\n                block.timestamp >= state.cfg.publicSaleStartTime) &&\n            (!state.cfg.usePublicSaleTimes ||\n                block.timestamp < state.cfg.publicSaleEndTime));\n    }\n\n    /**\n     * @notice Set an address authorized to call creditCardMint\n     * @param _creditCardMintAddresses The new address to authorize\n     */\n    function setCreditCardMintAddresses(\n        address[] memory _creditCardMintAddresses\n    ) external onlyOwner {\n        HeyMintStorage\n            .state()\n            .advCfg\n            .creditCardMintAddresses = _creditCardMintAddresses;\n    }\n\n    function _creditCardMint(uint256 _numTokens, address _to) internal {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(\n            isSenderAuthorizedForCreditCardMint(),\n            \"NOT_AUTHORIZED_ADDRESS\"\n        );\n        require(state.cfg.publicSaleActive, \"NOT_ACTIVE\");\n        require(_publicSaleTimeIsActive(), \"NOT_ACTIVE\");\n        require(\n            state.cfg.publicMintsAllowedPerAddress == 0 ||\n                _numberMinted(_to) + _numTokens <=\n                state.cfg.publicMintsAllowedPerAddress,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        require(\n            state.cfg.publicMintsAllowedPerTransaction == 0 ||\n                _numTokens <= state.cfg.publicMintsAllowedPerTransaction,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        require(\n            totalSupply() + _numTokens <= state.cfg.maxSupply,\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        uint256 publicPrice = publicPriceInWei();\n        if (state.cfg.heyMintFeeActive) {\n            uint256 heymintFee = _numTokens * heymintFeePerToken();\n            require(\n                msg.value == publicPrice * _numTokens + heymintFee,\n                \"INVALID_PRICE_PAID\"\n            );\n            (bool success, ) = heymintPayoutAddress.call{value: heymintFee}(\"\");\n            require(success, \"TRANSFER_FAILED\");\n        } else {\n            require(\n                msg.value == publicPrice * _numTokens,\n                \"INVALID_PRICE_PAID\"\n            );\n        }\n\n        if (state.cfg.fundingEndsAt > 0) {\n            uint256 firstTokenIdToMint = _nextTokenId();\n            for (uint256 i = 0; i < _numTokens; i++) {\n                HeyMintStorage.state().data.pricePaid[\n                    firstTokenIdToMint + i\n                ] = publicPrice;\n            }\n        }\n\n        _safeMint(_to, _numTokens);\n\n        if (totalSupply() >= state.cfg.maxSupply) {\n            state.cfg.publicSaleActive = false;\n        }\n    }\n\n    function creditCardMint(\n        uint256 _numTokens,\n        address _to\n    ) external payable nonReentrant {\n        _creditCardMint(_numTokens, _to);\n    }\n\n    /**\n     * @notice Allow for public minting of tokens via credit card with affiliate payment\n     * @param _affPaymentAddress The address to receive affiliate fees\n     * @param _affMessageHash The hash of the affiliate message containing the affiliate payment address & projectId\n     * @param _affSignature The signature for the affiliate payment message to verify\n     * @param _numTokens The number of tokens to mint\n     * @param _to The address to mint tokens to\n     */\n    function affiliateCreditCardMint(\n        address _affPaymentAddress,\n        bytes32 _affMessageHash,\n        bytes calldata _affSignature,\n        uint256 _numTokens,\n        address _to\n    ) external payable nonReentrant {\n        require(isPublicAffiliateMintActive(), \"NOT_ACTIVE\");\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(\n            keccak256(abi.encode(state.cfg.projectId, _affPaymentAddress)) ==\n                _affMessageHash,\n            \"MESSAGE_INVALID\"\n        );\n        require(\n            verifySignerAddress(_affMessageHash, _affSignature),\n            \"INVALID_SIGNATURE\"\n        );\n        _creditCardMint(_numTokens, _to);\n        uint256 affFee = (_numTokens *\n            publicPriceInWei() *\n            state.cfg.affiliateBasisPoints) / 10000;\n        (bool ok, ) = _affPaymentAddress.call{value: affFee}(\"\");\n        require(ok, \"TRANSFER_FAILED\");\n        emit HeyMintAffiliatePaid(_affPaymentAddress, _numTokens, affFee);\n    }\n\n    // ============ SOULBINDING ============\n\n    /**\n     * @notice Change the admin address used to transfer tokens if needed.\n     * @param _adminAddress The new soulbound admin address\n     */\n    function setSoulboundAdminAddress(\n        address _adminAddress\n    ) external onlyOwner {\n        AdvancedConfig storage advCfg = HeyMintStorage.state().advCfg;\n        require(!advCfg.soulbindAdminTransfersPermanentlyDisabled);\n        advCfg.soulboundAdminAddress = _adminAddress;\n    }\n\n    /**\n     * @notice Disallow admin transfers of soulbound tokens permanently.\n     */\n    function disableSoulbindAdminTransfersPermanently() external onlyOwner {\n        AdvancedConfig storage advCfg = HeyMintStorage.state().advCfg;\n        advCfg.soulboundAdminAddress = address(0);\n        advCfg.soulbindAdminTransfersPermanentlyDisabled = true;\n    }\n\n    /**\n     * @notice Turn soulbinding on or off\n     * @param _soulbindingActive If true soulbinding is active\n     */\n    function setSoulbindingState(bool _soulbindingActive) external onlyOwner {\n        HeyMintStorage.state().cfg.soulbindingActive = _soulbindingActive;\n    }\n\n    /**\n     * @notice Allows an admin address to initiate token transfers if user wallets get hacked or lost\n     * This function can only be used on soulbound tokens to prevent arbitrary transfers of normal tokens\n     * @param _from The address to transfer from\n     * @param _to The address to transfer to\n     * @param _tokenId The token id to transfer\n     */\n    function soulboundAdminTransfer(\n        address _from,\n        address _to,\n        uint256 _tokenId\n    ) external {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        address adminAddress = state.advCfg.soulboundAdminAddress == address(0)\n            ? owner()\n            : state.advCfg.soulboundAdminAddress;\n        require(msg.sender == adminAddress, \"NOT_ADMIN\");\n        require(state.cfg.soulbindingActive, \"NOT_ACTIVE\");\n        require(\n            !state.advCfg.soulbindAdminTransfersPermanentlyDisabled,\n            \"NOT_ACTIVE\"\n        );\n        state.data.soulboundAdminTransferInProgress = true;\n        _directApproveMsgSenderFor(_tokenId);\n        safeTransferFrom(_from, _to, _tokenId);\n        state.data.soulboundAdminTransferInProgress = false;\n    }\n\n    // ============ STAKING ============\n\n    /**\n     * @notice Turn staking on or off\n     * @param _stakingState The new state of staking (true = on, false = off)\n     */\n    function setStakingState(bool _stakingState) external onlyOwner {\n        HeyMintStorage.state().advCfg.stakingActive = _stakingState;\n    }\n\n    /**\n     * @notice Stake an arbitrary number of tokens\n     * @param _tokenIds The ids of the tokens to stake\n     */\n    function stakeTokens(uint256[] calldata _tokenIds) external {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(state.advCfg.stakingActive, \"NOT_ACTIVE\");\n        for (uint256 i = 0; i < _tokenIds.length; i++) {\n            uint256 tokenId = _tokenIds[i];\n            require(ownerOf(tokenId) == msg.sender, \"MUST_OWN_TOKEN\");\n            if (state.data.currentTimeStaked[tokenId] == 0) {\n                state.data.currentTimeStaked[tokenId] = block.timestamp;\n                emit Stake(tokenId);\n            }\n        }\n    }\n\n    /**\n     * @notice Unstake an arbitrary number of tokens\n     * @param _tokenIds The ids of the tokens to unstake\n     */\n    function unstakeTokens(uint256[] calldata _tokenIds) external {\n        Data storage data = HeyMintStorage.state().data;\n        for (uint256 i = 0; i < _tokenIds.length; i++) {\n            uint256 tokenId = _tokenIds[i];\n            require(ownerOf(tokenId) == msg.sender, \"MUST_OWN_TOKEN\");\n            if (data.currentTimeStaked[tokenId] != 0) {\n                data.totalTimeStaked[tokenId] +=\n                    block.timestamp -\n                    data.currentTimeStaked[tokenId];\n                data.currentTimeStaked[tokenId] = 0;\n                emit Unstake(tokenId);\n            }\n        }\n    }\n\n    /**\n     * @notice Allows for transfers (not sales) while staking\n     * @param _from The address of the current owner of the token\n     * @param _to The address of the new owner of the token\n     * @param _tokenId The id of the token to transfer\n     */\n    function stakingTransfer(\n        address _from,\n        address _to,\n        uint256 _tokenId\n    ) external {\n        Data storage data = HeyMintStorage.state().data;\n        require(ownerOf(_tokenId) == msg.sender, \"MUST_OWN_TOKEN\");\n        data.stakingTransferActive = true;\n        safeTransferFrom(_from, _to, _tokenId);\n        data.stakingTransferActive = false;\n    }\n\n    /**\n     * @notice Allow contract owner to forcibly unstake a token if needed\n     * @param _tokenId The id of the token to unstake\n     */\n    function adminUnstake(uint256 _tokenId) external onlyOwner {\n        Data storage data = HeyMintStorage.state().data;\n        require(HeyMintStorage.state().data.currentTimeStaked[_tokenId] != 0);\n        data.totalTimeStaked[_tokenId] +=\n            block.timestamp -\n            data.currentTimeStaked[_tokenId];\n        data.currentTimeStaked[_tokenId] = 0;\n        emit Unstake(_tokenId);\n    }\n\n    /**\n     * @notice Return the total amount of time a token has been staked\n     * @param _tokenId The id of the token to check\n     */\n    function totalTokenStakeTime(\n        uint256 _tokenId\n    ) external view returns (uint256) {\n        Data storage data = HeyMintStorage.state().data;\n        uint256 currentStakeStartTime = data.currentTimeStaked[_tokenId];\n        if (currentStakeStartTime != 0) {\n            return\n                (block.timestamp - currentStakeStartTime) +\n                data.totalTimeStaked[_tokenId];\n        }\n        return data.totalTimeStaked[_tokenId];\n    }\n\n    /**\n     * @notice Return the amount of time a token has been currently staked\n     * @param _tokenId The id of the token to check\n     */\n    function currentTokenStakeTime(\n        uint256 _tokenId\n    ) external view returns (uint256) {\n        uint256 currentStakeStartTime = HeyMintStorage\n            .state()\n            .data\n            .currentTimeStaked[_tokenId];\n        if (currentStakeStartTime != 0) {\n            return block.timestamp - currentStakeStartTime;\n        }\n        return 0;\n    }\n\n    // ============ FREE CLAIM ============\n\n    /**\n     * @notice To be updated by contract owner to allow free claiming tokens\n     * @param _freeClaimActive If true tokens can be claimed for free\n     */\n    function setFreeClaimState(bool _freeClaimActive) external onlyOwner {\n        AdvancedConfig storage advCfg = HeyMintStorage.state().advCfg;\n        if (_freeClaimActive) {\n            require(\n                advCfg.freeClaimContractAddress != address(0),\n                \"NOT_CONFIGURED\"\n            );\n            require(advCfg.mintsPerFreeClaim != 0, \"NOT_CONFIGURED\");\n        }\n        advCfg.freeClaimActive = _freeClaimActive;\n    }\n\n    /**\n     * @notice Set the contract address of the NFT eligible for free claim\n     * @param _freeClaimContractAddress The new contract address\n     */\n    function setFreeClaimContractAddress(\n        address _freeClaimContractAddress\n    ) external onlyOwner {\n        HeyMintStorage\n            .state()\n            .advCfg\n            .freeClaimContractAddress = _freeClaimContractAddress;\n    }\n\n    /**\n     * @notice Update the number of free mints claimable per token redeemed from the external ERC721 contract\n     * @param _mintsPerFreeClaim The new number of free mints per token redeemed\n     */\n    function updateMintsPerFreeClaim(\n        uint8 _mintsPerFreeClaim\n    ) external onlyOwner {\n        HeyMintStorage.state().advCfg.mintsPerFreeClaim = _mintsPerFreeClaim;\n    }\n\n    /**\n     * @notice Check if an array of tokens is eligible for free claim\n     * @param _tokenIDs The ids of the tokens to check\n     */\n    function checkFreeClaimEligibility(\n        uint256[] calldata _tokenIDs\n    ) external view returns (bool[] memory) {\n        Data storage data = HeyMintStorage.state().data;\n        bool[] memory eligible = new bool[](_tokenIDs.length);\n        for (uint256 i = 0; i < _tokenIDs.length; i++) {\n            eligible[i] = !data.freeClaimUsed[_tokenIDs[i]];\n        }\n        return eligible;\n    }\n\n    /**\n     * @notice Free claim token when msg.sender owns the token in the external contract\n     * @param _tokenIDs The ids of the tokens to redeem\n     */\n    function freeClaim(\n        uint256[] calldata _tokenIDs\n    ) external payable nonReentrant {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        uint256 tokenIdsLength = _tokenIDs.length;\n        uint256 totalMints = tokenIdsLength * state.advCfg.mintsPerFreeClaim;\n        require(\n            state.advCfg.freeClaimContractAddress != address(0),\n            \"NOT_CONFIGURED\"\n        );\n        require(state.advCfg.mintsPerFreeClaim != 0, \"NOT_CONFIGURED\");\n        require(state.advCfg.freeClaimActive, \"NOT_ACTIVE\");\n        require(\n            totalSupply() + totalMints <= state.cfg.maxSupply,\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        if (state.cfg.heyMintFeeActive) {\n            uint256 heymintFee = totalMints * heymintFeePerToken();\n            require(msg.value == heymintFee, \"PAYMENT_INCORRECT\");\n            (bool success, ) = heymintPayoutAddress.call{value: heymintFee}(\"\");\n            require(success, \"TRANSFER_FAILED\");\n        }\n        IERC721 ExternalERC721FreeClaimContract = IERC721(\n            state.advCfg.freeClaimContractAddress\n        );\n        for (uint256 i = 0; i < tokenIdsLength; i++) {\n            require(\n                ExternalERC721FreeClaimContract.ownerOf(_tokenIDs[i]) ==\n                    msg.sender,\n                \"MUST_OWN_TOKEN\"\n            );\n            require(\n                !state.data.freeClaimUsed[_tokenIDs[i]],\n                \"TOKEN_ALREADY_CLAIMED\"\n            );\n            state.data.freeClaimUsed[_tokenIDs[i]] = true;\n        }\n        _safeMint(msg.sender, totalMints);\n    }\n\n    // ============ RANDOM HASH ============\n\n    /**\n     * @notice To be updated by contract owner to allow random hash generation\n     * @param _randomHashActive true to enable random hash generation, false to disable\n     */\n    function setGenerateRandomHashState(\n        bool _randomHashActive\n    ) external onlyOwner {\n        BaseConfig storage cfg = HeyMintStorage.state().cfg;\n        cfg.randomHashActive = _randomHashActive;\n    }\n\n    /**\n     * @notice Retrieve random hashes for an array of token ids\n     * @param _tokenIDs The ids of the tokens to retrieve random hashes for\n     */\n    function getRandomHashes(\n        uint256[] calldata _tokenIDs\n    ) external view returns (bytes32[] memory) {\n        Data storage data = HeyMintStorage.state().data;\n        bytes32[] memory randomHashes = new bytes32[](_tokenIDs.length);\n        for (uint256 i = 0; i < _tokenIDs.length; i++) {\n            randomHashes[i] = data.randomHashStore[_tokenIDs[i]];\n        }\n        return randomHashes;\n    }\n}\n"
      },
      "contracts/implementations/HeyMintERC721AExtensionD.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {HeyMintERC721AUpgradeable} from \"./HeyMintERC721AUpgradeable.sol\";\nimport {AdvancedConfig, HeyMintStorage} from \"../libraries/HeyMintStorage.sol\";\nimport {MerkleProofUpgradeable} from \"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\";\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\n\ncontract HeyMintERC721AExtensionD is HeyMintERC721AUpgradeable {\n    using HeyMintStorage for HeyMintStorage.State;\n\n    event Loan(address from, address to, uint256 tokenId);\n    event LoanRetrieved(address from, address to, uint256 tokenId);\n\n    // Address of the HeyMint admin address\n    address public constant heymintAdminAddress =\n        0x52EA5F96f004d174470901Ba3F1984D349f0D3eF;\n    // Address where burnt tokens are sent.\n    address public constant burnAddress =\n        0x000000000000000000000000000000000000dEaD;\n\n    // ============ HEYMINT FEE ============\n\n    /**\n     * @notice Allows the heymintAdminAddress to set the heymint fee per token\n     * @param _heymintFeePerToken The new fee per token in wei\n     */\n    function setHeymintFeePerToken(uint256 _heymintFeePerToken) external {\n        require(msg.sender == heymintAdminAddress, \"MUST_BE_HEYMINT_ADMIN\");\n        HeyMintStorage.state().data.heymintFeePerToken = _heymintFeePerToken;\n    }\n\n    function setHeymintFeeState(bool _feeActive) external {\n        require(msg.sender == heymintAdminAddress, \"MUST_BE_HEYMINT_ADMIN\");\n        HeyMintStorage.state().cfg.heyMintFeeActive = _feeActive;\n    }\n\n    // ============ HEYMINT DEPOSIT TOKEN REDEMPTION ============\n\n    /**\n     * @notice Returns the deposit payment in wei. Deposit payment is stored with 5 decimals (1 = 0.00001 ETH), so total 5 + 13 == 18 decimals\n     */\n    function remainingDepositPaymentInWei() public view returns (uint256) {\n        return\n            uint256(HeyMintStorage.state().advCfg.remainingDepositPayment) *\n            10 ** 13;\n    }\n\n    /**\n     * @notice To be updated by contract owner to allow burning a deposit token to mint\n     * @param _depositClaimActive If true deposit tokens can be burned in order to mint\n     */\n    function setDepositClaimState(bool _depositClaimActive) external onlyOwner {\n        AdvancedConfig storage advCfg = HeyMintStorage.state().advCfg;\n        if (_depositClaimActive) {\n            require(advCfg.depositMerkleRoot != bytes32(0), \"NOT_CONFIGURED\");\n            require(\n                advCfg.depositContractAddress != address(0),\n                \"NOT_CONFIGURED\"\n            );\n        }\n        advCfg.depositClaimActive = _depositClaimActive;\n    }\n\n    /**\n     * @notice Set the merkle root used to validate the deposit tokens eligible for burning\n     * @dev Each leaf in the merkle tree is the token id of a deposit token\n     * @param _depositMerkleRoot The new merkle root\n     */\n    function setDepositMerkleRoot(\n        bytes32 _depositMerkleRoot\n    ) external onlyOwner {\n        HeyMintStorage.state().advCfg.depositMerkleRoot = _depositMerkleRoot;\n    }\n\n    /**\n     * @notice Set the address of the HeyMint deposit contract eligible for burning to mint\n     * @param _depositContractAddress The new deposit contract address\n     */\n    function setDepositContractAddress(\n        address _depositContractAddress\n    ) external onlyOwner {\n        HeyMintStorage\n            .state()\n            .advCfg\n            .depositContractAddress = _depositContractAddress;\n    }\n\n    /**\n     * @notice Set the remaining payment required in order to mint along with burning a deposit token\n     * @param _remainingDepositPayment The new remaining payment in centiETH\n     */\n    function setRemainingDepositPayment(\n        uint32 _remainingDepositPayment\n    ) external onlyOwner {\n        HeyMintStorage\n            .state()\n            .advCfg\n            .remainingDepositPayment = _remainingDepositPayment;\n    }\n\n    /**\n     * @notice Allows for burning deposit tokens in order to mint. The tokens must be eligible for burning.\n     * Additional payment may be required in addition to burning the deposit tokens.\n     * @dev This contract must be approved by the caller to transfer the deposit tokens being burned\n     * @param _tokenIds The token ids of the deposit tokens to burn\n     * @param _merkleProofs The merkle proofs for each token id verifying eligibility\n     */\n    function burnDepositTokensToMint(\n        uint256[] calldata _tokenIds,\n        bytes32[][] calldata _merkleProofs\n    ) external payable nonReentrant {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(state.advCfg.depositMerkleRoot != bytes32(0), \"NOT_CONFIGURED\");\n        require(\n            state.advCfg.depositContractAddress != address(0),\n            \"NOT_CONFIGURED\"\n        );\n        require(state.advCfg.depositClaimActive, \"NOT_ACTIVE\");\n        uint256 numberOfTokens = _tokenIds.length;\n        require(numberOfTokens > 0, \"NO_TOKEN_IDS_PROVIDED\");\n        require(\n            numberOfTokens == _merkleProofs.length,\n            \"ARRAY_LENGTHS_MUST_MATCH\"\n        );\n        require(\n            totalSupply() + numberOfTokens <= state.cfg.maxSupply,\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        require(\n            msg.value == remainingDepositPaymentInWei() * numberOfTokens,\n            \"INCORRECT_REMAINING_PAYMENT\"\n        );\n        IERC721 DepositContract = IERC721(state.advCfg.depositContractAddress);\n        for (uint256 i = 0; i < numberOfTokens; i++) {\n            require(\n                MerkleProofUpgradeable.verify(\n                    _merkleProofs[i],\n                    state.advCfg.depositMerkleRoot,\n                    keccak256(abi.encodePacked(_tokenIds[i]))\n                ),\n                \"INVALID_MERKLE_PROOF\"\n            );\n            require(\n                DepositContract.ownerOf(_tokenIds[i]) == msg.sender,\n                \"MUST_OWN_TOKEN\"\n            );\n            DepositContract.transferFrom(msg.sender, burnAddress, _tokenIds[i]);\n        }\n        _safeMint(msg.sender, numberOfTokens);\n    }\n\n    // ============ CONDITIONAL FUNDING ============\n\n    /**\n     * @notice Returns the funding target in wei. Funding target is stored with 2 decimals (1 = 0.01 ETH), so total 2 + 16 == 18 decimals\n     */\n    function fundingTargetInWei() public view returns (uint256) {\n        return uint256(HeyMintStorage.state().cfg.fundingTarget) * 10 ** 16;\n    }\n\n    /**\n     * @notice To be called by anyone once the funding duration has passed to determine if the funding target was reached\n     * If the funding target was not reached, all funds are refundable. Must be called before owner can withdraw funds\n     */\n    function determineFundingSuccess() external {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(state.cfg.fundingEndsAt > 0, \"NOT_CONFIGURED\");\n        require(\n            address(this).balance >= fundingTargetInWei(),\n            \"FUNDING_TARGET_NOT_MET\"\n        );\n        require(\n            !state.data.fundingSuccessDetermined,\n            \"SUCCESS_ALREADY_DETERMINED\"\n        );\n        state.data.fundingTargetReached = true;\n        state.data.fundingSuccessDetermined = true;\n    }\n\n    /**\n     * @notice Burn tokens and return the price paid to the token owner if the funding target was not reached\n     * Can be called starting 1 day after funding duration ends\n     * @param _tokenIds The ids of the tokens to be refunded\n     */\n    function burnToRefund(uint256[] calldata _tokenIds) external nonReentrant {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        // Prevent refunding tokens on a contract where conditional funding has not been enabled\n        require(state.cfg.fundingEndsAt > 0, \"NOT_CONFIGURED\");\n        require(\n            block.timestamp > uint256(state.cfg.fundingEndsAt) + 1 days,\n            \"FUNDING_PERIOD_STILL_ACTIVE\"\n        );\n        require(!state.data.fundingTargetReached, \"FUNDING_TARGET_WAS_MET\");\n        require(\n            address(this).balance < fundingTargetInWei(),\n            \"FUNDING_TARGET_WAS_MET\"\n        );\n\n        uint256 totalRefund = 0;\n\n        for (uint256 i = 0; i < _tokenIds.length; i++) {\n            require(ownerOf(_tokenIds[i]) == msg.sender, \"MUST_OWN_TOKEN\");\n            require(\n                state.data.pricePaid[_tokenIds[i]] > 0,\n                \"TOKEN_WAS_NOT_PURCHASED\"\n            );\n            safeTransferFrom(\n                msg.sender,\n                0x000000000000000000000000000000000000dEaD,\n                _tokenIds[i]\n            );\n            totalRefund += state.data.pricePaid[_tokenIds[i]];\n        }\n\n        (bool success, ) = payable(msg.sender).call{value: totalRefund}(\"\");\n        require(success, \"TRANSFER_FAILED\");\n    }\n\n    // ============ LOANING ============\n\n    /**\n     * @notice To be updated by contract owner to allow for loan functionality to turned on and off\n     * @param _loaningActive The new state of loaning (true = on, false = off)\n     */\n    function setLoaningActive(bool _loaningActive) external onlyOwner {\n        HeyMintStorage.state().advCfg.loaningActive = _loaningActive;\n    }\n\n    /**\n     * @notice Allow owner to loan their tokens to other addresses\n     * @param _tokenId The id of the token to loan\n     * @param _receiver The address of the receiver of the loan\n     */\n    function loan(uint256 _tokenId, address _receiver) external nonReentrant {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(\n            state.data.tokenOwnersOnLoan[_tokenId] == address(0),\n            \"CANNOT_LOAN_BORROWED_TOKEN\"\n        );\n        require(state.advCfg.loaningActive, \"NOT_ACTIVE\");\n        require(ownerOf(_tokenId) == msg.sender, \"MUST_OWN_TOKEN\");\n        require(_receiver != msg.sender, \"CANNOT_LOAN_TO_SELF\");\n        // Transfer the token - must do this before updating the mapping otherwise transfer will fail; nonReentrant modifier will prevent reentrancy\n        safeTransferFrom(msg.sender, _receiver, _tokenId);\n        // Add it to the mapping of originally loaned tokens\n        state.data.tokenOwnersOnLoan[_tokenId] = msg.sender;\n        // Add to the owner's loan balance\n        state.data.totalLoanedPerAddress[msg.sender] += 1;\n        state.data.currentLoanTotal += 1;\n        emit Loan(msg.sender, _receiver, _tokenId);\n    }\n\n    /**\n     * @notice Allow the original owner of a token to retrieve a loaned token\n     * @param _tokenId The id of the token to retrieve\n     */\n    function retrieveLoan(uint256 _tokenId) external nonReentrant {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        address borrowerAddress = ownerOf(_tokenId);\n        require(borrowerAddress != msg.sender, \"MUST_OWN_TOKEN\");\n        require(\n            state.data.tokenOwnersOnLoan[_tokenId] == msg.sender,\n            \"MUST_OWN_TOKEN\"\n        );\n        // Remove it from the array of loaned out tokens\n        delete state.data.tokenOwnersOnLoan[_tokenId];\n        // Subtract from the owner's loan balance\n        state.data.totalLoanedPerAddress[msg.sender] -= 1;\n        state.data.currentLoanTotal -= 1;\n        // Transfer the token back\n        _directApproveMsgSenderFor(_tokenId);\n        safeTransferFrom(borrowerAddress, msg.sender, _tokenId);\n        emit LoanRetrieved(borrowerAddress, msg.sender, _tokenId);\n    }\n\n    /**\n     * @notice Allow contract owner to retrieve a loan to prevent malicious floor listings\n     * @param _tokenId The id of the token to retrieve\n     */\n    function adminRetrieveLoan(uint256 _tokenId) external onlyOwner {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        address borrowerAddress = ownerOf(_tokenId);\n        address loanerAddress = state.data.tokenOwnersOnLoan[_tokenId];\n        require(loanerAddress != address(0), \"TOKEN_NOT_LOANED\");\n        // Remove it from the array of loaned out tokens\n        delete state.data.tokenOwnersOnLoan[_tokenId];\n        // Subtract from the owner's loan balance\n        state.data.totalLoanedPerAddress[loanerAddress] -= 1;\n        state.data.currentLoanTotal -= 1;\n        // Transfer the token back\n        _directApproveMsgSenderFor(_tokenId);\n        safeTransferFrom(borrowerAddress, loanerAddress, _tokenId);\n        emit LoanRetrieved(borrowerAddress, loanerAddress, _tokenId);\n    }\n\n    /**\n     * Returns the total number of loaned tokens\n     */\n    function totalLoaned() public view returns (uint256) {\n        return HeyMintStorage.state().data.currentLoanTotal;\n    }\n\n    /**\n     * Returns the loaned balance of an address\n     * @param _owner The address to check\n     */\n    function loanedBalanceOf(address _owner) public view returns (uint256) {\n        return HeyMintStorage.state().data.totalLoanedPerAddress[_owner];\n    }\n\n    /**\n     * Returns all the token ids loaned by a given address\n     * @param _owner The address to check\n     */\n    function loanedTokensByAddress(\n        address _owner\n    ) external view returns (uint256[] memory) {\n        uint256 totalTokensLoaned = loanedBalanceOf(_owner);\n        uint256 mintedSoFar = totalSupply();\n        uint256 tokenIdsIdx = 0;\n        uint256[] memory allTokenIds = new uint256[](totalTokensLoaned);\n        for (\n            uint256 i = 1;\n            i <= mintedSoFar && tokenIdsIdx != totalTokensLoaned;\n            i++\n        ) {\n            if (HeyMintStorage.state().data.tokenOwnersOnLoan[i] == _owner) {\n                allTokenIds[tokenIdsIdx] = i;\n                tokenIdsIdx++;\n            }\n        }\n        return allTokenIds;\n    }\n\n    // ============ REFUND ============\n\n    /**\n     * @notice Returns the refund price in wei. Refund price is stored with 5 decimals (1 = 0.00001 ETH), so total 5 + 13 == 18 decimals\n     */\n    function refundPriceInWei() public view returns (uint256) {\n        return uint256(HeyMintStorage.state().advCfg.refundPrice) * 10 ** 13;\n    }\n\n    /**\n     * Will return true if token holders can still return their tokens for a refund\n     */\n    function refundGuaranteeActive() public view returns (bool) {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        return block.timestamp < state.advCfg.refundEndsAt;\n    }\n\n    /**\n     * @notice Set the address where tokens are sent when refunded\n     * @param _refundAddress The new refund address\n     */\n    function setRefundAddress(address _refundAddress) external onlyOwner {\n        require(_refundAddress != address(0), \"CANNOT_SEND_TO_ZERO_ADDRESS\");\n        HeyMintStorage.state().advCfg.refundAddress = _refundAddress;\n    }\n\n    /**\n     * @notice Increase the period of time where token holders can still return their tokens for a refund\n     * @param _newRefundEndsAt The new timestamp when the refund period ends. Must be greater than the current timestamp\n     */\n    function increaseRefundEndsAt(uint32 _newRefundEndsAt) external onlyOwner {\n        AdvancedConfig storage advCfg = HeyMintStorage.state().advCfg;\n        require(\n            _newRefundEndsAt > advCfg.refundEndsAt,\n            \"MUST_INCREASE_DURATION\"\n        );\n        HeyMintStorage.state().advCfg.refundEndsAt = _newRefundEndsAt;\n    }\n\n    /**\n     * @notice Refund token and return the refund price to the token owner.\n     * @param _tokenId The id of the token to refund\n     */\n    function refund(uint256 _tokenId) external nonReentrant {\n        require(refundGuaranteeActive(), \"REFUND_GUARANTEE_EXPIRED\");\n        require(ownerOf(_tokenId) == msg.sender, \"MUST_OWN_TOKEN\");\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n\n        // In case refunds are enabled with conditional funding, don't allow burnToRefund on refunded tokens\n        if (state.cfg.fundingEndsAt > 0) {\n            delete state.data.pricePaid[_tokenId];\n        }\n\n        address addressToSendToken = state.advCfg.refundAddress != address(0)\n            ? state.advCfg.refundAddress\n            : owner();\n\n        safeTransferFrom(msg.sender, addressToSendToken, _tokenId);\n\n        (bool success, ) = payable(msg.sender).call{value: refundPriceInWei()}(\n            \"\"\n        );\n        require(success, \"TRANSFER_FAILED\");\n    }\n}\n"
      },
      "contracts/implementations/HeyMintERC721AExtensionE.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {HeyMintERC721AUpgradeable} from \"./HeyMintERC721AUpgradeable.sol\";\nimport {HeyMintStorage, BaseConfig, AdvancedConfig, BurnToken} from \"../libraries/HeyMintStorage.sol\";\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport {IERC1155} from \"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\";\nimport {IDelegateRegistry} from \"../interfaces/IDelegateRegistry.sol\";\n\ncontract HeyMintERC721AExtensionE is HeyMintERC721AUpgradeable {\n    using HeyMintStorage for HeyMintStorage.State;\n\n    event HeyMintAffiliatePaid(address to, uint256 numTokens, uint256 value);\n\n    // Address where burnt tokens are sent.\n    address public constant burnAddress =\n        0x000000000000000000000000000000000000dEaD;\n    // Address of the HeyMint admin address\n    address public constant heymintAdminAddress =\n        0x52EA5F96f004d174470901Ba3F1984D349f0D3eF;\n    // Address for delegation registry\n    address public constant delegationRegistryAddress =\n        0x00000000000000447e69651d841bD8D104Bed493;\n\n    // ============ PUBLIC MINT ============\n\n    /**\n     * @notice Checks if the public sale affiliate minting is currently active.\n     * @return A boolean indicating whether public sale affiliate minting is active.\n     */\n    function isPublicAffiliateMintActive() public view returns (bool) {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        return (state.cfg.presaleSignerAddress != address(0) &&\n            state.cfg.publicSaleAffiliateMintEnabled &&\n            state.cfg.publicSaleActive &&\n            state.cfg.publicPrice > 0 &&\n            state.cfg.affiliateBasisPoints > 0 &&\n            (!state.cfg.usePublicSaleTimes ||\n                block.timestamp >= state.cfg.publicSaleStartTime) &&\n            (!state.cfg.usePublicSaleTimes ||\n                block.timestamp < state.cfg.publicSaleEndTime));\n    }\n\n    /**\n     * @notice Returns if public sale times are active. If required config settings are not set, returns true.\n     */\n    function publicSaleTimeIsActive() public view returns (bool) {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        if (\n            state.cfg.usePublicSaleTimes == false ||\n            state.cfg.publicSaleStartTime == 0 ||\n            state.cfg.publicSaleEndTime == 0\n        ) {\n            return true;\n        }\n        return\n            block.timestamp >= state.cfg.publicSaleStartTime &&\n            block.timestamp <= state.cfg.publicSaleEndTime;\n    }\n\n    /**\n     * @notice Allow for public minting of tokens\n     * @param _numTokens The number of tokens to mint\n     */\n    function _publicMint(uint256 _numTokens) internal {\n        BaseConfig storage cfg = HeyMintStorage.state().cfg;\n        require(cfg.publicSaleActive, \"NOT_ACTIVE\");\n        require(publicSaleTimeIsActive(), \"NOT_ACTIVE\");\n        require(\n            cfg.publicMintsAllowedPerAddress == 0 ||\n                _numberMinted(msg.sender) + _numTokens <=\n                cfg.publicMintsAllowedPerAddress,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        require(\n            cfg.publicMintsAllowedPerTransaction == 0 ||\n                _numTokens <= cfg.publicMintsAllowedPerTransaction,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        require(\n            totalSupply() + _numTokens <= cfg.maxSupply,\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        uint256 publicPrice = publicPriceInWei();\n        if (cfg.heyMintFeeActive) {\n            uint256 heymintFee = _numTokens * heymintFeePerToken();\n            require(\n                msg.value == publicPrice * _numTokens + heymintFee,\n                \"INVALID_PRICE_PAID\"\n            );\n            (bool success, ) = heymintPayoutAddress.call{value: heymintFee}(\"\");\n            require(success, \"TRANSFER_FAILED\");\n        } else {\n            require(\n                msg.value == publicPrice * _numTokens,\n                \"INVALID_PRICE_PAID\"\n            );\n        }\n\n        if (cfg.fundingEndsAt > 0) {\n            uint256 firstTokenIdToMint = _nextTokenId();\n            for (uint256 i = 0; i < _numTokens; i++) {\n                HeyMintStorage.state().data.pricePaid[\n                    firstTokenIdToMint + i\n                ] = publicPrice;\n            }\n        }\n\n        _safeMint(msg.sender, _numTokens);\n\n        if (totalSupply() >= cfg.maxSupply) {\n            cfg.publicSaleActive = false;\n        }\n    }\n\n    /**\n     * @notice Allow for public minting of tokens\n     * @param _numTokens The number of tokens to mint\n     */\n    function publicMint(uint256 _numTokens) external payable nonReentrant {\n        _publicMint(_numTokens);\n    }\n\n    /**\n     * @notice Allow for public minting of tokens with affiliate payment\n     * @param _affPaymentAddress The address to receive affiliate fees\n     * @param _affMessageHash The hash of the affiliate message containing the affiliate payment address & projectId\n     * @param _affSignature The signature for the affiliate payment message to verify\n     * @param _numTokens The number of tokens to mint\n     */\n    function affiliatePublicMint(\n        address _affPaymentAddress,\n        bytes32 _affMessageHash,\n        bytes calldata _affSignature,\n        uint256 _numTokens\n    ) external payable nonReentrant {\n        require(isPublicAffiliateMintActive(), \"NOT_ACTIVE\");\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(\n            keccak256(abi.encode(state.cfg.projectId, _affPaymentAddress)) ==\n                _affMessageHash,\n            \"MESSAGE_INVALID\"\n        );\n        require(\n            verifySignerAddress(_affMessageHash, _affSignature),\n            \"INVALID_SIGNATURE\"\n        );\n        _publicMint(_numTokens);\n        uint256 affFee = (_numTokens *\n            publicPriceInWei() *\n            state.cfg.affiliateBasisPoints) / 10000;\n        (bool ok, ) = _affPaymentAddress.call{value: affFee}(\"\");\n        require(ok, \"TRANSFER_FAILED\");\n        emit HeyMintAffiliatePaid(_affPaymentAddress, _numTokens, affFee);\n    }\n\n    // ============ GIFT ============\n\n    /**\n     * @notice Allow owner to send 'mintNumber' tokens without cost to multiple addresses\n     * @param _receivers The addresses to send the tokens to\n     * @param _mintNumber The number of tokens to send to each address\n     */\n    function gift(\n        address[] calldata _receivers,\n        uint256[] calldata _mintNumber\n    ) external payable onlyOwner {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(\n            _receivers.length == _mintNumber.length,\n            \"ARRAY_LENGTHS_MUST_MATCH\"\n        );\n        uint256 totalMints = 0;\n        for (uint256 i = 0; i < _mintNumber.length; i++) {\n            totalMints += _mintNumber[i];\n        }\n        require(\n            totalSupply() + totalMints <= state.cfg.maxSupply,\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        if (state.cfg.heyMintFeeActive) {\n            uint256 heymintFee = (totalMints * heymintFeePerToken()) / 10;\n            require(msg.value == heymintFee, \"PAYMENT_INCORRECT\");\n            (bool success, ) = heymintPayoutAddress.call{value: heymintFee}(\"\");\n            require(success, \"TRANSFER_FAILED\");\n        }\n        for (uint256 i = 0; i < _receivers.length; i++) {\n            _safeMint(_receivers[i], _mintNumber[i]);\n        }\n    }\n\n    // ============ BURN TO MINT ============\n\n    /**\n     * @notice Returns the burn payment in wei. Price is stored with 5 decimals (1 = 0.00001 ETH), so total 5 + 13 == 18 decimals\n     */\n    function burnPaymentInWei() public view returns (uint256) {\n        return uint256(HeyMintStorage.state().advCfg.burnPayment) * 10 ** 13;\n    }\n\n    /**\n     * @notice To be updated by contract owner to allow burning to claim a token\n     * @param _burnClaimActive If true tokens can be burned in order to mint\n     */\n    function setBurnClaimState(bool _burnClaimActive) external onlyOwner {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        if (_burnClaimActive) {\n            require(state.burnTokens.length != 0, \"NOT_CONFIGURED\");\n            require(state.advCfg.mintsPerBurn != 0, \"NOT_CONFIGURED\");\n        }\n        state.advCfg.burnClaimActive = _burnClaimActive;\n    }\n\n    /**\n     * @notice Set the contract address of the NFT to be burned in order to mint\n     * @param _burnTokens An array of all tokens required for burning\n     */\n    function updateBurnTokens(\n        BurnToken[] calldata _burnTokens\n    ) external onlyOwner {\n        BurnToken[] storage burnTokens = HeyMintStorage.state().burnTokens;\n        uint256 oldBurnTokensLength = burnTokens.length;\n        uint256 newBurnTokensLength = _burnTokens.length;\n\n        // Update the existing BurnTokens and push any new BurnTokens\n        for (uint256 i = 0; i < newBurnTokensLength; i++) {\n            if (i < oldBurnTokensLength) {\n                burnTokens[i] = _burnTokens[i];\n            } else {\n                burnTokens.push(_burnTokens[i]);\n            }\n        }\n\n        // Pop any extra BurnTokens if the new array is shorter\n        for (uint256 i = oldBurnTokensLength; i > newBurnTokensLength; i--) {\n            burnTokens.pop();\n        }\n    }\n\n    /**\n     * @notice Update the number of free mints claimable per token burned\n     * @param _mintsPerBurn The new number of tokens that can be minted per burn transaction\n     */\n    function updateMintsPerBurn(uint8 _mintsPerBurn) external onlyOwner {\n        HeyMintStorage.state().advCfg.mintsPerBurn = _mintsPerBurn;\n    }\n\n    /**\n     * @notice Update the price required to be paid alongside a burn tx to mint (payment is per tx, not per token in the case of >1 mintsPerBurn)\n     * @param _burnPayment The new amount of payment required per burn transaction\n     */\n    function updatePaymentPerBurn(uint32 _burnPayment) external onlyOwner {\n        HeyMintStorage.state().advCfg.burnPayment = _burnPayment;\n    }\n\n    /**\n     * @notice If true, real token ids are used for metadata. If false, burn token ids are used for metadata if they exist.\n     * @param _useBurnTokenIdForMetadata If true, burn token ids are used for metadata if they exist. If false, real token ids are used.\n     */\n    function setUseBurnTokenIdForMetadata(\n        bool _useBurnTokenIdForMetadata\n    ) external onlyOwner {\n        HeyMintStorage\n            .state()\n            .advCfg\n            .useBurnTokenIdForMetadata = _useBurnTokenIdForMetadata;\n    }\n\n    /**\n     * @notice Burn tokens from other contracts in order to mint tokens on this contract\n     * @dev This contract must be approved by the caller to transfer the tokens being burned\n     * @param _contracts The contracts of the tokens to burn in the same order as the array burnTokens\n     * @param _tokenIds Nested array of token ids to burn for 721 and amounts to burn for 1155 corresponding to _contracts\n     * @param _tokensToMint The number of tokens to mint\n     * @param _vault The address of the cold wallet (or zero address if not using delegation)\n     */\n    function _burnToMint(\n        address[] calldata _contracts,\n        uint256[][] calldata _tokenIds,\n        uint256 _tokensToMint,\n        address _vault\n    ) internal {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        IDelegateRegistry delegateContract = IDelegateRegistry(\n            delegationRegistryAddress\n        );\n        require(state.burnTokens.length > 0, \"NOT_CONFIGURED\");\n        require(state.advCfg.mintsPerBurn != 0, \"NOT_CONFIGURED\");\n        require(state.advCfg.burnClaimActive, \"NOT_ACTIVE\");\n        require(\n            _contracts.length == _tokenIds.length,\n            \"ARRAY_LENGTHS_MUST_MATCH\"\n        );\n        require(\n            _contracts.length == state.burnTokens.length,\n            \"ARRAY_LENGTHS_MUST_MATCH\"\n        );\n        require(\n            totalSupply() + _tokensToMint <= state.cfg.maxSupply,\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        address mintWallet = _vault == address(0) ? msg.sender : _vault;\n\n        uint256 burnPaymentTotal = burnPaymentInWei() *\n            (_tokensToMint / state.advCfg.mintsPerBurn);\n        if (state.cfg.heyMintFeeActive) {\n            uint256 heymintFee = _tokensToMint * heymintFeePerToken();\n            require(\n                msg.value == burnPaymentTotal + heymintFee,\n                \"INVALID_PRICE_PAID\"\n            );\n            (bool success, ) = heymintPayoutAddress.call{value: heymintFee}(\"\");\n            require(success, \"TRANSFER_FAILED\");\n        } else {\n            require(msg.value == burnPaymentTotal, \"INVALID_PRICE_PAID\");\n        }\n\n        for (uint256 i = 0; i < state.burnTokens.length; i++) {\n            BurnToken memory burnToken = state.burnTokens[i];\n            require(\n                burnToken.contractAddress == _contracts[i],\n                \"INCORRECT_CONTRACT\"\n            );\n            require(\n                _vault == address(0) ||\n                    delegateContract.checkDelegateForContract(\n                        msg.sender,\n                        _vault,\n                        _contracts[i],\n                        \"\"\n                    )\n            );\n            if (burnToken.tokenType == 1) {\n                uint256 _tokenIdsLength = _tokenIds[i].length;\n                require(\n                    (_tokenIdsLength / burnToken.tokensPerBurn) *\n                        state.advCfg.mintsPerBurn ==\n                        _tokensToMint,\n                    \"INCORRECT_NO_OF_TOKENS_TO_BURN\"\n                );\n                for (uint256 j = 0; j < _tokenIdsLength; j++) {\n                    IERC721 burnContract = IERC721(_contracts[i]);\n                    uint256 tokenId = _tokenIds[i][j];\n                    require(\n                        burnContract.ownerOf(tokenId) == mintWallet,\n                        \"MUST_OWN_TOKEN\"\n                    );\n                    burnContract.transferFrom(mintWallet, burnAddress, tokenId);\n                }\n            } else if (burnToken.tokenType == 2) {\n                uint256 amountToBurn = _tokenIds[i][0];\n                require(\n                    (amountToBurn / burnToken.tokensPerBurn) *\n                        state.advCfg.mintsPerBurn ==\n                        _tokensToMint,\n                    \"INCORRECT_NO_OF_TOKENS_TO_BURN\"\n                );\n                IERC1155 burnContract = IERC1155(_contracts[i]);\n                require(\n                    burnContract.balanceOf(mintWallet, burnToken.tokenId) >=\n                        amountToBurn,\n                    \"MUST_OWN_TOKEN\"\n                );\n                burnContract.safeTransferFrom(\n                    mintWallet,\n                    burnAddress,\n                    burnToken.tokenId,\n                    amountToBurn,\n                    \"\"\n                );\n            }\n        }\n        if (state.advCfg.useBurnTokenIdForMetadata) {\n            require(\n                _tokenIds[0].length == _tokensToMint,\n                \"BURN_TOKENS_MUST_MATCH_MINT_NO\"\n            );\n            uint256 firstNewTokenId = _nextTokenId();\n            for (uint256 i = 0; i < _tokensToMint; i++) {\n                state.data.tokenIdToBurnTokenId[\n                    firstNewTokenId + i\n                ] = _tokenIds[0][i];\n            }\n        }\n        _safeMint(mintWallet, _tokensToMint);\n    }\n\n    /**\n     * @notice Burn tokens from other contracts in order to mint tokens on this contract\n     * @dev This contract must be approved by the caller to transfer the tokens being burned\n     * @param _contracts The contracts of the tokens to burn in the same order as the array burnTokens\n     * @param _tokenIds Nested array of token ids to burn for 721 and amounts to burn for 1155 corresponding to _contracts\n     * @param _tokensToMint The number of tokens to mint\n     */\n    function burnToMint(\n        address[] calldata _contracts,\n        uint256[][] calldata _tokenIds,\n        uint256 _tokensToMint\n    ) external payable nonReentrant {\n        _burnToMint(_contracts, _tokenIds, _tokensToMint, address(0));\n    }\n\n    /**\n     * @notice Burn tokens from other contracts in order to mint tokens on this contract using delegation\n     * @dev This contract must be approved by the caller to transfer the tokens being burned\n     * @param _contracts The contracts of the tokens to burn in the same order as the array burnTokens\n     * @param _tokenIds Nested array of token ids to burn for 721 and amounts to burn for 1155 corresponding to _contracts\n     * @param _tokensToMint The number of tokens to mint\n     * @param _vault The address of the cold wallet\n     */\n    function burnToMintDelegated(\n        address[] calldata _contracts,\n        uint256[][] calldata _tokenIds,\n        uint256 _tokensToMint,\n        address _vault\n    ) external payable nonReentrant {\n        _burnToMint(_contracts, _tokenIds, _tokensToMint, _vault);\n    }\n\n    // ============ ERC-2981 ROYALTY ============\n\n    /**\n     * @notice Updates royalty basis points\n     * @param _royaltyBps The new royalty basis points to use\n     */\n    function setRoyaltyBasisPoints(uint16 _royaltyBps) external onlyOwner {\n        HeyMintStorage.state().cfg.royaltyBps = _royaltyBps;\n    }\n\n    /**\n     * @notice Updates royalty payout address\n     * @param _royaltyPayoutAddress The new royalty payout address to use\n     */\n    function setRoyaltyPayoutAddress(\n        address _royaltyPayoutAddress\n    ) external onlyOwner {\n        HeyMintStorage\n            .state()\n            .advCfg\n            .royaltyPayoutAddress = _royaltyPayoutAddress;\n    }\n\n    // ============ PAYOUT ============\n\n    /**\n     * @notice Freeze all payout addresses so they can never be changed again\n     */\n    function freezePayoutAddresses() external onlyOwner {\n        HeyMintStorage.state().advCfg.payoutAddressesFrozen = true;\n    }\n\n    /**\n     * @notice Update payout addresses and basis points for each addresses' respective share of contract funds\n     * @param _payoutAddresses The new payout addresses to use\n     * @param _payoutBasisPoints The amount to pay out to each address in _payoutAddresses (in basis points)\n     */\n    function updatePayoutAddressesAndBasisPoints(\n        address[] calldata _payoutAddresses,\n        uint16[] calldata _payoutBasisPoints\n    ) external onlyOwner {\n        AdvancedConfig storage advCfg = HeyMintStorage.state().advCfg;\n        uint256 payoutBasisPointsLength = _payoutBasisPoints.length;\n        require(\n            !advCfg.payoutAddressesFrozen,\n            \"CANNOT_UPDATE_CONSTANT_VARIABLE\"\n        );\n        require(\n            _payoutAddresses.length == payoutBasisPointsLength,\n            \"ARRAY_LENGTHS_MUST_MATCH\"\n        );\n        uint256 totalBasisPoints = 0;\n        for (uint256 i = 0; i < payoutBasisPointsLength; i++) {\n            totalBasisPoints += _payoutBasisPoints[i];\n        }\n        require(totalBasisPoints == 10000, \"BASIS_POINTS_MUST_EQUAL_10000\");\n        advCfg.payoutAddresses = _payoutAddresses;\n        advCfg.payoutBasisPoints = _payoutBasisPoints;\n    }\n}\n"
      },
      "contracts/implementations/HeyMintERC721AReference.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n/**\n * @title HeyMint ERC721A Function Reference\n * @author HeyMint Launchpad (https://join.heymint.xyz)\n * @notice This is a function reference contract for Etherscan reference purposes only.\n * This contract includes all the functions from multiple implementation contracts.\n */\ncontract HeyMintERC721AReference {\n    struct BaseConfig {\n        bool publicSaleActive;\n        bool usePublicSaleTimes;\n        bool presaleActive;\n        bool usePresaleTimes;\n        bool soulbindingActive;\n        bool randomHashActive;\n        bool enforceRoyalties;\n        bool heyMintFeeActive;\n        uint8 publicMintsAllowedPerAddress;\n        uint8 presaleMintsAllowedPerAddress;\n        uint8 publicMintsAllowedPerTransaction;\n        uint8 presaleMintsAllowedPerTransaction;\n        uint16 maxSupply;\n        uint16 presaleMaxSupply;\n        uint16 royaltyBps;\n        uint32 publicPrice;\n        uint32 presalePrice;\n        uint24 projectId;\n        bool presaleAffiliateMintEnabled;\n        bool publicSaleAffiliateMintEnabled;\n        uint16 affiliateBasisPoints;\n        string uriBase;\n        address presaleSignerAddress;\n        uint32 publicSaleStartTime;\n        uint32 publicSaleEndTime;\n        uint32 presaleStartTime;\n        uint32 presaleEndTime;\n        uint32 fundingEndsAt;\n        uint32 fundingTarget;\n    }\n\n    struct AdvancedConfig {\n        bool stakingActive;\n        bool loaningActive;\n        bool freeClaimActive;\n        uint8 mintsPerFreeClaim;\n        address freeClaimContractAddress;\n        bool burnClaimActive;\n        bool useBurnTokenIdForMetadata;\n        uint8 mintsPerBurn;\n        uint32 burnPayment;\n        bool payoutAddressesFrozen;\n        uint32 refundEndsAt;\n        uint32 refundPrice;\n        bool metadataFrozen;\n        bool soulbindAdminTransfersPermanentlyDisabled;\n        bool depositClaimActive;\n        uint32 remainingDepositPayment;\n        bool subscriptionsEnabled;\n        uint32 subscriptionPrice;\n        uint32 subscriptionPeriod;\n        uint32 subscriptionGracePeriod;\n        bool subscriptionAdminTransfersPermanentlyDisabled;\n        address subscriptionErc20Address;\n        address depositContractAddress;\n        bytes32 depositMerkleRoot;\n        uint16[] payoutBasisPoints;\n        address[] payoutAddresses;\n        address royaltyPayoutAddress;\n        address soulboundAdminAddress;\n        address refundAddress;\n        address[] creditCardMintAddresses;\n        address subscriptionAdminAddress;\n    }\n\n    struct BurnToken {\n        address contractAddress;\n        uint8 tokenType;\n        uint8 tokensPerBurn;\n        uint16 tokenId;\n    }\n\n    struct TokenOwnership {\n        address addr;\n        uint64 startTimestamp;\n        bool burned;\n        uint24 extraData;\n    }\n\n    function CORI_SUBSCRIPTION_ADDRESS() external view returns (address) {}\n\n    function EMPTY_SUBSCRIPTION_ADDRESS() external view returns (address) {}\n\n    function approve(address to, uint256 tokenId) external payable {}\n\n    function balanceOf(address _owner) external view returns (uint256) {}\n\n    function defaultHeymintFeePerToken() external view returns (uint256) {}\n\n    function explicitOwnershipOf(\n        uint256 tokenId\n    ) external view returns (TokenOwnership memory) {}\n\n    function explicitOwnershipsOf(\n        uint256[] memory tokenIds\n    ) external view returns (TokenOwnership[] memory) {}\n\n    function freezeMetadata() external {}\n\n    function getApproved(uint256 tokenId) external view returns (address) {}\n\n    function heymintFeePerToken() external view returns (uint256) {}\n\n    function heymintPayoutAddress() external view returns (address) {}\n\n    function initialize(\n        string memory _name,\n        string memory _symbol,\n        BaseConfig memory _config\n    ) external {}\n\n    function isApprovedForAll(\n        address _owner,\n        address operator\n    ) external view returns (bool) {}\n\n    function isOperatorFilterRegistryRevoked() external view returns (bool) {}\n\n    function name() external view returns (string memory) {}\n\n    function numberMinted(address _owner) external view returns (uint256) {}\n\n    function owner() external view returns (address) {}\n\n    function ownerOf(uint256 tokenId) external view returns (address) {}\n\n    function pause() external {}\n\n    function paused() external view returns (bool) {}\n\n    function publicMint(uint256 _numTokens) external payable {}\n\n    function publicPriceInWei() external view returns (uint256) {}\n\n    function publicSaleTimeIsActive() external view returns (bool) {}\n\n    function reduceMaxSupply(uint16 _newMaxSupply) external {}\n\n    function refundGuaranteeActive() external view returns (bool) {}\n\n    function renounceOwnership() external {}\n\n    function revokeOperatorFilterRegistry() external {}\n\n    function royaltyInfo(\n        uint256,\n        uint256 _salePrice\n    ) external view returns (address, uint256) {}\n\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external payable {}\n\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) external payable {}\n\n    function setApprovalForAll(address operator, bool approved) external {}\n\n    function setBaseURI(string memory _newBaseURI) external {}\n\n    function setPublicMintsAllowedPerAddress(uint8 _mintsAllowed) external {}\n\n    function setPublicMintsAllowedPerTransaction(\n        uint8 _mintsAllowed\n    ) external {}\n\n    function setPublicPrice(uint32 _publicPrice) external {}\n\n    function setPublicSaleEndTime(uint32 _publicSaleEndTime) external {}\n\n    function setPublicSaleStartTime(uint32 _publicSaleStartTime) external {}\n\n    function setPublicSaleState(bool _saleActiveState) external {}\n\n    function setUsePublicSaleTimes(bool _usePublicSaleTimes) external {}\n\n    function setUser(uint256 tokenId, address user, uint64 expires) external {}\n\n    function supportsInterface(\n        bytes4 interfaceId\n    ) external view returns (bool) {}\n\n    function symbol() external view returns (string memory) {}\n\n    function tokenURI(uint256 tokenId) external view returns (string memory) {}\n\n    function tokensOfOwner(\n        address _owner\n    ) external view returns (uint256[] memory) {}\n\n    function tokensOfOwnerIn(\n        address _owner,\n        uint256 start,\n        uint256 stop\n    ) external view returns (uint256[] memory) {}\n\n    function totalSupply() external view returns (uint256) {}\n\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external payable {}\n\n    function transferOwnership(address newOwner) external {}\n\n    function unpause() external {}\n\n    function userExpires(uint256 tokenId) external view returns (uint256) {}\n\n    function userOf(uint256 tokenId) external view returns (address) {}\n\n    function withdraw() external {}\n\n    function freezePayoutAddresses() external {}\n\n    function getSettings()\n        external\n        view\n        returns (\n            BaseConfig memory,\n            AdvancedConfig memory,\n            BurnToken[] memory,\n            bool,\n            bool,\n            bool,\n            uint256\n        )\n    {}\n\n    function gift(\n        address[] memory _receivers,\n        uint256[] memory _mintNumber\n    ) external payable {}\n\n    function setRoyaltyBasisPoints(uint16 _royaltyBps) external {}\n\n    function setRoyaltyPayoutAddress(address _royaltyPayoutAddress) external {}\n\n    function updateAdvancedConfig(\n        AdvancedConfig memory _advancedConfig\n    ) external {}\n\n    function updateBaseConfig(BaseConfig memory _baseConfig) external {}\n\n    function updatePayoutAddressesAndBasisPoints(\n        address[] memory _payoutAddresses,\n        uint16[] memory _payoutBasisPoints\n    ) external {}\n\n    function burnAddress() external view returns (address) {}\n\n    function burnPaymentInWei() external view returns (uint256) {}\n\n    function burnToMint(\n        address[] memory _contracts,\n        uint256[][] memory _tokenIds,\n        uint256 _tokensToMint\n    ) external payable {}\n\n    function burnToMintDelegated(\n        address[] memory _contracts,\n        uint256[][] memory _tokenIds,\n        uint256 _tokensToMint,\n        address _vault\n    ) external payable {}\n\n    function presaleMint(\n        bytes32 _messageHash,\n        bytes memory _signature,\n        uint256 _numTokens,\n        uint256 _maximumAllowedMints\n    ) external payable {}\n\n    function presalePriceInWei() external view returns (uint256) {}\n\n    function presaleTimeIsActive() external view returns (bool) {}\n\n    function reducePresaleMaxSupply(uint16 _newPresaleMaxSupply) external {}\n\n    function setBurnClaimState(bool _burnClaimActive) external {}\n\n    function setPresaleEndTime(uint32 _presaleEndTime) external {}\n\n    function setPresaleMintsAllowedPerAddress(uint8 _mintsAllowed) external {}\n\n    function setPresaleMintsAllowedPerTransaction(\n        uint8 _mintsAllowed\n    ) external {}\n\n    function setPresalePrice(uint32 _presalePrice) external {}\n\n    function setPresaleSignerAddress(address _presaleSignerAddress) external {}\n\n    function setPresaleStartTime(uint32 _presaleStartTime) external {}\n\n    function setPresaleState(bool _saleActiveState) external {}\n\n    function setUseBurnTokenIdForMetadata(\n        bool _useBurnTokenIdForMetadata\n    ) external {}\n\n    function setUsePresaleTimes(bool _usePresaleTimes) external {}\n\n    function updateBurnTokens(BurnToken[] memory _burnTokens) external {}\n\n    function updateMintsPerBurn(uint8 _mintsPerBurn) external {}\n\n    function updatePaymentPerBurn(uint32 _burnPayment) external {}\n\n    function adminUnstake(uint256 _tokenId) external {}\n\n    function baseTokenURI() external view returns (string memory) {}\n\n    function checkFreeClaimEligibility(\n        uint256[] memory _tokenIDs\n    ) external view returns (bool[] memory) {}\n\n    function creditCardMint(uint256 _numTokens, address _to) external payable {}\n\n    function currentTokenStakeTime(\n        uint256 _tokenId\n    ) external view returns (uint256) {}\n\n    function disableSoulbindAdminTransfersPermanently() external {}\n\n    function freeClaim(uint256[] memory _tokenIDs) external payable {}\n\n    function getRandomHashes(\n        uint256[] memory _tokenIDs\n    ) external view returns (bytes32[] memory) {}\n\n    function setCreditCardMintAddresses(\n        address[] memory _creditCardMintAddresses\n    ) external {}\n\n    function setFreeClaimContractAddress(\n        address _freeClaimContractAddress\n    ) external {}\n\n    function setFreeClaimState(bool _freeClaimActive) external {}\n\n    function setGenerateRandomHashState(bool _randomHashActive) external {}\n\n    function setSoulbindingState(bool _soulbindingActive) external {}\n\n    function setSoulboundAdminAddress(address _adminAddress) external {}\n\n    function setStakingState(bool _stakingState) external {}\n\n    function setTokenURIs(\n        uint256[] memory _tokenIds,\n        string[] memory _newURIs\n    ) external {}\n\n    function soulboundAdminTransfer(\n        address _from,\n        address _to,\n        uint256 _tokenId\n    ) external {}\n\n    function stakeTokens(uint256[] memory _tokenIds) external {}\n\n    function stakingTransfer(\n        address _from,\n        address _to,\n        uint256 _tokenId\n    ) external {}\n\n    function totalTokenStakeTime(\n        uint256 _tokenId\n    ) external view returns (uint256) {}\n\n    function unstakeTokens(uint256[] memory _tokenIds) external {}\n\n    function updateMintsPerFreeClaim(uint8 _mintsPerFreeClaim) external {}\n\n    function adminRetrieveLoan(uint256 _tokenId) external {}\n\n    function burnDepositTokensToMint(\n        uint256[] memory _tokenIds,\n        bytes32[][] memory _merkleProofs\n    ) external payable {}\n\n    function burnToRefund(uint256[] memory _tokenIds) external {}\n\n    function determineFundingSuccess() external {}\n\n    function fundingTargetInWei() external view returns (uint256) {}\n\n    function heymintAdminAddress() external view returns (address) {}\n\n    function increaseRefundEndsAt(uint32 _newRefundEndsAt) external {}\n\n    function loan(uint256 _tokenId, address _receiver) external {}\n\n    function loanedBalanceOf(address _owner) external view returns (uint256) {}\n\n    function loanedTokensByAddress(\n        address _owner\n    ) external view returns (uint256[] memory) {}\n\n    function refund(uint256 _tokenId) external {}\n\n    function refundPriceInWei() external view returns (uint256) {}\n\n    function remainingDepositPaymentInWei() external view returns (uint256) {}\n\n    function retrieveLoan(uint256 _tokenId) external {}\n\n    function setDepositClaimState(bool _depositClaimActive) external {}\n\n    function setDepositContractAddress(\n        address _depositContractAddress\n    ) external {}\n\n    function setDepositMerkleRoot(bytes32 _depositMerkleRoot) external {}\n\n    function setHeymintFeePerToken(uint256 _heymintFeePerToken) external {}\n\n    function setHeymintFeeState(bool _feeActive) external {}\n\n    function setLoaningActive(bool _loaningActive) external {}\n\n    function setRefundAddress(address _refundAddress) external {}\n\n    function setRemainingDepositPayment(\n        uint32 _remainingDepositPayment\n    ) external {}\n\n    function totalLoaned() external view returns (uint256) {}\n\n    function isPublicAffiliateMintActive() public view returns (bool) {}\n\n    function affiliatePublicMint(\n        address _affPaymentAddress,\n        bytes32 _affMessageHash,\n        bytes calldata _affSignature,\n        uint256 _numTokens\n    ) external payable {}\n\n    function isPresaleAffiliateMintActive() public view returns (bool) {}\n\n    function affiliatePresaleMint(\n        address _affPaymentAddress,\n        bytes32 _affMessageHash,\n        bytes calldata _affSignature,\n        bytes32 _messageHash,\n        bytes calldata _signature,\n        uint256 _numTokens,\n        uint256 _maximumAllowedMints\n    ) external payable {}\n\n    function affiliateCreditCardMint(\n        address _affPaymentAddress,\n        bytes32 _affMessageHash,\n        bytes calldata _affSignature,\n        uint256 _numTokens,\n        address _to\n    ) external payable {}\n\n    function creditCardPresaleMint(\n        bytes32 _messageHash,\n        bytes calldata _signature,\n        uint256 _numTokens,\n        address _to,\n        bytes32 _emailAddress,\n        uint256 _maximumAllowedMints\n    ) external payable {}\n\n    function affiliateCreditCardPresaleMint(\n        address _affPaymentAddress,\n        bytes32 _affMessageHash,\n        bytes calldata _affSignature,\n        bytes32 _messageHash,\n        bytes calldata _signature,\n        uint256 _numTokens,\n        address _to,\n        bytes32 _emailAddress,\n        uint256 _maximumAllowedMints\n    ) external payable {}\n}\n"
      },
      "contracts/implementations/HeyMintERC721AUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Data, HeyMintStorage} from \"../libraries/HeyMintStorage.sol\";\nimport {ERC721AUpgradeable, IERC721AUpgradeable, ERC721AStorage} from \"erc721a-upgradeable/contracts/ERC721AUpgradeable.sol\";\nimport {ERC4907AUpgradeable} from \"erc721a-upgradeable/contracts/extensions/ERC4907AUpgradeable.sol\";\nimport {ERC721AQueryableUpgradeable} from \"erc721a-upgradeable/contracts/extensions/ERC721AQueryableUpgradeable.sol\";\nimport {IERC2981Upgradeable, IERC165Upgradeable} from \"@openzeppelin/contracts-upgradeable/interfaces/IERC2981Upgradeable.sol\";\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {ReentrancyGuardUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport {RevokableOperatorFiltererUpgradeable} from \"operator-filter-registry/src/upgradeable/RevokableOperatorFiltererUpgradeable.sol\";\nimport {ECDSAUpgradeable} from \"@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol\";\nimport {IHeyMintDefaults} from \"../interfaces/IHeyMintDefaults.sol\";\n\n/**\n * @title HeyMintERC721AUpgradeable\n * @author HeyMint Launchpad (https://join.heymint.xyz)\n * @notice This contract contains shared logic to be inherited by all implementation contracts\n */\ncontract HeyMintERC721AUpgradeable is\n    ERC4907AUpgradeable,\n    ERC721AQueryableUpgradeable,\n    OwnableUpgradeable,\n    PausableUpgradeable,\n    ReentrancyGuardUpgradeable,\n    RevokableOperatorFiltererUpgradeable\n{\n    using HeyMintStorage for HeyMintStorage.State;\n    using ECDSAUpgradeable for bytes32;\n\n    uint256 public constant defaultHeymintFeePerToken = 0.0008 ether;\n    address public constant heymintPayoutAddress =\n        0xE1FaC470dE8dE91c66778eaa155C64c7ceEFc851;\n    address constant HEYMINT_DEFAULTS_ADDR =\n        0x2A6BE4588DCd707A3cD027f567ac9971EfABb7bd;\n\n    // ============ BASE FUNCTIONALITY ============\n\n    /**\n     * @dev Overrides the default ERC721A _startTokenId() so tokens begin at 1 instead of 0\n     */\n    function _startTokenId() internal view virtual override returns (uint256) {\n        return 1;\n    }\n\n    /**\n     * @notice Wraps and exposes publicly _numberMinted() from ERC721A\n     * @param _owner The address of the owner to check\n     */\n    function numberMinted(address _owner) public view returns (uint256) {\n        return _numberMinted(_owner);\n    }\n\n    /**\n     * @dev Used to directly approve a token for transfers by the current msg.sender,\n     * bypassing the typical checks around msg.sender being the owner of a given token.\n     * This approval will be automatically deleted once the token is transferred.\n     * @param _tokenId The ID of the token to approve\n     */\n    function _directApproveMsgSenderFor(uint256 _tokenId) internal {\n        ERC721AStorage.layout()._tokenApprovals[_tokenId].value = msg.sender;\n    }\n\n    /**\n     * @notice Returns the owner of the contract\n     */\n    function owner()\n        public\n        view\n        virtual\n        override(OwnableUpgradeable, RevokableOperatorFiltererUpgradeable)\n        returns (address)\n    {\n        return OwnableUpgradeable.owner();\n    }\n\n    // https://chiru-labs.github.io/ERC721A/#/migration?id=supportsinterface\n    /**\n     * @notice Returns true if the contract implements the interface defined by interfaceId\n     * @param interfaceId The interface identifier, as specified in ERC-165\n     */\n    function supportsInterface(\n        bytes4 interfaceId\n    )\n        public\n        view\n        virtual\n        override(ERC721AUpgradeable, IERC721AUpgradeable, ERC4907AUpgradeable)\n        returns (bool)\n    {\n        // Supports the following interfaceIds:\n        // - IERC165: 0x01ffc9a7\n        // - IERC721: 0x80ac58cd\n        // - IERC721Metadata: 0x5b5e139f\n        // - IERC2981: 0x2a55205a\n        // - IERC4907: 0xad092b5c\n        return\n            ERC721AUpgradeable.supportsInterface(interfaceId) ||\n            type(IERC2981Upgradeable).interfaceId == interfaceId ||\n            ERC4907AUpgradeable.supportsInterface(interfaceId);\n    }\n\n    // ============ HEYMINT FEE ============\n\n    /**\n     * @notice Returns the HeyMint fee per token. If the fee is 0, the default fee is returned\n     */\n    function heymintFeePerToken() public view returns (uint256) {\n        uint256 fee = HeyMintStorage.state().data.heymintFeePerToken;\n        return fee == 0 ? defaultHeymintFeePerToken : fee;\n    }\n\n    // ============ OPERATOR FILTER REGISTRY ============\n\n    /**\n     * @notice Override default ERC-721 setApprovalForAll to require that the operator is not from a blocklisted exchange\n     * @dev See {IERC721-setApprovalForAll}.\n     * @param operator Address to add to the set of authorized operators\n     * @param approved True if the operator is approved, false to revoke approval\n     */\n    function setApprovalForAll(\n        address operator,\n        bool approved\n    )\n        public\n        override(ERC721AUpgradeable, IERC721AUpgradeable)\n        onlyAllowedOperatorApproval(operator)\n    {\n        require(\n            !HeyMintStorage.state().cfg.soulbindingActive,\n            \"TOKEN_IS_SOULBOUND\"\n        );\n        super.setApprovalForAll(operator, approved);\n    }\n\n    /**\n     * @notice Override default ERC721 approve to require that the operator is not from a blocklisted exchange\n     * @dev See {IERC721-approve}.\n     * @param to Address to receive the approval\n     * @param tokenId ID of the token to be approved\n     */\n    function approve(\n        address to,\n        uint256 tokenId\n    )\n        public\n        payable\n        override(ERC721AUpgradeable, IERC721AUpgradeable)\n        onlyAllowedOperatorApproval(to)\n    {\n        require(\n            !HeyMintStorage.state().cfg.soulbindingActive,\n            \"TOKEN_IS_SOULBOUND\"\n        );\n        super.approve(to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-transferFrom}.\n     *      The added modifier ensures that the operator is allowed by the OperatorFilterRegistry.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    )\n        public\n        payable\n        override(ERC721AUpgradeable, IERC721AUpgradeable)\n        onlyAllowedOperator(from)\n    {\n        super.transferFrom(from, to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     *      The added modifier ensures that the operator is allowed by the OperatorFilterRegistry.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    )\n        public\n        payable\n        override(ERC721AUpgradeable, IERC721AUpgradeable)\n        onlyAllowedOperator(from)\n    {\n        super.safeTransferFrom(from, to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     *      The added modifier ensures that the operator is allowed by the OperatorFilterRegistry.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    )\n        public\n        payable\n        override(ERC721AUpgradeable, IERC721AUpgradeable)\n        onlyAllowedOperator(from)\n    {\n        super.safeTransferFrom(from, to, tokenId, data);\n    }\n\n    // ============ RANDOM HASH ============\n\n    /**\n     * @notice Generate a suitably random hash from block data\n     * Can be used later to determine any sort of arbitrary outcome\n     * @param _tokenId The token ID to generate a random hash for\n     */\n    function _generateRandomHash(uint256 _tokenId) internal {\n        Data storage data = HeyMintStorage.state().data;\n        if (data.randomHashStore[_tokenId] == bytes32(0)) {\n            data.randomHashStore[_tokenId] = keccak256(\n                abi.encode(block.prevrandao, _tokenId)\n            );\n        }\n    }\n\n    // ============ TOKEN TRANSFER CHECKS ============\n\n    function _beforeTokenTransfers(\n        address from,\n        address to,\n        uint256 tokenId,\n        uint256 quantity\n    ) internal override whenNotPaused onlyAllowedOperator(from) {\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        require(\n            !state.advCfg.stakingActive ||\n                state.data.stakingTransferActive ||\n                state.data.currentTimeStaked[tokenId] == 0,\n            \"TOKEN_IS_STAKED\"\n        );\n        require(\n            state.data.tokenOwnersOnLoan[tokenId] == address(0),\n            \"CANNOT_TRANSFER_LOANED_TOKEN\"\n        );\n        if (\n            state.cfg.soulbindingActive &&\n            !state.data.soulboundAdminTransferInProgress\n        ) {\n            require(from == address(0), \"TOKEN_IS_SOULBOUND\");\n        }\n        if (state.cfg.randomHashActive && from == address(0)) {\n            _generateRandomHash(tokenId);\n        }\n\n        super._beforeTokenTransfers(from, to, tokenId, quantity);\n    }\n\n    // ============ MISC FUNCTIONS ============\n\n    /**\n     * @notice Returns the public price in wei. Public price is stored with 5 decimals (1 = 0.00001 ETH), so total 5 + 13 == 18 decimals\n     */\n    function publicPriceInWei() public view returns (uint256) {\n        return uint256(HeyMintStorage.state().cfg.publicPrice) * 10 ** 13;\n    }\n\n    /**\n     * @notice Verify that a signed message is validly signed by the presaleSignerAddress\n     * @param _messageHash The hash of the message to verify\n     * @param _signature The signature of the messageHash to verify\n     */\n    function verifySignerAddress(\n        bytes32 _messageHash,\n        bytes calldata _signature\n    ) internal view returns (bool) {\n        return\n            HeyMintStorage.state().cfg.presaleSignerAddress ==\n            _messageHash.toEthSignedMessageHash().recover(_signature);\n    }\n\n    /**\n     * @notice Returns true if the sender is authorized to call creditCardMint\n     */\n    function isSenderAuthorizedForCreditCardMint()\n        internal\n        view\n        returns (bool)\n    {\n        address[] memory defaultAddresses = IHeyMintDefaults(\n            HEYMINT_DEFAULTS_ADDR\n        ).getCreditCardDefaultAddresses();\n        for (uint256 i = 0; i < defaultAddresses.length; i++) {\n            if (msg.sender == defaultAddresses[i]) {\n                return true;\n            }\n        }\n        HeyMintStorage.State storage state = HeyMintStorage.state();\n        for (\n            uint256 i = 0;\n            i < state.advCfg.creditCardMintAddresses.length;\n            i++\n        ) {\n            if (msg.sender == state.advCfg.creditCardMintAddresses[i]) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
      },
      "contracts/interfaces/IAddressRelay.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.18;\n\nstruct Implementation {\n    address implAddress;\n    bytes4[] selectors;\n}\n\ninterface IAddressRelay {\n    /**\n     * @notice Returns the fallback implementation address\n     */\n    function fallbackImplAddress() external returns (address);\n\n    /**\n     * @notice Adds or updates selectors and their implementation addresses\n     * @param _selectors The selectors to add or update\n     * @param _implAddress The implementation address the selectors will point to\n     */\n    function addOrUpdateSelectors(\n        bytes4[] memory _selectors,\n        address _implAddress\n    ) external;\n\n    /**\n     * @notice Removes selectors\n     * @param _selectors The selectors to remove\n     */\n    function removeSelectors(bytes4[] memory _selectors) external;\n\n    /**\n     * @notice Removes an implementation address and all the selectors that point to it\n     * @param _implAddress The implementation address to remove\n     */\n    function removeImplAddressAndAllSelectors(address _implAddress) external;\n\n    /**\n     * @notice Returns the implementation address for a given function selector\n     * @param _functionSelector The function selector to get the implementation address for\n     */\n    function getImplAddress(\n        bytes4 _functionSelector\n    ) external view returns (address implAddress_);\n\n    /**\n     * @notice Returns all the implementation addresses and the selectors they support\n     * @return impls_ An array of Implementation structs\n     */\n    function getAllImplAddressesAndSelectors()\n        external\n        view\n        returns (Implementation[] memory impls_);\n\n    /**\n     * @notice Return all the fucntion selectors associated with an implementation address\n     * @param _implAddress The implementation address to get the selectors for\n     */\n    function getSelectorsForImplAddress(\n        address _implAddress\n    ) external view returns (bytes4[] memory selectors_);\n\n    /**\n     * @notice Sets the fallback implementation address to use when a function selector is not found\n     * @param _fallbackAddress The fallback implementation address\n     */\n    function setFallbackImplAddress(address _fallbackAddress) external;\n\n    /**\n     * @notice Updates the supported interfaces\n     * @param _interfaceId The interface ID to update\n     * @param _supported Whether the interface is supported or not\n     */\n    function updateSupportedInterfaces(\n        bytes4 _interfaceId,\n        bool _supported\n    ) external;\n\n    /**\n     * @notice Returns whether the interface is supported or not\n     * @param _interfaceId The interface ID to check\n     */\n    function supportsInterface(\n        bytes4 _interfaceId\n    ) external view returns (bool);\n}\n"
      },
      "contracts/interfaces/IDelegateRegistry.sol": {
        "content": "// SPDX-License-Identifier: CC0-1.0\npragma solidity >=0.8.13;\n\n/**\n * @title IDelegateRegistry\n * @custom:version 2.0\n * @custom:author foobar (0xfoobar)\n * @notice A standalone immutable registry storing delegated permissions from one address to another\n */\ninterface IDelegateRegistry {\n    /// @notice Delegation type, NONE is used when a delegation does not exist or is revoked\n    enum DelegationType {\n        NONE,\n        ALL,\n        CONTRACT,\n        ERC721,\n        ERC20,\n        ERC1155\n    }\n\n    /// @notice Struct for returning delegations\n    struct Delegation {\n        DelegationType type_;\n        address to;\n        address from;\n        bytes32 rights;\n        address contract_;\n        uint256 tokenId;\n        uint256 amount;\n    }\n\n    /// @notice Emitted when an address delegates or revokes rights for their entire wallet\n    event DelegateAll(\n        address indexed from,\n        address indexed to,\n        bytes32 rights,\n        bool enable\n    );\n\n    /// @notice Emitted when an address delegates or revokes rights for a contract address\n    event DelegateContract(\n        address indexed from,\n        address indexed to,\n        address indexed contract_,\n        bytes32 rights,\n        bool enable\n    );\n\n    /// @notice Emitted when an address delegates or revokes rights for an ERC721 tokenId\n    event DelegateERC721(\n        address indexed from,\n        address indexed to,\n        address indexed contract_,\n        uint256 tokenId,\n        bytes32 rights,\n        bool enable\n    );\n\n    /// @notice Emitted when an address delegates or revokes rights for an amount of ERC20 tokens\n    event DelegateERC20(\n        address indexed from,\n        address indexed to,\n        address indexed contract_,\n        bytes32 rights,\n        uint256 amount\n    );\n\n    /// @notice Emitted when an address delegates or revokes rights for an amount of an ERC1155 tokenId\n    event DelegateERC1155(\n        address indexed from,\n        address indexed to,\n        address indexed contract_,\n        uint256 tokenId,\n        bytes32 rights,\n        uint256 amount\n    );\n\n    /// @notice Thrown if multicall calldata is malformed\n    error MulticallFailed();\n\n    /**\n     * -----------  WRITE -----------\n     */\n\n    /**\n     * @notice Call multiple functions in the current contract and return the data from all of them if they all succeed\n     * @param data The encoded function data for each of the calls to make to this contract\n     * @return results The results from each of the calls passed in via data\n     */\n    function multicall(\n        bytes[] calldata data\n    ) external payable returns (bytes[] memory results);\n\n    /**\n     * @notice Allow the delegate to act on behalf of `msg.sender` for all contracts\n     * @param to The address to act as delegate\n     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights\n     * @param enable Whether to enable or disable this delegation, true delegates and false revokes\n     * @return delegationHash The unique identifier of the delegation\n     */\n    function delegateAll(\n        address to,\n        bytes32 rights,\n        bool enable\n    ) external payable returns (bytes32 delegationHash);\n\n    /**\n     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific contract\n     * @param to The address to act as delegate\n     * @param contract_ The contract whose rights are being delegated\n     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights\n     * @param enable Whether to enable or disable this delegation, true delegates and false revokes\n     * @return delegationHash The unique identifier of the delegation\n     */\n    function delegateContract(\n        address to,\n        address contract_,\n        bytes32 rights,\n        bool enable\n    ) external payable returns (bytes32 delegationHash);\n\n    /**\n     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific ERC721 token\n     * @param to The address to act as delegate\n     * @param contract_ The contract whose rights are being delegated\n     * @param tokenId The token id to delegate\n     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights\n     * @param enable Whether to enable or disable this delegation, true delegates and false revokes\n     * @return delegationHash The unique identifier of the delegation\n     */\n    function delegateERC721(\n        address to,\n        address contract_,\n        uint256 tokenId,\n        bytes32 rights,\n        bool enable\n    ) external payable returns (bytes32 delegationHash);\n\n    /**\n     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC20 tokens\n     * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)\n     * @param to The address to act as delegate\n     * @param contract_ The address for the fungible token contract\n     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights\n     * @param amount The amount to delegate, > 0 delegates and 0 revokes\n     * @return delegationHash The unique identifier of the delegation\n     */\n    function delegateERC20(\n        address to,\n        address contract_,\n        bytes32 rights,\n        uint256 amount\n    ) external payable returns (bytes32 delegationHash);\n\n    /**\n     * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC1155 tokens\n     * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)\n     * @param to The address to act as delegate\n     * @param contract_ The address of the contract that holds the token\n     * @param tokenId The token id to delegate\n     * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights\n     * @param amount The amount of that token id to delegate, > 0 delegates and 0 revokes\n     * @return delegationHash The unique identifier of the delegation\n     */\n    function delegateERC1155(\n        address to,\n        address contract_,\n        uint256 tokenId,\n        bytes32 rights,\n        uint256 amount\n    ) external payable returns (bytes32 delegationHash);\n\n    /**\n     * ----------- CHECKS -----------\n     */\n\n    /**\n     * @notice Check if `to` is a delegate of `from` for the entire wallet\n     * @param to The potential delegate address\n     * @param from The potential address who delegated rights\n     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only\n     * @return valid Whether delegate is granted to act on the from's behalf\n     */\n    function checkDelegateForAll(\n        address to,\n        address from,\n        bytes32 rights\n    ) external view returns (bool);\n\n    /**\n     * @notice Check if `to` is a delegate of `from` for the specified `contract_` or the entire wallet\n     * @param to The delegated address to check\n     * @param contract_ The specific contract address being checked\n     * @param from The cold wallet who issued the delegation\n     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only\n     * @return valid Whether delegate is granted to act on from's behalf for entire wallet or that specific contract\n     */\n    function checkDelegateForContract(\n        address to,\n        address from,\n        address contract_,\n        bytes32 rights\n    ) external view returns (bool);\n\n    /**\n     * @notice Check if `to` is a delegate of `from` for the specific `contract` and `tokenId`, the entire `contract_`, or the entire wallet\n     * @param to The delegated address to check\n     * @param contract_ The specific contract address being checked\n     * @param tokenId The token id for the token to delegating\n     * @param from The wallet that issued the delegation\n     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only\n     * @return valid Whether delegate is granted to act on from's behalf for entire wallet, that contract, or that specific tokenId\n     */\n    function checkDelegateForERC721(\n        address to,\n        address from,\n        address contract_,\n        uint256 tokenId,\n        bytes32 rights\n    ) external view returns (bool);\n\n    /**\n     * @notice Returns the amount of ERC20 tokens the delegate is granted rights to act on the behalf of\n     * @param to The delegated address to check\n     * @param contract_ The address of the token contract\n     * @param from The cold wallet who issued the delegation\n     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only\n     * @return balance The delegated balance, which will be 0 if the delegation does not exist\n     */\n    function checkDelegateForERC20(\n        address to,\n        address from,\n        address contract_,\n        bytes32 rights\n    ) external view returns (uint256);\n\n    /**\n     * @notice Returns the amount of a ERC1155 tokens the delegate is granted rights to act on the behalf of\n     * @param to The delegated address to check\n     * @param contract_ The address of the token contract\n     * @param tokenId The token id to check the delegated amount of\n     * @param from The cold wallet who issued the delegation\n     * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only\n     * @return balance The delegated balance, which will be 0 if the delegation does not exist\n     */\n    function checkDelegateForERC1155(\n        address to,\n        address from,\n        address contract_,\n        uint256 tokenId,\n        bytes32 rights\n    ) external view returns (uint256);\n\n    /**\n     * ----------- ENUMERATIONS -----------\n     */\n\n    /**\n     * @notice Returns all enabled delegations a given delegate has received\n     * @param to The address to retrieve delegations for\n     * @return delegations Array of Delegation structs\n     */\n    function getIncomingDelegations(\n        address to\n    ) external view returns (Delegation[] memory delegations);\n\n    /**\n     * @notice Returns all enabled delegations an address has given out\n     * @param from The address to retrieve delegations for\n     * @return delegations Array of Delegation structs\n     */\n    function getOutgoingDelegations(\n        address from\n    ) external view returns (Delegation[] memory delegations);\n\n    /**\n     * @notice Returns all hashes associated with enabled delegations an address has received\n     * @param to The address to retrieve incoming delegation hashes for\n     * @return delegationHashes Array of delegation hashes\n     */\n    function getIncomingDelegationHashes(\n        address to\n    ) external view returns (bytes32[] memory delegationHashes);\n\n    /**\n     * @notice Returns all hashes associated with enabled delegations an address has given out\n     * @param from The address to retrieve outgoing delegation hashes for\n     * @return delegationHashes Array of delegation hashes\n     */\n    function getOutgoingDelegationHashes(\n        address from\n    ) external view returns (bytes32[] memory delegationHashes);\n\n    /**\n     * @notice Returns the delegations for a given array of delegation hashes\n     * @param delegationHashes is an array of hashes that correspond to delegations\n     * @return delegations Array of Delegation structs, return empty structs for nonexistent or revoked delegations\n     */\n    function getDelegationsFromHashes(\n        bytes32[] calldata delegationHashes\n    ) external view returns (Delegation[] memory delegations);\n\n    /**\n     * ----------- STORAGE ACCESS -----------\n     */\n\n    /**\n     * @notice Allows external contracts to read arbitrary storage slots\n     */\n    function readSlot(bytes32 location) external view returns (bytes32);\n\n    /**\n     * @notice Allows external contracts to read an arbitrary array of storage slots\n     */\n    function readSlots(\n        bytes32[] calldata locations\n    ) external view returns (bytes32[] memory);\n}\n"
      },
      "contracts/interfaces/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.18;\n\ninterface IERC165 {\n    /// @notice Query if a contract implements an interface\n    /// @param interfaceId The interface identifier, as specified in ERC-165\n    /// @dev Interface identification is specified in ERC-165. This function\n    ///  uses less than 30,000 gas.\n    /// @return `true` if the contract implements `interfaceID` and\n    ///  `interfaceID` is not 0xffffffff, `false` otherwise\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "contracts/interfaces/IERC173.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.18;\n\n/// @title ERC-173 Contract Ownership Standard\n///  Note: the ERC-165 identifier for this interface is 0x7f5828d0\n/* is ERC165 */\ninterface IERC173 {\n    /// @dev This emits when ownership of a contract changes.\n    event OwnershipTransferred(\n        address indexed previousOwner,\n        address indexed newOwner\n    );\n\n    /// @notice Get the address of the owner\n    /// @return owner_ The address of the owner.\n    function owner() external view returns (address owner_);\n\n    /// @notice Set the address of the new owner of the contract\n    /// @dev Set _newOwner to address(0) to renounce any ownership.\n    /// @param _newOwner The address of the new owner of the contract\n    function transferOwnership(address _newOwner) external;\n}\n"
      },
      "contracts/interfaces/IExchangeOperatorAddressList.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.18;\n\ninterface IExchangeOperatorAddressList {\n    /**\n     * @notice Returns an integer representing the exchange a given operator address belongs to (0 if none)\n     * @param _operatorAddress The operator address to map to an exchange\n     */\n    function operatorAddressToExchange(\n        address _operatorAddress\n    ) external view returns (uint256);\n}\n"
      },
      "contracts/interfaces/IHeyMintDefaults.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.18;\n\ninterface IHeyMintDefaults {\n    function getCreditCardDefaultAddresses()\n        external\n        view\n        returns (address[] memory);\n}\n"
      },
      "contracts/libraries/HeyMintStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nstruct BaseConfig {\n    // If true tokens can be minted in the public sale\n    bool publicSaleActive;\n    // If enabled, automatic start and stop times for the public sale will be enforced, otherwise ignored\n    bool usePublicSaleTimes;\n    // If true tokens can be minted in the presale\n    bool presaleActive;\n    // If enabled, automatic start and stop times for the presale will be enforced, otherwise ignored\n    bool usePresaleTimes;\n    // If true, all tokens will be soulbound\n    bool soulbindingActive;\n    // If true, a random hash will be generated for each token\n    bool randomHashActive;\n    // If true, the default CORI subscription address will be used to enforce royalties with the Operator Filter Registry\n    bool enforceRoyalties;\n    // If true, HeyMint fees will be charged for minting tokens\n    bool heyMintFeeActive;\n    // The number of tokens that can be minted in the public sale per address\n    uint8 publicMintsAllowedPerAddress;\n    // The number of tokens that can be minted in the presale per address\n    uint8 presaleMintsAllowedPerAddress;\n    // The number of tokens that can be minted in the public sale per transaction\n    uint8 publicMintsAllowedPerTransaction;\n    // The number of tokens that can be minted in the presale sale per transaction\n    uint8 presaleMintsAllowedPerTransaction;\n    // Maximum supply of tokens that can be minted\n    uint16 maxSupply;\n    // Total number of tokens available for minting in the presale\n    uint16 presaleMaxSupply;\n    // The royalty payout percentage in basis points\n    uint16 royaltyBps;\n    // The price of a token in the public sale in 1/100,000 ETH - e.g. 1 = 0.00001 ETH, 100,000 = 1 ETH - multiply by 10^13 to get correct wei amount\n    uint32 publicPrice;\n    // The price of a token in the presale in 1/100,000 ETH\n    uint32 presalePrice;\n    // Used to create a default HeyMint Launchpad URI for token metadata to save gas over setting a custom URI and increase fetch reliability\n    uint24 projectId;\n    // If enabled, tokens can be minted using an affiliate during presale.\n    bool presaleAffiliateMintEnabled;\n    // If enabled, tokens can be minted using an affiliate during public sale.\n    bool publicSaleAffiliateMintEnabled;\n    // The percentage of the sale price to be paid to an affiliate in basis points.\n    uint16 affiliateBasisPoints;\n    // The base URI for all token metadata\n    string uriBase;\n    // The address used to sign and validate presale mints\n    address presaleSignerAddress;\n    // The automatic start time for the public sale (if usePublicSaleTimes is true and publicSaleActive is true)\n    uint32 publicSaleStartTime;\n    // The automatic end time for the public sale (if usePublicSaleTimes is true and publicSaleActive is true)\n    uint32 publicSaleEndTime;\n    // The automatic start time for the presale (if usePresaleTimes is true and presaleActive is true)\n    uint32 presaleStartTime;\n    // The automatic end time for the presale (if usePresaleTimes is true and presaleActive is true)\n    uint32 presaleEndTime;\n    // If set, the UTC timestamp in seconds by which the fundingTarget must be met or funds are refundable\n    uint32 fundingEndsAt;\n    // The amount of centiETH that must be raised by fundingEndsAt or funds are refundable - multiply by 10^16\n    uint32 fundingTarget;\n}\n\nstruct AdvancedConfig {\n    // When false, tokens cannot be staked but can still be unstaked\n    bool stakingActive;\n    // When false, tokens cannot be loaned but can still be retrieved\n    bool loaningActive;\n    // If true tokens can be claimed for free\n    bool freeClaimActive;\n    // The number of tokens that can be minted per free claim\n    uint8 mintsPerFreeClaim;\n    // Optional address of an NFT that is eligible for free claim\n    address freeClaimContractAddress;\n    // If true tokens can be burned in order to mint\n    bool burnClaimActive;\n    // If true, the original token id of a burned token will be used for metadata\n    bool useBurnTokenIdForMetadata;\n    // The number of tokens that can be minted per burn transaction\n    uint8 mintsPerBurn;\n    // The payment required alongside a burn transaction in order to mint in 1/100,000 ETH\n    uint32 burnPayment;\n    // Permanently freezes payout addresses and basis points so they can never be updated\n    bool payoutAddressesFrozen;\n    // If set, the UTC timestamp in seconds until which tokens are refundable for refundPrice\n    uint32 refundEndsAt;\n    // The amount returned to a user in a token refund in 1/100,000 ETH\n    uint32 refundPrice;\n    // Permanently freezes metadata so it can never be changed\n    bool metadataFrozen;\n    // If true the soulbind admin address is permanently disabled\n    bool soulbindAdminTransfersPermanentlyDisabled;\n    // If true deposit tokens can be burned in order to mint\n    bool depositClaimActive;\n    // If additional payment is required to mint, this is the amount required in centiETH\n    uint32 remainingDepositPayment;\n    // If subscriptions are enabled for the tokens minted by this contract\n    bool subscriptionsEnabled;\n    // Price to renew subscription in 1/100,000 ETH\n    uint32 subscriptionPrice;\n    // The number of seconds in a subscription period\n    uint32 subscriptionPeriod;\n    // The number of seconds after a subscription expires before it is consider inactive\n    uint32 subscriptionGracePeriod;\n    // If true, transfers of subscriptions by the contract owner are permanently disabled\n    bool subscriptionAdminTransfersPermanentlyDisabled;\n    // The contract address of the ERC-20 token used for subscription payments\n    address subscriptionErc20Address;\n    // The deposit token smart contract address\n    address depositContractAddress;\n    // The merkle root used to validate if deposit tokens are eligible to burn to mint\n    bytes32 depositMerkleRoot;\n    // The respective share of funds to be sent to each address in payoutAddresses in basis points\n    uint16[] payoutBasisPoints;\n    // The addresses to which funds are sent when a token is sold. If empty, funds are sent to the contract owner.\n    address[] payoutAddresses;\n    // Optional address where royalties are paid out. If not set, royalties are paid to the contract owner.\n    address royaltyPayoutAddress;\n    // Used to allow transferring soulbound tokens with admin privileges. Defaults to the contract owner if not set.\n    address soulboundAdminAddress;\n    // The address where refunded tokens are returned. If not set, refunded tokens are sent to the contract owner.\n    address refundAddress;\n    // Custom addresses that are allowed to call the credit card minting functions.\n    address[] creditCardMintAddresses;\n    // Used to allow transferring subscription tokens with admin privileges. Defaults to the contract owner if not set.\n    address subscriptionAdminAddress;\n}\n\nstruct BurnToken {\n    // The contract address of the token to be burned\n    address contractAddress;\n    // The type of contract - 1 = ERC-721, 2 = ERC-1155\n    uint8 tokenType;\n    // The number of tokens to burn per mint\n    uint8 tokensPerBurn;\n    // The ID of the token on an ERC-1155 contract eligible for burn; unused for ERC-721\n    uint16 tokenId;\n}\n\nstruct Data {\n    // ============ BASE FUNCTIONALITY ============\n    // HeyMint fee to be paid per minted token (if not set, defaults to defaultHeymintFeePerToken)\n    uint256 heymintFeePerToken;\n    // Keeps track of if advanced config settings have been initialized to prevent setting multiple times\n    bool advancedConfigInitialized;\n    // A mapping of token IDs to specific tokenURIs for tokens that have custom metadata\n    mapping(uint256 => string) tokenURIs;\n    // ============ CONDITIONAL FUNDING ============\n    // If true, the funding target was reached and funds are not refundable\n    bool fundingTargetReached;\n    // If true, funding success has been determined and determineFundingSuccess() can no longer be called\n    bool fundingSuccessDetermined;\n    // A mapping of token ID to price paid for the token\n    mapping(uint256 => uint256) pricePaid;\n    // ============ SOULBINDING ============\n    // Used to allow an admin to transfer soulbound tokens when necessary\n    bool soulboundAdminTransferInProgress;\n    // ============ BURN TO MINT ============\n    // Maps a token id to the burn token id that was used to mint it to match metadata\n    mapping(uint256 => uint256) tokenIdToBurnTokenId;\n    // ============ STAKING ============\n    // Used to allow direct transfers of staked tokens without unstaking first\n    bool stakingTransferActive;\n    // Returns the UNIX timestamp at which a token began staking if currently staked\n    mapping(uint256 => uint256) currentTimeStaked;\n    // Returns the total time a token has been staked in seconds, not counting the current staking time if any\n    mapping(uint256 => uint256) totalTimeStaked;\n    // ============ LOANING ============\n    // Used to keep track of the total number of tokens on loan\n    uint256 currentLoanTotal;\n    // Returns the total number of tokens loaned by an address\n    mapping(address => uint256) totalLoanedPerAddress;\n    // Returns the address of the original token owner if a token is currently on loan\n    mapping(uint256 => address) tokenOwnersOnLoan;\n    // ============ FREE CLAIM ============\n    // If true token has already been used to claim and cannot be used again\n    mapping(uint256 => bool) freeClaimUsed;\n    // ============ RANDOM HASH ============\n    // Stores a random hash for each token ID\n    mapping(uint256 => bytes32) randomHashStore;\n    // ============ PRESALE ============\n    // Keeps track of the number of tokens minted per email address (via credit card) during presale\n    mapping(bytes32 => uint256) tokensMintedByEmailAddress;\n    // ============ SUBSCRIPTION ============\n    // Stores the timestamp at which a subscription expires for a given token ID\n    mapping(uint256 => uint256) subscriptionExpiration;\n    // Used to allow an admin to transfer subscription tokens when necessary\n    bool subscriptionAdminTransferInProgress;\n}\n\nlibrary HeyMintStorage {\n    struct State {\n        BaseConfig cfg;\n        AdvancedConfig advCfg;\n        BurnToken[] burnTokens;\n        Data data;\n    }\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256(\"heymint.launchpad.storage.erc721a\");\n\n    function state() internal pure returns (State storage s) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            s.slot := slot\n        }\n    }\n}\n"
      },
      "contracts/libraries/RegistryHashes.sol": {
        "content": "// SPDX-License-Identifier: CC0-1.0\npragma solidity 0.8.18;\n\nimport {IDelegateRegistry} from \"../interfaces/IDelegateRegistry.sol\";\n\n/**\n * @title Library for calculating the hashes and storage locations used in the delegate registry\n *\n * The encoding for the 5 types of delegate registry hashes should be as follows:\n *\n * ALL:         keccak256(abi.encodePacked(rights, from, to))\n * CONTRACT:    keccak256(abi.encodePacked(rights, from, to, contract_))\n * ERC721:      keccak256(abi.encodePacked(rights, from, to, contract_, tokenId))\n * ERC20:       keccak256(abi.encodePacked(rights, from, to, contract_))\n * ERC1155:     keccak256(abi.encodePacked(rights, from, to, contract_, tokenId))\n *\n * To avoid collisions between the hashes with respect to type, the hash is shifted left by one byte\n * and the last byte is then encoded with a unique number for the delegation type\n *\n */\nlibrary RegistryHashes {\n    /// @dev Used to delete everything but the last byte of a 32 byte word with and(word, EXTRACT_LAST_BYTE)\n    uint256 internal constant EXTRACT_LAST_BYTE = 0xff;\n    /// @dev Constants for the delegate registry delegation type enumeration\n    uint256 internal constant ALL_TYPE = 1;\n    uint256 internal constant CONTRACT_TYPE = 2;\n    uint256 internal constant ERC721_TYPE = 3;\n    uint256 internal constant ERC20_TYPE = 4;\n    uint256 internal constant ERC1155_TYPE = 5;\n    /// @dev Constant for the location of the delegations array in the delegate registry, defined to be zero\n    uint256 internal constant DELEGATION_SLOT = 0;\n\n    /**\n     * @notice Helper function to decode last byte of a delegation hash into its delegation type enum\n     * @param inputHash The bytehash to decode the type from\n     * @return decodedType The delegation type\n     */\n    function decodeType(\n        bytes32 inputHash\n    ) internal pure returns (IDelegateRegistry.DelegationType decodedType) {\n        assembly {\n            decodedType := and(inputHash, EXTRACT_LAST_BYTE)\n        }\n    }\n\n    /**\n     * @notice Helper function that computes the storage location of a particular delegation array\n     * @dev Storage keys further down the array can be obtained by adding computedLocation with the element position\n     * @dev Follows the solidity storage location encoding for a mapping(bytes32 => fixedArray) at the position of the delegationSlot\n     * @param inputHash The bytehash to decode the type from\n     * @return computedLocation is the storage key of the delegation array at position 0\n     */\n    function location(\n        bytes32 inputHash\n    ) internal pure returns (bytes32 computedLocation) {\n        assembly (\"memory-safe\") {\n            // This block only allocates memory in the scratch space\n            mstore(0, inputHash)\n            mstore(32, DELEGATION_SLOT)\n            computedLocation := keccak256(0, 64) // Run keccak256 over bytes in scratch space to obtain the storage key\n        }\n    }\n\n    /**\n     * @notice Helper function to compute delegation hash for `DelegationType.ALL`\n     * @dev Equivalent to `keccak256(abi.encodePacked(rights, from, to))` then left-shift by 1 byte and write the delegation type to the cleaned last byte\n     * @dev Will not revert if `from` or `to` are > uint160, any input larger than uint160 for `from` and `to` will be cleaned to its lower 20 bytes\n     * @param from The address making the delegation\n     * @param rights The rights specified by the delegation\n     * @param to The address receiving the delegation\n     * @return hash The delegation parameters encoded with ALL_TYPE\n     */\n    function allHash(\n        address from,\n        bytes32 rights,\n        address to\n    ) internal pure returns (bytes32 hash) {\n        assembly (\"memory-safe\") {\n            // This block only allocates memory after the free memory pointer\n            let ptr := mload(64) // Load the free memory pointer\n            // Lay out the variables from last to first, agnostic to upper 96 bits of address words.\n            mstore(add(ptr, 40), to)\n            mstore(add(ptr, 20), from)\n            mstore(ptr, rights)\n            hash := or(shl(8, keccak256(ptr, 72)), ALL_TYPE) // Keccak-hashes the packed encoding, left-shifts by one byte, then writes type to the lowest-order byte\n        }\n    }\n\n    /**\n     * @notice Helper function to compute delegation location for `DelegationType.ALL`\n     * @dev Equivalent to `location(allHash(rights, from, to))`\n     * @dev Will not revert if `from` or `to` are > uint160, any input larger than uint160 for `from` and `to` will be cleaned to its lower 20 bytes\n     * @param from The address making the delegation\n     * @param rights The rights specified by the delegation\n     * @param to The address receiving the delegation\n     * @return computedLocation The storage location of the all delegation with those parameters in the delegations mapping\n     */\n    function allLocation(\n        address from,\n        bytes32 rights,\n        address to\n    ) internal pure returns (bytes32 computedLocation) {\n        assembly (\"memory-safe\") {\n            // This block only allocates memory after the free memory pointer and in the scratch space\n            let ptr := mload(64) // Load the free memory pointer\n            // Lay out the variables from last to first, agnostic to upper 96 bits of address words.\n            mstore(add(ptr, 40), to)\n            mstore(add(ptr, 20), from)\n            mstore(ptr, rights)\n            mstore(0, or(shl(8, keccak256(ptr, 72)), ALL_TYPE)) // Computes `allHash`, then stores the result in scratch space\n            mstore(32, DELEGATION_SLOT)\n            computedLocation := keccak256(0, 64) // Runs keccak over the scratch space to obtain the storage key\n        }\n    }\n\n    /**\n     * @notice Helper function to compute delegation hash for `DelegationType.CONTRACT`\n     * @dev Equivalent to keccak256(abi.encodePacked(rights, from, to, contract_)) left-shifted by 1 then last byte overwritten with CONTRACT_TYPE\n     * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes\n     * @param from The address making the delegation\n     * @param rights The rights specified by the delegation\n     * @param to The address receiving the delegation\n     * @param contract_ The address of the contract specified by the delegation\n     * @return hash The delegation parameters encoded with CONTRACT_TYPE\n     */\n    function contractHash(\n        address from,\n        bytes32 rights,\n        address to,\n        address contract_\n    ) internal pure returns (bytes32 hash) {\n        assembly (\"memory-safe\") {\n            // This block only allocates memory after the free memory pointer\n            let ptr := mload(64) // Load the free memory pointer\n            // Lay out the variables from last to first, agnostic to upper 96 bits of address words.\n            mstore(add(ptr, 60), contract_)\n            mstore(add(ptr, 40), to)\n            mstore(add(ptr, 20), from)\n            mstore(ptr, rights)\n            hash := or(shl(8, keccak256(ptr, 92)), CONTRACT_TYPE) // Keccak-hashes the packed encoding, left-shifts by one byte, then writes type to the lowest-order byte\n        }\n    }\n\n    /**\n     * @notice Helper function to compute delegation location for `DelegationType.CONTRACT`\n     * @dev Equivalent to `location(contractHash(rights, from, to, contract_))`\n     * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes\n     * @param from The address making the delegation\n     * @param rights The rights specified by the delegation\n     * @param to The address receiving the delegation\n     * @param contract_ The address of the contract specified by the delegation\n     * @return computedLocation The storage location of the contract delegation with those parameters in the delegations mapping\n     */\n    function contractLocation(\n        address from,\n        bytes32 rights,\n        address to,\n        address contract_\n    ) internal pure returns (bytes32 computedLocation) {\n        assembly (\"memory-safe\") {\n            // This block only allocates memory after the free memory pointer and in the scratch space\n            let ptr := mload(64) // Load free memory pointer\n            // Lay out the variables from last to first, agnostic to upper 96 bits of address words.\n            mstore(add(ptr, 60), contract_)\n            mstore(add(ptr, 40), to)\n            mstore(add(ptr, 20), from)\n            mstore(ptr, rights)\n            mstore(0, or(shl(8, keccak256(ptr, 92)), CONTRACT_TYPE)) // Computes `contractHash`, then stores the result in scratch space\n            mstore(32, DELEGATION_SLOT)\n            computedLocation := keccak256(0, 64) // Runs keccak over the scratch space to obtain the storage key\n        }\n    }\n\n    /**\n     * @notice Helper function to compute delegation hash for `DelegationType.ERC721`\n     * @dev Equivalent to `keccak256(abi.encodePacked(rights, from, to, contract_, tokenId)) left-shifted by 1 then last byte overwritten with ERC721_TYPE\n     * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes\n     * @param from The address making the delegation\n     * @param rights The rights specified by the delegation\n     * @param to The address receiving the delegation\n     * @param tokenId The id of the token specified by the delegation\n     * @param contract_ The address of the contract specified by the delegation\n     * @return hash The delegation parameters encoded with ERC721_TYPE\n     */\n    function erc721Hash(\n        address from,\n        bytes32 rights,\n        address to,\n        uint256 tokenId,\n        address contract_\n    ) internal pure returns (bytes32 hash) {\n        assembly (\"memory-safe\") {\n            // This block only allocates memory after the free memory pointer\n            let ptr := mload(64) // Cache the free memory pointer.\n            // Lay out the variables from last to first, agnostic to upper 96 bits of address words.\n            mstore(add(ptr, 92), tokenId)\n            mstore(add(ptr, 60), contract_)\n            mstore(add(ptr, 40), to)\n            mstore(add(ptr, 20), from)\n            mstore(ptr, rights)\n            hash := or(shl(8, keccak256(ptr, 124)), ERC721_TYPE) // Keccak-hashes the packed encoding, left-shifts by one byte, then writes type to the lowest-order byte\n        }\n    }\n\n    /**\n     * @notice Helper function to compute delegation location for `DelegationType.ERC721`\n     * @dev Equivalent to `location(ERC721Hash(rights, from, to, contract_, tokenId))`\n     * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes\n     * @param from The address making the delegation\n     * @param rights The rights specified by the delegation\n     * @param to The address receiving the delegation\n     * @param tokenId The id of the ERC721 token\n     * @param contract_ The address of the ERC721 token contract\n     * @return computedLocation The storage location of the ERC721 delegation with those parameters in the delegations mapping\n     */\n    function erc721Location(\n        address from,\n        bytes32 rights,\n        address to,\n        uint256 tokenId,\n        address contract_\n    ) internal pure returns (bytes32 computedLocation) {\n        assembly (\"memory-safe\") {\n            // This block only allocates memory after the free memory pointer and in the scratch space\n            let ptr := mload(64) // Cache the free memory pointer.\n            // Lay out the variables from last to first, agnostic to upper 96 bits of address words.\n            mstore(add(ptr, 92), tokenId)\n            mstore(add(ptr, 60), contract_)\n            mstore(add(ptr, 40), to)\n            mstore(add(ptr, 20), from)\n            mstore(ptr, rights)\n            mstore(0, or(shl(8, keccak256(ptr, 124)), ERC721_TYPE)) // Computes erc721Hash, then stores the result in scratch space\n            mstore(32, DELEGATION_SLOT)\n            computedLocation := keccak256(0, 64) // Runs keccak256 over the scratch space to obtain the storage key\n        }\n    }\n\n    /**\n     * @notice Helper function to compute delegation hash for `DelegationType.ERC20`\n     * @dev Equivalent to `keccak256(abi.encodePacked(rights, from, to, contract_))` with the last byte overwritten with ERC20_TYPE\n     * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes\n     * @param from The address making the delegation\n     * @param rights The rights specified by the delegation\n     * @param to The address receiving the delegation\n     * @param contract_ The address of the ERC20 token contract\n     * @return hash The parameters encoded with ERC20_TYPE\n     */\n    function erc20Hash(\n        address from,\n        bytes32 rights,\n        address to,\n        address contract_\n    ) internal pure returns (bytes32 hash) {\n        assembly (\"memory-safe\") {\n            // This block only allocates memory after the free memory pointer\n            let ptr := mload(64) // Load free memory pointer\n            // Lay out the variables from last to first, agnostic to upper 96 bits of address words.\n            mstore(add(ptr, 60), contract_)\n            mstore(add(ptr, 40), to)\n            mstore(add(ptr, 20), from)\n            mstore(ptr, rights)\n            hash := or(shl(8, keccak256(ptr, 92)), ERC20_TYPE) // Keccak-hashes the packed encoding, left-shifts by one byte, then writes type to the lowest-order byte\n        }\n    }\n\n    /**\n     * @notice Helper function to compute delegation location for `DelegationType.ERC20`\n     * @dev Equivalent to `location(ERC20Hash(rights, from, to, contract_))`\n     * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes\n     * @param from The address making the delegation\n     * @param rights The rights specified by the delegation\n     * @param to The address receiving the delegation\n     * @param contract_ The address of the ERC20 token contract\n     * @return computedLocation The storage location of the ERC20 delegation with those parameters in the delegations mapping\n     */\n    function erc20Location(\n        address from,\n        bytes32 rights,\n        address to,\n        address contract_\n    ) internal pure returns (bytes32 computedLocation) {\n        assembly (\"memory-safe\") {\n            // This block only allocates memory after the free memory pointer and in the scratch space\n            let ptr := mload(64) // Loads the free memory pointer\n            // Lay out the variables from last to first, agnostic to upper 96 bits of address words.\n            mstore(add(ptr, 60), contract_)\n            mstore(add(ptr, 40), to)\n            mstore(add(ptr, 20), from)\n            mstore(ptr, rights)\n            mstore(0, or(shl(8, keccak256(ptr, 92)), ERC20_TYPE)) // Computes erc20Hash, then stores the result in scratch space\n            mstore(32, DELEGATION_SLOT)\n            computedLocation := keccak256(0, 64) // Runs keccak over the scratch space to obtain the storage key\n        }\n    }\n\n    /**\n     * @notice Helper function to compute delegation hash for `DelegationType.ERC1155`\n     * @dev Equivalent to keccak256(abi.encodePacked(rights, from, to, contract_, tokenId)) left-shifted with the last byte overwritten with ERC1155_TYPE\n     * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes\n     * @param from The address making the delegation\n     * @param rights The rights specified by the delegation\n     * @param to The address receiving the delegation\n     * @param tokenId The id of the ERC1155 token\n     * @param contract_ The address of the ERC1155 token contract\n     * @return hash The parameters encoded with ERC1155_TYPE\n     */\n    function erc1155Hash(\n        address from,\n        bytes32 rights,\n        address to,\n        uint256 tokenId,\n        address contract_\n    ) internal pure returns (bytes32 hash) {\n        assembly (\"memory-safe\") {\n            // This block only allocates memory after the free memory pointer\n            let ptr := mload(64) // Load the free memory pointer.\n            // Lay out the variables from last to first, agnostic to upper 96 bits of address words.\n            mstore(add(ptr, 92), tokenId)\n            mstore(add(ptr, 60), contract_)\n            mstore(add(ptr, 40), to)\n            mstore(add(ptr, 20), from)\n            mstore(ptr, rights)\n            hash := or(shl(8, keccak256(ptr, 124)), ERC1155_TYPE) // Keccak-hashes the packed encoding, left-shifts by one byte, then writes type to the lowest-order byte\n        }\n    }\n\n    /**\n     * @notice Helper function to compute delegation location for `DelegationType.ERC1155`\n     * @dev Equivalent to `location(ERC1155Hash(rights, from, to, contract_, tokenId))`\n     * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes\n     * @param from The address making the delegation\n     * @param rights The rights specified by the delegation\n     * @param to The address receiving the delegation\n     * @param tokenId The id of the ERC1155 token\n     * @param contract_ The address of the ERC1155 token contract\n     * @return computedLocation The storage location of the ERC1155 delegation with those parameters in the delegations mapping\n     */\n    function erc1155Location(\n        address from,\n        bytes32 rights,\n        address to,\n        uint256 tokenId,\n        address contract_\n    ) internal pure returns (bytes32 computedLocation) {\n        assembly (\"memory-safe\") {\n            // This block only allocates memory after the free memory pointer and in the scratch space\n            let ptr := mload(64) // Cache the free memory pointer.\n            // Lay out the variables from last to first, agnostic to upper 96 bits of address words.\n            mstore(add(ptr, 92), tokenId)\n            mstore(add(ptr, 60), contract_)\n            mstore(add(ptr, 40), to)\n            mstore(add(ptr, 20), from)\n            mstore(ptr, rights)\n            mstore(0, or(shl(8, keccak256(ptr, 124)), ERC1155_TYPE)) // Computes erc1155Hash, then stores the result in scratch space\n            mstore(32, DELEGATION_SLOT)\n            computedLocation := keccak256(0, 64) // Runs keccak over the scratch space to obtain the storage key\n        }\n    }\n}\n"
      },
      "contracts/libraries/RegistryOps.sol": {
        "content": "// SPDX-License-Identifier: CC0-1.0\npragma solidity 0.8.18;\n\nlibrary RegistryOps {\n    /// @dev `x > y ? x : y`.\n    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        assembly {\n            // `gt(y, x)` will evaluate to 1 if `y > x`, else 0.\n            //\n            // If `y > x`:\n            //     `x ^ ((x ^ y) * 1) = x ^ (x ^ y) = (x ^ x) ^ y = 0 ^ y = y`.\n            // otherwise:\n            //     `x ^ ((x ^ y) * 0) = x ^ 0 = x`.\n            z := xor(x, mul(xor(x, y), gt(y, x)))\n        }\n    }\n\n    /// @dev `x & y`.\n    function and(bool x, bool y) internal pure returns (bool z) {\n        assembly {\n            z := and(iszero(iszero(x)), iszero(iszero(y))) // Compiler cleans dirty booleans on the stack to 1, so do the same here\n        }\n    }\n\n    /// @dev `x | y`.\n    function or(bool x, bool y) internal pure returns (bool z) {\n        assembly {\n            z := or(iszero(iszero(x)), iszero(iszero(y))) // Compiler cleans dirty booleans on the stack to 1, so do the same here\n        }\n    }\n}\n"
      },
      "contracts/libraries/RegistryStorage.sol": {
        "content": "// SPDX-License-Identifier: CC0-1.0\npragma solidity 0.8.18;\n\nlibrary RegistryStorage {\n    /// @dev Standardizes `from` storage flags to prevent double-writes in the delegation in/outbox if the same delegation is revoked and rewritten\n    address internal constant DELEGATION_EMPTY = address(0);\n    address internal constant DELEGATION_REVOKED = address(1);\n\n    /// @dev Standardizes storage positions of delegation data\n    uint256 internal constant POSITIONS_FIRST_PACKED = 0; //  | 4 bytes empty | first 8 bytes of contract address | 20 bytes of from address |\n    uint256 internal constant POSITIONS_SECOND_PACKED = 1; // |        last 12 bytes of contract address          | 20 bytes of to address   |\n    uint256 internal constant POSITIONS_RIGHTS = 2;\n    uint256 internal constant POSITIONS_TOKEN_ID = 3;\n    uint256 internal constant POSITIONS_AMOUNT = 4;\n\n    /// @dev Used to clean address types of dirty bits with `and(address, CLEAN_ADDRESS)`\n    uint256 internal constant CLEAN_ADDRESS =\n        0x00ffffffffffffffffffffffffffffffffffffffff;\n\n    /// @dev Used to clean everything but the first 8 bytes of an address\n    uint256 internal constant CLEAN_FIRST8_BYTES_ADDRESS =\n        0xffffffffffffffff << 96;\n\n    /// @dev Used to clean everything but the first 8 bytes of an address in the packed position\n    uint256 internal constant CLEAN_PACKED8_BYTES_ADDRESS =\n        0xffffffffffffffff << 160;\n\n    /**\n     * @notice Helper function that packs from, to, and contract_ address to into the two slot configuration\n     * @param from The address making the delegation\n     * @param to The address receiving the delegation\n     * @param contract_ The contract address associated with the delegation (optional)\n     * @return firstPacked The firstPacked storage configured with the parameters\n     * @return secondPacked The secondPacked storage configured with the parameters\n     * @dev Will not revert if `from`, `to`, and `contract_` are > uint160, any inputs with dirty bits outside the last 20 bytes will be cleaned\n     */\n    function packAddresses(\n        address from,\n        address to,\n        address contract_\n    ) internal pure returns (bytes32 firstPacked, bytes32 secondPacked) {\n        assembly {\n            firstPacked := or(\n                shl(64, and(contract_, CLEAN_FIRST8_BYTES_ADDRESS)),\n                and(from, CLEAN_ADDRESS)\n            )\n            secondPacked := or(shl(160, contract_), and(to, CLEAN_ADDRESS))\n        }\n    }\n\n    /**\n     * @notice Helper function that unpacks from, to, and contract_ address inside the firstPacked secondPacked storage configuration\n     * @param firstPacked The firstPacked storage to be decoded\n     * @param secondPacked The secondPacked storage to be decoded\n     * @return from The address making the delegation\n     * @return to The address receiving the delegation\n     * @return contract_ The contract address associated with the delegation\n     * @dev Will not revert if `from`, `to`, and `contract_` are > uint160, any inputs with dirty bits outside the last 20 bytes will be cleaned\n     */\n    function unpackAddresses(\n        bytes32 firstPacked,\n        bytes32 secondPacked\n    ) internal pure returns (address from, address to, address contract_) {\n        assembly {\n            from := and(firstPacked, CLEAN_ADDRESS)\n            to := and(secondPacked, CLEAN_ADDRESS)\n            contract_ := or(\n                shr(64, and(firstPacked, CLEAN_PACKED8_BYTES_ADDRESS)),\n                shr(160, secondPacked)\n            )\n        }\n    }\n\n    /**\n     * @notice Helper function that can unpack the from or to address from their respective packed slots in the registry\n     * @param packedSlot The slot containing the from or to address\n     * @return unpacked The `from` or `to` address\n     * @dev Will not work if you want to obtain the contract address, use unpackAddresses\n     */\n    function unpackAddress(\n        bytes32 packedSlot\n    ) internal pure returns (address unpacked) {\n        assembly {\n            unpacked := and(packedSlot, CLEAN_ADDRESS)\n        }\n    }\n}\n"
      },
      "contracts/testContracts/DelegateRegistry.sol": {
        "content": "// SPDX-License-Identifier: CC0-1.0\npragma solidity 0.8.18;\n\nimport {IDelegateRegistry as IDelegateRegistry} from \"../interfaces/IDelegateRegistry.sol\";\nimport {RegistryHashes as Hashes} from \"../libraries/RegistryHashes.sol\";\nimport {RegistryStorage as Storage} from \"../libraries/RegistryStorage.sol\";\nimport {RegistryOps as Ops} from \"../libraries/RegistryOps.sol\";\n\n/**\n * @title DelegateRegistry\n * @custom:version 2.0\n * @custom:coauthor foobar (0xfoobar)\n * @custom:coauthor mireynolds\n * @notice A standalone immutable registry storing delegated permissions from one address to another\n */\ncontract DelegateRegistry is IDelegateRegistry {\n    /// @dev Only this mapping should be used to verify delegations; the other mapping arrays are for enumerations\n    mapping(bytes32 => bytes32[5]) internal delegations;\n\n    /// @dev Vault delegation enumeration outbox, for pushing new hashes only\n    mapping(address => bytes32[]) internal outgoingDelegationHashes;\n\n    /// @dev Delegate enumeration inbox, for pushing new hashes only\n    mapping(address => bytes32[]) internal incomingDelegationHashes;\n\n    /**\n     * ----------- WRITE -----------\n     */\n\n    /// @inheritdoc IDelegateRegistry\n    function multicall(\n        bytes[] calldata data\n    ) external payable override returns (bytes[] memory results) {\n        results = new bytes[](data.length);\n        bool success;\n        unchecked {\n            for (uint256 i = 0; i < data.length; ++i) {\n                //slither-disable-next-line calls-loop,delegatecall-loop\n                (success, results[i]) = address(this).delegatecall(data[i]);\n                if (!success) revert MulticallFailed();\n            }\n        }\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function delegateAll(\n        address to,\n        bytes32 rights,\n        bool enable\n    ) external payable override returns (bytes32 hash) {\n        hash = Hashes.allHash(msg.sender, rights, to);\n        bytes32 location = Hashes.location(hash);\n        address loadedFrom = _loadFrom(location);\n        if (enable) {\n            if (loadedFrom == Storage.DELEGATION_EMPTY) {\n                _pushDelegationHashes(msg.sender, to, hash);\n                _writeDelegationAddresses(location, msg.sender, to, address(0));\n                if (rights != \"\")\n                    _writeDelegation(\n                        location,\n                        Storage.POSITIONS_RIGHTS,\n                        rights\n                    );\n            } else if (loadedFrom == Storage.DELEGATION_REVOKED) {\n                _updateFrom(location, msg.sender);\n            }\n        } else if (loadedFrom == msg.sender) {\n            _updateFrom(location, Storage.DELEGATION_REVOKED);\n        }\n        emit DelegateAll(msg.sender, to, rights, enable);\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function delegateContract(\n        address to,\n        address contract_,\n        bytes32 rights,\n        bool enable\n    ) external payable override returns (bytes32 hash) {\n        hash = Hashes.contractHash(msg.sender, rights, to, contract_);\n        bytes32 location = Hashes.location(hash);\n        address loadedFrom = _loadFrom(location);\n        if (enable) {\n            if (loadedFrom == Storage.DELEGATION_EMPTY) {\n                _pushDelegationHashes(msg.sender, to, hash);\n                _writeDelegationAddresses(location, msg.sender, to, contract_);\n                if (rights != \"\")\n                    _writeDelegation(\n                        location,\n                        Storage.POSITIONS_RIGHTS,\n                        rights\n                    );\n            } else if (loadedFrom == Storage.DELEGATION_REVOKED) {\n                _updateFrom(location, msg.sender);\n            }\n        } else if (loadedFrom == msg.sender) {\n            _updateFrom(location, Storage.DELEGATION_REVOKED);\n        }\n        emit DelegateContract(msg.sender, to, contract_, rights, enable);\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function delegateERC721(\n        address to,\n        address contract_,\n        uint256 tokenId,\n        bytes32 rights,\n        bool enable\n    ) external payable override returns (bytes32 hash) {\n        hash = Hashes.erc721Hash(msg.sender, rights, to, tokenId, contract_);\n        bytes32 location = Hashes.location(hash);\n        address loadedFrom = _loadFrom(location);\n        if (enable) {\n            if (loadedFrom == Storage.DELEGATION_EMPTY) {\n                _pushDelegationHashes(msg.sender, to, hash);\n                _writeDelegationAddresses(location, msg.sender, to, contract_);\n                _writeDelegation(location, Storage.POSITIONS_TOKEN_ID, tokenId);\n                if (rights != \"\")\n                    _writeDelegation(\n                        location,\n                        Storage.POSITIONS_RIGHTS,\n                        rights\n                    );\n            } else if (loadedFrom == Storage.DELEGATION_REVOKED) {\n                _updateFrom(location, msg.sender);\n            }\n        } else if (loadedFrom == msg.sender) {\n            _updateFrom(location, Storage.DELEGATION_REVOKED);\n        }\n        emit DelegateERC721(msg.sender, to, contract_, tokenId, rights, enable);\n    }\n\n    // @inheritdoc IDelegateRegistry\n    function delegateERC20(\n        address to,\n        address contract_,\n        bytes32 rights,\n        uint256 amount\n    ) external payable override returns (bytes32 hash) {\n        hash = Hashes.erc20Hash(msg.sender, rights, to, contract_);\n        bytes32 location = Hashes.location(hash);\n        address loadedFrom = _loadFrom(location);\n        if (amount != 0) {\n            if (loadedFrom == Storage.DELEGATION_EMPTY) {\n                _pushDelegationHashes(msg.sender, to, hash);\n                _writeDelegationAddresses(location, msg.sender, to, contract_);\n                _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount);\n                if (rights != \"\")\n                    _writeDelegation(\n                        location,\n                        Storage.POSITIONS_RIGHTS,\n                        rights\n                    );\n            } else if (loadedFrom == Storage.DELEGATION_REVOKED) {\n                _updateFrom(location, msg.sender);\n                _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount);\n            } else if (loadedFrom == msg.sender) {\n                _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount);\n            }\n        } else if (loadedFrom == msg.sender) {\n            _updateFrom(location, Storage.DELEGATION_REVOKED);\n            _writeDelegation(location, Storage.POSITIONS_AMOUNT, uint256(0));\n        }\n        emit DelegateERC20(msg.sender, to, contract_, rights, amount);\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function delegateERC1155(\n        address to,\n        address contract_,\n        uint256 tokenId,\n        bytes32 rights,\n        uint256 amount\n    ) external payable override returns (bytes32 hash) {\n        hash = Hashes.erc1155Hash(msg.sender, rights, to, tokenId, contract_);\n        bytes32 location = Hashes.location(hash);\n        address loadedFrom = _loadFrom(location);\n        if (amount != 0) {\n            if (loadedFrom == Storage.DELEGATION_EMPTY) {\n                _pushDelegationHashes(msg.sender, to, hash);\n                _writeDelegationAddresses(location, msg.sender, to, contract_);\n                _writeDelegation(location, Storage.POSITIONS_TOKEN_ID, tokenId);\n                _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount);\n                if (rights != \"\")\n                    _writeDelegation(\n                        location,\n                        Storage.POSITIONS_RIGHTS,\n                        rights\n                    );\n            } else if (loadedFrom == Storage.DELEGATION_REVOKED) {\n                _updateFrom(location, msg.sender);\n                _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount);\n            } else if (loadedFrom == msg.sender) {\n                _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount);\n            }\n        } else if (loadedFrom == msg.sender) {\n            _updateFrom(location, Storage.DELEGATION_REVOKED);\n            _writeDelegation(location, Storage.POSITIONS_AMOUNT, uint256(0));\n        }\n        emit DelegateERC1155(\n            msg.sender,\n            to,\n            contract_,\n            tokenId,\n            rights,\n            amount\n        );\n    }\n\n    /// @dev Transfer native token out\n    function sweep() external {\n        assembly (\"memory-safe\") {\n            // This hardcoded address is a CREATE2 factory counterfactual smart contract wallet that will always accept native token transfers\n            let result := call(\n                gas(),\n                0x000000dE1E80ea5a234FB5488fee2584251BC7e8,\n                selfbalance(),\n                0,\n                0,\n                0,\n                0\n            )\n        }\n    }\n\n    /**\n     * ----------- CHECKS -----------\n     */\n\n    /// @inheritdoc IDelegateRegistry\n    function checkDelegateForAll(\n        address to,\n        address from,\n        bytes32 rights\n    ) external view override returns (bool valid) {\n        if (!_invalidFrom(from)) {\n            valid = _validateFrom(Hashes.allLocation(from, \"\", to), from);\n            if (!Ops.or(rights == \"\", valid))\n                valid = _validateFrom(\n                    Hashes.allLocation(from, rights, to),\n                    from\n                );\n        }\n        assembly (\"memory-safe\") {\n            // Only first 32 bytes of scratch space is accessed\n            mstore(0, iszero(iszero(valid))) // Compiler cleans dirty booleans on the stack to 1, so do the same here\n            return(0, 32) // Direct return, skips Solidity's redundant copying to save gas\n        }\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function checkDelegateForContract(\n        address to,\n        address from,\n        address contract_,\n        bytes32 rights\n    ) external view override returns (bool valid) {\n        if (!_invalidFrom(from)) {\n            valid =\n                _validateFrom(Hashes.allLocation(from, \"\", to), from) ||\n                _validateFrom(\n                    Hashes.contractLocation(from, \"\", to, contract_),\n                    from\n                );\n            if (!Ops.or(rights == \"\", valid)) {\n                valid =\n                    _validateFrom(Hashes.allLocation(from, rights, to), from) ||\n                    _validateFrom(\n                        Hashes.contractLocation(from, rights, to, contract_),\n                        from\n                    );\n            }\n        }\n        assembly (\"memory-safe\") {\n            // Only first 32 bytes of scratch space is accessed\n            mstore(0, iszero(iszero(valid))) // Compiler cleans dirty booleans on the stack to 1, so do the same here\n            return(0, 32) // Direct return, skips Solidity's redundant copying to save gas\n        }\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function checkDelegateForERC721(\n        address to,\n        address from,\n        address contract_,\n        uint256 tokenId,\n        bytes32 rights\n    ) external view override returns (bool valid) {\n        if (!_invalidFrom(from)) {\n            valid =\n                _validateFrom(Hashes.allLocation(from, \"\", to), from) ||\n                _validateFrom(\n                    Hashes.contractLocation(from, \"\", to, contract_),\n                    from\n                ) ||\n                _validateFrom(\n                    Hashes.erc721Location(from, \"\", to, tokenId, contract_),\n                    from\n                );\n            if (!Ops.or(rights == \"\", valid)) {\n                valid =\n                    _validateFrom(Hashes.allLocation(from, rights, to), from) ||\n                    _validateFrom(\n                        Hashes.contractLocation(from, rights, to, contract_),\n                        from\n                    ) ||\n                    _validateFrom(\n                        Hashes.erc721Location(\n                            from,\n                            rights,\n                            to,\n                            tokenId,\n                            contract_\n                        ),\n                        from\n                    );\n            }\n        }\n        assembly (\"memory-safe\") {\n            // Only first 32 bytes of scratch space is accessed\n            mstore(0, iszero(iszero(valid))) // Compiler cleans dirty booleans on the stack to 1, so do the same here\n            return(0, 32) // Direct return, skips Solidity's redundant copying to save gas\n        }\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function checkDelegateForERC20(\n        address to,\n        address from,\n        address contract_,\n        bytes32 rights\n    ) external view override returns (uint256 amount) {\n        if (!_invalidFrom(from)) {\n            amount = (_validateFrom(Hashes.allLocation(from, \"\", to), from) ||\n                _validateFrom(\n                    Hashes.contractLocation(from, \"\", to, contract_),\n                    from\n                ))\n                ? type(uint256).max\n                : _loadDelegationUint(\n                    Hashes.erc20Location(from, \"\", to, contract_),\n                    Storage.POSITIONS_AMOUNT\n                );\n            if (!Ops.or(rights == \"\", amount == type(uint256).max)) {\n                uint256 rightsBalance = (_validateFrom(\n                    Hashes.allLocation(from, rights, to),\n                    from\n                ) ||\n                    _validateFrom(\n                        Hashes.contractLocation(from, rights, to, contract_),\n                        from\n                    ))\n                    ? type(uint256).max\n                    : _loadDelegationUint(\n                        Hashes.erc20Location(from, rights, to, contract_),\n                        Storage.POSITIONS_AMOUNT\n                    );\n                amount = Ops.max(rightsBalance, amount);\n            }\n        }\n        assembly (\"memory-safe\") {\n            mstore(0, amount) // Only first 32 bytes of scratch space being accessed\n            return(0, 32) // Direct return, skips Solidity's redundant copying to save gas\n        }\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function checkDelegateForERC1155(\n        address to,\n        address from,\n        address contract_,\n        uint256 tokenId,\n        bytes32 rights\n    ) external view override returns (uint256 amount) {\n        if (!_invalidFrom(from)) {\n            amount = (_validateFrom(Hashes.allLocation(from, \"\", to), from) ||\n                _validateFrom(\n                    Hashes.contractLocation(from, \"\", to, contract_),\n                    from\n                ))\n                ? type(uint256).max\n                : _loadDelegationUint(\n                    Hashes.erc1155Location(from, \"\", to, tokenId, contract_),\n                    Storage.POSITIONS_AMOUNT\n                );\n            if (!Ops.or(rights == \"\", amount == type(uint256).max)) {\n                uint256 rightsBalance = (_validateFrom(\n                    Hashes.allLocation(from, rights, to),\n                    from\n                ) ||\n                    _validateFrom(\n                        Hashes.contractLocation(from, rights, to, contract_),\n                        from\n                    ))\n                    ? type(uint256).max\n                    : _loadDelegationUint(\n                        Hashes.erc1155Location(\n                            from,\n                            rights,\n                            to,\n                            tokenId,\n                            contract_\n                        ),\n                        Storage.POSITIONS_AMOUNT\n                    );\n                amount = Ops.max(rightsBalance, amount);\n            }\n        }\n        assembly (\"memory-safe\") {\n            mstore(0, amount) // Only first 32 bytes of scratch space is accessed\n            return(0, 32) // Direct return, skips Solidity's redundant copying to save gas\n        }\n    }\n\n    /**\n     * ----------- ENUMERATIONS -----------\n     */\n\n    /// @inheritdoc IDelegateRegistry\n    function getIncomingDelegations(\n        address to\n    ) external view override returns (Delegation[] memory delegations_) {\n        delegations_ = _getValidDelegationsFromHashes(\n            incomingDelegationHashes[to]\n        );\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function getOutgoingDelegations(\n        address from\n    ) external view returns (Delegation[] memory delegations_) {\n        delegations_ = _getValidDelegationsFromHashes(\n            outgoingDelegationHashes[from]\n        );\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function getIncomingDelegationHashes(\n        address to\n    ) external view returns (bytes32[] memory delegationHashes) {\n        delegationHashes = _getValidDelegationHashesFromHashes(\n            incomingDelegationHashes[to]\n        );\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function getOutgoingDelegationHashes(\n        address from\n    ) external view returns (bytes32[] memory delegationHashes) {\n        delegationHashes = _getValidDelegationHashesFromHashes(\n            outgoingDelegationHashes[from]\n        );\n    }\n\n    /// @inheritdoc IDelegateRegistry\n    function getDelegationsFromHashes(\n        bytes32[] calldata hashes\n    ) external view returns (Delegation[] memory delegations_) {\n        delegations_ = new Delegation[](hashes.length);\n        unchecked {\n            for (uint256 i = 0; i < hashes.length; ++i) {\n                bytes32 location = Hashes.location(hashes[i]);\n                address from = _loadFrom(location);\n                if (_invalidFrom(from)) {\n                    delegations_[i] = Delegation({\n                        type_: DelegationType.NONE,\n                        to: address(0),\n                        from: address(0),\n                        rights: \"\",\n                        amount: 0,\n                        contract_: address(0),\n                        tokenId: 0\n                    });\n                } else {\n                    (\n                        ,\n                        address to,\n                        address contract_\n                    ) = _loadDelegationAddresses(location);\n                    delegations_[i] = Delegation({\n                        type_: Hashes.decodeType(hashes[i]),\n                        to: to,\n                        from: from,\n                        rights: _loadDelegationBytes32(\n                            location,\n                            Storage.POSITIONS_RIGHTS\n                        ),\n                        amount: _loadDelegationUint(\n                            location,\n                            Storage.POSITIONS_AMOUNT\n                        ),\n                        contract_: contract_,\n                        tokenId: _loadDelegationUint(\n                            location,\n                            Storage.POSITIONS_TOKEN_ID\n                        )\n                    });\n                }\n            }\n        }\n    }\n\n    /**\n     * ----------- EXTERNAL STORAGE ACCESS -----------\n     */\n\n    function readSlot(\n        bytes32 location\n    ) external view returns (bytes32 contents) {\n        assembly {\n            contents := sload(location)\n        }\n    }\n\n    function readSlots(\n        bytes32[] calldata locations\n    ) external view returns (bytes32[] memory contents) {\n        uint256 length = locations.length;\n        contents = new bytes32[](length);\n        bytes32 tempLocation;\n        bytes32 tempValue;\n        unchecked {\n            for (uint256 i = 0; i < length; ++i) {\n                tempLocation = locations[i];\n                assembly {\n                    tempValue := sload(tempLocation)\n                }\n                contents[i] = tempValue;\n            }\n        }\n    }\n\n    /**\n     * ----------- ERC165 -----------\n     */\n\n    /// @notice Query if a contract implements an ERC-165 interface\n    /// @param interfaceId The interface identifier\n    /// @return valid Whether the queried interface is supported\n    function supportsInterface(\n        bytes4 interfaceId\n    ) external pure returns (bool) {\n        return\n            Ops.or(\n                interfaceId == type(IDelegateRegistry).interfaceId,\n                interfaceId == 0x01ffc9a7\n            );\n    }\n\n    /**\n     * ----------- INTERNAL -----------\n     */\n\n    /// @dev Helper function to push new delegation hashes to the incoming and outgoing hashes mappings\n    function _pushDelegationHashes(\n        address from,\n        address to,\n        bytes32 delegationHash\n    ) internal {\n        outgoingDelegationHashes[from].push(delegationHash);\n        incomingDelegationHashes[to].push(delegationHash);\n    }\n\n    /// @dev Helper function that writes bytes32 data to delegation data location at array position\n    function _writeDelegation(\n        bytes32 location,\n        uint256 position,\n        bytes32 data\n    ) internal {\n        assembly {\n            sstore(add(location, position), data)\n        }\n    }\n\n    /// @dev Helper function that writes uint256 data to delegation data location at array position\n    function _writeDelegation(\n        bytes32 location,\n        uint256 position,\n        uint256 data\n    ) internal {\n        assembly {\n            sstore(add(location, position), data)\n        }\n    }\n\n    /// @dev Helper function that writes addresses according to the packing rule for delegation storage\n    function _writeDelegationAddresses(\n        bytes32 location,\n        address from,\n        address to,\n        address contract_\n    ) internal {\n        (bytes32 firstSlot, bytes32 secondSlot) = Storage.packAddresses(\n            from,\n            to,\n            contract_\n        );\n        uint256 firstPacked = Storage.POSITIONS_FIRST_PACKED;\n        uint256 secondPacked = Storage.POSITIONS_SECOND_PACKED;\n        assembly {\n            sstore(add(location, firstPacked), firstSlot)\n            sstore(add(location, secondPacked), secondSlot)\n        }\n    }\n\n    /// @dev Helper function that writes `from` while preserving the rest of the storage slot\n    function _updateFrom(bytes32 location, address from) internal {\n        uint256 firstPacked = Storage.POSITIONS_FIRST_PACKED;\n        uint256 cleanAddress = Storage.CLEAN_ADDRESS;\n        uint256 cleanUpper12Bytes = type(uint256).max << 160;\n        assembly {\n            let slot := and(\n                sload(add(location, firstPacked)),\n                cleanUpper12Bytes\n            )\n            sstore(\n                add(location, firstPacked),\n                or(slot, and(from, cleanAddress))\n            )\n        }\n    }\n\n    /// @dev Helper function that takes an array of delegation hashes and returns an array of Delegation structs with their onchain information\n    function _getValidDelegationsFromHashes(\n        bytes32[] storage hashes\n    ) internal view returns (Delegation[] memory delegations_) {\n        uint256 count = 0;\n        uint256 hashesLength = hashes.length;\n        bytes32 hash;\n        bytes32[] memory filteredHashes = new bytes32[](hashesLength);\n        unchecked {\n            for (uint256 i = 0; i < hashesLength; ++i) {\n                hash = hashes[i];\n                if (_invalidFrom(_loadFrom(Hashes.location(hash)))) continue;\n                filteredHashes[count++] = hash;\n            }\n            delegations_ = new Delegation[](count);\n            bytes32 location;\n            for (uint256 i = 0; i < count; ++i) {\n                hash = filteredHashes[i];\n                location = Hashes.location(hash);\n                (\n                    address from,\n                    address to,\n                    address contract_\n                ) = _loadDelegationAddresses(location);\n                delegations_[i] = Delegation({\n                    type_: Hashes.decodeType(hash),\n                    to: to,\n                    from: from,\n                    rights: _loadDelegationBytes32(\n                        location,\n                        Storage.POSITIONS_RIGHTS\n                    ),\n                    amount: _loadDelegationUint(\n                        location,\n                        Storage.POSITIONS_AMOUNT\n                    ),\n                    contract_: contract_,\n                    tokenId: _loadDelegationUint(\n                        location,\n                        Storage.POSITIONS_TOKEN_ID\n                    )\n                });\n            }\n        }\n    }\n\n    /// @dev Helper function that takes an array of delegation hashes and returns an array of valid delegation hashes\n    function _getValidDelegationHashesFromHashes(\n        bytes32[] storage hashes\n    ) internal view returns (bytes32[] memory validHashes) {\n        uint256 count = 0;\n        uint256 hashesLength = hashes.length;\n        bytes32 hash;\n        bytes32[] memory filteredHashes = new bytes32[](hashesLength);\n        unchecked {\n            for (uint256 i = 0; i < hashesLength; ++i) {\n                hash = hashes[i];\n                if (_invalidFrom(_loadFrom(Hashes.location(hash)))) continue;\n                filteredHashes[count++] = hash;\n            }\n            validHashes = new bytes32[](count);\n            for (uint256 i = 0; i < count; ++i) {\n                validHashes[i] = filteredHashes[i];\n            }\n        }\n    }\n\n    /// @dev Helper function that loads delegation data from a particular array position and returns as bytes32\n    function _loadDelegationBytes32(\n        bytes32 location,\n        uint256 position\n    ) internal view returns (bytes32 data) {\n        assembly {\n            data := sload(add(location, position))\n        }\n    }\n\n    /// @dev Helper function that loads delegation data from a particular array position and returns as uint256\n    function _loadDelegationUint(\n        bytes32 location,\n        uint256 position\n    ) internal view returns (uint256 data) {\n        assembly {\n            data := sload(add(location, position))\n        }\n    }\n\n    // @dev Helper function that loads the from address from storage according to the packing rule for delegation storage\n    function _loadFrom(bytes32 location) internal view returns (address) {\n        bytes32 data;\n        uint256 firstPacked = Storage.POSITIONS_FIRST_PACKED;\n        assembly {\n            data := sload(add(location, firstPacked))\n        }\n        return Storage.unpackAddress(data);\n    }\n\n    /// @dev Helper function to establish whether a delegation is enabled\n    function _validateFrom(\n        bytes32 location,\n        address from\n    ) internal view returns (bool) {\n        return (from == _loadFrom(location));\n    }\n\n    /// @dev Helper function that loads the address for the delegation according to the packing rule for delegation storage\n    function _loadDelegationAddresses(\n        bytes32 location\n    ) internal view returns (address from, address to, address contract_) {\n        bytes32 firstSlot;\n        bytes32 secondSlot;\n        uint256 firstPacked = Storage.POSITIONS_FIRST_PACKED;\n        uint256 secondPacked = Storage.POSITIONS_SECOND_PACKED;\n        assembly {\n            firstSlot := sload(add(location, firstPacked))\n            secondSlot := sload(add(location, secondPacked))\n        }\n        (from, to, contract_) = Storage.unpackAddresses(firstSlot, secondSlot);\n    }\n\n    function _invalidFrom(address from) internal pure returns (bool) {\n        return\n            Ops.or(\n                from == Storage.DELEGATION_EMPTY,\n                from == Storage.DELEGATION_REVOKED\n            );\n    }\n}\n"
      },
      "contracts/testContracts/EnumerableERC1155.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/security/Pausable.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/token/common/ERC2981.sol\";\n\n/**\n * @author Created with HeyMint Launchpad https://launchpad.heymint.xyz\n * @notice This contract handles minting Verification test tokens.\n */\ncontract EnumerableERC1155 is\n    ERC1155Supply,\n    Ownable,\n    Pausable,\n    ReentrancyGuard,\n    ERC2981\n{\n    using ECDSA for bytes32;\n\n    // Used to validate authorized presale mint addresses\n    address private presaleSignerAddress =\n        0x0fE6E0D15E6F775138Ab556dE54B96d5C1358F3D;\n    address public royaltyAddress = 0x7A4dF7B461f1bE3e88373a4d933aeefE2FAdcE71;\n    address[] public payoutAddresses = [\n        0xD3371FD388664Bd16A267788dbE977582B850f5b\n    ];\n    // Permanently freezes metadata for all tokens so they can never be changed\n    bool public allMetadataFrozen = false;\n    // If true, payout addresses and basis points are permanently frozen and can never be updated\n    bool public payoutAddressesFrozen;\n    // The amount of tokens minted by a given address for a given token id\n    mapping(address => mapping(uint256 => uint256))\n        public tokensMintedByAddress;\n    // Permanently freezes metadata for a specific token id so it can never be changed\n    mapping(uint256 => bool) public tokenMetadataFrozen;\n    // If true, the given token id can never be minted again\n    mapping(uint256 => bool) public tokenMintingPermanentlyDisabled;\n    mapping(uint256 => bool) public tokenPresaleSaleActive;\n    mapping(uint256 => bool) public tokenPublicSaleActive;\n    // If true, sale start and end times for the presale will be enforced, else ignored\n    mapping(uint256 => bool) public tokenUsePresaleTimes;\n    // If true, sale start and end times for the public sale will be enforced, else ignored\n    mapping(uint256 => bool) public tokenUsePublicSaleTimes;\n    mapping(uint256 => string) public tokenURI;\n    // Maximum supply of tokens that can be minted for each token id. If zero, this token is open edition and has no mint limit\n    mapping(uint256 => uint256) public tokenMaxSupply;\n    // If zero, this token is open edition and has no mint limit\n    mapping(uint256 => uint256) public tokenPresaleMaxSupply;\n    mapping(uint256 => uint256) public tokenPresaleMintsPerAddress;\n    mapping(uint256 => uint256) public tokenPresalePrice;\n    mapping(uint256 => uint256) public tokenPresaleSaleEndTime;\n    mapping(uint256 => uint256) public tokenPresaleSaleStartTime;\n    mapping(uint256 => uint256) public tokenPublicMintsPerAddress;\n    mapping(uint256 => uint256) public tokenPublicPrice;\n    mapping(uint256 => uint256) public tokenPublicSaleEndTime;\n    mapping(uint256 => uint256) public tokenPublicSaleStartTime;\n    string public name = \"Verification test\";\n    string public symbol = \"VRT\";\n    // The respective share of funds to be sent to each address in payoutAddresses in basis points\n    uint256[] public payoutBasisPoints = [10000];\n    uint96 public royaltyFee = 0;\n\n    constructor()\n        ERC1155(\n            \"ipfs://bafybeicin4rmb5y44r2a5jhwvobfgxutabetrttoi3u2po7pdymxt7dwdy/{id}\"\n        )\n    {\n        _setDefaultRoyalty(royaltyAddress, royaltyFee);\n        tokenPublicPrice[1] = 0.1 ether;\n        tokenPublicMintsPerAddress[1] = 0;\n        require(\n            payoutAddresses.length == payoutBasisPoints.length,\n            \"PAYOUT_ARRAYS_NOT_SAME_LENGTH\"\n        );\n        uint256 totalPayoutBasisPoints = 0;\n        for (uint256 i = 0; i < payoutBasisPoints.length; i++) {\n            totalPayoutBasisPoints += payoutBasisPoints[i];\n        }\n        require(\n            totalPayoutBasisPoints == 10000,\n            \"TOTAL_BASIS_POINTS_MUST_BE_10000\"\n        );\n    }\n\n    modifier originalUser() {\n        require(tx.origin == msg.sender, \"CANNOT_CALL_FROM_CONTRACT\");\n        _;\n    }\n\n    /**\n     * @notice Returns a custom URI for each token id if set\n     */\n    function uri(\n        uint256 _tokenId\n    ) public view override returns (string memory) {\n        // If no URI exists for the specific id requested, fallback to the default ERC-1155 URI.\n        if (bytes(tokenURI[_tokenId]).length == 0) {\n            return super.uri(_tokenId);\n        }\n        return tokenURI[_tokenId];\n    }\n\n    /**\n     * @notice Sets a URI for a specific token id.\n     */\n    function setURI(\n        uint256 _tokenId,\n        string calldata _newTokenURI\n    ) external onlyOwner {\n        require(\n            !allMetadataFrozen && !tokenMetadataFrozen[_tokenId],\n            \"METADATA_HAS_BEEN_FROZEN\"\n        );\n        tokenURI[_tokenId] = _newTokenURI;\n    }\n\n    /**\n     * @notice Update the global default ERC-1155 base URI\n     */\n    function setGlobalURI(string calldata _newTokenURI) external onlyOwner {\n        require(!allMetadataFrozen, \"METADATA_HAS_BEEN_FROZEN\");\n        _setURI(_newTokenURI);\n    }\n\n    /**\n     * @notice Freeze metadata for a specific token id so it can never be changed again\n     */\n    function freezeTokenMetadata(uint256 _tokenId) external onlyOwner {\n        require(\n            !tokenMetadataFrozen[_tokenId],\n            \"METADATA_HAS_ALREADY_BEEN_FROZEN\"\n        );\n        tokenMetadataFrozen[_tokenId] = true;\n    }\n\n    /**\n     * @notice Freeze all metadata so it can never be changed again\n     */\n    function freezeAllMetadata() external onlyOwner {\n        require(!allMetadataFrozen, \"METADATA_HAS_ALREADY_BEEN_FROZEN\");\n        allMetadataFrozen = true;\n    }\n\n    /**\n     * @notice Reduce the max supply of tokens for a given token id\n     * @param _newMaxSupply The new maximum supply of tokens available to mint\n     * @param _tokenId The token id to reduce the max supply for\n     */\n    function reduceMaxSupply(\n        uint256 _tokenId,\n        uint256 _newMaxSupply\n    ) external onlyOwner {\n        require(\n            tokenMaxSupply[_tokenId] == 0 ||\n                _newMaxSupply < tokenMaxSupply[_tokenId],\n            \"NEW_MAX_SUPPLY_TOO_HIGH\"\n        );\n        require(\n            _newMaxSupply >= totalSupply(_tokenId),\n            \"SUPPLY_LOWER_THAN_MINTED_TOKENS\"\n        );\n        tokenMaxSupply[_tokenId] = _newMaxSupply;\n    }\n\n    /**\n     * @notice Lock a token id so that it can never be minted again\n     */\n    function permanentlyDisableTokenMinting(\n        uint256 _tokenId\n    ) external onlyOwner {\n        tokenMintingPermanentlyDisabled[_tokenId] = true;\n    }\n\n    /**\n     * @notice Change the royalty fee for the collection\n     */\n    function setRoyaltyFee(uint96 _feeNumerator) external onlyOwner {\n        royaltyFee = _feeNumerator;\n        _setDefaultRoyalty(royaltyAddress, royaltyFee);\n    }\n\n    /**\n     * @notice Change the royalty address where royalty payouts are sent\n     */\n    function setRoyaltyAddress(address _royaltyAddress) external onlyOwner {\n        royaltyAddress = _royaltyAddress;\n        _setDefaultRoyalty(royaltyAddress, royaltyFee);\n    }\n\n    function pause() external onlyOwner {\n        _pause();\n    }\n\n    function unpause() external onlyOwner {\n        _unpause();\n    }\n\n    /**\n     * @notice Override ERC1155 such that zero amount token transfers are disallowed.\n     * This prevents arbitrary 'creation' of new tokens in the collection by anyone.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) public override {\n        require(amount > 0, \"AMOUNT_CANNOT_BE_ZERO\");\n        return super.safeTransferFrom(from, to, id, amount, data);\n    }\n\n    function supportsInterface(\n        bytes4 _interfaceId\n    ) public view override(ERC1155, ERC2981) returns (bool) {\n        return super.supportsInterface(_interfaceId);\n    }\n\n    /**\n     * @notice Allow owner to send tokens without cost to multiple addresses\n     */\n    function giftTokens(\n        uint256 _tokenId,\n        address[] calldata _receivers,\n        uint256[] calldata _mintNumber\n    ) external onlyOwner {\n        require(\n            !tokenMintingPermanentlyDisabled[_tokenId],\n            \"MINTING_PERMANENTLY_DISABLED\"\n        );\n        uint256 totalMint = 0;\n        for (uint256 i = 0; i < _mintNumber.length; i++) {\n            totalMint += _mintNumber[i];\n        }\n        // require either no tokenMaxSupply set or tokenMaxSupply not maxed out\n        require(\n            tokenMaxSupply[_tokenId] == 0 ||\n                totalSupply(_tokenId) + totalMint <= tokenMaxSupply[_tokenId],\n            \"MINT_TOO_LARGE\"\n        );\n        for (uint256 i = 0; i < _receivers.length; i++) {\n            _mint(_receivers[i], _tokenId, _mintNumber[i], \"\");\n        }\n    }\n\n    /**\n     * @notice To be updated by contract owner to allow public sale minting for a given token\n     */\n    function setTokenPublicSaleState(\n        uint256 _tokenId,\n        bool _saleActiveState\n    ) external onlyOwner {\n        require(\n            tokenPublicSaleActive[_tokenId] != _saleActiveState,\n            \"NEW_STATE_IDENTICAL_TO_OLD_STATE\"\n        );\n        tokenPublicSaleActive[_tokenId] = _saleActiveState;\n    }\n\n    /**\n     * @notice Update the public mint price for a given token\n     */\n    function setTokenPublicPrice(\n        uint256 _tokenId,\n        uint256 _publicPrice\n    ) external onlyOwner {\n        tokenPublicPrice[_tokenId] = _publicPrice;\n    }\n\n    /**\n     * @notice Set the maximum public mints allowed per a given address for a given token\n     */\n    function setTokenPublicMintsAllowedPerAddress(\n        uint256 _tokenId,\n        uint256 _mintsAllowed\n    ) external onlyOwner {\n        tokenPublicMintsPerAddress[_tokenId] = _mintsAllowed;\n    }\n\n    /**\n     * @notice Update the start time for public mint for a given token\n     */\n    function setTokenPublicSaleStartTime(\n        uint256 _tokenId,\n        uint256 _publicSaleStartTime\n    ) external onlyOwner {\n        require(_publicSaleStartTime > block.timestamp, \"TIME_IN_PAST\");\n        tokenPublicSaleStartTime[_tokenId] = _publicSaleStartTime;\n    }\n\n    /**\n     * @notice Update the end time for public mint for a given token\n     */\n    function setTokenPublicSaleEndTime(\n        uint256 _tokenId,\n        uint256 _publicSaleEndTime\n    ) external onlyOwner {\n        require(_publicSaleEndTime > block.timestamp, \"TIME_IN_PAST\");\n        tokenPublicSaleEndTime[_tokenId] = _publicSaleEndTime;\n    }\n\n    /**\n     * @notice Update whether or not to use the automatic public sale times for a given token\n     */\n    function setTokenUsePublicSaleTimes(\n        uint256 _tokenId,\n        bool _usePublicSaleTimes\n    ) external onlyOwner {\n        require(\n            tokenUsePublicSaleTimes[_tokenId] != _usePublicSaleTimes,\n            \"NEW_STATE_IDENTICAL_TO_OLD_STATE\"\n        );\n        tokenUsePublicSaleTimes[_tokenId] = _usePublicSaleTimes;\n    }\n\n    /**\n     * @notice Returns if public sale times are active for a given token\n     */\n    function tokenPublicSaleTimeIsActive(\n        uint256 _tokenId\n    ) public view returns (bool) {\n        if (tokenUsePublicSaleTimes[_tokenId] == false) {\n            return true;\n        }\n        return\n            block.timestamp >= tokenPublicSaleStartTime[_tokenId] &&\n            block.timestamp <= tokenPublicSaleEndTime[_tokenId];\n    }\n\n    /**\n     * @notice Allow for public minting of tokens for a given token\n     */\n    function mintToken(\n        uint256 _tokenId,\n        uint256 _numTokens\n    ) external payable originalUser nonReentrant {\n        require(tokenPublicSaleActive[_tokenId], \"PUBLIC_SALE_IS_NOT_ACTIVE\");\n        require(\n            tokenPublicSaleTimeIsActive(_tokenId),\n            \"PUBLIC_SALE_TIME_IS_NOT_ACTIVE\"\n        );\n        require(\n            tokenPublicMintsPerAddress[_tokenId] == 0 ||\n                tokensMintedByAddress[msg.sender][_tokenId] + _numTokens <=\n                tokenPublicMintsPerAddress[_tokenId],\n            \"MAX_MINTS_FOR_ADDRESS_EXCEEDED\"\n        );\n        require(\n            tokenMaxSupply[_tokenId] == 0 ||\n                totalSupply(_tokenId) + _numTokens <= tokenMaxSupply[_tokenId],\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        require(\n            msg.value == tokenPublicPrice[_tokenId] * _numTokens,\n            \"PAYMENT_INCORRECT\"\n        );\n        require(\n            !tokenMintingPermanentlyDisabled[_tokenId],\n            \"MINTING_PERMANENTLY_DISABLED\"\n        );\n\n        tokensMintedByAddress[msg.sender][_tokenId] += _numTokens;\n        _mint(msg.sender, _tokenId, _numTokens, \"\");\n\n        if (\n            tokenMaxSupply[_tokenId] != 0 &&\n            totalSupply(_tokenId) >= tokenMaxSupply[_tokenId]\n        ) {\n            tokenPublicSaleActive[_tokenId] = false;\n        }\n    }\n\n    /**\n     * @notice Set the signer address used to verify presale minting\n     */\n    function setPresaleSignerAddress(\n        address _presaleSignerAddress\n    ) external onlyOwner {\n        require(_presaleSignerAddress != address(0));\n        presaleSignerAddress = _presaleSignerAddress;\n    }\n\n    /**\n     * @notice To be updated by contract owner to allow presale minting for a given token\n     */\n    function setTokenPresaleState(\n        uint256 _tokenId,\n        bool _saleActiveState\n    ) external onlyOwner {\n        require(\n            tokenPresaleSaleActive[_tokenId] != _saleActiveState,\n            \"NEW_STATE_IDENTICAL_TO_OLD_STATE\"\n        );\n        tokenPresaleSaleActive[_tokenId] = _saleActiveState;\n    }\n\n    /**\n     * @notice Update the presale mint price for a given token\n     */\n    function setTokenPresalePrice(\n        uint256 _tokenId,\n        uint256 _presalePrice\n    ) external onlyOwner {\n        tokenPresalePrice[_tokenId] = _presalePrice;\n    }\n\n    /**\n     * @notice Set the maximum presale mints allowed per a given address for a given token\n     */\n    function setTokenPresaleMintsAllowedPerAddress(\n        uint256 _tokenId,\n        uint256 _mintsAllowed\n    ) external onlyOwner {\n        tokenPresaleMintsPerAddress[_tokenId] = _mintsAllowed;\n    }\n\n    /**\n     * @notice Reduce the presale max supply of tokens for a given token id\n     * @param _newPresaleMaxSupply The new maximum supply of tokens available to mint\n     * @param _tokenId The token id to reduce the max supply for\n     */\n    function reducePresaleMaxSupply(\n        uint256 _tokenId,\n        uint256 _newPresaleMaxSupply\n    ) external onlyOwner {\n        require(\n            tokenPresaleMaxSupply[_tokenId] == 0 ||\n                _newPresaleMaxSupply < tokenPresaleMaxSupply[_tokenId],\n            \"NEW_MAX_SUPPLY_TOO_HIGH\"\n        );\n        tokenPresaleMaxSupply[_tokenId] = _newPresaleMaxSupply;\n    }\n\n    /**\n     * @notice Update the start time for presale mint for a given token\n     */\n    function setTokenPresaleStartTime(\n        uint256 _tokenId,\n        uint256 _presaleStartTime\n    ) external onlyOwner {\n        require(_presaleStartTime > block.timestamp, \"TIME_IN_PAST\");\n        tokenPresaleSaleStartTime[_tokenId] = _presaleStartTime;\n    }\n\n    /**\n     * @notice Update the end time for presale mint for a given token\n     */\n    function setTokenPresaleEndTime(\n        uint256 _tokenId,\n        uint256 _presaleEndTime\n    ) external onlyOwner {\n        require(_presaleEndTime > block.timestamp, \"TIME_IN_PAST\");\n        tokenPresaleSaleEndTime[_tokenId] = _presaleEndTime;\n    }\n\n    /**\n     * @notice Update whether or not to use the automatic presale times for a given token\n     */\n    function setTokenUsePresaleTimes(\n        uint256 _tokenId,\n        bool _usePresaleTimes\n    ) external onlyOwner {\n        require(\n            tokenUsePresaleTimes[_tokenId] != _usePresaleTimes,\n            \"NEW_STATE_IDENTICAL_TO_OLD_STATE\"\n        );\n        tokenUsePresaleTimes[_tokenId] = _usePresaleTimes;\n    }\n\n    /**\n     * @notice Returns if presale times are active for a given token\n     */\n    function tokenPresaleTimeIsActive(\n        uint256 _tokenId\n    ) public view returns (bool) {\n        if (tokenUsePresaleTimes[_tokenId] == false) {\n            return true;\n        }\n        return\n            block.timestamp >= tokenPresaleSaleStartTime[_tokenId] &&\n            block.timestamp <= tokenPresaleSaleEndTime[_tokenId];\n    }\n\n    /**\n     * @notice Verify that a signed message is validly signed by the presaleSignerAddress\n     */\n    function verifySignerAddress(\n        bytes32 _messageHash,\n        bytes calldata _signature\n    ) private view returns (bool) {\n        return\n            presaleSignerAddress ==\n            _messageHash.toEthSignedMessageHash().recover(_signature);\n    }\n\n    /**\n     * @notice Allow for allowlist minting of tokens\n     */\n    function presaleMint(\n        bytes32 _messageHash,\n        bytes calldata _signature,\n        uint256 _tokenId,\n        uint256 _numTokens,\n        uint256 _maximumAllowedMints\n    ) external payable originalUser nonReentrant {\n        require(tokenPresaleSaleActive[_tokenId], \"PRESALE_IS_NOT_ACTIVE\");\n        require(\n            tokenPresaleTimeIsActive(_tokenId),\n            \"PRESALE_TIME_IS_NOT_ACTIVE\"\n        );\n        require(\n            !tokenMintingPermanentlyDisabled[_tokenId],\n            \"MINTING_PERMANENTLY_DISABLED\"\n        );\n        require(\n            tokenPresaleMintsPerAddress[_tokenId] == 0 ||\n                tokensMintedByAddress[msg.sender][_tokenId] + _numTokens <=\n                tokenPresaleMintsPerAddress[_tokenId],\n            \"MAX_MINTS_PER_ADDRESS_EXCEEDED\"\n        );\n        require(\n            _maximumAllowedMints == 0 ||\n                tokensMintedByAddress[msg.sender][_tokenId] + _numTokens <=\n                _maximumAllowedMints,\n            \"MAX_MINTS_EXCEEDED\"\n        );\n        require(\n            tokenPresaleMaxSupply[_tokenId] == 0 ||\n                totalSupply(_tokenId) + _numTokens <=\n                tokenPresaleMaxSupply[_tokenId],\n            \"MAX_SUPPLY_EXCEEDED\"\n        );\n        require(\n            msg.value == tokenPresalePrice[_tokenId] * _numTokens,\n            \"PAYMENT_INCORRECT\"\n        );\n        require(\n            keccak256(abi.encode(msg.sender, _maximumAllowedMints, _tokenId)) ==\n                _messageHash,\n            \"MESSAGE_INVALID\"\n        );\n        require(\n            verifySignerAddress(_messageHash, _signature),\n            \"SIGNATURE_VALIDATION_FAILED\"\n        );\n\n        tokensMintedByAddress[msg.sender][_tokenId] += _numTokens;\n        _mint(msg.sender, _tokenId, _numTokens, \"\");\n\n        if (\n            tokenPresaleMaxSupply[_tokenId] != 0 &&\n            totalSupply(_tokenId) >= tokenPresaleMaxSupply[_tokenId]\n        ) {\n            tokenPresaleSaleActive[_tokenId] = false;\n        }\n    }\n\n    /**\n     * @notice Freeze all payout addresses and percentages so they can never be changed again\n     */\n    function freezePayoutAddresses() external onlyOwner {\n        require(!payoutAddressesFrozen, \"PAYOUT_ADDRESSES_ALREADY_FROZEN\");\n        payoutAddressesFrozen = true;\n    }\n\n    /**\n     * @notice Update payout addresses and basis points for each addresses' respective share of contract funds\n     */\n    function updatePayoutAddressesAndBasisPoints(\n        address[] calldata _payoutAddresses,\n        uint256[] calldata _payoutBasisPoints\n    ) external onlyOwner {\n        require(!payoutAddressesFrozen, \"PAYOUT_ADDRESSES_FROZEN\");\n        require(\n            _payoutAddresses.length == _payoutBasisPoints.length,\n            \"ARRAY_LENGTHS_MUST_MATCH\"\n        );\n        uint256 totalBasisPoints = 0;\n        for (uint256 i = 0; i < _payoutBasisPoints.length; i++) {\n            totalBasisPoints += _payoutBasisPoints[i];\n        }\n        require(totalBasisPoints == 10000, \"TOTAL_BASIS_POINTS_MUST_BE_10000\");\n        payoutAddresses = _payoutAddresses;\n        payoutBasisPoints = _payoutBasisPoints;\n    }\n\n    /**\n     * @notice Withdraws all funds held within contract\n     */\n    function withdraw() external onlyOwner nonReentrant {\n        require(address(this).balance > 0, \"CONTRACT_HAS_NO_BALANCE\");\n        uint256 balance = address(this).balance;\n        for (uint256 i = 0; i < payoutAddresses.length; i++) {\n            uint256 amount = (balance * payoutBasisPoints[i]) / 10000;\n            (bool success, ) = payoutAddresses[i].call{value: amount}(\"\");\n            require(success, \"Transfer failed.\");\n        }\n    }\n\n    /**\n     * @notice Override default ERC-1155 setApprovalForAll to require that the operator is not from a blocklisted exchange\n     * @param operator Address to add to the set of authorized operators\n     * @param approved True if the operator is approved, false to revoke approval\n     */\n    function setApprovalForAll(\n        address operator,\n        bool approved\n    ) public override {\n        super.setApprovalForAll(operator, approved);\n    }\n\n    function _beforeTokenTransfer(\n        address operator,\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal override whenNotPaused {\n        super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n    }\n}\n"
      },
      "contracts/testContracts/EnumerableERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {ERC721Enumerable, ERC721} from \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\";\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {Counters} from \"@openzeppelin/contracts/utils/Counters.sol\";\n\n/**\n * @title Basic Enumerable ERC721 Contract\n * @author Ben Yu\n * @notice An ERC721Enumerable contract with basic functionality\n */\ncontract EnumerableERC721 is ERC721Enumerable, Ownable {\n    using Counters for Counters.Counter;\n    Counters.Counter private supplyCounter;\n\n    uint256 public constant PRICE = 0.01 ether;\n    uint256 public constant MAX_SUPPLY = 1000;\n\n    string public baseTokenURI =\n        \"ipfs://bafybeih5lgrstt7kredzhpcvmft2qefue5pl3ykrdktadw5w62zd7cbkja/\";\n    bool public publicSaleActive;\n\n    /**\n     * @notice Initialize the contract\n     */\n    constructor() ERC721(\"Test Contract\", \"TEST\") {\n        // Start token IDs at 1\n        supplyCounter.increment();\n    }\n\n    /**\n     * @notice Override the default base URI function to provide a real base URI\n     */\n    function _baseURI() internal view virtual override returns (string memory) {\n        return baseTokenURI;\n    }\n\n    /**\n     * @notice Update the base token URI\n     * @param _newBaseURI New base URI\n     */\n    function setBaseURI(string calldata _newBaseURI) external onlyOwner {\n        baseTokenURI = _newBaseURI;\n    }\n\n    /**\n     * @notice Allows for public minting of tokens\n     * @param _mintNumber Number of tokens to mint\n     */\n    function publicMint(uint256 _mintNumber) external payable virtual {\n        require(msg.value == PRICE * _mintNumber, \"INVALID_PRICE\");\n        require((totalSupply() + _mintNumber) <= MAX_SUPPLY, \"MINT_TOO_LARGE\");\n\n        for (uint256 i = 0; i < _mintNumber; i++) {\n            _safeMint(msg.sender, supplyCounter.current());\n            supplyCounter.increment();\n        }\n    }\n\n    /**\n     * @notice Allow owner to send `mintNumber` tokens without cost to multiple addresses\n     * @param _receivers Array of addresses to send tokens to\n     * @param _mintNumber Number of tokens to send to each address\n     */\n    function gift(\n        address[] calldata _receivers,\n        uint256 _mintNumber\n    ) external onlyOwner {\n        require(\n            (totalSupply() + (_receivers.length * _mintNumber)) <= MAX_SUPPLY,\n            \"MINT_TOO_LARGE\"\n        );\n\n        for (uint256 i = 0; i < _receivers.length; i++) {\n            for (uint256 j = 0; j < _mintNumber; j++) {\n                _safeMint(_receivers[i], supplyCounter.current());\n                supplyCounter.increment();\n            }\n        }\n    }\n\n    /**\n     * @notice Allow contract owner to withdraw funds\n     */\n    function withdraw() external onlyOwner {\n        payable(owner()).transfer(address(this).balance);\n    }\n}\n"
      },
      "contracts/testContracts/HeyMintDefaults.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\n\ninterface IHeyMintDefaults {\n    function getCreditCardDefaultAddresses()\n        external\n        view\n        returns (address[] memory);\n}\n\n/**\n * @author Created by HeyMint Launchpad https://join.heymint.xyz\n * @notice This contract contains base defaults shared across all HeyMint proxy contracts\n */\ncontract HeyMintDefaults is IHeyMintDefaults, Ownable {\n    address[] private creditCardDefaultAddresses;\n\n    function getCreditCardDefaultAddresses()\n        external\n        view\n        returns (address[] memory)\n    {\n        return creditCardDefaultAddresses;\n    }\n\n    function setCreditCardDefaultAddresses(\n        address[] calldata _newAddresses\n    ) external onlyOwner {\n        creditCardDefaultAddresses = _newAddresses;\n    }\n}\n"
      },
      "erc721a-upgradeable/contracts/ERC721A__Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable diamond facet contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\n\nimport {ERC721A__InitializableStorage} from './ERC721A__InitializableStorage.sol';\n\nabstract contract ERC721A__Initializable {\n    using ERC721A__InitializableStorage for ERC721A__InitializableStorage.Layout;\n\n    /**\n     * @dev Modifier to protect an initializer function from being invoked twice.\n     */\n    modifier initializerERC721A() {\n        // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n        // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\n        // contract may have been reentered.\n        require(\n            ERC721A__InitializableStorage.layout()._initializing\n                ? _isConstructor()\n                : !ERC721A__InitializableStorage.layout()._initialized,\n            'ERC721A__Initializable: contract is already initialized'\n        );\n\n        bool isTopLevelCall = !ERC721A__InitializableStorage.layout()._initializing;\n        if (isTopLevelCall) {\n            ERC721A__InitializableStorage.layout()._initializing = true;\n            ERC721A__InitializableStorage.layout()._initialized = true;\n        }\n\n        _;\n\n        if (isTopLevelCall) {\n            ERC721A__InitializableStorage.layout()._initializing = false;\n        }\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} modifier, directly or indirectly.\n     */\n    modifier onlyInitializingERC721A() {\n        require(\n            ERC721A__InitializableStorage.layout()._initializing,\n            'ERC721A__Initializable: contract is not initializing'\n        );\n        _;\n    }\n\n    /// @dev Returns true if and only if the function is running in the constructor\n    function _isConstructor() private view returns (bool) {\n        // extcodesize checks the size of the code stored in an address, and\n        // address returns the current address. Since the code is still not\n        // deployed when running a constructor, any checks on its code size will\n        // yield zero, making it an effective way to detect if a contract is\n        // under construction or not.\n        address self = address(this);\n        uint256 cs;\n        assembly {\n            cs := extcodesize(self)\n        }\n        return cs == 0;\n    }\n}\n"
      },
      "erc721a-upgradeable/contracts/ERC721A__InitializableStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is a base storage for the  initialization function for upgradeable diamond facet contracts\n **/\n\nlibrary ERC721A__InitializableStorage {\n    struct Layout {\n        /*\n         * Indicates that the contract has been initialized.\n         */\n        bool _initialized;\n        /*\n         * Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    bytes32 internal constant STORAGE_SLOT = keccak256('ERC721A.contracts.storage.initializable.facet');\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "erc721a-upgradeable/contracts/ERC721AStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nlibrary ERC721AStorage {\n    // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364).\n    struct TokenApprovalRef {\n        address value;\n    }\n\n    struct Layout {\n        // =============================================================\n        //                            STORAGE\n        // =============================================================\n\n        // The next token ID to be minted.\n        uint256 _currentIndex;\n        // The number of tokens burned.\n        uint256 _burnCounter;\n        // Token name\n        string _name;\n        // Token symbol\n        string _symbol;\n        // Mapping from token ID to ownership details\n        // An empty struct value does not necessarily mean the token is unowned.\n        // See {_packedOwnershipOf} implementation for details.\n        //\n        // Bits Layout:\n        // - [0..159]   `addr`\n        // - [160..223] `startTimestamp`\n        // - [224]      `burned`\n        // - [225]      `nextInitialized`\n        // - [232..255] `extraData`\n        mapping(uint256 => uint256) _packedOwnerships;\n        // Mapping owner address to address data.\n        //\n        // Bits Layout:\n        // - [0..63]    `balance`\n        // - [64..127]  `numberMinted`\n        // - [128..191] `numberBurned`\n        // - [192..255] `aux`\n        mapping(address => uint256) _packedAddressData;\n        // Mapping from token ID to approved address.\n        mapping(uint256 => ERC721AStorage.TokenApprovalRef) _tokenApprovals;\n        // Mapping from owner to operator approvals\n        mapping(address => mapping(address => bool)) _operatorApprovals;\n    }\n\n    bytes32 internal constant STORAGE_SLOT = keccak256('ERC721A.contracts.storage.ERC721A');\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "erc721a-upgradeable/contracts/ERC721AUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// ERC721A Contracts v4.2.3\n// Creator: Chiru Labs\n\npragma solidity ^0.8.4;\n\nimport './IERC721AUpgradeable.sol';\nimport {ERC721AStorage} from './ERC721AStorage.sol';\nimport './ERC721A__Initializable.sol';\n\n/**\n * @dev Interface of ERC721 token receiver.\n */\ninterface ERC721A__IERC721ReceiverUpgradeable {\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n\n/**\n * @title ERC721A\n *\n * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721)\n * Non-Fungible Token Standard, including the Metadata extension.\n * Optimized for lower gas during batch mints.\n *\n * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...)\n * starting from `_startTokenId()`.\n *\n * Assumptions:\n *\n * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply.\n * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256).\n */\ncontract ERC721AUpgradeable is ERC721A__Initializable, IERC721AUpgradeable {\n    using ERC721AStorage for ERC721AStorage.Layout;\n\n    // =============================================================\n    //                           CONSTANTS\n    // =============================================================\n\n    // Mask of an entry in packed address data.\n    uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;\n\n    // The bit position of `numberMinted` in packed address data.\n    uint256 private constant _BITPOS_NUMBER_MINTED = 64;\n\n    // The bit position of `numberBurned` in packed address data.\n    uint256 private constant _BITPOS_NUMBER_BURNED = 128;\n\n    // The bit position of `aux` in packed address data.\n    uint256 private constant _BITPOS_AUX = 192;\n\n    // Mask of all 256 bits in packed address data except the 64 bits for `aux`.\n    uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;\n\n    // The bit position of `startTimestamp` in packed ownership.\n    uint256 private constant _BITPOS_START_TIMESTAMP = 160;\n\n    // The bit mask of the `burned` bit in packed ownership.\n    uint256 private constant _BITMASK_BURNED = 1 << 224;\n\n    // The bit position of the `nextInitialized` bit in packed ownership.\n    uint256 private constant _BITPOS_NEXT_INITIALIZED = 225;\n\n    // The bit mask of the `nextInitialized` bit in packed ownership.\n    uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225;\n\n    // The bit position of `extraData` in packed ownership.\n    uint256 private constant _BITPOS_EXTRA_DATA = 232;\n\n    // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`.\n    uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1;\n\n    // The mask of the lower 160 bits for addresses.\n    uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;\n\n    // The maximum `quantity` that can be minted with {_mintERC2309}.\n    // This limit is to prevent overflows on the address data entries.\n    // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309}\n    // is required to cause an overflow, which is unrealistic.\n    uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000;\n\n    // The `Transfer` event signature is given by:\n    // `keccak256(bytes(\"Transfer(address,address,uint256)\"))`.\n    bytes32 private constant _TRANSFER_EVENT_SIGNATURE =\n        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;\n\n    // =============================================================\n    //                          CONSTRUCTOR\n    // =============================================================\n\n    function __ERC721A_init(string memory name_, string memory symbol_) internal onlyInitializingERC721A {\n        __ERC721A_init_unchained(name_, symbol_);\n    }\n\n    function __ERC721A_init_unchained(string memory name_, string memory symbol_) internal onlyInitializingERC721A {\n        ERC721AStorage.layout()._name = name_;\n        ERC721AStorage.layout()._symbol = symbol_;\n        ERC721AStorage.layout()._currentIndex = _startTokenId();\n    }\n\n    // =============================================================\n    //                   TOKEN COUNTING OPERATIONS\n    // =============================================================\n\n    /**\n     * @dev Returns the starting token ID.\n     * To change the starting token ID, please override this function.\n     */\n    function _startTokenId() internal view virtual returns (uint256) {\n        return 0;\n    }\n\n    /**\n     * @dev Returns the next token ID to be minted.\n     */\n    function _nextTokenId() internal view virtual returns (uint256) {\n        return ERC721AStorage.layout()._currentIndex;\n    }\n\n    /**\n     * @dev Returns the total number of tokens in existence.\n     * Burned tokens will reduce the count.\n     * To get the total number of tokens minted, please see {_totalMinted}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        // Counter underflow is impossible as _burnCounter cannot be incremented\n        // more than `_currentIndex - _startTokenId()` times.\n        unchecked {\n            return ERC721AStorage.layout()._currentIndex - ERC721AStorage.layout()._burnCounter - _startTokenId();\n        }\n    }\n\n    /**\n     * @dev Returns the total amount of tokens minted in the contract.\n     */\n    function _totalMinted() internal view virtual returns (uint256) {\n        // Counter underflow is impossible as `_currentIndex` does not decrement,\n        // and it is initialized to `_startTokenId()`.\n        unchecked {\n            return ERC721AStorage.layout()._currentIndex - _startTokenId();\n        }\n    }\n\n    /**\n     * @dev Returns the total number of tokens burned.\n     */\n    function _totalBurned() internal view virtual returns (uint256) {\n        return ERC721AStorage.layout()._burnCounter;\n    }\n\n    // =============================================================\n    //                    ADDRESS DATA OPERATIONS\n    // =============================================================\n\n    /**\n     * @dev Returns the number of tokens in `owner`'s account.\n     */\n    function balanceOf(address owner) public view virtual override returns (uint256) {\n        if (owner == address(0)) revert BalanceQueryForZeroAddress();\n        return ERC721AStorage.layout()._packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY;\n    }\n\n    /**\n     * Returns the number of tokens minted by `owner`.\n     */\n    function _numberMinted(address owner) internal view returns (uint256) {\n        return\n            (ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY;\n    }\n\n    /**\n     * Returns the number of tokens burned by or on behalf of `owner`.\n     */\n    function _numberBurned(address owner) internal view returns (uint256) {\n        return\n            (ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY;\n    }\n\n    /**\n     * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).\n     */\n    function _getAux(address owner) internal view returns (uint64) {\n        return uint64(ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_AUX);\n    }\n\n    /**\n     * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).\n     * If there are multiple variables, please pack them into a uint64.\n     */\n    function _setAux(address owner, uint64 aux) internal virtual {\n        uint256 packed = ERC721AStorage.layout()._packedAddressData[owner];\n        uint256 auxCasted;\n        // Cast `aux` with assembly to avoid redundant masking.\n        assembly {\n            auxCasted := aux\n        }\n        packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX);\n        ERC721AStorage.layout()._packedAddressData[owner] = packed;\n    }\n\n    // =============================================================\n    //                            IERC165\n    // =============================================================\n\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        // The interface IDs are constants representing the first 4 bytes\n        // of the XOR of all function selectors in the interface.\n        // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165)\n        // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`)\n        return\n            interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165.\n            interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721.\n            interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata.\n    }\n\n    // =============================================================\n    //                        IERC721Metadata\n    // =============================================================\n\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() public view virtual override returns (string memory) {\n        return ERC721AStorage.layout()._name;\n    }\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return ERC721AStorage.layout()._symbol;\n    }\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();\n\n        string memory baseURI = _baseURI();\n        return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : '';\n    }\n\n    /**\n     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n     * by default, it can be overridden in child contracts.\n     */\n    function _baseURI() internal view virtual returns (string memory) {\n        return '';\n    }\n\n    // =============================================================\n    //                     OWNERSHIPS OPERATIONS\n    // =============================================================\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n        return address(uint160(_packedOwnershipOf(tokenId)));\n    }\n\n    /**\n     * @dev Gas spent here starts off proportional to the maximum mint batch size.\n     * It gradually moves to O(1) as tokens get transferred around over time.\n     */\n    function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) {\n        return _unpackedOwnership(_packedOwnershipOf(tokenId));\n    }\n\n    /**\n     * @dev Returns the unpacked `TokenOwnership` struct at `index`.\n     */\n    function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) {\n        return _unpackedOwnership(ERC721AStorage.layout()._packedOwnerships[index]);\n    }\n\n    /**\n     * @dev Initializes the ownership slot minted at `index` for efficiency purposes.\n     */\n    function _initializeOwnershipAt(uint256 index) internal virtual {\n        if (ERC721AStorage.layout()._packedOwnerships[index] == 0) {\n            ERC721AStorage.layout()._packedOwnerships[index] = _packedOwnershipOf(index);\n        }\n    }\n\n    /**\n     * Returns the packed ownership data of `tokenId`.\n     */\n    function _packedOwnershipOf(uint256 tokenId) private view returns (uint256 packed) {\n        if (_startTokenId() <= tokenId) {\n            packed = ERC721AStorage.layout()._packedOwnerships[tokenId];\n            // If not burned.\n            if (packed & _BITMASK_BURNED == 0) {\n                // If the data at the starting slot does not exist, start the scan.\n                if (packed == 0) {\n                    if (tokenId >= ERC721AStorage.layout()._currentIndex) revert OwnerQueryForNonexistentToken();\n                    // Invariant:\n                    // There will always be an initialized ownership slot\n                    // (i.e. `ownership.addr != address(0) && ownership.burned == false`)\n                    // before an unintialized ownership slot\n                    // (i.e. `ownership.addr == address(0) && ownership.burned == false`)\n                    // Hence, `tokenId` will not underflow.\n                    //\n                    // We can directly compare the packed value.\n                    // If the address is zero, packed will be zero.\n                    for (;;) {\n                        unchecked {\n                            packed = ERC721AStorage.layout()._packedOwnerships[--tokenId];\n                        }\n                        if (packed == 0) continue;\n                        return packed;\n                    }\n                }\n                // Otherwise, the data exists and is not burned. We can skip the scan.\n                // This is possible because we have already achieved the target condition.\n                // This saves 2143 gas on transfers of initialized tokens.\n                return packed;\n            }\n        }\n        revert OwnerQueryForNonexistentToken();\n    }\n\n    /**\n     * @dev Returns the unpacked `TokenOwnership` struct from `packed`.\n     */\n    function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) {\n        ownership.addr = address(uint160(packed));\n        ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP);\n        ownership.burned = packed & _BITMASK_BURNED != 0;\n        ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA);\n    }\n\n    /**\n     * @dev Packs ownership data into a single uint256.\n     */\n    function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) {\n        assembly {\n            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.\n            owner := and(owner, _BITMASK_ADDRESS)\n            // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`.\n            result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags))\n        }\n    }\n\n    /**\n     * @dev Returns the `nextInitialized` flag set if `quantity` equals 1.\n     */\n    function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) {\n        // For branchless setting of the `nextInitialized` flag.\n        assembly {\n            // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`.\n            result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1))\n        }\n    }\n\n    // =============================================================\n    //                      APPROVAL OPERATIONS\n    // =============================================================\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account. See {ERC721A-_approve}.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     */\n    function approve(address to, uint256 tokenId) public payable virtual override {\n        _approve(to, tokenId, true);\n    }\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\n        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();\n\n        return ERC721AStorage.layout()._tokenApprovals[tokenId].value;\n    }\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom}\n     * for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) public virtual override {\n        ERC721AStorage.layout()._operatorApprovals[_msgSenderERC721A()][operator] = approved;\n        emit ApprovalForAll(_msgSenderERC721A(), operator, approved);\n    }\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}.\n     */\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n        return ERC721AStorage.layout()._operatorApprovals[owner][operator];\n    }\n\n    /**\n     * @dev Returns whether `tokenId` exists.\n     *\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n     *\n     * Tokens start existing when they are minted. See {_mint}.\n     */\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\n        return\n            _startTokenId() <= tokenId &&\n            tokenId < ERC721AStorage.layout()._currentIndex && // If within bounds,\n            ERC721AStorage.layout()._packedOwnerships[tokenId] & _BITMASK_BURNED == 0; // and not burned.\n    }\n\n    /**\n     * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`.\n     */\n    function _isSenderApprovedOrOwner(\n        address approvedAddress,\n        address owner,\n        address msgSender\n    ) private pure returns (bool result) {\n        assembly {\n            // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.\n            owner := and(owner, _BITMASK_ADDRESS)\n            // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean.\n            msgSender := and(msgSender, _BITMASK_ADDRESS)\n            // `msgSender == owner || msgSender == approvedAddress`.\n            result := or(eq(msgSender, owner), eq(msgSender, approvedAddress))\n        }\n    }\n\n    /**\n     * @dev Returns the storage slot and value for the approved address of `tokenId`.\n     */\n    function _getApprovedSlotAndAddress(uint256 tokenId)\n        private\n        view\n        returns (uint256 approvedAddressSlot, address approvedAddress)\n    {\n        ERC721AStorage.TokenApprovalRef storage tokenApproval = ERC721AStorage.layout()._tokenApprovals[tokenId];\n        // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`.\n        assembly {\n            approvedAddressSlot := tokenApproval.slot\n            approvedAddress := sload(approvedAddressSlot)\n        }\n    }\n\n    // =============================================================\n    //                      TRANSFER OPERATIONS\n    // =============================================================\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token\n     * by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) public payable virtual override {\n        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);\n\n        if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner();\n\n        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);\n\n        // The nested ifs save around 20+ gas over a compound boolean condition.\n        if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))\n            if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();\n\n        if (to == address(0)) revert TransferToZeroAddress();\n\n        _beforeTokenTransfers(from, to, tokenId, 1);\n\n        // Clear approvals from the previous owner.\n        assembly {\n            if approvedAddress {\n                // This is equivalent to `delete _tokenApprovals[tokenId]`.\n                sstore(approvedAddressSlot, 0)\n            }\n        }\n\n        // Underflow of the sender's balance is impossible because we check for\n        // ownership above and the recipient's balance can't realistically overflow.\n        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.\n        unchecked {\n            // We can directly increment and decrement the balances.\n            --ERC721AStorage.layout()._packedAddressData[from]; // Updates: `balance -= 1`.\n            ++ERC721AStorage.layout()._packedAddressData[to]; // Updates: `balance += 1`.\n\n            // Updates:\n            // - `address` to the next owner.\n            // - `startTimestamp` to the timestamp of transfering.\n            // - `burned` to `false`.\n            // - `nextInitialized` to `true`.\n            ERC721AStorage.layout()._packedOwnerships[tokenId] = _packOwnershipData(\n                to,\n                _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked)\n            );\n\n            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .\n            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {\n                uint256 nextTokenId = tokenId + 1;\n                // If the next slot's address is zero and not burned (i.e. packed value is zero).\n                if (ERC721AStorage.layout()._packedOwnerships[nextTokenId] == 0) {\n                    // If the next slot is within bounds.\n                    if (nextTokenId != ERC721AStorage.layout()._currentIndex) {\n                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.\n                        ERC721AStorage.layout()._packedOwnerships[nextTokenId] = prevOwnershipPacked;\n                    }\n                }\n            }\n        }\n\n        emit Transfer(from, to, tokenId);\n        _afterTokenTransfers(from, to, tokenId, 1);\n    }\n\n    /**\n     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) public payable virtual override {\n        safeTransferFrom(from, to, tokenId, '');\n    }\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token\n     * by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement\n     * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory _data\n    ) public payable virtual override {\n        transferFrom(from, to, tokenId);\n        if (to.code.length != 0)\n            if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {\n                revert TransferToNonERC721ReceiverImplementer();\n            }\n    }\n\n    /**\n     * @dev Hook that is called before a set of serially-ordered token IDs\n     * are about to be transferred. This includes minting.\n     * And also called before burning one token.\n     *\n     * `startTokenId` - the first token ID to be transferred.\n     * `quantity` - the amount to be transferred.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be\n     * transferred to `to`.\n     * - When `from` is zero, `tokenId` will be minted for `to`.\n     * - When `to` is zero, `tokenId` will be burned by `from`.\n     * - `from` and `to` are never both zero.\n     */\n    function _beforeTokenTransfers(\n        address from,\n        address to,\n        uint256 startTokenId,\n        uint256 quantity\n    ) internal virtual {}\n\n    /**\n     * @dev Hook that is called after a set of serially-ordered token IDs\n     * have been transferred. This includes minting.\n     * And also called after one token has been burned.\n     *\n     * `startTokenId` - the first token ID to be transferred.\n     * `quantity` - the amount to be transferred.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been\n     * transferred to `to`.\n     * - When `from` is zero, `tokenId` has been minted for `to`.\n     * - When `to` is zero, `tokenId` has been burned by `from`.\n     * - `from` and `to` are never both zero.\n     */\n    function _afterTokenTransfers(\n        address from,\n        address to,\n        uint256 startTokenId,\n        uint256 quantity\n    ) internal virtual {}\n\n    /**\n     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract.\n     *\n     * `from` - Previous owner of the given token ID.\n     * `to` - Target address that will receive the token.\n     * `tokenId` - Token ID to be transferred.\n     * `_data` - Optional data to send along with the call.\n     *\n     * Returns whether the call correctly returned the expected magic value.\n     */\n    function _checkContractOnERC721Received(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory _data\n    ) private returns (bool) {\n        try\n            ERC721A__IERC721ReceiverUpgradeable(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data)\n        returns (bytes4 retval) {\n            return retval == ERC721A__IERC721ReceiverUpgradeable(to).onERC721Received.selector;\n        } catch (bytes memory reason) {\n            if (reason.length == 0) {\n                revert TransferToNonERC721ReceiverImplementer();\n            } else {\n                assembly {\n                    revert(add(32, reason), mload(reason))\n                }\n            }\n        }\n    }\n\n    // =============================================================\n    //                        MINT OPERATIONS\n    // =============================================================\n\n    /**\n     * @dev Mints `quantity` tokens and transfers them to `to`.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `quantity` must be greater than 0.\n     *\n     * Emits a {Transfer} event for each mint.\n     */\n    function _mint(address to, uint256 quantity) internal virtual {\n        uint256 startTokenId = ERC721AStorage.layout()._currentIndex;\n        if (quantity == 0) revert MintZeroQuantity();\n\n        _beforeTokenTransfers(address(0), to, startTokenId, quantity);\n\n        // Overflows are incredibly unrealistic.\n        // `balance` and `numberMinted` have a maximum limit of 2**64.\n        // `tokenId` has a maximum limit of 2**256.\n        unchecked {\n            // Updates:\n            // - `balance += quantity`.\n            // - `numberMinted += quantity`.\n            //\n            // We can directly add to the `balance` and `numberMinted`.\n            ERC721AStorage.layout()._packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);\n\n            // Updates:\n            // - `address` to the owner.\n            // - `startTimestamp` to the timestamp of minting.\n            // - `burned` to `false`.\n            // - `nextInitialized` to `quantity == 1`.\n            ERC721AStorage.layout()._packedOwnerships[startTokenId] = _packOwnershipData(\n                to,\n                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)\n            );\n\n            uint256 toMasked;\n            uint256 end = startTokenId + quantity;\n\n            // Use assembly to loop and emit the `Transfer` event for gas savings.\n            // The duplicated `log4` removes an extra check and reduces stack juggling.\n            // The assembly, together with the surrounding Solidity code, have been\n            // delicately arranged to nudge the compiler into producing optimized opcodes.\n            assembly {\n                // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.\n                toMasked := and(to, _BITMASK_ADDRESS)\n                // Emit the `Transfer` event.\n                log4(\n                    0, // Start of data (0, since no data).\n                    0, // End of data (0, since no data).\n                    _TRANSFER_EVENT_SIGNATURE, // Signature.\n                    0, // `address(0)`.\n                    toMasked, // `to`.\n                    startTokenId // `tokenId`.\n                )\n\n                // The `iszero(eq(,))` check ensures that large values of `quantity`\n                // that overflows uint256 will make the loop run out of gas.\n                // The compiler will optimize the `iszero` away for performance.\n                for {\n                    let tokenId := add(startTokenId, 1)\n                } iszero(eq(tokenId, end)) {\n                    tokenId := add(tokenId, 1)\n                } {\n                    // Emit the `Transfer` event. Similar to above.\n                    log4(0, 0, _TRANSFER_EVENT_SIGNATURE, 0, toMasked, tokenId)\n                }\n            }\n            if (toMasked == 0) revert MintToZeroAddress();\n\n            ERC721AStorage.layout()._currentIndex = end;\n        }\n        _afterTokenTransfers(address(0), to, startTokenId, quantity);\n    }\n\n    /**\n     * @dev Mints `quantity` tokens and transfers them to `to`.\n     *\n     * This function is intended for efficient minting only during contract creation.\n     *\n     * It emits only one {ConsecutiveTransfer} as defined in\n     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),\n     * instead of a sequence of {Transfer} event(s).\n     *\n     * Calling this function outside of contract creation WILL make your contract\n     * non-compliant with the ERC721 standard.\n     * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309\n     * {ConsecutiveTransfer} event is only permissible during contract creation.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `quantity` must be greater than 0.\n     *\n     * Emits a {ConsecutiveTransfer} event.\n     */\n    function _mintERC2309(address to, uint256 quantity) internal virtual {\n        uint256 startTokenId = ERC721AStorage.layout()._currentIndex;\n        if (to == address(0)) revert MintToZeroAddress();\n        if (quantity == 0) revert MintZeroQuantity();\n        if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) revert MintERC2309QuantityExceedsLimit();\n\n        _beforeTokenTransfers(address(0), to, startTokenId, quantity);\n\n        // Overflows are unrealistic due to the above check for `quantity` to be below the limit.\n        unchecked {\n            // Updates:\n            // - `balance += quantity`.\n            // - `numberMinted += quantity`.\n            //\n            // We can directly add to the `balance` and `numberMinted`.\n            ERC721AStorage.layout()._packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);\n\n            // Updates:\n            // - `address` to the owner.\n            // - `startTimestamp` to the timestamp of minting.\n            // - `burned` to `false`.\n            // - `nextInitialized` to `quantity == 1`.\n            ERC721AStorage.layout()._packedOwnerships[startTokenId] = _packOwnershipData(\n                to,\n                _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)\n            );\n\n            emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to);\n\n            ERC721AStorage.layout()._currentIndex = startTokenId + quantity;\n        }\n        _afterTokenTransfers(address(0), to, startTokenId, quantity);\n    }\n\n    /**\n     * @dev Safely mints `quantity` tokens and transfers them to `to`.\n     *\n     * Requirements:\n     *\n     * - If `to` refers to a smart contract, it must implement\n     * {IERC721Receiver-onERC721Received}, which is called for each safe transfer.\n     * - `quantity` must be greater than 0.\n     *\n     * See {_mint}.\n     *\n     * Emits a {Transfer} event for each mint.\n     */\n    function _safeMint(\n        address to,\n        uint256 quantity,\n        bytes memory _data\n    ) internal virtual {\n        _mint(to, quantity);\n\n        unchecked {\n            if (to.code.length != 0) {\n                uint256 end = ERC721AStorage.layout()._currentIndex;\n                uint256 index = end - quantity;\n                do {\n                    if (!_checkContractOnERC721Received(address(0), to, index++, _data)) {\n                        revert TransferToNonERC721ReceiverImplementer();\n                    }\n                } while (index < end);\n                // Reentrancy protection.\n                if (ERC721AStorage.layout()._currentIndex != end) revert();\n            }\n        }\n    }\n\n    /**\n     * @dev Equivalent to `_safeMint(to, quantity, '')`.\n     */\n    function _safeMint(address to, uint256 quantity) internal virtual {\n        _safeMint(to, quantity, '');\n    }\n\n    // =============================================================\n    //                       APPROVAL OPERATIONS\n    // =============================================================\n\n    /**\n     * @dev Equivalent to `_approve(to, tokenId, false)`.\n     */\n    function _approve(address to, uint256 tokenId) internal virtual {\n        _approve(to, tokenId, false);\n    }\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the\n     * zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function _approve(\n        address to,\n        uint256 tokenId,\n        bool approvalCheck\n    ) internal virtual {\n        address owner = ownerOf(tokenId);\n\n        if (approvalCheck)\n            if (_msgSenderERC721A() != owner)\n                if (!isApprovedForAll(owner, _msgSenderERC721A())) {\n                    revert ApprovalCallerNotOwnerNorApproved();\n                }\n\n        ERC721AStorage.layout()._tokenApprovals[tokenId].value = to;\n        emit Approval(owner, to, tokenId);\n    }\n\n    // =============================================================\n    //                        BURN OPERATIONS\n    // =============================================================\n\n    /**\n     * @dev Equivalent to `_burn(tokenId, false)`.\n     */\n    function _burn(uint256 tokenId) internal virtual {\n        _burn(tokenId, false);\n    }\n\n    /**\n     * @dev Destroys `tokenId`.\n     * The approval is cleared when the token is burned.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _burn(uint256 tokenId, bool approvalCheck) internal virtual {\n        uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);\n\n        address from = address(uint160(prevOwnershipPacked));\n\n        (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);\n\n        if (approvalCheck) {\n            // The nested ifs save around 20+ gas over a compound boolean condition.\n            if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))\n                if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved();\n        }\n\n        _beforeTokenTransfers(from, address(0), tokenId, 1);\n\n        // Clear approvals from the previous owner.\n        assembly {\n            if approvedAddress {\n                // This is equivalent to `delete _tokenApprovals[tokenId]`.\n                sstore(approvedAddressSlot, 0)\n            }\n        }\n\n        // Underflow of the sender's balance is impossible because we check for\n        // ownership above and the recipient's balance can't realistically overflow.\n        // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.\n        unchecked {\n            // Updates:\n            // - `balance -= 1`.\n            // - `numberBurned += 1`.\n            //\n            // We can directly decrement the balance, and increment the number burned.\n            // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.\n            ERC721AStorage.layout()._packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1;\n\n            // Updates:\n            // - `address` to the last owner.\n            // - `startTimestamp` to the timestamp of burning.\n            // - `burned` to `true`.\n            // - `nextInitialized` to `true`.\n            ERC721AStorage.layout()._packedOwnerships[tokenId] = _packOwnershipData(\n                from,\n                (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked)\n            );\n\n            // If the next slot may not have been initialized (i.e. `nextInitialized == false`) .\n            if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {\n                uint256 nextTokenId = tokenId + 1;\n                // If the next slot's address is zero and not burned (i.e. packed value is zero).\n                if (ERC721AStorage.layout()._packedOwnerships[nextTokenId] == 0) {\n                    // If the next slot is within bounds.\n                    if (nextTokenId != ERC721AStorage.layout()._currentIndex) {\n                        // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.\n                        ERC721AStorage.layout()._packedOwnerships[nextTokenId] = prevOwnershipPacked;\n                    }\n                }\n            }\n        }\n\n        emit Transfer(from, address(0), tokenId);\n        _afterTokenTransfers(from, address(0), tokenId, 1);\n\n        // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times.\n        unchecked {\n            ERC721AStorage.layout()._burnCounter++;\n        }\n    }\n\n    // =============================================================\n    //                     EXTRA DATA OPERATIONS\n    // =============================================================\n\n    /**\n     * @dev Directly sets the extra data for the ownership data `index`.\n     */\n    function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual {\n        uint256 packed = ERC721AStorage.layout()._packedOwnerships[index];\n        if (packed == 0) revert OwnershipNotInitializedForExtraData();\n        uint256 extraDataCasted;\n        // Cast `extraData` with assembly to avoid redundant masking.\n        assembly {\n            extraDataCasted := extraData\n        }\n        packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA);\n        ERC721AStorage.layout()._packedOwnerships[index] = packed;\n    }\n\n    /**\n     * @dev Called during each token transfer to set the 24bit `extraData` field.\n     * Intended to be overridden by the cosumer contract.\n     *\n     * `previousExtraData` - the value of `extraData` before transfer.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be\n     * transferred to `to`.\n     * - When `from` is zero, `tokenId` will be minted for `to`.\n     * - When `to` is zero, `tokenId` will be burned by `from`.\n     * - `from` and `to` are never both zero.\n     */\n    function _extraData(\n        address from,\n        address to,\n        uint24 previousExtraData\n    ) internal view virtual returns (uint24) {}\n\n    /**\n     * @dev Returns the next extra data for the packed ownership data.\n     * The returned result is shifted into position.\n     */\n    function _nextExtraData(\n        address from,\n        address to,\n        uint256 prevOwnershipPacked\n    ) private view returns (uint256) {\n        uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA);\n        return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA;\n    }\n\n    // =============================================================\n    //                       OTHER OPERATIONS\n    // =============================================================\n\n    /**\n     * @dev Returns the message sender (defaults to `msg.sender`).\n     *\n     * If you are writing GSN compatible contracts, you need to override this function.\n     */\n    function _msgSenderERC721A() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    /**\n     * @dev Converts a uint256 to its ASCII string decimal representation.\n     */\n    function _toString(uint256 value) internal pure virtual returns (string memory str) {\n        assembly {\n            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but\n            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.\n            // We will need 1 word for the trailing zeros padding, 1 word for the length,\n            // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.\n            let m := add(mload(0x40), 0xa0)\n            // Update the free memory pointer to allocate.\n            mstore(0x40, m)\n            // Assign the `str` to the end.\n            str := sub(m, 0x20)\n            // Zeroize the slot after the string.\n            mstore(str, 0)\n\n            // Cache the end of the memory to calculate the length later.\n            let end := str\n\n            // We write the string from rightmost digit to leftmost digit.\n            // The following is essentially a do-while loop that also handles the zero case.\n            // prettier-ignore\n            for { let temp := value } 1 {} {\n                str := sub(str, 1)\n                // Write the character to the pointer.\n                // The ASCII index of the '0' character is 48.\n                mstore8(str, add(48, mod(temp, 10)))\n                // Keep dividing `temp` until zero.\n                temp := div(temp, 10)\n                // prettier-ignore\n                if iszero(temp) { break }\n            }\n\n            let length := sub(end, str)\n            // Move the pointer 32 bytes leftwards to make room for the length.\n            str := sub(str, 0x20)\n            // Store the length.\n            mstore(str, length)\n        }\n    }\n}\n"
      },
      "erc721a-upgradeable/contracts/extensions/ERC4907AStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport {ERC4907AUpgradeable} from './ERC4907AUpgradeable.sol';\n\nlibrary ERC4907AStorage {\n    struct Layout {\n        // Mapping from token ID to user info.\n        //\n        // Bits Layout:\n        // - [0..159]   `user`\n        // - [160..223] `expires`\n        mapping(uint256 => uint256) _packedUserInfo;\n    }\n\n    bytes32 internal constant STORAGE_SLOT = keccak256('ERC721A.contracts.storage.ERC4907A');\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "erc721a-upgradeable/contracts/extensions/ERC4907AUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// ERC721A Contracts v4.2.3\n// Creator: Chiru Labs\n\npragma solidity ^0.8.4;\n\nimport './IERC4907AUpgradeable.sol';\nimport '../ERC721AUpgradeable.sol';\nimport {ERC4907AStorage} from './ERC4907AStorage.sol';\nimport '../ERC721A__Initializable.sol';\n\n/**\n * @title ERC4907A\n *\n * @dev [ERC4907](https://eips.ethereum.org/EIPS/eip-4907) compliant\n * extension of ERC721A, which allows owners and authorized addresses\n * to add a time-limited role with restricted permissions to ERC721 tokens.\n */\nabstract contract ERC4907AUpgradeable is ERC721A__Initializable, ERC721AUpgradeable, IERC4907AUpgradeable {\n    using ERC4907AStorage for ERC4907AStorage.Layout;\n\n    function __ERC4907A_init() internal onlyInitializingERC721A {\n        __ERC4907A_init_unchained();\n    }\n\n    function __ERC4907A_init_unchained() internal onlyInitializingERC721A {}\n\n    // The bit position of `expires` in packed user info.\n    uint256 private constant _BITPOS_EXPIRES = 160;\n\n    /**\n     * @dev Sets the `user` and `expires` for `tokenId`.\n     * The zero address indicates there is no user.\n     *\n     * Requirements:\n     *\n     * - The caller must own `tokenId` or be an approved operator.\n     */\n    function setUser(\n        uint256 tokenId,\n        address user,\n        uint64 expires\n    ) public virtual override {\n        // Require the caller to be either the token owner or an approved operator.\n        address owner = ownerOf(tokenId);\n        if (_msgSenderERC721A() != owner)\n            if (!isApprovedForAll(owner, _msgSenderERC721A()))\n                if (getApproved(tokenId) != _msgSenderERC721A()) revert SetUserCallerNotOwnerNorApproved();\n\n        ERC4907AStorage.layout()._packedUserInfo[tokenId] =\n            (uint256(expires) << _BITPOS_EXPIRES) |\n            uint256(uint160(user));\n\n        emit UpdateUser(tokenId, user, expires);\n    }\n\n    /**\n     * @dev Returns the user address for `tokenId`.\n     * The zero address indicates that there is no user or if the user is expired.\n     */\n    function userOf(uint256 tokenId) public view virtual override returns (address) {\n        uint256 packed = ERC4907AStorage.layout()._packedUserInfo[tokenId];\n        assembly {\n            // Branchless `packed *= (block.timestamp <= expires ? 1 : 0)`.\n            // If the `block.timestamp == expires`, the `lt` clause will be true\n            // if there is a non-zero user address in the lower 160 bits of `packed`.\n            packed := mul(\n                packed,\n                // `block.timestamp <= expires ? 1 : 0`.\n                lt(shl(_BITPOS_EXPIRES, timestamp()), packed)\n            )\n        }\n        return address(uint160(packed));\n    }\n\n    /**\n     * @dev Returns the user's expires of `tokenId`.\n     */\n    function userExpires(uint256 tokenId) public view virtual override returns (uint256) {\n        return ERC4907AStorage.layout()._packedUserInfo[tokenId] >> _BITPOS_EXPIRES;\n    }\n\n    /**\n     * @dev Override of {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId)\n        public\n        view\n        virtual\n        override(ERC721AUpgradeable, IERC721AUpgradeable)\n        returns (bool)\n    {\n        // The interface ID for ERC4907 is `0xad092b5c`,\n        // as defined in [ERC4907](https://eips.ethereum.org/EIPS/eip-4907).\n        return super.supportsInterface(interfaceId) || interfaceId == 0xad092b5c;\n    }\n\n    /**\n     * @dev Returns the user address for `tokenId`, ignoring the expiry status.\n     */\n    function _explicitUserOf(uint256 tokenId) internal view virtual returns (address) {\n        return address(uint160(ERC4907AStorage.layout()._packedUserInfo[tokenId]));\n    }\n}\n"
      },
      "erc721a-upgradeable/contracts/extensions/ERC721AQueryableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// ERC721A Contracts v4.2.3\n// Creator: Chiru Labs\n\npragma solidity ^0.8.4;\n\nimport './IERC721AQueryableUpgradeable.sol';\nimport '../ERC721AUpgradeable.sol';\nimport '../ERC721A__Initializable.sol';\n\n/**\n * @title ERC721AQueryable.\n *\n * @dev ERC721A subclass with convenience query functions.\n */\nabstract contract ERC721AQueryableUpgradeable is\n    ERC721A__Initializable,\n    ERC721AUpgradeable,\n    IERC721AQueryableUpgradeable\n{\n    function __ERC721AQueryable_init() internal onlyInitializingERC721A {\n        __ERC721AQueryable_init_unchained();\n    }\n\n    function __ERC721AQueryable_init_unchained() internal onlyInitializingERC721A {}\n\n    /**\n     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.\n     *\n     * If the `tokenId` is out of bounds:\n     *\n     * - `addr = address(0)`\n     * - `startTimestamp = 0`\n     * - `burned = false`\n     * - `extraData = 0`\n     *\n     * If the `tokenId` is burned:\n     *\n     * - `addr = <Address of owner before token was burned>`\n     * - `startTimestamp = <Timestamp when token was burned>`\n     * - `burned = true`\n     * - `extraData = <Extra data when token was burned>`\n     *\n     * Otherwise:\n     *\n     * - `addr = <Address of owner>`\n     * - `startTimestamp = <Timestamp of start of ownership>`\n     * - `burned = false`\n     * - `extraData = <Extra data at start of ownership>`\n     */\n    function explicitOwnershipOf(uint256 tokenId) public view virtual override returns (TokenOwnership memory) {\n        TokenOwnership memory ownership;\n        if (tokenId < _startTokenId() || tokenId >= _nextTokenId()) {\n            return ownership;\n        }\n        ownership = _ownershipAt(tokenId);\n        if (ownership.burned) {\n            return ownership;\n        }\n        return _ownershipOf(tokenId);\n    }\n\n    /**\n     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.\n     * See {ERC721AQueryable-explicitOwnershipOf}\n     */\n    function explicitOwnershipsOf(uint256[] calldata tokenIds)\n        external\n        view\n        virtual\n        override\n        returns (TokenOwnership[] memory)\n    {\n        unchecked {\n            uint256 tokenIdsLength = tokenIds.length;\n            TokenOwnership[] memory ownerships = new TokenOwnership[](tokenIdsLength);\n            for (uint256 i; i != tokenIdsLength; ++i) {\n                ownerships[i] = explicitOwnershipOf(tokenIds[i]);\n            }\n            return ownerships;\n        }\n    }\n\n    /**\n     * @dev Returns an array of token IDs owned by `owner`,\n     * in the range [`start`, `stop`)\n     * (i.e. `start <= tokenId < stop`).\n     *\n     * This function allows for tokens to be queried if the collection\n     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.\n     *\n     * Requirements:\n     *\n     * - `start < stop`\n     */\n    function tokensOfOwnerIn(\n        address owner,\n        uint256 start,\n        uint256 stop\n    ) external view virtual override returns (uint256[] memory) {\n        unchecked {\n            if (start >= stop) revert InvalidQueryRange();\n            uint256 tokenIdsIdx;\n            uint256 stopLimit = _nextTokenId();\n            // Set `start = max(start, _startTokenId())`.\n            if (start < _startTokenId()) {\n                start = _startTokenId();\n            }\n            // Set `stop = min(stop, stopLimit)`.\n            if (stop > stopLimit) {\n                stop = stopLimit;\n            }\n            uint256 tokenIdsMaxLength = balanceOf(owner);\n            // Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`,\n            // to cater for cases where `balanceOf(owner)` is too big.\n            if (start < stop) {\n                uint256 rangeLength = stop - start;\n                if (rangeLength < tokenIdsMaxLength) {\n                    tokenIdsMaxLength = rangeLength;\n                }\n            } else {\n                tokenIdsMaxLength = 0;\n            }\n            uint256[] memory tokenIds = new uint256[](tokenIdsMaxLength);\n            if (tokenIdsMaxLength == 0) {\n                return tokenIds;\n            }\n            // We need to call `explicitOwnershipOf(start)`,\n            // because the slot at `start` may not be initialized.\n            TokenOwnership memory ownership = explicitOwnershipOf(start);\n            address currOwnershipAddr;\n            // If the starting slot exists (i.e. not burned), initialize `currOwnershipAddr`.\n            // `ownership.address` will not be zero, as `start` is clamped to the valid token ID range.\n            if (!ownership.burned) {\n                currOwnershipAddr = ownership.addr;\n            }\n            for (uint256 i = start; i != stop && tokenIdsIdx != tokenIdsMaxLength; ++i) {\n                ownership = _ownershipAt(i);\n                if (ownership.burned) {\n                    continue;\n                }\n                if (ownership.addr != address(0)) {\n                    currOwnershipAddr = ownership.addr;\n                }\n                if (currOwnershipAddr == owner) {\n                    tokenIds[tokenIdsIdx++] = i;\n                }\n            }\n            // Downsize the array to fit.\n            assembly {\n                mstore(tokenIds, tokenIdsIdx)\n            }\n            return tokenIds;\n        }\n    }\n\n    /**\n     * @dev Returns an array of token IDs owned by `owner`.\n     *\n     * This function scans the ownership mapping and is O(`totalSupply`) in complexity.\n     * It is meant to be called off-chain.\n     *\n     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into\n     * multiple smaller scans if the collection is large enough to cause\n     * an out-of-gas error (10K collections should be fine).\n     */\n    function tokensOfOwner(address owner) external view virtual override returns (uint256[] memory) {\n        unchecked {\n            uint256 tokenIdsIdx;\n            address currOwnershipAddr;\n            uint256 tokenIdsLength = balanceOf(owner);\n            uint256[] memory tokenIds = new uint256[](tokenIdsLength);\n            TokenOwnership memory ownership;\n            for (uint256 i = _startTokenId(); tokenIdsIdx != tokenIdsLength; ++i) {\n                ownership = _ownershipAt(i);\n                if (ownership.burned) {\n                    continue;\n                }\n                if (ownership.addr != address(0)) {\n                    currOwnershipAddr = ownership.addr;\n                }\n                if (currOwnershipAddr == owner) {\n                    tokenIds[tokenIdsIdx++] = i;\n                }\n            }\n            return tokenIds;\n        }\n    }\n}\n"
      },
      "erc721a-upgradeable/contracts/extensions/IERC4907AUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// ERC721A Contracts v4.2.3\n// Creator: Chiru Labs\n\npragma solidity ^0.8.4;\n\nimport '../IERC721AUpgradeable.sol';\n\n/**\n * @dev Interface of ERC4907A.\n */\ninterface IERC4907AUpgradeable is IERC721AUpgradeable {\n    /**\n     * The caller must own the token or be an approved operator.\n     */\n    error SetUserCallerNotOwnerNorApproved();\n\n    /**\n     * @dev Emitted when the `user` of an NFT or the `expires` of the `user` is changed.\n     * The zero address for user indicates that there is no user address.\n     */\n    event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires);\n\n    /**\n     * @dev Sets the `user` and `expires` for `tokenId`.\n     * The zero address indicates there is no user.\n     *\n     * Requirements:\n     *\n     * - The caller must own `tokenId` or be an approved operator.\n     */\n    function setUser(\n        uint256 tokenId,\n        address user,\n        uint64 expires\n    ) external;\n\n    /**\n     * @dev Returns the user address for `tokenId`.\n     * The zero address indicates that there is no user or if the user is expired.\n     */\n    function userOf(uint256 tokenId) external view returns (address);\n\n    /**\n     * @dev Returns the user's expires of `tokenId`.\n     */\n    function userExpires(uint256 tokenId) external view returns (uint256);\n}\n"
      },
      "erc721a-upgradeable/contracts/extensions/IERC721AQueryableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// ERC721A Contracts v4.2.3\n// Creator: Chiru Labs\n\npragma solidity ^0.8.4;\n\nimport '../IERC721AUpgradeable.sol';\n\n/**\n * @dev Interface of ERC721AQueryable.\n */\ninterface IERC721AQueryableUpgradeable is IERC721AUpgradeable {\n    /**\n     * Invalid query range (`start` >= `stop`).\n     */\n    error InvalidQueryRange();\n\n    /**\n     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.\n     *\n     * If the `tokenId` is out of bounds:\n     *\n     * - `addr = address(0)`\n     * - `startTimestamp = 0`\n     * - `burned = false`\n     * - `extraData = 0`\n     *\n     * If the `tokenId` is burned:\n     *\n     * - `addr = <Address of owner before token was burned>`\n     * - `startTimestamp = <Timestamp when token was burned>`\n     * - `burned = true`\n     * - `extraData = <Extra data when token was burned>`\n     *\n     * Otherwise:\n     *\n     * - `addr = <Address of owner>`\n     * - `startTimestamp = <Timestamp of start of ownership>`\n     * - `burned = false`\n     * - `extraData = <Extra data at start of ownership>`\n     */\n    function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory);\n\n    /**\n     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.\n     * See {ERC721AQueryable-explicitOwnershipOf}\n     */\n    function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory);\n\n    /**\n     * @dev Returns an array of token IDs owned by `owner`,\n     * in the range [`start`, `stop`)\n     * (i.e. `start <= tokenId < stop`).\n     *\n     * This function allows for tokens to be queried if the collection\n     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.\n     *\n     * Requirements:\n     *\n     * - `start < stop`\n     */\n    function tokensOfOwnerIn(\n        address owner,\n        uint256 start,\n        uint256 stop\n    ) external view returns (uint256[] memory);\n\n    /**\n     * @dev Returns an array of token IDs owned by `owner`.\n     *\n     * This function scans the ownership mapping and is O(`totalSupply`) in complexity.\n     * It is meant to be called off-chain.\n     *\n     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into\n     * multiple smaller scans if the collection is large enough to cause\n     * an out-of-gas error (10K collections should be fine).\n     */\n    function tokensOfOwner(address owner) external view returns (uint256[] memory);\n}\n"
      },
      "erc721a-upgradeable/contracts/IERC721AUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// ERC721A Contracts v4.2.3\n// Creator: Chiru Labs\n\npragma solidity ^0.8.4;\n\n/**\n * @dev Interface of ERC721A.\n */\ninterface IERC721AUpgradeable {\n    /**\n     * The caller must own the token or be an approved operator.\n     */\n    error ApprovalCallerNotOwnerNorApproved();\n\n    /**\n     * The token does not exist.\n     */\n    error ApprovalQueryForNonexistentToken();\n\n    /**\n     * Cannot query the balance for the zero address.\n     */\n    error BalanceQueryForZeroAddress();\n\n    /**\n     * Cannot mint to the zero address.\n     */\n    error MintToZeroAddress();\n\n    /**\n     * The quantity of tokens minted must be more than zero.\n     */\n    error MintZeroQuantity();\n\n    /**\n     * The token does not exist.\n     */\n    error OwnerQueryForNonexistentToken();\n\n    /**\n     * The caller must own the token or be an approved operator.\n     */\n    error TransferCallerNotOwnerNorApproved();\n\n    /**\n     * The token must be owned by `from`.\n     */\n    error TransferFromIncorrectOwner();\n\n    /**\n     * Cannot safely transfer to a contract that does not implement the\n     * ERC721Receiver interface.\n     */\n    error TransferToNonERC721ReceiverImplementer();\n\n    /**\n     * Cannot transfer to the zero address.\n     */\n    error TransferToZeroAddress();\n\n    /**\n     * The token does not exist.\n     */\n    error URIQueryForNonexistentToken();\n\n    /**\n     * The `quantity` minted with ERC2309 exceeds the safety limit.\n     */\n    error MintERC2309QuantityExceedsLimit();\n\n    /**\n     * The `extraData` cannot be set on an unintialized ownership slot.\n     */\n    error OwnershipNotInitializedForExtraData();\n\n    // =============================================================\n    //                            STRUCTS\n    // =============================================================\n\n    struct TokenOwnership {\n        // The address of the owner.\n        address addr;\n        // Stores the start time of ownership with minimal overhead for tokenomics.\n        uint64 startTimestamp;\n        // Whether the token has been burned.\n        bool burned;\n        // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.\n        uint24 extraData;\n    }\n\n    // =============================================================\n    //                         TOKEN COUNTERS\n    // =============================================================\n\n    /**\n     * @dev Returns the total number of tokens in existence.\n     * Burned tokens will reduce the count.\n     * To get the total number of tokens minted, please see {_totalMinted}.\n     */\n    function totalSupply() external view returns (uint256);\n\n    // =============================================================\n    //                            IERC165\n    // =============================================================\n\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n\n    // =============================================================\n    //                            IERC721\n    // =============================================================\n\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables\n     * (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in `owner`'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`,\n     * checking first that contract recipients are aware of the ERC721 protocol\n     * to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be have been allowed to move\n     * this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement\n     * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes calldata data\n    ) external payable;\n\n    /**\n     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external payable;\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom}\n     * whenever possible.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token\n     * by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external payable;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the\n     * zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external payable;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom}\n     * for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool _approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}.\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n\n    // =============================================================\n    //                        IERC721Metadata\n    // =============================================================\n\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n\n    // =============================================================\n    //                           IERC2309\n    // =============================================================\n\n    /**\n     * @dev Emitted when tokens in `fromTokenId` to `toTokenId`\n     * (inclusive) is transferred from `from` to `to`, as defined in the\n     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.\n     *\n     * See {_mintERC2309} for more details.\n     */\n    event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);\n}\n"
      },
      "operator-filter-registry/src/IOperatorFilterRegistry.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\ninterface IOperatorFilterRegistry {\n    /**\n     * @notice Returns true if operator is not filtered for a given token, either by address or codeHash. Also returns\n     *         true if supplied registrant address is not registered.\n     */\n    function isOperatorAllowed(address registrant, address operator) external view returns (bool);\n\n    /**\n     * @notice Registers an address with the registry. May be called by address itself or by EIP-173 owner.\n     */\n    function register(address registrant) external;\n\n    /**\n     * @notice Registers an address with the registry and \"subscribes\" to another address's filtered operators and codeHashes.\n     */\n    function registerAndSubscribe(address registrant, address subscription) external;\n\n    /**\n     * @notice Registers an address with the registry and copies the filtered operators and codeHashes from another\n     *         address without subscribing.\n     */\n    function registerAndCopyEntries(address registrant, address registrantToCopy) external;\n\n    /**\n     * @notice Unregisters an address with the registry and removes its subscription. May be called by address itself or by EIP-173 owner.\n     *         Note that this does not remove any filtered addresses or codeHashes.\n     *         Also note that any subscriptions to this registrant will still be active and follow the existing filtered addresses and codehashes.\n     */\n    function unregister(address addr) external;\n\n    /**\n     * @notice Update an operator address for a registered address - when filtered is true, the operator is filtered.\n     */\n    function updateOperator(address registrant, address operator, bool filtered) external;\n\n    /**\n     * @notice Update multiple operators for a registered address - when filtered is true, the operators will be filtered. Reverts on duplicates.\n     */\n    function updateOperators(address registrant, address[] calldata operators, bool filtered) external;\n\n    /**\n     * @notice Update a codeHash for a registered address - when filtered is true, the codeHash is filtered.\n     */\n    function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;\n\n    /**\n     * @notice Update multiple codeHashes for a registered address - when filtered is true, the codeHashes will be filtered. Reverts on duplicates.\n     */\n    function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;\n\n    /**\n     * @notice Subscribe an address to another registrant's filtered operators and codeHashes. Will remove previous\n     *         subscription if present.\n     *         Note that accounts with subscriptions may go on to subscribe to other accounts - in this case,\n     *         subscriptions will not be forwarded. Instead the former subscription's existing entries will still be\n     *         used.\n     */\n    function subscribe(address registrant, address registrantToSubscribe) external;\n\n    /**\n     * @notice Unsubscribe an address from its current subscribed registrant, and optionally copy its filtered operators and codeHashes.\n     */\n    function unsubscribe(address registrant, bool copyExistingEntries) external;\n\n    /**\n     * @notice Get the subscription address of a given registrant, if any.\n     */\n    function subscriptionOf(address addr) external returns (address registrant);\n\n    /**\n     * @notice Get the set of addresses subscribed to a given registrant.\n     *         Note that order is not guaranteed as updates are made.\n     */\n    function subscribers(address registrant) external returns (address[] memory);\n\n    /**\n     * @notice Get the subscriber at a given index in the set of addresses subscribed to a given registrant.\n     *         Note that order is not guaranteed as updates are made.\n     */\n    function subscriberAt(address registrant, uint256 index) external returns (address);\n\n    /**\n     * @notice Copy filtered operators and codeHashes from a different registrantToCopy to addr.\n     */\n    function copyEntriesOf(address registrant, address registrantToCopy) external;\n\n    /**\n     * @notice Returns true if operator is filtered by a given address or its subscription.\n     */\n    function isOperatorFiltered(address registrant, address operator) external returns (bool);\n\n    /**\n     * @notice Returns true if the hash of an address's code is filtered by a given address or its subscription.\n     */\n    function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);\n\n    /**\n     * @notice Returns true if a codeHash is filtered by a given address or its subscription.\n     */\n    function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);\n\n    /**\n     * @notice Returns a list of filtered operators for a given address or its subscription.\n     */\n    function filteredOperators(address addr) external returns (address[] memory);\n\n    /**\n     * @notice Returns the set of filtered codeHashes for a given address or its subscription.\n     *         Note that order is not guaranteed as updates are made.\n     */\n    function filteredCodeHashes(address addr) external returns (bytes32[] memory);\n\n    /**\n     * @notice Returns the filtered operator at the given index of the set of filtered operators for a given address or\n     *         its subscription.\n     *         Note that order is not guaranteed as updates are made.\n     */\n    function filteredOperatorAt(address registrant, uint256 index) external returns (address);\n\n    /**\n     * @notice Returns the filtered codeHash at the given index of the list of filtered codeHashes for a given address or\n     *         its subscription.\n     *         Note that order is not guaranteed as updates are made.\n     */\n    function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);\n\n    /**\n     * @notice Returns true if an address has registered\n     */\n    function isRegistered(address addr) external returns (bool);\n\n    /**\n     * @dev Convenience method to compute the code hash of an arbitrary contract\n     */\n    function codeHashOf(address addr) external returns (bytes32);\n}\n"
      },
      "operator-filter-registry/src/upgradeable/OperatorFiltererUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\nimport {IOperatorFilterRegistry} from \"../IOperatorFilterRegistry.sol\";\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\n/**\n * @title  OperatorFiltererUpgradeable\n * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another\n *         registrant's entries in the OperatorFilterRegistry when the init function is called.\n * @dev    This smart contract is meant to be inherited by token contracts so they can use the following:\n *         - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods.\n *         - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods.\n */\nabstract contract OperatorFiltererUpgradeable is Initializable {\n    /// @notice Emitted when an operator is not allowed.\n    error OperatorNotAllowed(address operator);\n\n    IOperatorFilterRegistry constant OPERATOR_FILTER_REGISTRY =\n        IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);\n\n    /// @dev The upgradeable initialize function that should be called when the contract is being upgraded.\n    function __OperatorFilterer_init(address subscriptionOrRegistrantToCopy, bool subscribe)\n        internal\n        onlyInitializing\n    {\n        // If an inheriting token contract is deployed to a network without the registry deployed, the modifier\n        // will not revert, but the contract will need to be registered with the registry once it is deployed in\n        // order for the modifier to filter addresses.\n        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {\n            if (!OPERATOR_FILTER_REGISTRY.isRegistered(address(this))) {\n                if (subscribe) {\n                    OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);\n                } else {\n                    if (subscriptionOrRegistrantToCopy != address(0)) {\n                        OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy);\n                    } else {\n                        OPERATOR_FILTER_REGISTRY.register(address(this));\n                    }\n                }\n            }\n        }\n    }\n\n    /**\n     * @dev A helper modifier to check if the operator is allowed.\n     */\n    modifier onlyAllowedOperator(address from) virtual {\n        // Allow spending tokens from addresses with balance\n        // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred\n        // from an EOA.\n        if (from != msg.sender) {\n            _checkFilterOperator(msg.sender);\n        }\n        _;\n    }\n\n    /**\n     * @dev A helper modifier to check if the operator approval is allowed.\n     */\n    modifier onlyAllowedOperatorApproval(address operator) virtual {\n        _checkFilterOperator(operator);\n        _;\n    }\n\n    /**\n     * @dev A helper function to check if the operator is allowed.\n     */\n    function _checkFilterOperator(address operator) internal view virtual {\n        // Check registry code length to facilitate testing in environments without a deployed registry.\n        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {\n            // under normal circumstances, this function will revert rather than return false, but inheriting or\n            // upgraded contracts may specify their own OperatorFilterRegistry implementations, which may behave\n            // differently\n            if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) {\n                revert OperatorNotAllowed(operator);\n            }\n        }\n    }\n}\n"
      },
      "operator-filter-registry/src/upgradeable/RevokableOperatorFiltererUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\nimport {OperatorFiltererUpgradeable} from \"./OperatorFiltererUpgradeable.sol\";\n\n/**\n * @title  Upgradeable storage layout for RevokableOperatorFiltererUpgradeable.\n * @notice Upgradeable contracts must use a storage layout that can be used across upgrades.\n *         Only append new variables to the end of the layout.\n */\nlibrary RevokableOperatorFiltererUpgradeableStorage {\n    struct Layout {\n        /// @dev Whether the OperatorFilterRegistry has been revoked.\n        bool _isOperatorFilterRegistryRevoked;\n    }\n\n    /// @dev The storage slot for the layout.\n    bytes32 internal constant STORAGE_SLOT = keccak256(\"RevokableOperatorFiltererUpgradeable.contracts.storage\");\n\n    /// @dev The layout of the storage.\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n\n/**\n * @title  RevokableOperatorFilterer\n * @notice This contract is meant to allow contracts to permanently opt out of the OperatorFilterRegistry. The Registry\n *         itself has an \"unregister\" function, but if the contract is ownable, the owner can re-register at any point.\n *         As implemented, this abstract contract allows the contract owner to toggle the\n *         isOperatorFilterRegistryRevoked flag in order to permanently bypass the OperatorFilterRegistry checks.\n */\nabstract contract RevokableOperatorFiltererUpgradeable is OperatorFiltererUpgradeable {\n    using RevokableOperatorFiltererUpgradeableStorage for RevokableOperatorFiltererUpgradeableStorage.Layout;\n\n    error OnlyOwner();\n    error AlreadyRevoked();\n\n    event OperatorFilterRegistryRevoked();\n\n    function __RevokableOperatorFilterer_init(address subscriptionOrRegistrantToCopy, bool subscribe) internal {\n        OperatorFiltererUpgradeable.__OperatorFilterer_init(subscriptionOrRegistrantToCopy, subscribe);\n    }\n\n    /**\n     * @dev A helper function to check if the operator is allowed.\n     */\n    function _checkFilterOperator(address operator) internal view virtual override {\n        // Check registry code length to facilitate testing in environments without a deployed registry.\n        if (\n            !RevokableOperatorFiltererUpgradeableStorage.layout()._isOperatorFilterRegistryRevoked\n                && address(OPERATOR_FILTER_REGISTRY).code.length > 0\n        ) {\n            // under normal circumstances, this function will revert rather than return false, but inheriting or\n            // upgraded contracts may specify their own OperatorFilterRegistry implementations, which may behave\n            // differently\n            if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) {\n                revert OperatorNotAllowed(operator);\n            }\n        }\n    }\n\n    /**\n     * @notice Disable the isOperatorFilterRegistryRevoked flag. OnlyOwner.\n     */\n    function revokeOperatorFilterRegistry() external {\n        if (msg.sender != owner()) {\n            revert OnlyOwner();\n        }\n        if (RevokableOperatorFiltererUpgradeableStorage.layout()._isOperatorFilterRegistryRevoked) {\n            revert AlreadyRevoked();\n        }\n        RevokableOperatorFiltererUpgradeableStorage.layout()._isOperatorFilterRegistryRevoked = true;\n        emit OperatorFilterRegistryRevoked();\n    }\n\n    function isOperatorFilterRegistryRevoked() public view returns (bool) {\n        return RevokableOperatorFiltererUpgradeableStorage.layout()._isOperatorFilterRegistryRevoked;\n    }\n\n    /**\n     * @dev assume the contract has an owner, but leave specific Ownable implementation up to inheriting contract\n     */\n    function owner() public view virtual returns (address);\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 10000
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    }
  }}