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/interfaces/IERC20.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title ERC20 token implementation.\n */\ninterface IERC20 {\n    /**\n     * @notice Emitted when tokens have been transferred.\n     * @param from The address that originally owned the tokens.\n     * @param to The address that received the tokens.\n     * @param amount The number of tokens that were transferred.\n     */\n    event Transfer(address indexed from, address indexed to, uint amount);\n\n    /**\n     * @notice Emitted when a user has provided allowance to another user for transferring tokens on its behalf.\n     * @param owner The address that is providing the allowance.\n     * @param spender The address that received the allowance.\n     * @param amount The number of tokens that were added to `spender`'s allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint amount);\n\n    /**\n     * @notice Thrown when the address interacting with the contract does not have sufficient allowance to transfer tokens from another contract.\n     * @param required The necessary allowance.\n     * @param existing The current allowance.\n     */\n    error InsufficientAllowance(uint required, uint existing);\n\n    /**\n     * @notice Thrown when the address interacting with the contract does not have sufficient tokens.\n     * @param required The necessary balance.\n     * @param existing The current balance.\n     */\n    error InsufficientBalance(uint required, uint existing);\n\n    /**\n     * @notice Retrieves the name of the token, e.g. \"Synthetix Network 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\".\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 number of decimals used by the token. The default is 18.\n     * @return The number of decimals.\n     */\n    function decimals() external view returns (uint8);\n\n    /**\n     * @notice Returns the total number of tokens in circulation (minted - burnt).\n     * @return The total number of tokens.\n     */\n    function totalSupply() external view returns (uint);\n\n    /**\n     * @notice Returns the balance of a user.\n     * @param owner The address whose balance is being retrieved.\n     * @return The number of tokens owned by the user.\n     */\n    function balanceOf(address owner) external view returns (uint);\n\n    /**\n     * @notice Returns how many tokens a user has allowed another user to transfer on its behalf.\n     * @param owner The user who has given the allowance.\n     * @param spender The user who was given the allowance.\n     * @return The amount of tokens `spender` can transfer on `owner`'s behalf.\n     */\n    function allowance(address owner, address spender) external view returns (uint);\n\n    /**\n     * @notice Transfer tokens from one address to another.\n     * @param to The address that will receive the tokens.\n     * @param amount The amount of tokens to be transferred.\n     * @return A boolean which is true if the operation succeeded.\n     */\n    function transfer(address to, uint amount) external returns (bool);\n\n    /**\n     * @notice Allows users to provide allowance to other users so that they can transfer tokens on their behalf.\n     * @param spender The address that is receiving the allowance.\n     * @param amount The amount of tokens that are being added to the allowance.\n     * @return A boolean which is true if the operation succeeded.\n     */\n    function approve(address spender, uint amount) external returns (bool);\n\n    /**\n     * @notice Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);\n\n    /**\n     * @notice Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);\n\n    /**\n     * @notice Allows a user who has been given allowance to transfer tokens on another user's behalf.\n     * @param from The address that owns the tokens that are being transferred.\n     * @param to The address that will receive the tokens.\n     * @param amount The number of tokens to transfer.\n     * @return A boolean which is true if the operation succeeded.\n     */\n    function transferFrom(address from, address to, uint amount) external 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/IUUPSImplementation.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title Contract to be used as the implementation of a Universal Upgradeable Proxy Standard (UUPS) proxy.\n *\n * Important: A UUPS proxy requires its upgradeability functions to be in the implementation as opposed to the proxy. This means that if the proxy is upgraded to an implementation that does not support this interface, it will no longer be upgradeable.\n */\ninterface IUUPSImplementation {\n    /**\n     * @notice Thrown when an incoming implementation will not be able to receive future upgrades.\n     */\n    error ImplementationIsSterile(address implementation);\n\n    /**\n     * @notice Thrown intentionally when testing future upgradeability of an implementation.\n     */\n    error UpgradeSimulationFailed();\n\n    /**\n     * @notice Emitted when the implementation of the proxy has been upgraded.\n     * @param self The address of the proxy whose implementation was upgraded.\n     * @param implementation The address of the proxy's new implementation.\n     */\n    event Upgraded(address indexed self, address implementation);\n\n    /**\n     * @notice Allows the proxy to be upgraded to a new implementation.\n     * @param newImplementation The address of the proxy's new implementation.\n     * @dev Will revert if `newImplementation` is not upgradeable.\n     * @dev The implementation of this function needs to be protected by some sort of access control such as `onlyOwner`.\n     */\n    function upgradeTo(address newImplementation) external;\n\n    /**\n     * @notice Function used to determine if a new implementation will be able to receive future upgrades in `upgradeTo`.\n     * @param newImplementation The address of the new implementation being tested for future upgradeability.\n     * @dev This function will always revert, but will revert with different error messages. The function `upgradeTo` uses this error to determine the future upgradeability of the implementation in question.\n     */\n    function simulateUpgradeTo(address newImplementation) external;\n\n    /**\n     * @notice Retrieves the current implementation of the proxy.\n     * @return The address of the current implementation.\n     */\n    function getImplementation() external view returns (address);\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/proxy/AbstractProxy.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nabstract contract AbstractProxy {\n    fallback() external payable {\n        _forward();\n    }\n\n    receive() external payable {\n        _forward();\n    }\n\n    function _forward() internal {\n        address implementation = _getImplementation();\n\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            calldatacopy(0, 0, calldatasize())\n\n            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n            returndatacopy(0, 0, returndatasize())\n\n            switch result\n            case 0 {\n                revert(0, returndatasize())\n            }\n            default {\n                return(0, returndatasize())\n            }\n        }\n    }\n\n    function _getImplementation() internal view virtual returns (address);\n}\n"
      },
      "@synthetixio/core-contracts/contracts/proxy/ProxyStorage.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\ncontract ProxyStorage {\n    bytes32 private constant _SLOT_PROXY_STORAGE =\n        keccak256(abi.encode(\"io.synthetix.core-contracts.Proxy\"));\n\n    struct ProxyStore {\n        address implementation;\n        bool simulatingUpgrade;\n    }\n\n    function _proxyStore() internal pure returns (ProxyStore storage store) {\n        bytes32 s = _SLOT_PROXY_STORAGE;\n        assembly {\n            store.slot := s\n        }\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/proxy/UUPSProxy.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"./AbstractProxy.sol\";\nimport \"./ProxyStorage.sol\";\nimport \"../errors/AddressError.sol\";\nimport \"../utils/AddressUtil.sol\";\n\ncontract UUPSProxy is AbstractProxy, ProxyStorage {\n    constructor(address firstImplementation) {\n        if (firstImplementation == address(0)) {\n            revert AddressError.ZeroAddress();\n        }\n\n        if (!AddressUtil.isContract(firstImplementation)) {\n            revert AddressError.NotAContract(firstImplementation);\n        }\n\n        _proxyStore().implementation = firstImplementation;\n    }\n\n    function _getImplementation() internal view virtual override returns (address) {\n        return _proxyStore().implementation;\n    }\n}\n"
      },
      "@synthetixio/core-contracts/contracts/proxy/UUPSProxyWithOwner.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport {UUPSProxy} from \"./UUPSProxy.sol\";\nimport {OwnableStorage} from \"../ownership/OwnableStorage.sol\";\n\ncontract UUPSProxyWithOwner is UUPSProxy {\n    // solhint-disable-next-line no-empty-blocks\n    constructor(address firstImplementation, address initialOwner) UUPSProxy(firstImplementation) {\n        OwnableStorage.load().owner = initialOwner;\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-modules/contracts/interfaces/IAssociatedSystemsModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title Module for connecting a system with other associated systems.\n\n * Associated systems become available to all system modules for communication and interaction, but as opposed to inter-modular communications, interactions with associated systems will require the use of `CALL`.\n *\n * Associated systems can be managed or unmanaged.\n * - Managed systems are connected via a proxy, which means that their implementation can be updated, and the system controls the execution context of the associated system. Example, an snxUSD token connected to the system, and controlled by the system.\n * - Unmanaged systems are just addresses tracked by the system, for which it has no control whatsoever. Example, Uniswap v3, Curve, etc.\n *\n * Furthermore, associated systems are typed in the AssociatedSystem utility library (See AssociatedSystem.sol):\n * - KIND_ERC20: A managed associated system specifically wrapping an ERC20 implementation.\n * - KIND_ERC721: A managed associated system specifically wrapping an ERC721 implementation.\n * - KIND_UNMANAGED: Any unmanaged associated system.\n */\ninterface IAssociatedSystemsModule {\n    /**\n     * @notice Emitted when an associated system is set.\n     * @param kind The type of associated system (managed ERC20, managed ERC721, unmanaged, etc - See the AssociatedSystem util).\n     * @param id The bytes32 identifier of the associated system.\n     * @param proxy The main external contract address of the associated system.\n     * @param impl The address of the implementation of the associated system (if not behind a proxy, will equal `proxy`).\n     */\n    event AssociatedSystemSet(\n        bytes32 indexed kind,\n        bytes32 indexed id,\n        address proxy,\n        address impl\n    );\n\n    /**\n     * @notice Emitted when the function you are calling requires an associated system, but it\n     * has not been registered\n     */\n    error MissingAssociatedSystem(bytes32 id);\n\n    /**\n     * @notice Creates or initializes a managed associated ERC20 token.\n     * @param id The bytes32 identifier of the associated system. If the id is new to the system, it will create a new proxy for the associated system.\n     * @param name The token name that will be used to initialize the proxy.\n     * @param symbol The token symbol that will be used to initialize the proxy.\n     * @param decimals The token decimals that will be used to initialize the proxy.\n     * @param impl The ERC20 implementation of the proxy.\n     */\n    function initOrUpgradeToken(\n        bytes32 id,\n        string memory name,\n        string memory symbol,\n        uint8 decimals,\n        address impl\n    ) external;\n\n    /**\n     * @notice Creates or initializes a managed associated ERC721 token.\n     * @param id The bytes32 identifier of the associated system. If the id is new to the system, it will create a new proxy for the associated system.\n     * @param name The token name that will be used to initialize the proxy.\n     * @param symbol The token symbol that will be used to initialize the proxy.\n     * @param uri The token uri that will be used to initialize the proxy.\n     * @param impl The ERC721 implementation of the proxy.\n     */\n    function initOrUpgradeNft(\n        bytes32 id,\n        string memory name,\n        string memory symbol,\n        string memory uri,\n        address impl\n    ) external;\n\n    /**\n     * @notice Registers an unmanaged external contract in the system.\n     * @param id The bytes32 identifier to use to reference the associated system.\n     * @param endpoint The address of the associated system.\n     *\n     * Note: The system will not be able to control or upgrade the associated system, only communicate with it.\n     */\n    function registerUnmanagedSystem(bytes32 id, address endpoint) external;\n\n    /**\n     * @notice Retrieves an associated system.\n     * @param id The bytes32 identifier used to reference the associated system.\n     * @return addr The external contract address of the associated system.\n     * @return kind The type of associated system (managed ERC20, managed ERC721, unmanaged, etc - See the AssociatedSystem util).\n     */\n    function getAssociatedSystem(bytes32 id) external view returns (address addr, bytes32 kind);\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/interfaces/IOwnerModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title Module for giving a system owner based access control.\n */\n// solhint-disable-next-line no-empty-blocks\ninterface IOwnerModule {\n\n}\n"
      },
      "@synthetixio/core-modules/contracts/interfaces/ITokenModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"@synthetixio/core-contracts/contracts/interfaces/IERC20.sol\";\n\n/**\n * @title Module wrapping an ERC20 token implementation.\n */\ninterface ITokenModule is IERC20 {\n    /**\n     * @notice Returns wether 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 decimals.\n     */\n    function initialize(\n        string memory tokenName,\n        string memory tokenSymbol,\n        uint8 tokenDecimals\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 amount The amount of tokens to mint.\n     */\n    function mint(address to, uint amount) external;\n\n    /**\n     * @notice Allows the owner to burn tokens.\n     * @param from The address whose tokens will be burnt.\n     * @param amount The amount of tokens to burn.\n     */\n    function burn(address from, uint amount) external;\n\n    /**\n     * @notice Allows an address that holds tokens to provide allowance to another.\n     * @param from The address that is providing allowance.\n     * @param spender The address that is given allowance.\n     * @param amount The amount of allowance being given.\n     */\n    function setAllowance(address from, address spender, uint amount) external;\n}\n"
      },
      "@synthetixio/core-modules/contracts/modules/AssociatedSystemsModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"@synthetixio/core-contracts/contracts/errors/InitError.sol\";\nimport \"@synthetixio/core-contracts/contracts/ownership/OwnableStorage.sol\";\nimport \"@synthetixio/core-contracts/contracts/proxy/UUPSProxyWithOwner.sol\";\nimport \"../interfaces/IAssociatedSystemsModule.sol\";\n\nimport \"@synthetixio/core-contracts/contracts/interfaces/IUUPSImplementation.sol\";\nimport \"../interfaces/IOwnerModule.sol\";\nimport \"../interfaces/ITokenModule.sol\";\nimport \"../interfaces/INftModule.sol\";\n\nimport \"../storage/AssociatedSystem.sol\";\n\n/**\n * @title Module for connecting a system with other associated systems.\n * @dev See IAssociatedSystemsModule.\n */\ncontract AssociatedSystemsModule is IAssociatedSystemsModule {\n    using AssociatedSystem for AssociatedSystem.Data;\n\n    modifier onlyIfAssociated(bytes32 id) {\n        if (address(AssociatedSystem.load(id).proxy) == address(0)) {\n            revert MissingAssociatedSystem(id);\n        }\n\n        _;\n    }\n\n    /**\n     * @inheritdoc IAssociatedSystemsModule\n     */\n    function initOrUpgradeToken(\n        bytes32 id,\n        string memory name,\n        string memory symbol,\n        uint8 decimals,\n        address impl\n    ) external override {\n        OwnableStorage.onlyOwner();\n        _initOrUpgradeToken(id, name, symbol, decimals, impl);\n    }\n\n    /**\n     * @inheritdoc IAssociatedSystemsModule\n     */\n    function initOrUpgradeNft(\n        bytes32 id,\n        string memory name,\n        string memory symbol,\n        string memory uri,\n        address impl\n    ) external override {\n        OwnableStorage.onlyOwner();\n        _initOrUpgradeNft(id, name, symbol, uri, impl);\n    }\n\n    /**\n     * @inheritdoc IAssociatedSystemsModule\n     */\n    function registerUnmanagedSystem(bytes32 id, address endpoint) external override {\n        OwnableStorage.onlyOwner();\n        // empty string require kind will make sure the system is either unregistered or already unmanaged\n        AssociatedSystem.load(id).expectKind(\"\");\n\n        _setAssociatedSystem(id, AssociatedSystem.KIND_UNMANAGED, endpoint, endpoint);\n    }\n\n    /**\n     * @inheritdoc IAssociatedSystemsModule\n     */\n    function getAssociatedSystem(\n        bytes32 id\n    ) external view override returns (address addr, bytes32 kind) {\n        addr = AssociatedSystem.load(id).proxy;\n        kind = AssociatedSystem.load(id).kind;\n    }\n\n    function _setAssociatedSystem(bytes32 id, bytes32 kind, address proxy, address impl) internal {\n        AssociatedSystem.load(id).set(proxy, impl, kind);\n        emit AssociatedSystemSet(kind, id, proxy, impl);\n    }\n\n    function _upgradeToken(\n        bytes32 id,\n        address impl\n    ) internal returns (AssociatedSystem.Data storage store) {\n        store = AssociatedSystem.load(id);\n        store.expectKind(AssociatedSystem.KIND_ERC20);\n\n        store.impl = impl;\n\n        address proxy = store.proxy;\n\n        // tell the associated proxy to upgrade to the new implementation\n        IUUPSImplementation(proxy).upgradeTo(impl);\n\n        emit AssociatedSystemSet(AssociatedSystem.KIND_ERC20, id, proxy, impl);\n    }\n\n    function _upgradeNft(\n        bytes32 id,\n        address impl\n    ) internal returns (AssociatedSystem.Data storage store) {\n        store = AssociatedSystem.load(id);\n        store.expectKind(AssociatedSystem.KIND_ERC721);\n\n        store.impl = impl;\n\n        address proxy = store.proxy;\n\n        // tell the associated proxy to upgrade to the new implementation\n        IUUPSImplementation(proxy).upgradeTo(impl);\n\n        emit AssociatedSystemSet(AssociatedSystem.KIND_ERC721, id, proxy, impl);\n    }\n\n    function _initOrUpgradeToken(\n        bytes32 id,\n        string memory name,\n        string memory symbol,\n        uint8 decimals,\n        address impl\n    ) internal {\n        AssociatedSystem.Data storage store = AssociatedSystem.load(id);\n\n        if (store.proxy != address(0)) {\n            if (store.impl != impl) {\n                _upgradeToken(id, impl);\n            }\n            ITokenModule(store.proxy).initialize(name, symbol, decimals);\n        } else {\n            // create a new proxy and own it\n            address proxy = address(new UUPSProxyWithOwner(impl, address(this)));\n\n            ITokenModule(proxy).initialize(name, symbol, decimals);\n\n            _setAssociatedSystem(id, AssociatedSystem.KIND_ERC20, proxy, impl);\n        }\n    }\n\n    function _initOrUpgradeNft(\n        bytes32 id,\n        string memory name,\n        string memory symbol,\n        string memory uri,\n        address impl\n    ) internal {\n        OwnableStorage.onlyOwner();\n        AssociatedSystem.Data storage store = AssociatedSystem.load(id);\n\n        if (store.proxy != address(0)) {\n            _upgradeNft(id, impl);\n        } else {\n            // create a new proxy and own it\n            address proxy = address(new UUPSProxyWithOwner(impl, address(this)));\n\n            INftModule(proxy).initialize(name, symbol, uri);\n\n            _setAssociatedSystem(id, AssociatedSystem.KIND_ERC721, proxy, impl);\n        }\n    }\n}\n"
      },
      "@synthetixio/core-modules/contracts/storage/AssociatedSystem.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"../interfaces/ITokenModule.sol\";\nimport \"../interfaces/INftModule.sol\";\n\nlibrary AssociatedSystem {\n    struct Data {\n        address proxy;\n        address impl;\n        bytes32 kind;\n    }\n\n    error MismatchAssociatedSystemKind(bytes32 expected, bytes32 actual);\n\n    bytes32 public constant KIND_ERC20 = \"erc20\";\n    bytes32 public constant KIND_ERC721 = \"erc721\";\n    bytes32 public constant KIND_UNMANAGED = \"unmanaged\";\n\n    function load(bytes32 id) internal pure returns (Data storage store) {\n        bytes32 s = keccak256(abi.encode(\"io.synthetix.core-modules.AssociatedSystem\", id));\n        assembly {\n            store.slot := s\n        }\n    }\n\n    function getAddress(Data storage self) internal view returns (address) {\n        return self.proxy;\n    }\n\n    function asToken(Data storage self) internal view returns (ITokenModule) {\n        expectKind(self, KIND_ERC20);\n        return ITokenModule(self.proxy);\n    }\n\n    function asNft(Data storage self) internal view returns (INftModule) {\n        expectKind(self, KIND_ERC721);\n        return INftModule(self.proxy);\n    }\n\n    function set(Data storage self, address proxy, address impl, bytes32 kind) internal {\n        self.proxy = proxy;\n        self.impl = impl;\n        self.kind = kind;\n    }\n\n    function expectKind(Data storage self, bytes32 kind) internal view {\n        bytes32 actualKind = self.kind;\n\n        if (actualKind != kind && actualKind != KIND_UNMANAGED) {\n            revert MismatchAssociatedSystemKind(kind, actualKind);\n        }\n    }\n}\n"
      },
      "contracts/modules/associated-systems/AssociatedSystemsModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport {AssociatedSystemsModule as BaseAssociatedSystemsModule} from \"@synthetixio/core-modules/contracts/modules/AssociatedSystemsModule.sol\";\n\n/**\n * @title Module for connecting to other systems.\n * See core-modules/../AssociatedSystemsModule\n */\n// solhint-disable-next-line no-empty-blocks\ncontract AssociatedSystemsModule is BaseAssociatedSystemsModule {\n\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}