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/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/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/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"
      },
      "@synthetixio/core-modules/contracts/storage/FeatureFlag.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"@synthetixio/core-contracts/contracts/utils/SetUtil.sol\";\nimport \"@synthetixio/core-contracts/contracts/utils/ERC2771Context.sol\";\n\nlibrary FeatureFlag {\n    using SetUtil for SetUtil.AddressSet;\n\n    error FeatureUnavailable(bytes32 which);\n\n    struct Data {\n        bytes32 name;\n        bool allowAll;\n        bool denyAll;\n        SetUtil.AddressSet permissionedAddresses;\n        address[] deniers;\n    }\n\n    function load(bytes32 featureName) internal pure returns (Data storage store) {\n        bytes32 s = keccak256(abi.encode(\"io.synthetix.core-modules.FeatureFlag\", featureName));\n        assembly {\n            store.slot := s\n        }\n    }\n\n    function ensureAccessToFeature(bytes32 feature) internal view {\n        if (!hasAccess(feature, ERC2771Context._msgSender())) {\n            revert FeatureUnavailable(feature);\n        }\n    }\n\n    function hasAccess(bytes32 feature, address value) internal view returns (bool) {\n        Data storage store = FeatureFlag.load(feature);\n\n        if (store.denyAll) {\n            return false;\n        }\n\n        return store.allowAll || store.permissionedAddresses.contains(value);\n    }\n\n    function isDenier(Data storage self, address possibleDenier) internal view returns (bool) {\n        for (uint i = 0; i < self.deniers.length; i++) {\n            if (self.deniers[i] == possibleDenier) {\n                return true;\n            }\n        }\n\n        return false;\n    }\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/ICrossChainUSDModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\n/**\n * @title Module for the cross-chain transfers of stablecoins.\n */\ninterface ICrossChainUSDModule {\n    event TransferCrossChainInitiated(\n        uint64 indexed destChainId,\n        uint256 indexed amount,\n        address sender\n    );\n\n    /**\n     * @notice Allows users to transfer tokens cross-chain using CCIP.\n     * @param destChainId The id of the chain where tokens are to be transferred to.\n     * @param amount The amount of tokens to be transferred, denominated with 18 decimals of precision.\n     * @return gasTokenUsed The amount of fees paid in the cross-chain transfer, denominated with 18 decimals of precision.\n     */\n    function transferCrossChain(\n        uint64 destChainId,\n        uint256 amount\n    ) external payable returns (uint256 gasTokenUsed);\n}\n"
      },
      "contracts/modules/core/CrossChainUSDModule.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity >=0.8.11 <0.9.0;\n\nimport \"../../interfaces/ICrossChainUSDModule.sol\";\nimport \"@synthetixio/core-modules/contracts/interfaces/ITokenModule.sol\";\nimport \"@synthetixio/core-contracts/contracts/utils/ERC2771Context.sol\";\n\nimport \"../../storage/CrossChain.sol\";\n\nimport \"@synthetixio/core-modules/contracts/storage/AssociatedSystem.sol\";\nimport \"@synthetixio/core-modules/contracts/storage/FeatureFlag.sol\";\n\n/**\n * @title Module for the cross-chain transfers of stablecoins.\n * @dev See ICrossChainUSDModule.\n */\ncontract CrossChainUSDModule is ICrossChainUSDModule {\n    using CrossChain for CrossChain.Data;\n    using AssociatedSystem for AssociatedSystem.Data;\n\n    uint256 private constant _TRANSFER_GAS_LIMIT = 100000;\n    bytes32 private constant _USD_TOKEN = \"USDToken\";\n    bytes32 private constant _TRANSFER_CROSS_CHAIN_FEATURE_FLAG = \"transferCrossChain\";\n\n    /**\n     * @inheritdoc ICrossChainUSDModule\n     */\n    function transferCrossChain(\n        uint64 destChainId,\n        uint256 amount\n    ) external payable returns (uint256 gasTokenUsed) {\n        FeatureFlag.ensureAccessToFeature(_TRANSFER_CROSS_CHAIN_FEATURE_FLAG);\n\n        CrossChain.Data storage cc = CrossChain.load();\n        ITokenModule usdToken = AssociatedSystem.load(_USD_TOKEN).asToken();\n        usdToken.transferFrom(ERC2771Context._msgSender(), address(this), amount);\n        usdToken.approve(address(cc.ccipRouter), amount);\n\n        gasTokenUsed = cc.teleport(destChainId, address(usdToken), amount, _TRANSFER_GAS_LIMIT);\n        CrossChain.refundLeftoverGas(gasTokenUsed);\n\n        emit TransferCrossChainInitiated(destChainId, amount, ERC2771Context._msgSender());\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/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": {}
    }
  }}