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/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/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/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/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/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/SetUtil.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"./SafeCast.sol\";\n\nlibrary SetUtil {\n    using SafeCastAddress for address;\n    using SafeCastBytes32 for bytes32;\n    using SafeCastU256 for uint256;\n\n    // ----------------------------------------\n    // Uint support\n    // ----------------------------------------\n\n    struct UintSet {\n        Bytes32Set raw;\n    }\n\n    function add(UintSet storage set, uint value) internal {\n        add(set.raw, value.toBytes32());\n    }\n\n    function remove(UintSet storage set, uint value) internal {\n        remove(set.raw, value.toBytes32());\n    }\n\n    function replace(UintSet storage set, uint value, uint newValue) internal {\n        replace(set.raw, value.toBytes32(), newValue.toBytes32());\n    }\n\n    function contains(UintSet storage set, uint value) internal view returns (bool) {\n        return contains(set.raw, value.toBytes32());\n    }\n\n    function length(UintSet storage set) internal view returns (uint) {\n        return length(set.raw);\n    }\n\n    function valueAt(UintSet storage set, uint position) internal view returns (uint) {\n        return valueAt(set.raw, position).toUint();\n    }\n\n    function positionOf(UintSet storage set, uint value) internal view returns (uint) {\n        return positionOf(set.raw, value.toBytes32());\n    }\n\n    function values(UintSet storage set) internal view returns (uint[] memory) {\n        bytes32[] memory store = values(set.raw);\n        uint[] memory result;\n\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // ----------------------------------------\n    // Address support\n    // ----------------------------------------\n\n    struct AddressSet {\n        Bytes32Set raw;\n    }\n\n    function add(AddressSet storage set, address value) internal {\n        add(set.raw, value.toBytes32());\n    }\n\n    function remove(AddressSet storage set, address value) internal {\n        remove(set.raw, value.toBytes32());\n    }\n\n    function replace(AddressSet storage set, address value, address newValue) internal {\n        replace(set.raw, value.toBytes32(), newValue.toBytes32());\n    }\n\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return contains(set.raw, value.toBytes32());\n    }\n\n    function length(AddressSet storage set) internal view returns (uint) {\n        return length(set.raw);\n    }\n\n    function valueAt(AddressSet storage set, uint position) internal view returns (address) {\n        return valueAt(set.raw, position).toAddress();\n    }\n\n    function positionOf(AddressSet storage set, address value) internal view returns (uint) {\n        return positionOf(set.raw, value.toBytes32());\n    }\n\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = values(set.raw);\n        address[] memory result;\n\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // ----------------------------------------\n    // Core bytes32 support\n    // ----------------------------------------\n\n    error PositionOutOfBounds();\n    error ValueNotInSet();\n    error ValueAlreadyInSet();\n\n    struct Bytes32Set {\n        bytes32[] _values;\n        mapping(bytes32 => uint) _positions; // Position zero is never used.\n    }\n\n    function add(Bytes32Set storage set, bytes32 value) internal {\n        if (contains(set, value)) {\n            revert ValueAlreadyInSet();\n        }\n\n        set._values.push(value);\n        set._positions[value] = set._values.length;\n    }\n\n    function remove(Bytes32Set storage set, bytes32 value) internal {\n        uint position = set._positions[value];\n        if (position == 0) {\n            revert ValueNotInSet();\n        }\n\n        uint index = position - 1;\n        uint lastIndex = set._values.length - 1;\n\n        // If the element being deleted is not the last in the values,\n        // move the last element to its position.\n        if (index != lastIndex) {\n            bytes32 lastValue = set._values[lastIndex];\n\n            set._values[index] = lastValue;\n            set._positions[lastValue] = position;\n        }\n\n        // Remove the last element in the values.\n        set._values.pop();\n        delete set._positions[value];\n    }\n\n    function replace(Bytes32Set storage set, bytes32 value, bytes32 newValue) internal {\n        if (!contains(set, value)) {\n            revert ValueNotInSet();\n        }\n\n        if (contains(set, newValue)) {\n            revert ValueAlreadyInSet();\n        }\n\n        uint position = set._positions[value];\n        delete set._positions[value];\n\n        uint index = position - 1;\n\n        set._values[index] = newValue;\n        set._positions[newValue] = position;\n    }\n\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return set._positions[value] != 0;\n    }\n\n    function length(Bytes32Set storage set) internal view returns (uint) {\n        return set._values.length;\n    }\n\n    function valueAt(Bytes32Set storage set, uint position) internal view returns (bytes32) {\n        if (position == 0 || position > set._values.length) {\n            revert PositionOutOfBounds();\n        }\n\n        uint index = position - 1;\n\n        return set._values[index];\n    }\n\n    function positionOf(Bytes32Set storage set, bytes32 value) internal view returns (uint) {\n        if (!contains(set, value)) {\n            revert ValueNotInSet();\n        }\n\n        return set._positions[value];\n    }\n\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        return set._values;\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/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/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/interfaces/external/IAny2EVMMessageReceiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"../../utils/CcipClient.sol\";\n\n/// @notice Application contracts that intend to receive messages from\n/// the router should implement this interface.\ninterface IAny2EVMMessageReceiver {\n    /// @notice Router calls this to deliver a message.\n    /// If this reverts, any token transfers also revert. The message\n    /// will move to a FAILED state and become available for manual execution\n    /// as a retry. Fees already paid are NOT currently refunded (may change).\n    /// @param message CCIP Message\n    /// @dev Note ensure you check the msg.sender is the router\n    function ccipReceive(CcipClient.Any2EVMMessage calldata message) external;\n}\n"
      },
      "contracts/interfaces/external/ICcipRouterClient.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"../../utils/CcipClient.sol\";\n\ninterface ICcipRouterClient {\n    error UnsupportedDestinationChain(uint64 destinationChainId);\n    /// @dev Sender is not whitelisted\n    error SenderNotAllowed(address sender);\n    error InsufficientFeeTokenAmount();\n    /// @dev Sent msg.value with a non-empty feeToken\n    error InvalidMsgValue();\n\n    /// @notice Checks if the given chain ID is supported for sending/receiving.\n    /// @param chainId The chain to check\n    /// @return supported is true if it is supported, false if not\n    function isChainSupported(uint64 chainId) external view returns (bool supported);\n\n    /// @notice Gets a list of all supported tokens which can be sent or received\n    /// to/from a given chain id.\n    /// @param chainId The chainId.\n    /// @return tokens The addresses of all tokens that are supported.\n    function getSupportedTokens(uint64 chainId) external view returns (address[] memory tokens);\n\n    /// @param destinationChainId The destination chain ID\n    /// @param message The cross-chain CCIP message including data and/or tokens\n    /// @return fee returns execution fee for the specified message\n    /// delivery to destination chain\n    /// @dev returns 0 fee on invalid message.\n    function getFee(\n        uint64 destinationChainId,\n        CcipClient.EVM2AnyMessage memory message\n    ) external view returns (uint256 fee);\n\n    /// @notice Request a message to be sent to the destination chain\n    /// @param destinationChainId The destination chain ID\n    /// @param message The cross-chain CCIP message including data and/or tokens\n    /// @return messageId The message ID\n    /// @dev Note if msg.value is larger than the required fee (from getFee) we accept\n    /// the overpayment with no refund.\n    function ccipSend(\n        uint64 destinationChainId,\n        CcipClient.EVM2AnyMessage calldata message\n    ) external payable returns (bytes32 messageId);\n}\n"
      },
      "contracts/interfaces/IUtilsModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport {IERC165} from \"@synthetixio/core-contracts/contracts/interfaces/IERC165.sol\";\n\n/**\n * @title Module with assorted utility functions.\n */\ninterface IUtilsModule is IERC165 {\n    /**\n     * @notice Emitted when a new cross chain network becomes supported by the protocol\n     */\n    event NewSupportedCrossChainNetwork(uint64 newChainId);\n\n    /**\n     * @notice Configure CCIP addresses on the stablecoin.\n     * @param ccipRouter The address on this chain to which CCIP messages will be sent or received.\n     * @param ccipTokenPool The address where CCIP fees will be sent to when sending and receiving cross chain messages.\n     */\n    function configureChainlinkCrossChain(address ccipRouter, address ccipTokenPool) external;\n\n    /**\n     * @notice Used to add new cross chain networks to the protocol\n     * Ignores a network if it matches the current chain id\n     * Ignores a network if it has already been added\n     * @param supportedNetworks array of all networks that are supported by the protocol\n     * @param ccipSelectors the ccip \"selector\" which maps to the chain id on the same index. must be same length as `supportedNetworks`\n     * @return numRegistered the number of networks that were actually registered\n     */\n    function setSupportedCrossChainNetworks(\n        uint64[] memory supportedNetworks,\n        uint64[] memory ccipSelectors\n    ) external returns (uint256 numRegistered);\n\n    /**\n     * @notice Configure the system's single oracle manager address.\n     * @param oracleManagerAddress The address of the oracle manager.\n     */\n    function configureOracleManager(address oracleManagerAddress) external;\n\n    /**\n     * @notice Configure a generic value in the KV system\n     * @param k the key of the value to set\n     * @param v the value that the key should be set to\n     */\n    function setConfig(bytes32 k, bytes32 v) external;\n\n    /**\n     * @notice Read a generic value from the KV system\n     * @param k the key to read\n     * @return v the value set on the specified k\n     */\n    function getConfig(bytes32 k) external view returns (bytes32 v);\n\n    /**\n     * @notice Read a UINT value from the KV system\n     * @param k the key to read\n     * @return v the value set on the specified k\n     */\n    function getConfigUint(bytes32 k) external view returns (uint256 v);\n\n    /**\n     * @notice Read a Address value from the KV system\n     * @param k the key to read\n     * @return v the value set on the specified k\n     */\n    function getConfigAddress(bytes32 k) external view returns (address v);\n\n    /**\n     * @notice Checks if the address is the trusted forwarder\n     * @param forwarder The address to check\n     * @return Whether the address is the trusted forwarder\n     */\n    function isTrustedForwarder(address forwarder) external pure returns (bool);\n\n    /**\n     * @notice Provides the address of the trusted forwarder\n     * @return Address of the trusted forwarder\n     */\n    function getTrustedForwarder() external pure returns (address);\n}\n"
      },
      "contracts/modules/core/UtilsModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"@synthetixio/core-modules/contracts/interfaces/IAssociatedSystemsModule.sol\";\nimport \"@synthetixio/core-modules/contracts/storage/AssociatedSystem.sol\";\nimport \"@synthetixio/core-contracts/contracts/ownership/OwnableStorage.sol\";\nimport \"@synthetixio/core-contracts/contracts/errors/ParameterError.sol\";\nimport \"@synthetixio/core-contracts/contracts/utils/SafeCast.sol\";\nimport \"@synthetixio/core-contracts/contracts/utils/ERC2771Context.sol\";\n\nimport \"../../interfaces/IUtilsModule.sol\";\n\nimport \"../../storage/CrossChain.sol\";\nimport \"../../storage/OracleManager.sol\";\nimport \"../../storage/Config.sol\";\n\nimport \"../../interfaces/external/IAny2EVMMessageReceiver.sol\";\n\n/**\n * @title Module with assorted utility functions.\n * @dev See IUtilsModule.\n */\ncontract UtilsModule is IUtilsModule {\n    using AssociatedSystem for AssociatedSystem.Data;\n    using SetUtil for SetUtil.UintSet;\n    using SafeCastU256 for uint256;\n\n    bytes32 private constant _USD_TOKEN = \"USDToken\";\n    bytes32 private constant _CCIP_CHAINLINK_SEND = \"ccipChainlinkSend\";\n    bytes32 private constant _CCIP_CHAINLINK_RECV = \"ccipChainlinkRecv\";\n    bytes32 private constant _CCIP_CHAINLINK_TOKEN_POOL = \"ccipChainlinkTokenPool\";\n\n    /**\n     * @inheritdoc IUtilsModule\n     */\n    function configureChainlinkCrossChain(\n        address ccipRouter,\n        address ccipTokenPool\n    ) external override {\n        OwnableStorage.onlyOwner();\n\n        CrossChain.Data storage cc = CrossChain.load();\n\n        cc.ccipRouter = ICcipRouterClient(ccipRouter);\n\n        IAssociatedSystemsModule usdToken = IAssociatedSystemsModule(\n            AssociatedSystem.load(_USD_TOKEN).proxy\n        );\n\n        usdToken.registerUnmanagedSystem(_CCIP_CHAINLINK_SEND, ccipRouter);\n        usdToken.registerUnmanagedSystem(_CCIP_CHAINLINK_RECV, ccipRouter);\n        usdToken.registerUnmanagedSystem(_CCIP_CHAINLINK_TOKEN_POOL, ccipTokenPool);\n    }\n\n    /**\n     * @inheritdoc IUtilsModule\n     */\n    function setSupportedCrossChainNetworks(\n        uint64[] memory supportedNetworks,\n        uint64[] memory ccipSelectors\n    ) external returns (uint256 numRegistered) {\n        OwnableStorage.onlyOwner();\n\n        uint64 myChainId = block.chainid.to64();\n\n        if (ccipSelectors.length != supportedNetworks.length) {\n            revert ParameterError.InvalidParameter(\"ccipSelectors\", \"must match length\");\n        }\n\n        CrossChain.Data storage cc = CrossChain.load();\n        for (uint i = 0; i < supportedNetworks.length; i++) {\n            if (supportedNetworks[i] == myChainId) continue;\n            if (\n                supportedNetworks[i] != myChainId &&\n                !cc.supportedNetworks.contains(supportedNetworks[i])\n            ) {\n                numRegistered++;\n                cc.supportedNetworks.add(supportedNetworks[i]);\n                emit NewSupportedCrossChainNetwork(supportedNetworks[i]);\n            }\n\n            cc.ccipChainIdToSelector[supportedNetworks[i]] = ccipSelectors[i];\n            cc.ccipSelectorToChainId[ccipSelectors[i]] = supportedNetworks[i];\n        }\n    }\n\n    /**\n     * @inheritdoc IUtilsModule\n     */\n    function isTrustedForwarder(address forwarder) external pure returns (bool) {\n        return ERC2771Context.isTrustedForwarder(forwarder);\n    }\n\n    /**\n     * @inheritdoc IUtilsModule\n     */\n    function getTrustedForwarder() external pure returns (address) {\n        return ERC2771Context.trustedForwarder();\n    }\n\n    /**\n     * @inheritdoc IUtilsModule\n     */\n    function configureOracleManager(address oracleManagerAddress) external override {\n        OwnableStorage.onlyOwner();\n\n        OracleManager.Data storage oracle = OracleManager.load();\n        oracle.oracleManagerAddress = oracleManagerAddress;\n    }\n\n    function setConfig(bytes32 k, bytes32 v) external override {\n        OwnableStorage.onlyOwner();\n        return Config.put(k, v);\n    }\n\n    function getConfig(bytes32 k) external view override returns (bytes32 v) {\n        return Config.read(k, 0);\n    }\n\n    function getConfigUint(bytes32 k) external view override returns (uint256 v) {\n        return Config.readUint(k, 0);\n    }\n\n    function getConfigAddress(bytes32 k) external view override returns (address v) {\n        return Config.readAddress(k, address(0));\n    }\n\n    function supportsInterface(\n        bytes4 interfaceId\n    ) public view virtual override(IERC165) returns (bool) {\n        return\n            interfaceId == type(IAny2EVMMessageReceiver).interfaceId ||\n            interfaceId == this.supportsInterface.selector;\n    }\n}\n"
      },
      "contracts/storage/Config.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title System wide configuration for anything\n */\nlibrary Config {\n    struct Data {\n        uint256 __unused;\n    }\n\n    /**\n     * @dev Returns a config value\n     */\n    function read(bytes32 k, bytes32 zeroValue) internal view returns (bytes32 v) {\n        bytes32 s = keccak256(abi.encode(\"Config\", k));\n        assembly {\n            v := sload(s)\n        }\n\n        if (v == bytes32(0)) {\n            v = zeroValue;\n        }\n    }\n\n    function readUint(bytes32 k, uint256 zeroValue) internal view returns (uint256 v) {\n        // solhint-disable-next-line numcast/safe-cast\n        return uint(read(k, bytes32(zeroValue)));\n    }\n\n    function readAddress(bytes32 k, address zeroValue) internal view returns (address v) {\n        // solhint-disable-next-line numcast/safe-cast\n        return address(uint160(readUint(k, uint160(zeroValue))));\n    }\n\n    function put(bytes32 k, bytes32 v) internal {\n        bytes32 s = keccak256(abi.encode(\"Config\", k));\n        assembly {\n            sstore(s, v)\n        }\n    }\n}\n"
      },
      "contracts/storage/CrossChain.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport {SetUtil} from \"@synthetixio/core-contracts/contracts/utils/SetUtil.sol\";\nimport {AccessError} from \"@synthetixio/core-contracts/contracts/errors/AccessError.sol\";\n\nimport \"@synthetixio/core-contracts/contracts/utils/ERC2771Context.sol\";\nimport \"@synthetixio/core-contracts/contracts/interfaces/IERC20.sol\";\nimport \"../interfaces/external/ICcipRouterClient.sol\";\n\n/**\n * @title System wide configuration for anything\n */\nlibrary CrossChain {\n    using SetUtil for SetUtil.UintSet;\n\n    event ProcessedCcipMessage(bytes payload, bytes result);\n\n    error NotCcipRouter(address);\n    error UnsupportedNetwork(uint64);\n    error InsufficientCcipFee(uint256 requiredAmount, uint256 availableAmount);\n    error InvalidMessage();\n\n    bytes32 private constant _SLOT_CROSS_CHAIN =\n        keccak256(abi.encode(\"io.synthetix.synthetix.CrossChain\"));\n\n    struct Data {\n        ICcipRouterClient ccipRouter;\n        SetUtil.UintSet supportedNetworks;\n        mapping(uint64 => uint64) ccipChainIdToSelector;\n        mapping(uint64 => uint64) ccipSelectorToChainId;\n    }\n\n    function load() internal pure returns (Data storage crossChain) {\n        bytes32 s = _SLOT_CROSS_CHAIN;\n        assembly {\n            crossChain.slot := s\n        }\n    }\n\n    function processCcipReceive(Data storage self, CcipClient.Any2EVMMessage memory data) internal {\n        if (\n            address(self.ccipRouter) == address(0) ||\n            ERC2771Context._msgSender() != address(self.ccipRouter)\n        ) {\n            revert NotCcipRouter(ERC2771Context._msgSender());\n        }\n\n        uint64 sourceChainId = self.ccipSelectorToChainId[data.sourceChainSelector];\n\n        if (!self.supportedNetworks.contains(sourceChainId)) {\n            revert UnsupportedNetwork(sourceChainId);\n        }\n\n        address sender = abi.decode(data.sender, (address));\n        if (sender != address(this)) {\n            revert AccessError.Unauthorized(sender);\n        }\n\n        address caller;\n        bytes memory payload;\n\n        if (data.tokenAmounts.length == 1) {\n            address to = abi.decode(data.data, (address));\n\n            caller = data.tokenAmounts[0].token;\n            payload = abi.encodeWithSelector(\n                IERC20.transfer.selector,\n                to,\n                data.tokenAmounts[0].amount\n            );\n        } else {\n            revert InvalidMessage();\n        }\n\n        // at this point, everything should be good to send the message to ourselves.\n        // the below `onlyCrossChain` function will verify that the caller is self\n        (bool success, bytes memory result) = caller.call(payload);\n\n        if (!success) {\n            uint len = result.length;\n            assembly {\n                revert(add(result, 0x20), len)\n            }\n        }\n\n        emit ProcessedCcipMessage(payload, result);\n    }\n\n    function onlyCrossChain() internal view {\n        if (ERC2771Context._msgSender() != address(this)) {\n            revert AccessError.Unauthorized(ERC2771Context._msgSender());\n        }\n    }\n\n    /**\n     * @dev Transfers tokens to a destination chain.\n     */\n    function teleport(\n        Data storage self,\n        uint64 destChainId,\n        address token,\n        uint256 amount,\n        uint256 gasLimit\n    ) internal returns (uint256 gasTokenUsed) {\n        ICcipRouterClient router = self.ccipRouter;\n\n        CcipClient.EVMTokenAmount[] memory tokenAmounts = new CcipClient.EVMTokenAmount[](1);\n        tokenAmounts[0] = CcipClient.EVMTokenAmount(token, amount);\n\n        bytes memory data = abi.encode(ERC2771Context._msgSender());\n        CcipClient.EVM2AnyMessage memory sentMsg = CcipClient.EVM2AnyMessage(\n            abi.encode(address(this)), // abi.encode(receiver address) for dest EVM chains\n            data,\n            tokenAmounts,\n            address(0), // Address of feeToken. address(0) means you will send msg.value.\n            CcipClient._argsToBytes(CcipClient.EVMExtraArgsV1(gasLimit, false))\n        );\n\n        uint64 chainSelector = self.ccipChainIdToSelector[destChainId];\n        uint256 fee = router.getFee(chainSelector, sentMsg);\n\n        // need to check sufficient fee here or else the error is very confusing\n        if (address(this).balance < fee) {\n            revert InsufficientCcipFee(fee, address(this).balance);\n        }\n\n        router.ccipSend{value: fee}(chainSelector, sentMsg);\n\n        return fee;\n    }\n\n    function refundLeftoverGas(uint256 gasTokenUsed) internal returns (uint256 amountRefunded) {\n        amountRefunded = msg.value - gasTokenUsed;\n\n        (bool success, bytes memory result) = ERC2771Context._msgSender().call{\n            value: amountRefunded\n        }(\"\");\n\n        if (!success) {\n            uint256 len = result.length;\n            assembly {\n                revert(result, len)\n            }\n        }\n    }\n}\n"
      },
      "contracts/storage/OracleManager.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title Represents Oracle Manager\n */\nlibrary OracleManager {\n    bytes32 private constant _SLOT_ORACLE_MANAGER =\n        keccak256(abi.encode(\"io.synthetix.synthetix.OracleManager\"));\n\n    struct Data {\n        /**\n         * @dev The oracle manager address.\n         */\n        address oracleManagerAddress;\n    }\n\n    /**\n     * @dev Loads the singleton storage info about the oracle manager.\n     */\n    function load() internal pure returns (Data storage oracleManager) {\n        bytes32 s = _SLOT_ORACLE_MANAGER;\n        assembly {\n            oracleManager.slot := s\n        }\n    }\n}\n"
      },
      "contracts/utils/CcipClient.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nlibrary CcipClient {\n    struct EVMTokenAmount {\n        address token; // token address on the local chain\n        uint256 amount;\n    }\n\n    struct Any2EVMMessage {\n        bytes32 messageId; // MessageId corresponding to ccipSend on source\n        uint64 sourceChainSelector;\n        bytes sender; // abi.decode(sender) if coming from an EVM chain\n        bytes data; // payload sent in original message\n        EVMTokenAmount[] tokenAmounts;\n    }\n\n    // If extraArgs is empty bytes, the default is\n    // 200k gas limit and strict = false.\n    struct EVM2AnyMessage {\n        bytes receiver; // abi.encode(receiver address) for dest EVM chains\n        bytes data; // Data payload\n        EVMTokenAmount[] tokenAmounts; // Token transfers\n        address feeToken; // Address of feeToken. address(0) means you will send msg.value.\n        bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1)\n    }\n\n    // extraArgs will evolve to support new features\n    // bytes4(keccak256(\"CCIP EVMExtraArgsV1\"));\n    bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9;\n    struct EVMExtraArgsV1 {\n        uint256 gasLimit; // ATTENTION!!! MAX GAS LIMIT 4M FOR ALPHA TESTING\n        bool strict; // See strict sequencing details below.\n    }\n\n    function _argsToBytes(\n        EVMExtraArgsV1 memory extraArgs\n    ) internal pure returns (bytes memory bts) {\n        return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs);\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}