creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@synthetixio/core-contracts/contracts/errors/AccessError.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title Library for access related errors.\n */\nlibrary AccessError {\n    /**\n     * @dev Thrown when an address tries to perform an unauthorized action.\n     * @param addr The address that attempts the action.\n     */\n    error Unauthorized(address addr);\n}\n"
      },
      "@synthetixio/core-contracts/contracts/errors/AddressError.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title Library for address related errors.\n */\nlibrary AddressError {\n    /**\n     * @dev Thrown when a zero address was passed as a function parameter (0x0000000000000000000000000000000000000000).\n     */\n    error ZeroAddress();\n\n    /**\n     * @dev Thrown when an address representing a contract is expected, but no code is found at the address.\n     * @param contr The address that was expected to be a contract.\n     */\n    error NotAContract(address contr);\n}\n"
      },
      "@synthetixio/core-contracts/contracts/errors/InitError.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title Library for initialization related errors.\n */\nlibrary InitError {\n    /**\n     * @dev Thrown when attempting to initialize a contract that is already initialized.\n     */\n    error AlreadyInitialized();\n\n    /**\n     * @dev Thrown when attempting to interact with a contract that has not been initialized yet.\n     */\n    error NotInitialized();\n}\n"
      },
      "@synthetixio/core-contracts/contracts/errors/ParameterError.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title Library for errors related with expected function parameters.\n */\nlibrary ParameterError {\n    /**\n     * @dev Thrown when an invalid parameter is used in a function.\n     * @param parameter The name of the parameter.\n     * @param reason The reason why the received parameter is invalid.\n     */\n    error InvalidParameter(string parameter, string reason);\n}\n"
      },
      "@synthetixio/core-contracts/contracts/initializable/InitializableMixin.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"../errors/InitError.sol\";\n\n/**\n * @title Mixin for contracts that require initialization.\n */\nabstract contract InitializableMixin {\n    /**\n     * @dev Reverts if contract is not initialized.\n     */\n    modifier onlyIfInitialized() {\n        if (!_isInitialized()) {\n            revert InitError.NotInitialized();\n        }\n\n        _;\n    }\n\n    /**\n     * @dev Reverts if contract is already initialized.\n     */\n    modifier onlyIfNotInitialized() {\n        if (_isInitialized()) {\n            revert InitError.AlreadyInitialized();\n        }\n\n        _;\n    }\n\n    /**\n     * @dev Override this function to determine if the contract is initialized.\n     * @return True if initialized, false otherwise.\n     */\n    function _isInitialized() internal view virtual returns (bool);\n}\n"
      },
      "@synthetixio/core-contracts/contracts/interfaces/IERC165.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title ERC165 interface for determining if a contract supports a given interface.\n */\ninterface IERC165 {\n    /**\n     * @notice Determines if the contract in question supports the specified interface.\n     * @param interfaceID XOR of all selectors in the contract.\n     * @return True if the contract supports the specified interface.\n     */\n    function supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"
      },
      "@synthetixio/core-contracts/contracts/interfaces/IERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title ERC721 non-fungible token (NFT) contract.\n */\ninterface IERC721 {\n    /**\n     * @notice Thrown when an address attempts to provide allowance to itself.\n     * @param addr The address attempting to provide allowance.\n     */\n    error CannotSelfApprove(address addr);\n\n    /**\n     * @notice Thrown when attempting to transfer a token to an address that does not satisfy IERC721Receiver requirements.\n     * @param addr The address that cannot receive the tokens.\n     */\n    error InvalidTransferRecipient(address addr);\n\n    /**\n     * @notice Thrown when attempting to specify an owner which is not valid (ex. the 0x00000... address)\n     */\n    error InvalidOwner(address addr);\n\n    /**\n     * @notice Thrown when attempting to operate on a token id that does not exist.\n     * @param id The token id that does not exist.\n     */\n    error TokenDoesNotExist(uint256 id);\n\n    /**\n     * @notice Thrown when attempting to mint a token that already exists.\n     * @param id The token id that already exists.\n     */\n    error TokenAlreadyMinted(uint256 id);\n\n    /**\n     * @notice 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     * @notice 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     * @notice 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     * @notice Returns the number of tokens in ``owner``'s account.\n     *\n     * Requirements:\n     *\n     * - `holder` must be a valid address\n     */\n    function balanceOf(address holder) external view returns (uint256 balance);\n\n    /**\n     * @notice 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     * @notice 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     * @notice 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(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @notice Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} 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 by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @notice 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     * @notice 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     * @notice 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     * @notice 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"
      },
      "@synthetixio/core-contracts/contracts/interfaces/IERC721Enumerable.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"./IERC721.sol\";\n\n/**\n * @title ERC721 extension with helper functions that allow the enumeration of NFT tokens.\n */\ninterface IERC721Enumerable is IERC721 {\n    /**\n     * @notice Thrown calling *ByIndex function with an index greater than the number of tokens existing\n     * @param requestedIndex The index requested by the caller\n     * @param length The length of the list that is being iterated, making the max index queryable length - 1\n     */\n    error IndexOverrun(uint requestedIndex, uint length);\n\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     * Requirements:\n     * - `owner` must be a valid address\n     * - `index` must be less than the balance of the tokens for the owner\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     * Requirements:\n     * - `index` must be less than the total supply of the tokens\n     */\n    function tokenByIndex(uint256 index) external view returns (uint256);\n}\n"
      },
      "@synthetixio/core-contracts/contracts/interfaces/IERC721Metadata.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @title Additional metadata for IERC721 tokens.\n */\ninterface IERC721Metadata is IERC165 {\n    /**\n     * @notice Retrieves the name of the token, e.g. \"Synthetix Account Token\".\n     * @return A string with the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @notice Retrieves the symbol of the token, e.g. \"SNX-ACC\".\n     * @return A string with the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @notice Retrieves the off-chain URI where the specified token id may contain associated data, such as images, audio, etc.\n     * @param tokenId The numeric id of the token in question.\n     * @return The URI of the token in question.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
      },
      "@synthetixio/core-contracts/contracts/interfaces/IERC721Receiver.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title ERC721 extension that allows contracts to receive tokens with `safeTransferFrom`.\n */\ninterface IERC721Receiver {\n    /**\n     * @notice Function that will be called by ERC721 tokens implementing the `safeTransferFrom` function.\n     * @dev The contract transferring the token will revert if the receiving contract does not implement this function.\n     * @param operator The address that is executing the transfer.\n     * @param from The address whose token is being transferred.\n     * @param tokenId The numeric id of the token being transferred.\n     * @param data Optional additional data that may be passed by the operator, and could be used by the implementing contract.\n     * @return The selector of this function (IERC721Receiver.onERC721Received.selector). Caller will revert if not returned.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes memory data\n    ) external returns (bytes4);\n}\n"
      },
      "@synthetixio/core-contracts/contracts/ownership/OwnableStorage.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"../errors/AccessError.sol\";\n\nlibrary OwnableStorage {\n    bytes32 private constant _SLOT_OWNABLE_STORAGE =\n        keccak256(abi.encode(\"io.synthetix.core-contracts.Ownable\"));\n\n    struct Data {\n        address owner;\n        address nominatedOwner;\n    }\n\n    function load() internal pure returns (Data storage store) {\n        bytes32 s = _SLOT_OWNABLE_STORAGE;\n        assembly {\n            store.slot := s\n        }\n    }\n\n    function onlyOwner() internal view {\n        if (msg.sender != getOwner()) {\n            revert AccessError.Unauthorized(msg.sender);\n        }\n    }\n\n    function getOwner() internal view returns (address) {\n        return OwnableStorage.load().owner;\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/token/ERC721.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"../interfaces/IERC721.sol\";\nimport \"../interfaces/IERC721Metadata.sol\";\nimport \"../interfaces/IERC721Receiver.sol\";\nimport \"../errors/AddressError.sol\";\nimport \"../errors/AccessError.sol\";\nimport \"../errors/InitError.sol\";\nimport \"../errors/ParameterError.sol\";\nimport \"./ERC721Storage.sol\";\nimport \"../utils/AddressUtil.sol\";\nimport \"../utils/StringUtil.sol\";\nimport \"../utils/ERC2771Context.sol\";\n\n/*\n * @title ERC721 non-fungible token (NFT) contract.\n * See IERC721.\n *\n * Reference implementations:\n * - OpenZeppelin - https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol\n */\ncontract ERC721 is IERC721, IERC721Metadata {\n    /**\n     * @inheritdoc IERC165\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return\n            interfaceId == this.supportsInterface.selector || // ERC165\n            interfaceId == type(IERC721).interfaceId ||\n            interfaceId == type(IERC721Metadata).interfaceId;\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function balanceOf(address holder) public view virtual override returns (uint balance) {\n        if (holder == address(0)) {\n            revert InvalidOwner(holder);\n        }\n\n        return ERC721Storage.load().balanceOf[holder];\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n        if (!_exists(tokenId)) {\n            revert TokenDoesNotExist(tokenId);\n        }\n\n        return ERC721Storage.load().ownerOf[tokenId];\n    }\n\n    /**\n     * @inheritdoc IERC721Metadata\n     */\n    function name() external view virtual override returns (string memory) {\n        return ERC721Storage.load().name;\n    }\n\n    /**\n     * @inheritdoc IERC721Metadata\n     */\n    function symbol() external view virtual override returns (string memory) {\n        return ERC721Storage.load().symbol;\n    }\n\n    /**\n     * @inheritdoc IERC721Metadata\n     */\n    function tokenURI(uint256 tokenId) external view virtual override returns (string memory) {\n        if (!_exists(tokenId)) {\n            revert TokenDoesNotExist(tokenId);\n        }\n\n        string memory baseURI = ERC721Storage.load().baseTokenURI;\n\n        return\n            bytes(baseURI).length > 0\n                ? string(abi.encodePacked(baseURI, StringUtil.uintToString(tokenId)))\n                : \"\";\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n\n    function approve(address to, uint256 tokenId) public virtual override {\n        ERC721Storage.Data storage store = ERC721Storage.load();\n        address holder = store.ownerOf[tokenId];\n\n        if (to == holder) {\n            revert CannotSelfApprove(to);\n        }\n\n        if (\n            ERC2771Context._msgSender() != holder &&\n            !isApprovedForAll(holder, ERC2771Context._msgSender())\n        ) {\n            revert AccessError.Unauthorized(ERC2771Context._msgSender());\n        }\n\n        _approve(to, tokenId);\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function getApproved(uint256 tokenId) public view virtual override returns (address operator) {\n        if (!_exists(tokenId)) {\n            revert TokenDoesNotExist(tokenId);\n        }\n\n        return ERC721Storage.load().tokenApprovals[tokenId];\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n\n    function setApprovalForAll(address operator, bool approved) public virtual override {\n        if (ERC2771Context._msgSender() == operator) {\n            revert CannotSelfApprove(operator);\n        }\n\n        ERC721Storage.load().operatorApprovals[ERC2771Context._msgSender()][operator] = approved;\n\n        emit ApprovalForAll(ERC2771Context._msgSender(), operator, approved);\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n    function isApprovedForAll(\n        address holder,\n        address operator\n    ) public view virtual override returns (bool) {\n        return ERC721Storage.load().operatorApprovals[holder][operator];\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n\n    function transferFrom(address from, address to, uint256 tokenId) public virtual override {\n        if (!_isApprovedOrOwner(ERC2771Context._msgSender(), tokenId)) {\n            revert AccessError.Unauthorized(ERC2771Context._msgSender());\n        }\n\n        _transfer(from, to, tokenId);\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n\n    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @inheritdoc IERC721\n     */\n\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) public virtual override {\n        if (!_isApprovedOrOwner(ERC2771Context._msgSender(), tokenId)) {\n            revert AccessError.Unauthorized(ERC2771Context._msgSender());\n        }\n\n        _transfer(from, to, tokenId);\n        if (!_checkOnERC721Received(from, to, tokenId, data)) {\n            revert InvalidTransferRecipient(to);\n        }\n    }\n\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\n        return ERC721Storage.load().ownerOf[tokenId] != address(0);\n    }\n\n    function _isApprovedOrOwner(\n        address spender,\n        uint256 tokenId\n    ) internal view virtual returns (bool) {\n        address holder = ownerOf(tokenId);\n\n        // Not checking tokenId existence since it is checked in ownerOf() and getApproved()\n\n        return (spender == holder ||\n            getApproved(tokenId) == spender ||\n            isApprovedForAll(holder, spender));\n    }\n\n    function _mint(address to, uint256 tokenId) internal virtual {\n        ERC721Storage.Data storage store = ERC721Storage.load();\n        if (to == address(0)) {\n            revert AddressError.ZeroAddress();\n        }\n\n        if (tokenId == 0) {\n            revert ParameterError.InvalidParameter(\"tokenId\", \"cannot be zero\");\n        }\n\n        if (_exists(tokenId)) {\n            revert TokenAlreadyMinted(tokenId);\n        }\n\n        _beforeTransfer(address(0), to, tokenId);\n\n        store.balanceOf[to] += 1;\n        store.ownerOf[tokenId] = to;\n\n        _postTransfer(address(0), to, tokenId);\n\n        emit Transfer(address(0), to, tokenId);\n    }\n\n    function _burn(uint256 tokenId) internal virtual {\n        ERC721Storage.Data storage store = ERC721Storage.load();\n        address holder = store.ownerOf[tokenId];\n\n        _approve(address(0), tokenId);\n\n        _beforeTransfer(holder, address(0), tokenId);\n\n        store.balanceOf[holder] -= 1;\n        delete store.ownerOf[tokenId];\n\n        _postTransfer(holder, address(0), tokenId);\n\n        emit Transfer(holder, address(0), tokenId);\n    }\n\n    function _transfer(address from, address to, uint256 tokenId) internal virtual {\n        ERC721Storage.Data storage store = ERC721Storage.load();\n\n        if (ownerOf(tokenId) != from) {\n            revert AccessError.Unauthorized(from);\n        }\n\n        if (to == address(0)) {\n            revert AddressError.ZeroAddress();\n        }\n\n        _beforeTransfer(from, to, tokenId);\n\n        // Clear approvals from the previous holder\n        _approve(address(0), tokenId);\n\n        store.balanceOf[from] -= 1;\n        store.balanceOf[to] += 1;\n        store.ownerOf[tokenId] = to;\n\n        _postTransfer(from, to, tokenId);\n\n        emit Transfer(from, to, tokenId);\n    }\n\n    function _approve(address to, uint256 tokenId) internal virtual {\n        ERC721Storage.load().tokenApprovals[tokenId] = to;\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n    }\n\n    function _checkOnERC721Received(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal returns (bool) {\n        if (AddressUtil.isContract(to)) {\n            try\n                IERC721Receiver(to).onERC721Received(\n                    ERC2771Context._msgSender(),\n                    from,\n                    tokenId,\n                    data\n                )\n            returns (bytes4 retval) {\n                return retval == IERC721Receiver.onERC721Received.selector;\n            } catch {\n                return false;\n            }\n        } else {\n            return true;\n        }\n    }\n\n    function _beforeTransfer(\n        address from,\n        address to,\n        uint256 tokenId // solhint-disable-next-line no-empty-blocks\n    ) internal virtual {}\n\n    function _postTransfer(\n        address from,\n        address to,\n        uint256 tokenId // solhint-disable-next-line no-empty-blocks\n    ) internal virtual {}\n\n    function _initialize(\n        string memory tokenName,\n        string memory tokenSymbol,\n        string memory baseTokenURI\n    ) internal virtual {\n        ERC721Storage.Data storage store = ERC721Storage.load();\n        if (\n            bytes(store.name).length > 0 ||\n            bytes(store.symbol).length > 0 ||\n            bytes(store.baseTokenURI).length > 0\n        ) {\n            revert InitError.AlreadyInitialized();\n        }\n\n        if (bytes(tokenName).length == 0 || bytes(tokenSymbol).length == 0) {\n            revert ParameterError.InvalidParameter(\"name/symbol\", \"must not be empty\");\n        }\n\n        store.name = tokenName;\n        store.symbol = tokenSymbol;\n        store.baseTokenURI = baseTokenURI;\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/token/ERC721Enumerable.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"./ERC721.sol\";\nimport \"./ERC721EnumerableStorage.sol\";\nimport \"../interfaces/IERC721Enumerable.sol\";\n\n/*\n * @title ERC721 extension with helper functions that allow the enumeration of NFT tokens.\n * See IERC721Enumerable\n *\n * Reference implementations:\n * - OpenZeppelin - https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/extensions/ERC721EnumerableStorage.sol\n */\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\n    /**\n     * @inheritdoc IERC165\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return\n            super.supportsInterface(interfaceId) ||\n            interfaceId == type(IERC721Enumerable).interfaceId;\n    }\n\n    /**\n     * @inheritdoc IERC721Enumerable\n     */\n    function tokenOfOwnerByIndex(\n        address owner,\n        uint256 index\n    ) public view virtual override returns (uint256) {\n        if (ERC721.balanceOf(owner) <= index) {\n            revert IndexOverrun(index, ERC721.balanceOf(owner));\n        }\n        return ERC721EnumerableStorage.load().ownedTokens[owner][index];\n    }\n\n    /**\n     * @inheritdoc IERC721Enumerable\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return ERC721EnumerableStorage.load().allTokens.length;\n    }\n\n    /**\n     * @dev Returns the total amount of tokens stored by the contract.\n     */\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\n        if (index >= ERC721Enumerable.totalSupply()) {\n            revert IndexOverrun(index, ERC721Enumerable.totalSupply());\n        }\n        return ERC721EnumerableStorage.load().allTokens[index];\n    }\n\n    function _beforeTransfer(address from, address to, uint256 tokenId) internal virtual override {\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    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\n        uint256 length = ERC721.balanceOf(to);\n        ERC721EnumerableStorage.load().ownedTokens[to][length] = tokenId;\n        ERC721EnumerableStorage.load().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        ERC721EnumerableStorage.load().allTokensIndex[tokenId] = ERC721EnumerableStorage\n            .load()\n            .allTokens\n            .length;\n        ERC721EnumerableStorage.load().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 = ERC721EnumerableStorage.load().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 = ERC721EnumerableStorage.load().ownedTokens[from][lastTokenIndex];\n\n            ERC721EnumerableStorage.load().ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n            ERC721EnumerableStorage.load().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 ERC721EnumerableStorage.load().ownedTokensIndex[tokenId];\n        delete ERC721EnumerableStorage.load().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 = ERC721EnumerableStorage.load().allTokens.length - 1;\n        uint256 tokenIndex = ERC721EnumerableStorage.load().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 = ERC721EnumerableStorage.load().allTokens[lastTokenIndex];\n\n        ERC721EnumerableStorage.load().allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n        ERC721EnumerableStorage.load().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 ERC721EnumerableStorage.load().allTokensIndex[tokenId];\n        ERC721EnumerableStorage.load().allTokens.pop();\n    }\n\n    function _initialize(\n        string memory tokenName,\n        string memory tokenSymbol,\n        string memory baseTokenURI\n    ) internal virtual override {\n        super._initialize(tokenName, tokenSymbol, baseTokenURI);\n        if (ERC721EnumerableStorage.load().allTokens.length > 0) {\n            revert InitError.AlreadyInitialized();\n        }\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/token/ERC721EnumerableStorage.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nlibrary ERC721EnumerableStorage {\n    bytes32 private constant _SLOT_ERC721_ENUMERABLE_STORAGE =\n        keccak256(abi.encode(\"io.synthetix.core-contracts.ERC721Enumerable\"));\n\n    struct Data {\n        mapping(uint256 => uint256) ownedTokensIndex;\n        mapping(uint256 => uint256) allTokensIndex;\n        mapping(address => mapping(uint256 => uint256)) ownedTokens;\n        uint256[] allTokens;\n    }\n\n    function load() internal pure returns (Data storage store) {\n        bytes32 s = _SLOT_ERC721_ENUMERABLE_STORAGE;\n        assembly {\n            store.slot := s\n        }\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/token/ERC721Storage.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nlibrary ERC721Storage {\n    bytes32 private constant _SLOT_ERC721_STORAGE =\n        keccak256(abi.encode(\"io.synthetix.core-contracts.ERC721\"));\n\n    struct Data {\n        string name;\n        string symbol;\n        string baseTokenURI;\n        mapping(uint256 => address) ownerOf;\n        mapping(address => uint256) balanceOf;\n        mapping(uint256 => address) tokenApprovals;\n        mapping(address => mapping(address => bool)) operatorApprovals;\n    }\n\n    function load() internal pure returns (Data storage store) {\n        bytes32 s = _SLOT_ERC721_STORAGE;\n        assembly {\n            store.slot := s\n        }\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/AddressUtil.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nlibrary AddressUtil {\n    function isContract(address account) internal view returns (bool) {\n        uint256 size;\n\n        assembly {\n            size := extcodesize(account)\n        }\n\n        return size > 0;\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/ERC2771Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/* solhint-disable meta-transactions/no-msg-sender */\n/* solhint-disable meta-transactions/no-msg-data */\n\nlibrary ERC2771Context {\n    // This is the trusted-multicall-forwarder. The address is constant due to CREATE2.\n    address private constant TRUSTED_FORWARDER = 0xE2C5658cC5C448B48141168f3e475dF8f65A1e3e;\n\n    function _msgSender() internal view returns (address sender) {\n        if (isTrustedForwarder(msg.sender) && msg.data.length >= 20) {\n            // The assembly code is more direct than the Solidity version using `abi.decode`.\n            /// @solidity memory-safe-assembly\n            assembly {\n                sender := shr(96, calldataload(sub(calldatasize(), 20)))\n            }\n        } else {\n            return msg.sender;\n        }\n    }\n\n    function _msgData() internal view returns (bytes calldata) {\n        if (isTrustedForwarder(msg.sender) && msg.data.length >= 20) {\n            return msg.data[:msg.data.length - 20];\n        } else {\n            return msg.data;\n        }\n    }\n\n    function isTrustedForwarder(address forwarder) internal pure returns (bool) {\n        return forwarder == TRUSTED_FORWARDER;\n    }\n\n    function trustedForwarder() internal pure returns (address) {\n        return TRUSTED_FORWARDER;\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * Utilities that convert numeric types avoiding silent overflows.\n */\nimport \"./SafeCast/SafeCastU32.sol\";\nimport \"./SafeCast/SafeCastI32.sol\";\nimport \"./SafeCast/SafeCastI24.sol\";\nimport \"./SafeCast/SafeCastU56.sol\";\nimport \"./SafeCast/SafeCastI56.sol\";\nimport \"./SafeCast/SafeCastU64.sol\";\nimport \"./SafeCast/SafeCastI64.sol\";\nimport \"./SafeCast/SafeCastI128.sol\";\nimport \"./SafeCast/SafeCastI256.sol\";\nimport \"./SafeCast/SafeCastU128.sol\";\nimport \"./SafeCast/SafeCastU160.sol\";\nimport \"./SafeCast/SafeCastU256.sol\";\nimport \"./SafeCast/SafeCastAddress.sol\";\nimport \"./SafeCast/SafeCastBytes32.sol\";\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastAddress.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastAddress {\n    function toBytes32(address x) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(x)));\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastBytes32.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastBytes32 {\n    function toAddress(bytes32 x) internal pure returns (address) {\n        return address(uint160(uint256(x)));\n    }\n\n    function toUint(bytes32 x) internal pure returns (uint) {\n        return uint(x);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastI128.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastI128 {\n    error OverflowInt128ToUint128();\n    error OverflowInt128ToInt32();\n\n    function toUint(int128 x) internal pure returns (uint128) {\n        // ----------------<==============o==============>-----------------\n        // ----------------xxxxxxxxxxxxxxxo===============>----------------\n        if (x < 0) {\n            revert OverflowInt128ToUint128();\n        }\n\n        return uint128(x);\n    }\n\n    function to256(int128 x) internal pure returns (int256) {\n        return int256(x);\n    }\n\n    function to32(int128 x) internal pure returns (int32) {\n        // ----------------<==============o==============>-----------------\n        // ----------------xxxxxxxxxxxx<==o==>xxxxxxxxxxxx-----------------\n        if (x < int(type(int32).min) || x > int(type(int32).max)) {\n            revert OverflowInt128ToInt32();\n        }\n\n        return int32(x);\n    }\n\n    function zero() internal pure returns (int128) {\n        return int128(0);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastI24.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastI24 {\n    function to256(int24 x) internal pure returns (int256) {\n        return int256(x);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastI256.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastI256 {\n    error OverflowInt256ToUint256();\n    error OverflowInt256ToInt128();\n    error OverflowInt256ToInt24();\n\n    function to128(int256 x) internal pure returns (int128) {\n        // ----<==========================o===========================>----\n        // ----xxxxxxxxxxxx<==============o==============>xxxxxxxxxxxxx----\n        if (x < int256(type(int128).min) || x > int256(type(int128).max)) {\n            revert OverflowInt256ToInt128();\n        }\n\n        return int128(x);\n    }\n\n    function to24(int256 x) internal pure returns (int24) {\n        // ----<==========================o===========================>----\n        // ----xxxxxxxxxxxxxxxxxxxx<======o=======>xxxxxxxxxxxxxxxxxxxx----\n        if (x < int256(type(int24).min) || x > int256(type(int24).max)) {\n            revert OverflowInt256ToInt24();\n        }\n\n        return int24(x);\n    }\n\n    function toUint(int256 x) internal pure returns (uint256) {\n        // ----<==========================o===========================>----\n        // ----xxxxxxxxxxxxxxxxxxxxxxxxxxxo===============================>\n        if (x < 0) {\n            revert OverflowInt256ToUint256();\n        }\n\n        return uint256(x);\n    }\n\n    function zero() internal pure returns (int256) {\n        return int256(0);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastI32.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastI32 {\n    error OverflowInt32ToUint32();\n\n    function toUint(int32 x) internal pure returns (uint32) {\n        // ----------------------<========o========>----------------------\n        // ----------------------xxxxxxxxxo=========>----------------------\n        if (x < 0) {\n            revert OverflowInt32ToUint32();\n        }\n\n        return uint32(x);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastI56.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastI56 {\n    error OverflowInt56ToInt24();\n\n    function to24(int56 x) internal pure returns (int24) {\n        // ----------------------<========o========>-----------------------\n        // ----------------------xxx<=====o=====>xxx-----------------------\n        if (x < int(type(int24).min) || x > int(type(int24).max)) {\n            revert OverflowInt56ToInt24();\n        }\n\n        return int24(x);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastI64.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastI64 {\n    error OverflowInt64ToUint64();\n\n    function toUint(int64 x) internal pure returns (uint64) {\n        // ----------------------<========o========>----------------------\n        // ----------------------xxxxxxxxxo=========>----------------------\n        if (x < 0) {\n            revert OverflowInt64ToUint64();\n        }\n\n        return uint64(x);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastU128.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastU128 {\n    error OverflowUint128ToInt128();\n\n    function to256(uint128 x) internal pure returns (uint256) {\n        return uint256(x);\n    }\n\n    function toInt(uint128 x) internal pure returns (int128) {\n        // -------------------------------o===============>----------------\n        // ----------------<==============o==============>x----------------\n        if (x > uint128(type(int128).max)) {\n            revert OverflowUint128ToInt128();\n        }\n\n        return int128(x);\n    }\n\n    function toBytes32(uint128 x) internal pure returns (bytes32) {\n        return bytes32(uint256(x));\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastU160.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastU160 {\n    function to256(uint160 x) internal pure returns (uint256) {\n        return uint256(x);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastU256.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastU256 {\n    error OverflowUint256ToUint128();\n    error OverflowUint256ToInt256();\n    error OverflowUint256ToUint64();\n    error OverflowUint256ToUint32();\n    error OverflowUint256ToUint160();\n\n    function to128(uint256 x) internal pure returns (uint128) {\n        // -------------------------------o===============================>\n        // -------------------------------o===============>xxxxxxxxxxxxxxxx\n        if (x > type(uint128).max) {\n            revert OverflowUint256ToUint128();\n        }\n\n        return uint128(x);\n    }\n\n    function to64(uint256 x) internal pure returns (uint64) {\n        // -------------------------------o===============================>\n        // -------------------------------o======>xxxxxxxxxxxxxxxxxxxxxxxxx\n        if (x > type(uint64).max) {\n            revert OverflowUint256ToUint64();\n        }\n\n        return uint64(x);\n    }\n\n    function to32(uint256 x) internal pure returns (uint32) {\n        // -------------------------------o===============================>\n        // -------------------------------o===>xxxxxxxxxxxxxxxxxxxxxxxxxxxx\n        if (x > type(uint32).max) {\n            revert OverflowUint256ToUint32();\n        }\n\n        return uint32(x);\n    }\n\n    function to160(uint256 x) internal pure returns (uint160) {\n        // -------------------------------o===============================>\n        // -------------------------------o==================>xxxxxxxxxxxxx\n        if (x > type(uint160).max) {\n            revert OverflowUint256ToUint160();\n        }\n\n        return uint160(x);\n    }\n\n    function toBytes32(uint256 x) internal pure returns (bytes32) {\n        return bytes32(x);\n    }\n\n    function toInt(uint256 x) internal pure returns (int256) {\n        // -------------------------------o===============================>\n        // ----<==========================o===========================>xxxx\n        if (x > uint256(type(int256).max)) {\n            revert OverflowUint256ToInt256();\n        }\n\n        return int256(x);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastU32.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastU32 {\n    error OverflowUint32ToInt32();\n\n    function toInt(uint32 x) internal pure returns (int32) {\n        // -------------------------------o=========>----------------------\n        // ----------------------<========o========>x----------------------\n        if (x > uint32(type(int32).max)) {\n            revert OverflowUint32ToInt32();\n        }\n\n        return int32(x);\n    }\n\n    function to256(uint32 x) internal pure returns (uint256) {\n        return uint256(x);\n    }\n\n    function to56(uint32 x) internal pure returns (uint56) {\n        return uint56(x);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastU56.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastU56 {\n    error OverflowUint56ToInt56();\n\n    function toInt(uint56 x) internal pure returns (int56) {\n        // -------------------------------o=========>----------------------\n        // ----------------------<========o========>x----------------------\n        if (x > uint56(type(int56).max)) {\n            revert OverflowUint56ToInt56();\n        }\n\n        return int56(x);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/SafeCast/SafeCastU64.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title See SafeCast.sol.\n */\nlibrary SafeCastU64 {\n    error OverflowUint64ToInt64();\n\n    function toInt(uint64 x) internal pure returns (int64) {\n        // -------------------------------o=========>----------------------\n        // ----------------------<========o========>x----------------------\n        if (x > uint64(type(int64).max)) {\n            revert OverflowUint64ToInt64();\n        }\n\n        return int64(x);\n    }\n\n    function to256(uint64 x) internal pure returns (uint256) {\n        return uint256(x);\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/utils/StringUtil.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/*\n    Reference implementations:\n    * OpenZeppelin - https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Strings.sol\n*/\n\nlibrary StringUtil {\n    function uintToString(uint value) internal pure returns (string memory) {\n        if (value == 0) {\n            return \"0\";\n        }\n\n        uint256 temp = value;\n        uint256 digits;\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n\n        bytes memory buffer = new bytes(digits);\n        while (value != 0) {\n            digits -= 1;\n            // solhint-disable-next-line numcast/safe-cast\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n\n        return string(buffer);\n    }\n}\n"
      },
      "@synthetixio/core-modules/contracts/interfaces/INftModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"@synthetixio/core-contracts/contracts/interfaces/IERC721Enumerable.sol\";\n\n/**\n * @title Module wrapping an ERC721 token implementation.\n */\ninterface INftModule is IERC721Enumerable {\n    /**\n     * @notice Returns whether the token has been initialized.\n     * @return A boolean with the result of the query.\n     */\n    function isInitialized() external view returns (bool);\n\n    /**\n     * @notice Initializes the token with name, symbol, and uri.\n     */\n    function initialize(\n        string memory tokenName,\n        string memory tokenSymbol,\n        string memory uri\n    ) external;\n\n    /**\n     * @notice Allows the owner to mint tokens.\n     * @param to The address to receive the newly minted tokens.\n     * @param tokenId The ID of the newly minted token\n     */\n    function mint(address to, uint tokenId) external;\n\n    /**\n     * @notice Allows the owner to mint tokens. Verifies that the receiver can receive the token\n     * @param to The address to receive the newly minted token.\n     * @param tokenId The ID of the newly minted token\n     * @param data any data which should be sent to the receiver\n     */\n    function safeMint(address to, uint256 tokenId, bytes memory data) external;\n\n    /**\n     * @notice Allows the owner to burn tokens.\n     * @param tokenId The token to burn\n     */\n    function burn(uint tokenId) external;\n\n    /**\n     * @notice Allows an address that holds tokens to provide allowance to another.\n     * @param tokenId The token which should be allowed to spender\n     * @param spender The address that is given allowance.\n     */\n    function setAllowance(uint tokenId, address spender) external;\n\n    /**\n     * @notice Allows the owner to update the base token URI.\n     * @param uri The new base token uri\n     */\n    function setBaseTokenURI(string memory uri) external;\n}\n"
      },
      "@synthetixio/core-modules/contracts/modules/NftModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"@synthetixio/core-contracts/contracts/token/ERC721Enumerable.sol\";\nimport \"@synthetixio/core-contracts/contracts/utils/AddressUtil.sol\";\nimport \"@synthetixio/core-contracts/contracts/initializable/InitializableMixin.sol\";\nimport \"@synthetixio/core-contracts/contracts/ownership/OwnableStorage.sol\";\nimport \"@synthetixio/core-contracts/contracts/errors/AddressError.sol\";\n\nimport \"../storage/Initialized.sol\";\n\nimport \"../interfaces/INftModule.sol\";\n\n/**\n * @title Module wrapping an ERC721 token implementation.\n * See INftModule.\n */\ncontract NftModule is INftModule, ERC721Enumerable, InitializableMixin {\n    bytes32 internal constant _INITIALIZED_NAME = \"NftModule\";\n\n    /**\n     * @inheritdoc INftModule\n     */\n    function isInitialized() external view returns (bool) {\n        return _isInitialized();\n    }\n\n    /**\n     * @inheritdoc INftModule\n     */\n    function initialize(\n        string memory tokenName,\n        string memory tokenSymbol,\n        string memory uri\n    ) external {\n        OwnableStorage.onlyOwner();\n\n        _initialize(tokenName, tokenSymbol, uri);\n        Initialized.load(_INITIALIZED_NAME).initialized = true;\n    }\n\n    /**\n     * @inheritdoc INftModule\n     */\n    function burn(uint256 tokenId) external override {\n        OwnableStorage.onlyOwner();\n        _burn(tokenId);\n    }\n\n    /**\n     * @inheritdoc INftModule\n     */\n    function mint(address to, uint256 tokenId) external override {\n        OwnableStorage.onlyOwner();\n        _mint(to, tokenId);\n    }\n\n    /**\n     * @inheritdoc INftModule\n     */\n    function safeMint(address to, uint256 tokenId, bytes memory data) external override {\n        OwnableStorage.onlyOwner();\n        _mint(to, tokenId);\n\n        if (!_checkOnERC721Received(address(0), to, tokenId, data)) {\n            revert InvalidTransferRecipient(to);\n        }\n    }\n\n    /**\n     * @inheritdoc INftModule\n     */\n    function setBaseTokenURI(string memory uri) external override {\n        OwnableStorage.onlyOwner();\n        ERC721Storage.load().baseTokenURI = uri;\n    }\n\n    /**\n     * @inheritdoc INftModule\n     */\n    function setAllowance(uint tokenId, address spender) external override {\n        OwnableStorage.onlyOwner();\n        ERC721Storage.load().tokenApprovals[tokenId] = spender;\n    }\n\n    function _isInitialized() internal view override returns (bool) {\n        return Initialized.load(_INITIALIZED_NAME).initialized;\n    }\n}\n"
      },
      "@synthetixio/core-modules/contracts/storage/Initialized.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nlibrary Initialized {\n    struct Data {\n        bool initialized;\n    }\n\n    function load(bytes32 id) internal pure returns (Data storage store) {\n        bytes32 s = keccak256(abi.encode(\"io.synthetix.code-modules.Initialized\", id));\n        assembly {\n            store.slot := s\n        }\n    }\n}\n"
      },
      "contracts/interfaces/IAccountModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title Module for managing accounts.\n * @notice Manages the system's account token NFT. Every user will need to register an account before being able to interact with the system.\n */\ninterface IAccountModule {\n    /**\n     * @notice Thrown when the account interacting with the system is expected to be the associated account token, but is not.\n     */\n    error OnlyAccountTokenProxy(address origin);\n\n    /**\n     * @notice Thrown when an account attempts to renounce a permission that it didn't have.\n     */\n    error PermissionNotGranted(uint128 accountId, bytes32 permission, address user);\n\n    /**\n     * @notice Thrown when the requested account ID is greater or equal to type(uint128).max / 2\n     */\n    error InvalidAccountId(uint128 accountId);\n\n    /**\n     * @notice Emitted when an account token with id `accountId` is minted to `sender`.\n     * @param accountId The id of the account.\n     * @param owner The address that owns the created account.\n     */\n    event AccountCreated(uint128 indexed accountId, address indexed owner);\n\n    /**\n     * @notice Emitted when `user` is granted `permission` by `sender` for account `accountId`.\n     * @param accountId The id of the account that granted the permission.\n     * @param permission The bytes32 identifier of the permission.\n     * @param user The target address to whom the permission was granted.\n     * @param sender The Address that granted the permission.\n     */\n    event PermissionGranted(\n        uint128 indexed accountId,\n        bytes32 indexed permission,\n        address indexed user,\n        address sender\n    );\n\n    /**\n     * @notice Emitted when `user` has `permission` renounced or revoked by `sender` for account `accountId`.\n     * @param accountId The id of the account that has had the permission revoked.\n     * @param permission The bytes32 identifier of the permission.\n     * @param user The target address for which the permission was revoked.\n     * @param sender The address that revoked the permission.\n     */\n    event PermissionRevoked(\n        uint128 indexed accountId,\n        bytes32 indexed permission,\n        address indexed user,\n        address sender\n    );\n\n    /**\n     * @dev Data structure for tracking each user's permissions.\n     */\n    struct AccountPermissions {\n        /**\n         * @dev The address for which all the permissions are granted.\n         */\n        address user;\n        /**\n         * @dev The array of permissions given to the associated address.\n         */\n        bytes32[] permissions;\n    }\n\n    /**\n     * @notice Returns an array of `AccountPermission` for the provided `accountId`.\n     * @param accountId The id of the account whose permissions are being retrieved.\n     * @return accountPerms An array of AccountPermission objects describing the permissions granted to the account.\n     */\n    function getAccountPermissions(\n        uint128 accountId\n    ) external view returns (AccountPermissions[] memory accountPerms);\n\n    /**\n     * @notice Mints an account token with id `requestedAccountId` to `ERC2771Context._msgSender()`.\n     * @param requestedAccountId The id requested for the account being created. Reverts if id already exists.\n     *\n     * Requirements:\n     *\n     * - `requestedAccountId` must not already be minted.\n     * - `requestedAccountId` must be less than type(uint128).max / 2\n     *\n     * Emits a {AccountCreated} event.\n     */\n    function createAccount(uint128 requestedAccountId) external;\n\n    /**\n     * @notice Mints an account token with an available id to `ERC2771Context._msgSender()`.\n     *\n     * Emits a {AccountCreated} event.\n     */\n    function createAccount() external returns (uint128 accountId);\n\n    /**\n     * @notice Called by AccountTokenModule to notify the system when the account token is transferred.\n     * @dev Resets user permissions and assigns ownership of the account token to the new holder.\n     * @param to The new holder of the account NFT.\n     * @param accountId The id of the account that was just transferred.\n     *\n     * Requirements:\n     *\n     * - `ERC2771Context._msgSender()` must be the account token.\n     */\n    function notifyAccountTransfer(address to, uint128 accountId) external;\n\n    /**\n     * @notice Grants `permission` to `user` for account `accountId`.\n     * @param accountId The id of the account that granted the permission.\n     * @param permission The bytes32 identifier of the permission.\n     * @param user The target address that received the permission.\n     *\n     * Requirements:\n     *\n     * - `ERC2771Context._msgSender()` must own the account token with ID `accountId` or have the \"admin\" permission.\n     *\n     * Emits a {PermissionGranted} event.\n     */\n    function grantPermission(uint128 accountId, bytes32 permission, address user) external;\n\n    /**\n     * @notice Revokes `permission` from `user` for account `accountId`.\n     * @param accountId The id of the account that revoked the permission.\n     * @param permission The bytes32 identifier of the permission.\n     * @param user The target address that no longer has the permission.\n     *\n     * Requirements:\n     *\n     * - `ERC2771Context._msgSender()` must own the account token with ID `accountId` or have the \"admin\" permission.\n     *\n     * Emits a {PermissionRevoked} event.\n     */\n    function revokePermission(uint128 accountId, bytes32 permission, address user) external;\n\n    /**\n     * @notice Revokes `permission` from `ERC2771Context._msgSender()` for account `accountId`.\n     * @param accountId The id of the account whose permission was renounced.\n     * @param permission The bytes32 identifier of the permission.\n     *\n     * Emits a {PermissionRevoked} event.\n     */\n    function renouncePermission(uint128 accountId, bytes32 permission) external;\n\n    /**\n     * @notice Returns `true` if `user` has been granted `permission` for account `accountId`.\n     * @param accountId The id of the account whose permission is being queried.\n     * @param permission The bytes32 identifier of the permission.\n     * @param user The target address whose permission is being queried.\n     * @return hasPermission A boolean with the response of the query.\n     */\n    function hasPermission(\n        uint128 accountId,\n        bytes32 permission,\n        address user\n    ) external view returns (bool hasPermission);\n\n    /**\n     * @notice Returns `true` if `target` is authorized to `permission` for account `accountId`.\n     * @param accountId The id of the account whose permission is being queried.\n     * @param permission The bytes32 identifier of the permission.\n     * @param target The target address whose permission is being queried.\n     * @return isAuthorized A boolean with the response of the query.\n     */\n    function isAuthorized(\n        uint128 accountId,\n        bytes32 permission,\n        address target\n    ) external view returns (bool isAuthorized);\n\n    /**\n     * @notice Returns the address for the account token used by the module.\n     * @return accountNftToken The address of the account token.\n     */\n    function getAccountTokenAddress() external view returns (address accountNftToken);\n\n    /**\n     * @notice Returns the address that owns a given account, as recorded by the system.\n     * @param accountId The account id whose owner is being retrieved.\n     * @return owner The owner of the given account id.\n     */\n    function getAccountOwner(uint128 accountId) external view returns (address owner);\n\n    /**\n     * @notice Returns the last unix timestamp that a permissioned action was taken with this account\n     * @param accountId The account id to check\n     * @return timestamp The unix timestamp of the last time a permissioned action occured with the account\n     */\n    function getAccountLastInteraction(uint128 accountId) external view returns (uint256 timestamp);\n}\n"
      },
      "contracts/interfaces/IAccountTokenModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"@synthetixio/core-modules/contracts/interfaces/INftModule.sol\";\n\n/**\n * @title Module with custom NFT logic for the account token.\n */\n// solhint-disable-next-line no-empty-blocks\ninterface IAccountTokenModule is INftModule {\n\n}\n"
      },
      "contracts/modules/account/AccountTokenModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"@synthetixio/core-modules/contracts/modules/NftModule.sol\";\nimport \"../../../contracts/interfaces/IAccountTokenModule.sol\";\nimport \"../../../contracts/interfaces/IAccountModule.sol\";\n\nimport \"@synthetixio/core-contracts/contracts/utils/SafeCast.sol\";\n\n/**\n * @title Module with custom NFT logic for the account token.\n * @dev See IAccountTokenModule.\n */\ncontract AccountTokenModule is IAccountTokenModule, NftModule {\n    using SafeCastU256 for uint256;\n\n    /**\n     * @dev Updates account RBAC storage to track the current owner of the token.\n     */\n    function _postTransfer(\n        address, // from (unused)\n        address to,\n        uint256 tokenId\n    ) internal virtual override {\n        IAccountModule(OwnableStorage.getOwner()).notifyAccountTransfer(to, tokenId.to128());\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}