{
  "language": "Solidity",
  "sources": {
    "contracts/L1/L1ERC721Bridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L1ERC721Bridge\n * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to\n *         make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n *         acts as an escrow for ERC721 tokens deposited into L2.\n */\ncontract L1ERC721Bridge is ERC721Bridge, Semver {\n    /**\n     * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token\n     *         by ID was deposited for a given L2 token.\n     */\n    mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;\n\n    /**\n     * @custom:semver 1.0.0\n     *\n     * @param _messenger   Address of the CrossDomainMessenger on this network.\n     * @param _otherBridge Address of the ERC721 bridge on the other network.\n     */\n    constructor(address _messenger, address _otherBridge)\n        Semver(1, 0, 0)\n        ERC721Bridge(_messenger, _otherBridge)\n    {}\n\n    /*************************\n     * Cross-chain Functions *\n     *************************/\n\n    /**\n     * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n     *         recipient on this domain.\n     *\n     * @param _localToken  Address of the ERC721 token on this domain.\n     * @param _remoteToken Address of the ERC721 token on the other domain.\n     * @param _from        Address that triggered the bridge on the other domain.\n     * @param _to          Address to receive the token on this domain.\n     * @param _tokenId     ID of the token being deposited.\n     * @param _extraData   Optional data to forward to L2. Data supplied here will not be used to\n     *                     execute any code on L2 and is only emitted as extra data for the\n     *                     convenience of off-chain tooling.\n     */\n    function finalizeBridgeERC721(\n        address _localToken,\n        address _remoteToken,\n        address _from,\n        address _to,\n        uint256 _tokenId,\n        bytes calldata _extraData\n    ) external onlyOtherBridge {\n        require(_localToken != address(this), \"L1ERC721Bridge: local token cannot be self\");\n\n        // Checks that the L1/L2 NFT pair has a token ID that is escrowed in the L1 Bridge.\n        require(\n            deposits[_localToken][_remoteToken][_tokenId] == true,\n            \"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\"\n        );\n\n        // Mark that the token ID for this L1/L2 token pair is no longer escrowed in the L1\n        // Bridge.\n        deposits[_localToken][_remoteToken][_tokenId] = false;\n\n        // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the\n        // withdrawer.\n        IERC721(_localToken).safeTransferFrom(address(this), _to, _tokenId);\n\n        // slither-disable-next-line reentrancy-events\n        emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n    }\n\n    /**\n     * @inheritdoc ERC721Bridge\n     */\n    function _initiateBridgeERC721(\n        address _localToken,\n        address _remoteToken,\n        address _from,\n        address _to,\n        uint256 _tokenId,\n        uint32 _minGasLimit,\n        bytes calldata _extraData\n    ) internal override {\n        require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n        // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId)\n        bytes memory message = abi.encodeWithSelector(\n            L2ERC721Bridge.finalizeBridgeERC721.selector,\n            _remoteToken,\n            _localToken,\n            _from,\n            _to,\n            _tokenId,\n            _extraData\n        );\n\n        // Lock token into bridge\n        deposits[_localToken][_remoteToken][_tokenId] = true;\n        IERC721(_localToken).transferFrom(_from, address(this), _tokenId);\n\n        // Send calldata into L2\n        messenger.sendMessage(otherBridge, message, _minGasLimit);\n        emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n    }\n}\n"
    },
    "contracts/universal/op-erc721/ERC721Bridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n    CrossDomainMessenger\n} from \"@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title ERC721Bridge\n * @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.\n */\nabstract contract ERC721Bridge {\n    /**\n     * @notice Emitted when an ERC721 bridge to the other network is initiated.\n     *\n     * @param localToken  Address of the token on this domain.\n     * @param remoteToken Address of the token on the remote domain.\n     * @param from        Address that initiated bridging action.\n     * @param to          Address to receive the token.\n     * @param tokenId     ID of the specific token deposited.\n     * @param extraData   Extra data for use on the client-side.\n     */\n    event ERC721BridgeInitiated(\n        address indexed localToken,\n        address indexed remoteToken,\n        address indexed from,\n        address to,\n        uint256 tokenId,\n        bytes extraData\n    );\n\n    /**\n     * @notice Emitted when an ERC721 bridge from the other network is finalized.\n     *\n     * @param localToken  Address of the token on this domain.\n     * @param remoteToken Address of the token on the remote domain.\n     * @param from        Address that initiated bridging action.\n     * @param to          Address to receive the token.\n     * @param tokenId     ID of the specific token deposited.\n     * @param extraData   Extra data for use on the client-side.\n     */\n    event ERC721BridgeFinalized(\n        address indexed localToken,\n        address indexed remoteToken,\n        address indexed from,\n        address to,\n        uint256 tokenId,\n        bytes extraData\n    );\n\n    /**\n     * @notice Messenger contract on this domain.\n     */\n    CrossDomainMessenger public immutable messenger;\n\n    /**\n     * @notice Address of the bridge on the other network.\n     */\n    address public immutable otherBridge;\n\n    /**\n     * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n     */\n    uint256[49] private __gap;\n\n    /**\n     * @notice Ensures that the caller is a cross-chain message from the other bridge.\n     */\n    modifier onlyOtherBridge() {\n        require(\n            msg.sender == address(messenger) && messenger.xDomainMessageSender() == otherBridge,\n            \"ERC721Bridge: function can only be called from the other bridge\"\n        );\n        _;\n    }\n\n    /**\n     * @param _messenger   Address of the CrossDomainMessenger on this network.\n     * @param _otherBridge Address of the ERC721 bridge on the other network.\n     */\n    constructor(address _messenger, address _otherBridge) {\n        require(_messenger != address(0), \"ERC721Bridge: messenger cannot be address(0)\");\n        require(_otherBridge != address(0), \"ERC721Bridge: other bridge cannot be address(0)\");\n\n        messenger = CrossDomainMessenger(_messenger);\n        otherBridge = _otherBridge;\n    }\n\n    /**\n     * @notice Initiates a bridge of an NFT to the caller's account on the other chain. Note that\n     *         this function can only be called by EOAs. Smart contract wallets should use the\n     *         `bridgeERC721To` function after ensuring that the recipient address on the remote\n     *         chain exists. Also note that the current owner of the token on this chain must\n     *         approve this contract to operate the NFT before it can be bridged.\n     *         **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n     *         bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n     *         wait for the one-week challenge period to elapse before their Optimism-native NFT\n     *         can be refunded on L2.\n     *\n     * @param _localToken  Address of the ERC721 on this domain.\n     * @param _remoteToken Address of the ERC721 on the remote domain.\n     * @param _tokenId     Token ID to bridge.\n     * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n     * @param _extraData   Optional data to forward to the other chain. Data supplied here will not\n     *                     be used to execute any code on the other chain and is only emitted as\n     *                     extra data for the convenience of off-chain tooling.\n     */\n    function bridgeERC721(\n        address _localToken,\n        address _remoteToken,\n        uint256 _tokenId,\n        uint32 _minGasLimit,\n        bytes calldata _extraData\n    ) external {\n        // Modifier requiring sender to be EOA. This prevents against a user error that would occur\n        // if the sender is a smart contract wallet that has a different address on the remote chain\n        // (or doesn't have an address on the remote chain at all). The user would fail to receive\n        // the NFT if they use this function because it sends the NFT to the same address as the\n        // caller. This check could be bypassed by a malicious contract via initcode, but it takes\n        // care of the user error we want to avoid.\n        require(!Address.isContract(msg.sender), \"ERC721Bridge: account is not externally owned\");\n\n        _initiateBridgeERC721(\n            _localToken,\n            _remoteToken,\n            msg.sender,\n            msg.sender,\n            _tokenId,\n            _minGasLimit,\n            _extraData\n        );\n    }\n\n    /**\n     * @notice Initiates a bridge of an NFT to some recipient's account on the other chain. Note\n     *         that the current owner of the token on this chain must approve this contract to\n     *         operate the NFT before it can be bridged.\n     *         **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n     *         bridge only supports ERC721s originally deployed on Ethereum. Users will need to\n     *         wait for the one-week challenge period to elapse before their Optimism-native NFT\n     *         can be refunded on L2.\n     *\n     * @param _localToken  Address of the ERC721 on this domain.\n     * @param _remoteToken Address of the ERC721 on the remote domain.\n     * @param _to          Address to receive the token on the other domain.\n     * @param _tokenId     Token ID to bridge.\n     * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n     * @param _extraData   Optional data to forward to the other chain. Data supplied here will not\n     *                     be used to execute any code on the other chain and is only emitted as\n     *                     extra data for the convenience of off-chain tooling.\n     */\n    function bridgeERC721To(\n        address _localToken,\n        address _remoteToken,\n        address _to,\n        uint256 _tokenId,\n        uint32 _minGasLimit,\n        bytes calldata _extraData\n    ) external {\n        require(_to != address(0), \"ERC721Bridge: nft recipient cannot be address(0)\");\n\n        _initiateBridgeERC721(\n            _localToken,\n            _remoteToken,\n            msg.sender,\n            _to,\n            _tokenId,\n            _minGasLimit,\n            _extraData\n        );\n    }\n\n    /**\n     * @notice Internal function for initiating a token bridge to the other domain.\n     *\n     * @param _localToken  Address of the ERC721 on this domain.\n     * @param _remoteToken Address of the ERC721 on the remote domain.\n     * @param _from        Address of the sender on this domain.\n     * @param _to          Address to receive the token on the other domain.\n     * @param _tokenId     Token ID to bridge.\n     * @param _minGasLimit Minimum gas limit for the bridge message on the other domain.\n     * @param _extraData   Optional data to forward to the other domain. Data supplied here will\n     *                     not be used to execute any code on the other domain and is only emitted\n     *                     as extra data for the convenience of off-chain tooling.\n     */\n    function _initiateBridgeERC721(\n        address _localToken,\n        address _remoteToken,\n        address _from,\n        address _to,\n        uint256 _tokenId,\n        uint32 _minGasLimit,\n        bytes calldata _extraData\n    ) internal virtual;\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/IERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes calldata data\n    ) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: 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(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool _approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"
    },
    "contracts/L2/L2ERC721Bridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/op-erc721/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/op-erc721/IOptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title L2ERC721Bridge\n * @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to\n *         make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract\n *         acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.\n *         This contract also acts as a burner for tokens being withdrawn.\n *         **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This\n *         bridge ONLY supports ERC721s originally deployed on Ethereum. Users will need to\n *         wait for the one-week challenge period to elapse before their Optimism-native NFT\n *         can be refunded on L2.\n */\ncontract L2ERC721Bridge is ERC721Bridge, Semver {\n    /**\n     * @custom:semver 1.0.0\n     *\n     * @param _messenger   Address of the CrossDomainMessenger on this network.\n     * @param _otherBridge Address of the ERC721 bridge on the other network.\n     */\n    constructor(address _messenger, address _otherBridge)\n        Semver(1, 0, 0)\n        ERC721Bridge(_messenger, _otherBridge)\n    {}\n\n    /**\n     * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the\n     *         recipient on this domain.\n     *\n     * @param _localToken  Address of the ERC721 token on this domain.\n     * @param _remoteToken Address of the ERC721 token on the other domain.\n     * @param _from        Address that triggered the bridge on the other domain.\n     * @param _to          Address to receive the token on this domain.\n     * @param _tokenId     ID of the token being deposited.\n     * @param _extraData   Optional data to forward to L1. Data supplied here will not be used to\n     *                     execute any code on L1 and is only emitted as extra data for the\n     *                     convenience of off-chain tooling.\n     */\n    function finalizeBridgeERC721(\n        address _localToken,\n        address _remoteToken,\n        address _from,\n        address _to,\n        uint256 _tokenId,\n        bytes calldata _extraData\n    ) external onlyOtherBridge {\n        require(_localToken != address(this), \"L2ERC721Bridge: local token cannot be self\");\n\n        // Note that supportsInterface makes a callback to the _localToken address which is user\n        // provided.\n        require(\n            ERC165Checker.supportsInterface(_localToken, type(IOptimismMintableERC721).interfaceId),\n            \"L2ERC721Bridge: local token interface is not compliant\"\n        );\n\n        require(\n            _remoteToken == IOptimismMintableERC721(_localToken).remoteToken(),\n            \"L2ERC721Bridge: wrong remote token for Optimism Mintable ERC721 local token\"\n        );\n\n        // When a deposit is finalized, we give the NFT with the same tokenId to the account\n        // on L2. Note that safeMint makes a callback to the _to address which is user provided.\n        IOptimismMintableERC721(_localToken).safeMint(_to, _tokenId);\n\n        // slither-disable-next-line reentrancy-events\n        emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n    }\n\n    /**\n     * @inheritdoc ERC721Bridge\n     */\n    function _initiateBridgeERC721(\n        address _localToken,\n        address _remoteToken,\n        address _from,\n        address _to,\n        uint256 _tokenId,\n        uint32 _minGasLimit,\n        bytes calldata _extraData\n    ) internal override {\n        require(_remoteToken != address(0), \"ERC721Bridge: remote token cannot be address(0)\");\n\n        // Check that the withdrawal is being initiated by the NFT owner\n        require(\n            _from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),\n            \"Withdrawal is not being initiated by NFT owner\"\n        );\n\n        // Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)\n        // slither-disable-next-line reentrancy-events\n        address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();\n        require(\n            remoteToken == _remoteToken,\n            \"L2ERC721Bridge: remote token does not match given value\"\n        );\n\n        // When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2\n        // usage\n        // slither-disable-next-line reentrancy-events\n        IOptimismMintableERC721(_localToken).burn(_from, _tokenId);\n\n        bytes memory message = abi.encodeWithSelector(\n            L1ERC721Bridge.finalizeBridgeERC721.selector,\n            remoteToken,\n            _localToken,\n            _from,\n            _to,\n            _tokenId,\n            _extraData\n        );\n\n        // Send message to L1 bridge\n        // slither-disable-next-line reentrancy-events\n        messenger.sendMessage(otherBridge, message, _minGasLimit);\n\n        // slither-disable-next-line reentrancy-events\n        emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n    }\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\n\n/**\n * @title Semver\n * @notice Semver is a simple contract for managing contract versions.\n */\ncontract Semver {\n    /**\n     * @notice Contract version number (major).\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    uint256 private immutable MAJOR_VERSION;\n\n    /**\n     * @notice Contract version number (minor).\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    uint256 private immutable MINOR_VERSION;\n\n    /**\n     * @notice Contract version number (patch).\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    uint256 private immutable PATCH_VERSION;\n\n    /**\n     * @param _major Version number (major).\n     * @param _minor Version number (minor).\n     * @param _patch Version number (patch).\n     */\n    constructor(\n        uint256 _major,\n        uint256 _minor,\n        uint256 _patch\n    ) {\n        MAJOR_VERSION = _major;\n        MINOR_VERSION = _minor;\n        PATCH_VERSION = _patch;\n    }\n\n    /**\n     * @notice Returns the full semver contract version.\n     *\n     * @return Semver contract version as a string.\n     */\n    function version() public view returns (string memory) {\n        return\n            string(\n                abi.encodePacked(\n                    Strings.toString(MAJOR_VERSION),\n                    \".\",\n                    Strings.toString(MINOR_VERSION),\n                    \".\",\n                    Strings.toString(PATCH_VERSION)\n                )\n            );\n    }\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/universal/CrossDomainMessenger.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n    OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n    PausableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {\n    ReentrancyGuardUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n *         libAddressManager variable used to exist. Must be the first contract in the inheritance\n *         tree of the CrossDomainMessenger\n */\ncontract CrossDomainMessengerLegacySpacer {\n    /**\n     * @custom:legacy\n     * @custom:spacer libAddressManager\n     * @notice Spacer for backwards compatibility.\n     */\n    address private spacer_0_0_20;\n}\n\n/**\n * @custom:upgradeable\n * @title CrossDomainMessenger\n * @notice CrossDomainMessenger is a base contract that provides the core logic for the L1 and L2\n *         cross-chain messenger contracts. It's designed to be a universal interface that only\n *         needs to be extended slightly to provide low-level message passing functionality on each\n *         chain it's deployed on. Currently only designed for message passing between two paired\n *         chains and does not support one-to-many interactions.\n */\nabstract contract CrossDomainMessenger is\n    CrossDomainMessengerLegacySpacer,\n    OwnableUpgradeable,\n    PausableUpgradeable,\n    ReentrancyGuardUpgradeable\n{\n    /**\n     * @notice Current message version identifier.\n     */\n    uint16 public constant MESSAGE_VERSION = 1;\n\n    /**\n     * @notice Constant overhead added to the base gas for a message.\n     */\n    uint32 public constant MIN_GAS_CONSTANT_OVERHEAD = 200_000;\n\n    /**\n     * @notice Numerator for dynamic overhead added to the base gas for a message.\n     */\n    uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 1016;\n\n    /**\n     * @notice Denominator for dynamic overhead added to the base gas for a message.\n     */\n    uint32 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 1000;\n\n    /**\n     * @notice Extra gas added to base gas for each byte of calldata in a message.\n     */\n    uint32 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n    /**\n     * @notice Minimum amount of gas required to relay a message.\n     */\n    uint256 internal constant RELAY_GAS_REQUIRED = 45_000;\n\n    /**\n     * @notice Amount of gas held in reserve to guarantee that relay execution completes.\n     */\n    uint256 internal constant RELAY_GAS_BUFFER = RELAY_GAS_REQUIRED - 5000;\n\n    /**\n     * @notice Initial value for the xDomainMsgSender variable. We set this to a non-zero value\n     *         because performing an SSTORE on a non-zero value is significantly cheaper than on a\n     *         zero value.\n     */\n    address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n    /**\n     * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n     */\n    address public immutable otherMessenger;\n\n    /**\n     * @custom:legacy\n     * @custom:spacer blockedMessages\n     * @notice Spacer for backwards compatibility.\n     */\n    mapping(bytes32 => bool) private spacer_201_0_32;\n\n    /**\n     * @custom:legacy\n     * @custom:spacer relayedMessages\n     * @notice Spacer for backwards compatibility.\n     */\n    mapping(bytes32 => bool) private spacer_202_0_32;\n\n    /**\n     * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n     *         be present in this mapping if it has successfully been relayed on this chain, and\n     *         can therefore not be relayed again.\n     */\n    mapping(bytes32 => bool) public successfulMessages;\n\n    /**\n     * @notice Address of the sender of the currently executing message on the other chain. If the\n     *         value of this variable is the default value (0x00000000...dead) then no message is\n     *         currently being executed. Use the xDomainMessageSender getter which will throw an\n     *         error if this is the case.\n     */\n    address internal xDomainMsgSender;\n\n    /**\n     * @notice Nonce for the next message to be sent, without the message version applied. Use the\n     *         messageNonce getter which will insert the message version into the nonce to give you\n     *         the actual nonce to be used for the message.\n     */\n    uint240 internal msgNonce;\n\n    /**\n     * @notice Mapping of message hashes to boolean receipt values. Note that a message will only\n     *         be present in this mapping if it failed to be relayed on this chain at least once.\n     *         If a message is successfully relayed on the first attempt, then it will only be\n     *         present within the successfulMessages mapping.\n     */\n    mapping(bytes32 => bool) public receivedMessages;\n\n    /**\n     * @notice Reserve extra slots in the storage layout for future upgrades.\n     *         A gap size of 41 was chosen here, so that the first slot used in a child contract\n     *         would be a multiple of 50.\n     */\n    uint256[42] private __gap;\n\n    /**\n     * @notice Emitted whenever a message is sent to the other chain.\n     *\n     * @param target       Address of the recipient of the message.\n     * @param sender       Address of the sender of the message.\n     * @param message      Message to trigger the recipient address with.\n     * @param messageNonce Unique nonce attached to the message.\n     * @param gasLimit     Minimum gas limit that the message can be executed with.\n     */\n    event SentMessage(\n        address indexed target,\n        address sender,\n        bytes message,\n        uint256 messageNonce,\n        uint256 gasLimit\n    );\n\n    /**\n     * @notice Additional event data to emit, required as of Bedrock. Cannot be merged with the\n     *         SentMessage event without breaking the ABI of this contract, this is good enough.\n     *\n     * @param sender Address of the sender of the message.\n     * @param value  ETH value sent along with the message to the recipient.\n     */\n    event SentMessageExtension1(address indexed sender, uint256 value);\n\n    /**\n     * @notice Emitted whenever a message is successfully relayed on this chain.\n     *\n     * @param msgHash Hash of the message that was relayed.\n     */\n    event RelayedMessage(bytes32 indexed msgHash);\n\n    /**\n     * @notice Emitted whenever a message fails to be relayed on this chain.\n     *\n     * @param msgHash Hash of the message that failed to be relayed.\n     */\n    event FailedRelayedMessage(bytes32 indexed msgHash);\n\n    /**\n     * @param _otherMessenger Address of the messenger on the paired chain.\n     */\n    constructor(address _otherMessenger) {\n        otherMessenger = _otherMessenger;\n    }\n\n    /**\n     * @notice Allows the owner of this contract to temporarily pause message relaying. Backup\n     *         security mechanism just in case. Owner should be the same as the upgrade wallet to\n     *         maintain the security model of the system as a whole.\n     */\n    function pause() external onlyOwner {\n        _pause();\n    }\n\n    /**\n     * @notice Allows the owner of this contract to resume message relaying once paused.\n     */\n    function unpause() external onlyOwner {\n        _unpause();\n    }\n\n    /**\n     * @notice Sends a message to some target address on the other chain. Note that if the call\n     *         always reverts, then the message will be unrelayable, and any ETH sent will be\n     *         permanently locked. The same will occur if the target on the other chain is\n     *         considered unsafe (see the _isUnsafeTarget() function).\n     *\n     * @param _target      Target contract or wallet address.\n     * @param _message     Message to trigger the target address with.\n     * @param _minGasLimit Minimum gas limit that the message can be executed with.\n     */\n    function sendMessage(\n        address _target,\n        bytes calldata _message,\n        uint32 _minGasLimit\n    ) external payable {\n        // Triggers a message to the other messenger. Note that the amount of gas provided to the\n        // message is the amount of gas requested by the user PLUS the base gas value. We want to\n        // guarantee the property that the call to the target contract will always have at least\n        // the minimum gas limit specified by the user.\n        _sendMessage(\n            otherMessenger,\n            baseGas(_message, _minGasLimit),\n            msg.value,\n            abi.encodeWithSelector(\n                this.relayMessage.selector,\n                messageNonce(),\n                msg.sender,\n                _target,\n                msg.value,\n                _minGasLimit,\n                _message\n            )\n        );\n\n        emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit);\n        emit SentMessageExtension1(msg.sender, msg.value);\n\n        unchecked {\n            ++msgNonce;\n        }\n    }\n\n    /**\n     * @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only\n     *         be executed via cross-chain call from the other messenger OR if the message was\n     *         already received once and is currently being replayed.\n     *\n     * @param _nonce       Nonce of the message being relayed.\n     * @param _sender      Address of the user who sent the message.\n     * @param _target      Address that the message is targeted at.\n     * @param _value       ETH value to send with the message.\n     * @param _minGasLimit Minimum amount of gas that the message can be executed with.\n     * @param _message     Message to send to the target.\n     */\n    function relayMessage(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _minGasLimit,\n        bytes calldata _message\n    ) external payable nonReentrant whenNotPaused {\n        (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n\n        // Block any messages that aren't version 1. All version 0 messages have been guaranteed to\n        // be relayed OR have been migrated to version 1 messages. Version 0 messages do not commit\n        // to the value or minGasLimit fields, which can create unexpected issues for end-users.\n        require(\n            version == 1,\n            \"CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade\"\n        );\n\n        bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n            _nonce,\n            _sender,\n            _target,\n            _value,\n            _minGasLimit,\n            _message\n        );\n\n        if (_isOtherMessenger()) {\n            // This property should always hold when the message is first submitted (as opposed to\n            // being replayed).\n            assert(msg.value == _value);\n        } else {\n            require(\n                msg.value == 0,\n                \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n            );\n\n            require(\n                receivedMessages[versionedHash],\n                \"CrossDomainMessenger: message cannot be replayed\"\n            );\n        }\n\n        require(\n            _isUnsafeTarget(_target) == false,\n            \"CrossDomainMessenger: cannot send message to blocked system address\"\n        );\n\n        require(\n            successfulMessages[versionedHash] == false,\n            \"CrossDomainMessenger: message has already been relayed\"\n        );\n\n        require(\n            gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,\n            \"CrossDomainMessenger: insufficient gas to relay message\"\n        );\n\n        xDomainMsgSender = _sender;\n        bool success = SafeCall.call(_target, gasleft() - RELAY_GAS_BUFFER, _value, _message);\n        xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n\n        if (success == true) {\n            successfulMessages[versionedHash] = true;\n            emit RelayedMessage(versionedHash);\n        } else {\n            receivedMessages[versionedHash] = true;\n            emit FailedRelayedMessage(versionedHash);\n        }\n    }\n\n    /**\n     * @notice Retrieves the address of the contract or wallet that initiated the currently\n     *         executing message on the other chain. Will throw an error if there is no message\n     *         currently being executed. Allows the recipient of a call to see who triggered it.\n     *\n     * @return Address of the sender of the currently executing message on the other chain.\n     */\n    function xDomainMessageSender() external view returns (address) {\n        require(\n            xDomainMsgSender != DEFAULT_XDOMAIN_SENDER,\n            \"CrossDomainMessenger: xDomainMessageSender is not set\"\n        );\n\n        return xDomainMsgSender;\n    }\n\n    /**\n     * @notice Retrieves the next message nonce. Message version will be added to the upper two\n     *         bytes of the message nonce. Message version allows us to treat messages as having\n     *         different structures.\n     *\n     * @return Nonce of the next message to be sent, with added message version.\n     */\n    function messageNonce() public view returns (uint256) {\n        return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);\n    }\n\n    /**\n     * @notice Computes the amount of gas required to guarantee that a given message will be\n     *         received on the other chain without running out of gas. Guaranteeing that a message\n     *         will not run out of gas is important because this ensures that a message can always\n     *         be replayed on the other chain if it fails to execute completely.\n     *\n     * @param _message     Message to compute the amount of required gas for.\n     * @param _minGasLimit Minimum desired gas limit when message goes to target.\n     *\n     * @return Amount of gas required to guarantee message receipt.\n     */\n    function baseGas(bytes calldata _message, uint32 _minGasLimit) public pure returns (uint32) {\n        return\n            // Dynamic overhead\n            ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n                MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n            // Calldata overhead\n            (uint32(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\n            // Constant overhead\n            MIN_GAS_CONSTANT_OVERHEAD;\n    }\n\n    /**\n     * @notice Intializer.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function __CrossDomainMessenger_init() internal onlyInitializing {\n        xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;\n        __Context_init_unchained();\n        __Ownable_init_unchained();\n        __Pausable_init_unchained();\n        __ReentrancyGuard_init_unchained();\n    }\n\n    /**\n     * @notice Sends a low-level message to the other messenger. Needs to be implemented by child\n     *         contracts because the logic for this depends on the network where the messenger is\n     *         being deployed.\n     *\n     * @param _to       Recipient of the message on the other chain.\n     * @param _gasLimit Minimum gas limit the message can be executed with.\n     * @param _value    Amount of ETH to send with the message.\n     * @param _data     Message data.\n     */\n    function _sendMessage(\n        address _to,\n        uint64 _gasLimit,\n        uint256 _value,\n        bytes memory _data\n    ) internal virtual;\n\n    /**\n     * @notice Checks whether the message is coming from the other messenger. Implemented by child\n     *         contracts because the logic for this depends on the network where the messenger is\n     *         being deployed.\n     *\n     * @return Whether the message is coming from the other messenger.\n     */\n    function _isOtherMessenger() internal view virtual returns (bool);\n\n    /**\n     * @notice Checks whether a given call target is a system address that could cause the\n     *         messenger to peform an unsafe action. This is NOT a mechanism for blocking user\n     *         addresses. This is ONLY used to prevent the execution of messages to specific\n     *         system addresses that could cause security issues, e.g., having the\n     *         CrossDomainMessenger send messages to itself.\n     *\n     * @param _target Address of the contract to check.\n     *\n     * @return Whether or not the address is an unsafe system address.\n     */\n    function _isUnsafeTarget(address _target) internal view virtual returns (bool);\n}\n"
    },
    "@openzeppelin/contracts/utils/Address.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    function __Pausable_init() internal onlyInitializing {\n        __Pausable_init_unchained();\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        require(!paused(), \"Pausable: paused\");\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        require(paused(), \"Pausable: not paused\");\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        // On the first call to nonReentrant, _notEntered will be true\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n\n        _;\n\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/libraries/SafeCall.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title SafeCall\n * @notice Perform low level safe calls\n */\nlibrary SafeCall {\n    /**\n     * @notice Perform a low level call without copying any returndata\n     *\n     * @param _target   Address to call\n     * @param _gas      Amount of gas to pass to the call\n     * @param _value    Amount of value to pass to the call\n     * @param _calldata Calldata to pass to the call\n     */\n    function call(\n        address _target,\n        uint256 _gas,\n        uint256 _value,\n        bytes memory _calldata\n    ) internal returns (bool) {\n        bool _success;\n        assembly {\n            _success := call(\n                _gas, // gas\n                _target, // recipient\n                _value, // ether value\n                add(_calldata, 0x20), // inloc\n                mload(_calldata), // inlen\n                0, // outloc\n                0 // outlen\n            )\n        }\n        return _success;\n    }\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/libraries/Hashing.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Encoding } from \"./Encoding.sol\";\n\n/**\n * @title Hashing\n * @notice Hashing handles Optimism's various different hashing schemes.\n */\nlibrary Hashing {\n    /**\n     * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\n     *         given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\n     *         system.\n     *\n     * @param _tx User deposit transaction to hash.\n     *\n     * @return Hash of the RLP encoded L2 deposit transaction.\n     */\n    function hashDepositTransaction(Types.UserDepositTransaction memory _tx)\n        internal\n        pure\n        returns (bytes32)\n    {\n        return keccak256(Encoding.encodeDepositTransaction(_tx));\n    }\n\n    /**\n     * @notice Computes the deposit transaction's \"source hash\", a value that guarantees the hash\n     *         of the L2 transaction that corresponds to a deposit is unique and is\n     *         deterministically generated from L1 transaction data.\n     *\n     * @param _l1BlockHash Hash of the L1 block where the deposit was included.\n     * @param _logIndex    The index of the log that created the deposit transaction.\n     *\n     * @return Hash of the deposit transaction's \"source hash\".\n     */\n    function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex)\n        internal\n        pure\n        returns (bytes32)\n    {\n        bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\n        return keccak256(abi.encode(bytes32(0), depositId));\n    }\n\n    /**\n     * @notice Hashes the cross domain message based on the version that is encoded into the\n     *         message nonce.\n     *\n     * @param _nonce    Message nonce with version encoded into the first two bytes.\n     * @param _sender   Address of the sender of the message.\n     * @param _target   Address of the target of the message.\n     * @param _value    ETH value to send to the target.\n     * @param _gasLimit Gas limit to use for the message.\n     * @param _data     Data to send with the message.\n     *\n     * @return Hashed cross domain message.\n     */\n    function hashCrossDomainMessage(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) internal pure returns (bytes32) {\n        (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n        if (version == 0) {\n            return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\n        } else if (version == 1) {\n            return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n        } else {\n            revert(\"Hashing: unknown cross domain message version\");\n        }\n    }\n\n    /**\n     * @notice Hashes a cross domain message based on the V0 (legacy) encoding.\n     *\n     * @param _target Address of the target of the message.\n     * @param _sender Address of the sender of the message.\n     * @param _data   Data to send with the message.\n     * @param _nonce  Message nonce.\n     *\n     * @return Hashed cross domain message.\n     */\n    function hashCrossDomainMessageV0(\n        address _target,\n        address _sender,\n        bytes memory _data,\n        uint256 _nonce\n    ) internal pure returns (bytes32) {\n        return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\n    }\n\n    /**\n     * @notice Hashes a cross domain message based on the V1 (current) encoding.\n     *\n     * @param _nonce    Message nonce.\n     * @param _sender   Address of the sender of the message.\n     * @param _target   Address of the target of the message.\n     * @param _value    ETH value to send to the target.\n     * @param _gasLimit Gas limit to use for the message.\n     * @param _data     Data to send with the message.\n     *\n     * @return Hashed cross domain message.\n     */\n    function hashCrossDomainMessageV1(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) internal pure returns (bytes32) {\n        return\n            keccak256(\n                Encoding.encodeCrossDomainMessageV1(\n                    _nonce,\n                    _sender,\n                    _target,\n                    _value,\n                    _gasLimit,\n                    _data\n                )\n            );\n    }\n\n    /**\n     * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\n     *\n     * @param _tx Withdrawal transaction to hash.\n     *\n     * @return Hashed withdrawal transaction.\n     */\n    function hashWithdrawal(Types.WithdrawalTransaction memory _tx)\n        internal\n        pure\n        returns (bytes32)\n    {\n        return\n            keccak256(\n                abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data)\n            );\n    }\n\n    /**\n     * @notice Hashes the various elements of an output root proof into an output root hash which\n     *         can be used to check if the proof is valid.\n     *\n     * @param _outputRootProof Output root proof which should hash to an output root.\n     *\n     * @return Hashed output root proof.\n     */\n    function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof)\n        internal\n        pure\n        returns (bytes32)\n    {\n        return\n            keccak256(\n                abi.encode(\n                    _outputRootProof.version,\n                    _outputRootProof.stateRoot,\n                    _outputRootProof.messagePasserStorageRoot,\n                    _outputRootProof.latestBlockhash\n                )\n            );\n    }\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/libraries/Encoding.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Types } from \"./Types.sol\";\nimport { Hashing } from \"./Hashing.sol\";\nimport { RLPWriter } from \"./rlp/RLPWriter.sol\";\n\n/**\n * @title Encoding\n * @notice Encoding handles Optimism's various different encoding schemes.\n */\nlibrary Encoding {\n    /**\n     * @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\n     *         to the L2 system. Useful for searching for a deposit in the L2 system. The\n     *         transaction is prefixed with 0x7e to identify its EIP-2718 type.\n     *\n     * @param _tx User deposit transaction to encode.\n     *\n     * @return RLP encoded L2 deposit transaction.\n     */\n    function encodeDepositTransaction(Types.UserDepositTransaction memory _tx)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\n        bytes[] memory raw = new bytes[](8);\n        raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\n        raw[1] = RLPWriter.writeAddress(_tx.from);\n        raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\"\") : RLPWriter.writeAddress(_tx.to);\n        raw[3] = RLPWriter.writeUint(_tx.mint);\n        raw[4] = RLPWriter.writeUint(_tx.value);\n        raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\n        raw[6] = RLPWriter.writeBool(false);\n        raw[7] = RLPWriter.writeBytes(_tx.data);\n        return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\n    }\n\n    /**\n     * @notice Encodes the cross domain message based on the version that is encoded into the\n     *         message nonce.\n     *\n     * @param _nonce    Message nonce with version encoded into the first two bytes.\n     * @param _sender   Address of the sender of the message.\n     * @param _target   Address of the target of the message.\n     * @param _value    ETH value to send to the target.\n     * @param _gasLimit Gas limit to use for the message.\n     * @param _data     Data to send with the message.\n     *\n     * @return Encoded cross domain message.\n     */\n    function encodeCrossDomainMessage(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) internal pure returns (bytes memory) {\n        (, uint16 version) = decodeVersionedNonce(_nonce);\n        if (version == 0) {\n            return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\n        } else if (version == 1) {\n            return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n        } else {\n            revert(\"Encoding: unknown cross domain message version\");\n        }\n    }\n\n    /**\n     * @notice Encodes a cross domain message based on the V0 (legacy) encoding.\n     *\n     * @param _target Address of the target of the message.\n     * @param _sender Address of the sender of the message.\n     * @param _data   Data to send with the message.\n     * @param _nonce  Message nonce.\n     *\n     * @return Encoded cross domain message.\n     */\n    function encodeCrossDomainMessageV0(\n        address _target,\n        address _sender,\n        bytes memory _data,\n        uint256 _nonce\n    ) internal pure returns (bytes memory) {\n        return\n            abi.encodeWithSignature(\n                \"relayMessage(address,address,bytes,uint256)\",\n                _target,\n                _sender,\n                _data,\n                _nonce\n            );\n    }\n\n    /**\n     * @notice Encodes a cross domain message based on the V1 (current) encoding.\n     *\n     * @param _nonce    Message nonce.\n     * @param _sender   Address of the sender of the message.\n     * @param _target   Address of the target of the message.\n     * @param _value    ETH value to send to the target.\n     * @param _gasLimit Gas limit to use for the message.\n     * @param _data     Data to send with the message.\n     *\n     * @return Encoded cross domain message.\n     */\n    function encodeCrossDomainMessageV1(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) internal pure returns (bytes memory) {\n        return\n            abi.encodeWithSignature(\n                \"relayMessage(uint256,address,address,uint256,uint256,bytes)\",\n                _nonce,\n                _sender,\n                _target,\n                _value,\n                _gasLimit,\n                _data\n            );\n    }\n\n    /**\n     * @notice Adds a version number into the first two bytes of a message nonce.\n     *\n     * @param _nonce   Message nonce to encode into.\n     * @param _version Version number to encode into the message nonce.\n     *\n     * @return Message nonce with version encoded into the first two bytes.\n     */\n    function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\n        uint256 nonce;\n        assembly {\n            nonce := or(shl(240, _version), _nonce)\n        }\n        return nonce;\n    }\n\n    /**\n     * @notice Pulls the version out of a version-encoded nonce.\n     *\n     * @param _nonce Message nonce with version encoded into the first two bytes.\n     *\n     * @return Nonce without encoded version.\n     * @return Version of the message.\n     */\n    function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\n        uint240 nonce;\n        uint16 version;\n        assembly {\n            nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\n            version := shr(240, _nonce)\n        }\n        return (nonce, version);\n    }\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n     * initialization step. This is essential to configure modules that are added through upgrades and that require\n     * initialization.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized < type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n                /// @solidity memory-safe-assembly\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/libraries/Types.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Types\n * @notice Contains various types used throughout the Optimism contract system.\n */\nlibrary Types {\n    /**\n     * @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\n     *         timestamp that the output root is posted. This timestamp is used to verify that the\n     *         finalization period has passed since the output root was submitted.\n     */\n    struct OutputProposal {\n        bytes32 outputRoot;\n        uint256 timestamp;\n    }\n\n    /**\n     * @notice Struct representing the elements that are hashed together to generate an output root\n     *         which itself represents a snapshot of the L2 state.\n     */\n    struct OutputRootProof {\n        bytes32 version;\n        bytes32 stateRoot;\n        bytes32 messagePasserStorageRoot;\n        bytes32 latestBlockhash;\n    }\n\n    /**\n     * @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\n     *         user (as opposed to a system deposit transaction generated by the system).\n     */\n    struct UserDepositTransaction {\n        address from;\n        address to;\n        bool isCreation;\n        uint256 value;\n        uint256 mint;\n        uint64 gasLimit;\n        bytes data;\n        bytes32 l1BlockHash;\n        uint256 logIndex;\n    }\n\n    /**\n     * @notice Struct representing a withdrawal transaction.\n     */\n    struct WithdrawalTransaction {\n        uint256 nonce;\n        address sender;\n        address target;\n        uint256 value;\n        uint256 gasLimit;\n        bytes data;\n    }\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/libraries/rlp/RLPWriter.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @custom:attribution https://github.com/bakaoh/solidity-rlp-encode\n * @title RLPWriter\n * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's\n *         RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor\n *         modifications to improve legibility.\n */\nlibrary RLPWriter {\n    /**\n     * @notice RLP encodes a byte string.\n     *\n     * @param _in The byte string to encode.\n     *\n     * @return The RLP encoded string in bytes.\n     */\n    function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\n        bytes memory encoded;\n\n        if (_in.length == 1 && uint8(_in[0]) < 128) {\n            encoded = _in;\n        } else {\n            encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\n        }\n\n        return encoded;\n    }\n\n    /**\n     * @notice RLP encodes a list of RLP encoded byte byte strings.\n     *\n     * @param _in The list of RLP encoded byte strings.\n     *\n     * @return The RLP encoded list of items in bytes.\n     */\n    function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\n        bytes memory list = _flatten(_in);\n        return abi.encodePacked(_writeLength(list.length, 192), list);\n    }\n\n    /**\n     * @notice RLP encodes a string.\n     *\n     * @param _in The string to encode.\n     *\n     * @return The RLP encoded string in bytes.\n     */\n    function writeString(string memory _in) internal pure returns (bytes memory) {\n        return writeBytes(bytes(_in));\n    }\n\n    /**\n     * @notice RLP encodes an address.\n     *\n     * @param _in The address to encode.\n     *\n     * @return The RLP encoded address in bytes.\n     */\n    function writeAddress(address _in) internal pure returns (bytes memory) {\n        return writeBytes(abi.encodePacked(_in));\n    }\n\n    /**\n     * @notice RLP encodes a uint.\n     *\n     * @param _in The uint256 to encode.\n     *\n     * @return The RLP encoded uint256 in bytes.\n     */\n    function writeUint(uint256 _in) internal pure returns (bytes memory) {\n        return writeBytes(_toBinary(_in));\n    }\n\n    /**\n     * @notice RLP encodes a bool.\n     *\n     * @param _in The bool to encode.\n     *\n     * @return The RLP encoded bool in bytes.\n     */\n    function writeBool(bool _in) internal pure returns (bytes memory) {\n        bytes memory encoded = new bytes(1);\n        encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\n        return encoded;\n    }\n\n    /**\n     * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.\n     *\n     * @param _len    The length of the string or the payload.\n     * @param _offset 128 if item is string, 192 if item is list.\n     *\n     * @return RLP encoded bytes.\n     */\n    function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\n        bytes memory encoded;\n\n        if (_len < 56) {\n            encoded = new bytes(1);\n            encoded[0] = bytes1(uint8(_len) + uint8(_offset));\n        } else {\n            uint256 lenLen;\n            uint256 i = 1;\n            while (_len / i != 0) {\n                lenLen++;\n                i *= 256;\n            }\n\n            encoded = new bytes(lenLen + 1);\n            encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\n            for (i = 1; i <= lenLen; i++) {\n                encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\n            }\n        }\n\n        return encoded;\n    }\n\n    /**\n     * @notice Encode integer in big endian binary form with no leading zeroes.\n     *\n     * @param _x The integer to encode.\n     *\n     * @return RLP encoded bytes.\n     */\n    function _toBinary(uint256 _x) private pure returns (bytes memory) {\n        bytes memory b = abi.encodePacked(_x);\n\n        uint256 i = 0;\n        for (; i < 32; i++) {\n            if (b[i] != 0) {\n                break;\n            }\n        }\n\n        bytes memory res = new bytes(32 - i);\n        for (uint256 j = 0; j < res.length; j++) {\n            res[j] = b[i++];\n        }\n\n        return res;\n    }\n\n    /**\n     * @custom:attribution https://github.com/Arachnid/solidity-stringutils\n     * @notice Copies a piece of memory to another location.\n     *\n     * @param _dest Destination location.\n     * @param _src  Source location.\n     * @param _len  Length of memory to copy.\n     */\n    function _memcpy(\n        uint256 _dest,\n        uint256 _src,\n        uint256 _len\n    ) private pure {\n        uint256 dest = _dest;\n        uint256 src = _src;\n        uint256 len = _len;\n\n        for (; len >= 32; len -= 32) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n            dest += 32;\n            src += 32;\n        }\n\n        uint256 mask;\n        unchecked {\n            mask = 256**(32 - len) - 1;\n        }\n        assembly {\n            let srcpart := and(mload(src), not(mask))\n            let destpart := and(mload(dest), mask)\n            mstore(dest, or(destpart, srcpart))\n        }\n    }\n\n    /**\n     * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder\n     * @notice Flattens a list of byte strings into one byte string.\n     *\n     * @param _list List of byte strings to flatten.\n     *\n     * @return The flattened byte string.\n     */\n    function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\n        if (_list.length == 0) {\n            return new bytes(0);\n        }\n\n        uint256 len;\n        uint256 i = 0;\n        for (; i < _list.length; i++) {\n            len += _list[i].length;\n        }\n\n        bytes memory flattened = new bytes(len);\n        uint256 flattenedPtr;\n        assembly {\n            flattenedPtr := add(flattened, 0x20)\n        }\n\n        for (i = 0; i < _list.length; i++) {\n            bytes memory item = _list[i];\n\n            uint256 listPtr;\n            assembly {\n                listPtr := add(item, 0x20)\n            }\n\n            _memcpy(flattenedPtr, listPtr, item.length);\n            flattenedPtr += _list[i].length;\n        }\n\n        return flattened;\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n    // As per the EIP-165 spec, no interface should ever match 0xffffffff\n    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n    /**\n     * @dev Returns true if `account` supports the {IERC165} interface,\n     */\n    function supportsERC165(address account) internal view returns (bool) {\n        // Any contract that implements ERC165 must explicitly indicate support of\n        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n        return\n            _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n            !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n    }\n\n    /**\n     * @dev Returns true if `account` supports the interface defined by\n     * `interfaceId`. Support for {IERC165} itself is queried automatically.\n     *\n     * See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n        // query support of both ERC165 as per the spec and support of _interfaceId\n        return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n    }\n\n    /**\n     * @dev Returns a boolean array where each value corresponds to the\n     * interfaces passed in and whether they're supported or not. This allows\n     * you to batch check interfaces for a contract where your expectation\n     * is that some interfaces may not be supported.\n     *\n     * See {IERC165-supportsInterface}.\n     *\n     * _Available since v3.4._\n     */\n    function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n        internal\n        view\n        returns (bool[] memory)\n    {\n        // an array of booleans corresponding to interfaceIds and whether they're supported or not\n        bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n        // query support of ERC165 itself\n        if (supportsERC165(account)) {\n            // query support of each interface in interfaceIds\n            for (uint256 i = 0; i < interfaceIds.length; i++) {\n                interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n            }\n        }\n\n        return interfaceIdsSupported;\n    }\n\n    /**\n     * @dev Returns true if `account` supports all the interfaces defined in\n     * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n     *\n     * Batch-querying can lead to gas savings by skipping repeated checks for\n     * {IERC165} support.\n     *\n     * See {IERC165-supportsInterface}.\n     */\n    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n        // query support of ERC165 itself\n        if (!supportsERC165(account)) {\n            return false;\n        }\n\n        // query support of each interface in _interfaceIds\n        for (uint256 i = 0; i < interfaceIds.length; i++) {\n            if (!_supportsERC165Interface(account, interfaceIds[i])) {\n                return false;\n            }\n        }\n\n        // all interfaces supported\n        return true;\n    }\n\n    /**\n     * @notice Query if a contract implements an interface, does not check ERC165 support\n     * @param account The address of the contract to query for support of an interface\n     * @param interfaceId The interface identifier, as specified in ERC-165\n     * @return true if the contract at account indicates support of the interface with\n     * identifier interfaceId, false otherwise\n     * @dev Assumes that account contains a contract that supports ERC165, otherwise\n     * the behavior of this method is undefined. This precondition can be checked\n     * with {supportsERC165}.\n     * Interface identification is specified in ERC-165.\n     */\n    function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n        bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n        (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n        if (result.length < 32) return false;\n        return success && abi.decode(result, (bool));\n    }\n}\n"
    },
    "contracts/universal/op-erc721/IOptimismMintableERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n    IERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\";\n\n/**\n * @title IOptimismMintableERC721\n * @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.\n *         Tokens that follow this standard can be easily transferred across the ERC721 bridge.\n */\ninterface IOptimismMintableERC721 is IERC721Enumerable {\n    /**\n     * @notice Emitted when a token is minted.\n     *\n     * @param account Address of the account the token was minted to.\n     * @param tokenId Token ID of the minted token.\n     */\n    event Mint(address indexed account, uint256 tokenId);\n\n    /**\n     * @notice Emitted when a token is burned.\n     *\n     * @param account Address of the account the token was burned from.\n     * @param tokenId Token ID of the burned token.\n     */\n    event Burn(address indexed account, uint256 tokenId);\n\n    /**\n     * @notice Chain ID of the chain where the remote token is deployed.\n     */\n    function remoteChainId() external view returns (uint256);\n\n    /**\n     * @notice Address of the token on the remote domain.\n     */\n    function remoteToken() external view returns (address);\n\n    /**\n     * @notice Address of the ERC721 bridge on this network.\n     */\n    function bridge() external view returns (address);\n\n    /**\n     * @notice Mints some token ID for a user, checking first that contract recipients\n     *         are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * @param _to      Address of the user to mint the token for.\n     * @param _tokenId Token ID to mint.\n     */\n    function safeMint(address _to, uint256 _tokenId) external;\n\n    /**\n     * @notice Burns a token ID from a user.\n     *\n     * @param _from    Address of the user to burn the token from.\n     * @param _tokenId Token ID to burn.\n     */\n    function burn(address _from, uint256 _tokenId) external;\n}\n"
    },
    "@openzeppelin/contracts/utils/Strings.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        // Inspired by OraclizeAPI's implementation - MIT licence\n        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n        if (value == 0) {\n            return \"0\";\n        }\n        uint256 temp = value;\n        uint256 digits;\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n        bytes memory buffer = new bytes(digits);\n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return \"0x00\";\n        }\n        uint256 temp = value;\n        uint256 length = 0;\n        while (temp != 0) {\n            length++;\n            temp >>= 8;\n        }\n        return toHexString(value, length);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _HEX_SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n    /**\n     * @dev Returns the total amount of tokens stored by the contract.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n     */\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\n\n    /**\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n     * Use along with {totalSupply} to enumerate all tokens.\n     */\n    function tokenByIndex(uint256 index) external view returns (uint256);\n}\n"
    },
    "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismMintableERC721 } from \"./OptimismMintableERC721.sol\";\nimport { Semver } from \"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC721Factory\n * @notice Factory contract for creating OptimismMintableERC721 contracts.\n */\ncontract OptimismMintableERC721Factory is Semver {\n    /**\n     * @notice Emitted whenever a new OptimismMintableERC721 contract is created.\n     *\n     * @param localToken  Address of the token on the this domain.\n     * @param remoteToken Address of the token on the remote domain.\n     * @param deployer    Address of the initiator of the deployment\n     */\n    event OptimismMintableERC721Created(\n        address indexed localToken,\n        address indexed remoteToken,\n        address deployer\n    );\n\n    /**\n     * @notice Address of the ERC721 bridge on this network.\n     */\n    address public immutable bridge;\n\n    /**\n     * @notice Chain ID for the remote network.\n     */\n    uint256 public immutable remoteChainId;\n\n    /**\n     * @notice Tracks addresses created by this factory.\n     */\n    mapping(address => bool) public isOptimismMintableERC721;\n\n    /**\n     * @custom:semver 1.0.0\n     *\n     * @param _bridge Address of the ERC721 bridge on this network.\n     */\n    constructor(address _bridge, uint256 _remoteChainId) Semver(1, 0, 0) {\n        require(\n            _bridge != address(0),\n            \"OptimismMintableERC721Factory: bridge cannot be address(0)\"\n        );\n        require(\n            _remoteChainId != 0,\n            \"OptimismMintableERC721Factory: remote chain id cannot be zero\"\n        );\n\n        bridge = _bridge;\n        remoteChainId = _remoteChainId;\n    }\n\n    /**\n     * @notice Creates an instance of the standard ERC721.\n     *\n     * @param _remoteToken Address of the corresponding token on the other domain.\n     * @param _name        ERC721 name.\n     * @param _symbol      ERC721 symbol.\n     */\n    function createOptimismMintableERC721(\n        address _remoteToken,\n        string memory _name,\n        string memory _symbol\n    ) external returns (address) {\n        require(\n            _remoteToken != address(0),\n            \"OptimismMintableERC721Factory: L1 token address cannot be address(0)\"\n        );\n\n        address localToken = address(\n            new OptimismMintableERC721(bridge, remoteChainId, _remoteToken, _name, _symbol)\n        );\n\n        isOptimismMintableERC721[localToken] = true;\n        emit OptimismMintableERC721Created(localToken, _remoteToken, msg.sender);\n\n        return localToken;\n    }\n}\n"
    },
    "contracts/universal/op-erc721/OptimismMintableERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {\n    ERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\";\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { IOptimismMintableERC721 } from \"./IOptimismMintableERC721.sol\";\n\n/**\n * @title OptimismMintableERC721\n * @notice This contract is the remote representation for some token that lives on another network,\n *         typically an Optimism representation of an Ethereum-based token. Standard reference\n *         implementation that can be extended or modified according to your needs.\n */\ncontract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {\n    /**\n     * @inheritdoc IOptimismMintableERC721\n     */\n    uint256 public immutable remoteChainId;\n\n    /**\n     * @inheritdoc IOptimismMintableERC721\n     */\n    address public immutable remoteToken;\n\n    /**\n     * @inheritdoc IOptimismMintableERC721\n     */\n    address public immutable bridge;\n\n    /**\n     * @notice Base token URI for this token.\n     */\n    string public baseTokenURI;\n\n    /**\n     * @param _bridge        Address of the bridge on this network.\n     * @param _remoteChainId Chain ID where the remote token is deployed.\n     * @param _remoteToken   Address of the corresponding token on the other network.\n     * @param _name          ERC721 name.\n     * @param _symbol        ERC721 symbol.\n     */\n    constructor(\n        address _bridge,\n        uint256 _remoteChainId,\n        address _remoteToken,\n        string memory _name,\n        string memory _symbol\n    ) ERC721(_name, _symbol) {\n        require(_bridge != address(0), \"OptimismMintableERC721: bridge cannot be address(0)\");\n        require(_remoteChainId != 0, \"OptimismMintableERC721: remote chain id cannot be zero\");\n        require(\n            _remoteToken != address(0),\n            \"OptimismMintableERC721: remote token cannot be address(0)\"\n        );\n\n        remoteChainId = _remoteChainId;\n        remoteToken = _remoteToken;\n        bridge = _bridge;\n\n        // Creates a base URI in the format specified by EIP-681:\n        // https://eips.ethereum.org/EIPS/eip-681\n        baseTokenURI = string(\n            abi.encodePacked(\n                \"ethereum:\",\n                Strings.toHexString(uint160(_remoteToken), 20),\n                \"@\",\n                Strings.toString(_remoteChainId),\n                \"/tokenURI?uint256=\"\n            )\n        );\n    }\n\n    /**\n     * @notice Modifier that prevents callers other than the bridge from calling the function.\n     */\n    modifier onlyBridge() {\n        require(msg.sender == bridge, \"OptimismMintableERC721: only bridge can call this function\");\n        _;\n    }\n\n    /**\n     * @inheritdoc IOptimismMintableERC721\n     */\n    function safeMint(address _to, uint256 _tokenId) external virtual onlyBridge {\n        _safeMint(_to, _tokenId);\n\n        emit Mint(_to, _tokenId);\n    }\n\n    /**\n     * @inheritdoc IOptimismMintableERC721\n     */\n    function burn(address _from, uint256 _tokenId) external virtual onlyBridge {\n        _burn(_tokenId);\n\n        emit Burn(_from, _tokenId);\n    }\n\n    /**\n     * @notice Checks if a given interface ID is supported by this contract.\n     *\n     * @param _interfaceId The interface ID to check.\n     *\n     * @return True if the interface ID is supported, false otherwise.\n     */\n    function supportsInterface(bytes4 _interfaceId)\n        public\n        view\n        override(ERC721Enumerable, IERC165)\n        returns (bool)\n    {\n        bytes4 iface1 = type(IERC165).interfaceId;\n        bytes4 iface2 = type(IOptimismMintableERC721).interfaceId;\n        return\n            _interfaceId == iface1 ||\n            _interfaceId == iface2 ||\n            super.supportsInterface(_interfaceId);\n    }\n\n    /**\n     * @notice Returns the base token URI.\n     *\n     * @return Base token URI.\n     */\n    function _baseURI() internal view virtual override returns (string memory) {\n        return baseTokenURI;\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC721.sol\";\nimport \"./IERC721Enumerable.sol\";\n\n/**\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\n * enumerability of all the token ids in the contract as well as all token ids owned by each\n * account.\n */\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\n    // Mapping from owner to list of owned token IDs\n    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\n\n    // Mapping from token ID to index of the owner tokens list\n    mapping(uint256 => uint256) private _ownedTokensIndex;\n\n    // Array with all token ids, used for enumeration\n    uint256[] private _allTokens;\n\n    // Mapping from token id to position in the allTokens array\n    mapping(uint256 => uint256) private _allTokensIndex;\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\n        return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\n     */\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\n        require(index < ERC721.balanceOf(owner), \"ERC721Enumerable: owner index out of bounds\");\n        return _ownedTokens[owner][index];\n    }\n\n    /**\n     * @dev See {IERC721Enumerable-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _allTokens.length;\n    }\n\n    /**\n     * @dev See {IERC721Enumerable-tokenByIndex}.\n     */\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\n        require(index < ERC721Enumerable.totalSupply(), \"ERC721Enumerable: global index out of bounds\");\n        return _allTokens[index];\n    }\n\n    /**\n     * @dev Hook that is called before any token transfer. This includes minting\n     * and burning.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n     * transferred to `to`.\n     * - When `from` is zero, `tokenId` will be minted for `to`.\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual override {\n        super._beforeTokenTransfer(from, to, tokenId);\n\n        if (from == address(0)) {\n            _addTokenToAllTokensEnumeration(tokenId);\n        } else if (from != to) {\n            _removeTokenFromOwnerEnumeration(from, tokenId);\n        }\n        if (to == address(0)) {\n            _removeTokenFromAllTokensEnumeration(tokenId);\n        } else if (to != from) {\n            _addTokenToOwnerEnumeration(to, tokenId);\n        }\n    }\n\n    /**\n     * @dev Private function to add a token to this extension's ownership-tracking data structures.\n     * @param to address representing the new owner of the given token ID\n     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n     */\n    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\n        uint256 length = ERC721.balanceOf(to);\n        _ownedTokens[to][length] = tokenId;\n        _ownedTokensIndex[tokenId] = length;\n    }\n\n    /**\n     * @dev Private function to add a token to this extension's token tracking data structures.\n     * @param tokenId uint256 ID of the token to be added to the tokens list\n     */\n    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\n        _allTokensIndex[tokenId] = _allTokens.length;\n        _allTokens.push(tokenId);\n    }\n\n    /**\n     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n     * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n     * @param from address representing the previous owner of the given token ID\n     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n     */\n    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\n        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\n        // then delete the last slot (swap and pop).\n\n        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\n        uint256 tokenIndex = _ownedTokensIndex[tokenId];\n\n        // When the token to delete is the last token, the swap operation is unnecessary\n        if (tokenIndex != lastTokenIndex) {\n            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\n\n            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n        }\n\n        // This also deletes the contents at the last position of the array\n        delete _ownedTokensIndex[tokenId];\n        delete _ownedTokens[from][lastTokenIndex];\n    }\n\n    /**\n     * @dev Private function to remove a token from this extension's token tracking data structures.\n     * This has O(1) time complexity, but alters the order of the _allTokens array.\n     * @param tokenId uint256 ID of the token to be removed from the tokens list\n     */\n    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\n        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\n        // then delete the last slot (swap and pop).\n\n        uint256 lastTokenIndex = _allTokens.length - 1;\n        uint256 tokenIndex = _allTokensIndex[tokenId];\n\n        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\n        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\n        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\n        uint256 lastTokenId = _allTokens[lastTokenIndex];\n\n        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n\n        // This also deletes the contents at the last position of the array\n        delete _allTokensIndex[tokenId];\n        _allTokens.pop();\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/ERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n    using Address for address;\n    using Strings for uint256;\n\n    // Token name\n    string private _name;\n\n    // Token symbol\n    string private _symbol;\n\n    // Mapping from token ID to owner address\n    mapping(uint256 => address) private _owners;\n\n    // Mapping owner address to token count\n    mapping(address => uint256) private _balances;\n\n    // Mapping from token ID to approved address\n    mapping(uint256 => address) private _tokenApprovals;\n\n    // Mapping from owner to operator approvals\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n    /**\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n        return\n            interfaceId == type(IERC721).interfaceId ||\n            interfaceId == type(IERC721Metadata).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC721-balanceOf}.\n     */\n    function balanceOf(address owner) public view virtual override returns (uint256) {\n        require(owner != address(0), \"ERC721: balance query for the zero address\");\n        return _balances[owner];\n    }\n\n    /**\n     * @dev See {IERC721-ownerOf}.\n     */\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n        address owner = _owners[tokenId];\n        require(owner != address(0), \"ERC721: owner query for nonexistent token\");\n        return owner;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-name}.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-symbol}.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-tokenURI}.\n     */\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n        require(_exists(tokenId), \"ERC721Metadata: URI query for nonexistent token\");\n\n        string memory baseURI = _baseURI();\n        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n    }\n\n    /**\n     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n     * by default, can be overridden in child contracts.\n     */\n    function _baseURI() internal view virtual returns (string memory) {\n        return \"\";\n    }\n\n    /**\n     * @dev See {IERC721-approve}.\n     */\n    function approve(address to, uint256 tokenId) public virtual override {\n        address owner = ERC721.ownerOf(tokenId);\n        require(to != owner, \"ERC721: approval to current owner\");\n\n        require(\n            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n            \"ERC721: approve caller is not owner nor approved for all\"\n        );\n\n        _approve(to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-getApproved}.\n     */\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\n        require(_exists(tokenId), \"ERC721: approved query for nonexistent token\");\n\n        return _tokenApprovals[tokenId];\n    }\n\n    /**\n     * @dev See {IERC721-setApprovalForAll}.\n     */\n    function setApprovalForAll(address operator, bool approved) public virtual override {\n        _setApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /**\n     * @dev See {IERC721-isApprovedForAll}.\n     */\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n        return _operatorApprovals[owner][operator];\n    }\n\n    /**\n     * @dev See {IERC721-transferFrom}.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) public virtual override {\n        //solhint-disable-next-line max-line-length\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n\n        _transfer(from, to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) public virtual override {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory _data\n    ) public virtual override {\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n        _safeTransfer(from, to, tokenId, _data);\n    }\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n     *\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeTransfer(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory _data\n    ) internal virtual {\n        _transfer(from, to, tokenId);\n        require(_checkOnERC721Received(from, to, tokenId, _data), \"ERC721: transfer to non ERC721Receiver implementer\");\n    }\n\n    /**\n     * @dev Returns whether `tokenId` exists.\n     *\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n     *\n     * Tokens start existing when they are minted (`_mint`),\n     * and stop existing when they are burned (`_burn`).\n     */\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\n        return _owners[tokenId] != address(0);\n    }\n\n    /**\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n        require(_exists(tokenId), \"ERC721: operator query for nonexistent token\");\n        address owner = ERC721.ownerOf(tokenId);\n        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n    }\n\n    /**\n     * @dev Safely mints `tokenId` and transfers it to `to`.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeMint(address to, uint256 tokenId) internal virtual {\n        _safeMint(to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeMint(\n        address to,\n        uint256 tokenId,\n        bytes memory _data\n    ) internal virtual {\n        _mint(to, tokenId);\n        require(\n            _checkOnERC721Received(address(0), to, tokenId, _data),\n            \"ERC721: transfer to non ERC721Receiver implementer\"\n        );\n    }\n\n    /**\n     * @dev Mints `tokenId` and transfers it to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - `to` cannot be the zero address.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _mint(address to, uint256 tokenId) internal virtual {\n        require(to != address(0), \"ERC721: mint to the zero address\");\n        require(!_exists(tokenId), \"ERC721: token already minted\");\n\n        _beforeTokenTransfer(address(0), to, tokenId);\n\n        _balances[to] += 1;\n        _owners[tokenId] = to;\n\n        emit Transfer(address(0), to, tokenId);\n\n        _afterTokenTransfer(address(0), to, tokenId);\n    }\n\n    /**\n     * @dev Destroys `tokenId`.\n     * The approval is cleared when the token is burned.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _burn(uint256 tokenId) internal virtual {\n        address owner = ERC721.ownerOf(tokenId);\n\n        _beforeTokenTransfer(owner, address(0), tokenId);\n\n        // Clear approvals\n        _approve(address(0), tokenId);\n\n        _balances[owner] -= 1;\n        delete _owners[tokenId];\n\n        emit Transfer(owner, address(0), tokenId);\n\n        _afterTokenTransfer(owner, address(0), tokenId);\n    }\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _transfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {\n        require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n        require(to != address(0), \"ERC721: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, tokenId);\n\n        // Clear approvals from the previous owner\n        _approve(address(0), tokenId);\n\n        _balances[from] -= 1;\n        _balances[to] += 1;\n        _owners[tokenId] = to;\n\n        emit Transfer(from, to, tokenId);\n\n        _afterTokenTransfer(from, to, tokenId);\n    }\n\n    /**\n     * @dev Approve `to` to operate on `tokenId`\n     *\n     * Emits a {Approval} event.\n     */\n    function _approve(address to, uint256 tokenId) internal virtual {\n        _tokenApprovals[tokenId] = to;\n        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n    }\n\n    /**\n     * @dev Approve `operator` to operate on all of `owner` tokens\n     *\n     * Emits a {ApprovalForAll} event.\n     */\n    function _setApprovalForAll(\n        address owner,\n        address operator,\n        bool approved\n    ) internal virtual {\n        require(owner != operator, \"ERC721: approve to caller\");\n        _operatorApprovals[owner][operator] = approved;\n        emit ApprovalForAll(owner, operator, approved);\n    }\n\n    /**\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n     * The call is not executed if the target address is not a contract.\n     *\n     * @param from address representing the previous owner of the given token ID\n     * @param to target address that will receive the tokens\n     * @param tokenId uint256 ID of the token to be transferred\n     * @param _data bytes optional data to send along with the call\n     * @return bool whether the call correctly returned the expected magic value\n     */\n    function _checkOnERC721Received(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory _data\n    ) private returns (bool) {\n        if (to.isContract()) {\n            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\n                return retval == IERC721Receiver.onERC721Received.selector;\n            } catch (bytes memory reason) {\n                if (reason.length == 0) {\n                    revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n                } else {\n                    assembly {\n                        revert(add(32, reason), mload(reason))\n                    }\n                }\n            }\n        } else {\n            return true;\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any token transfer. This includes minting\n     * and burning.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n     * transferred to `to`.\n     * - When `from` is zero, `tokenId` will be minted for `to`.\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {}\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
    },
    "@openzeppelin/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/ERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/legacy/AddressManager.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:legacy\n * @title AddressManager\n * @notice AddressManager is a legacy contract that was used in the old version of the Optimism\n *         system to manage a registry of string names to addresses. We now use a more standard\n *         proxy system instead, but this contract is still necessary for backwards compatibility\n *         with several older contracts.\n */\ncontract AddressManager is Ownable {\n    /**\n     * @notice Mapping of the hashes of string names to addresses.\n     */\n    mapping(bytes32 => address) private addresses;\n\n    /**\n     * @notice Emitted when an address is modified in the registry.\n     *\n     * @param name       String name being set in the registry.\n     * @param newAddress Address set for the given name.\n     * @param oldAddress Address that was previously set for the given name.\n     */\n    event AddressSet(string indexed name, address newAddress, address oldAddress);\n\n    /**\n     * @notice Changes the address associated with a particular name.\n     *\n     * @param _name    String name to associate an address with.\n     * @param _address Address to associate with the name.\n     */\n    function setAddress(string memory _name, address _address) external onlyOwner {\n        bytes32 nameHash = _getNameHash(_name);\n        address oldAddress = addresses[nameHash];\n        addresses[nameHash] = _address;\n\n        emit AddressSet(_name, _address, oldAddress);\n    }\n\n    /**\n     * @notice Retrieves the address associated with a given name.\n     *\n     * @param _name Name to retrieve an address for.\n     *\n     * @return Address associated with the given name.\n     */\n    function getAddress(string memory _name) external view returns (address) {\n        return addresses[_getNameHash(_name)];\n    }\n\n    /**\n     * @notice Computes the hash of a name.\n     *\n     * @param _name Name to compute a hash for.\n     *\n     * @return Hash of the given name.\n     */\n    function _getNameHash(string memory _name) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(_name));\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/Ownable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\nimport { Proxy } from \"./Proxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\n\n/**\n * @title IStaticERC1967Proxy\n * @notice IStaticERC1967Proxy is a static version of the ERC1967 proxy interface.\n */\ninterface IStaticERC1967Proxy {\n    function implementation() external view returns (address);\n\n    function admin() external view returns (address);\n}\n\n/**\n * @title IStaticL1ChugSplashProxy\n * @notice IStaticL1ChugSplashProxy is a static version of the ChugSplash proxy interface.\n */\ninterface IStaticL1ChugSplashProxy {\n    function getImplementation() external view returns (address);\n\n    function getOwner() external view returns (address);\n}\n\n/**\n * @title ProxyAdmin\n * @notice This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy,\n *         based on the OpenZeppelin implementation. It has backwards compatibility logic to work\n *         with the various types of proxies that have been deployed by Optimism in the past.\n */\ncontract ProxyAdmin is Owned {\n    /**\n     * @notice The proxy types that the ProxyAdmin can manage.\n     *\n     * @custom:value ERC1967    Represents an ERC1967 compliant transparent proxy interface.\n     * @custom:value CHUGSPLASH Represents the Chugsplash proxy interface (legacy).\n     * @custom:value RESOLVED   Represents the ResolvedDelegate proxy (legacy).\n     */\n    enum ProxyType {\n        ERC1967,\n        CHUGSPLASH,\n        RESOLVED\n    }\n\n    /**\n     * @custom:legacy\n     * @notice A mapping of proxy types, used for backwards compatibility.\n     */\n    mapping(address => ProxyType) public proxyType;\n\n    /**\n     * @custom:legacy\n     * @notice A reverse mapping of addresses to names held in the AddressManager. This must be\n     *         manually kept up to date with changes in the AddressManager for this contract\n     *         to be able to work as an admin for the ResolvedDelegateProxy type.\n     */\n    mapping(address => string) public implementationName;\n\n    /**\n     * @custom:legacy\n     * @notice The address of the address manager, this is required to manage the\n     *         ResolvedDelegateProxy type.\n     */\n    AddressManager public addressManager;\n\n    /**\n     * @custom:legacy\n     * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n     */\n    bool internal upgrading = false;\n\n    /**\n     * @param _owner Address of the initial owner of this contract.\n     */\n    constructor(address _owner) Owned(_owner) {}\n\n    /**\n     * @notice Sets the proxy type for a given address. Only required for non-standard (legacy)\n     *         proxy types.\n     *\n     * @param _address Address of the proxy.\n     * @param _type    Type of the proxy.\n     */\n    function setProxyType(address _address, ProxyType _type) external onlyOwner {\n        proxyType[_address] = _type;\n    }\n\n    /**\n     * @notice Sets the implementation name for a given address. Only required for\n     *         ResolvedDelegateProxy type proxies that have an implementation name.\n     *\n     * @param _address Address of the ResolvedDelegateProxy.\n     * @param _name    Name of the implementation for the proxy.\n     */\n    function setImplementationName(address _address, string memory _name) external onlyOwner {\n        implementationName[_address] = _name;\n    }\n\n    /**\n     * @notice Set the address of the AddressManager. This is required to manage legacy\n     *         ResolvedDelegateProxy type proxy contracts.\n     *\n     * @param _address Address of the AddressManager.\n     */\n    function setAddressManager(AddressManager _address) external onlyOwner {\n        addressManager = _address;\n    }\n\n    /**\n     * @custom:legacy\n     * @notice Set an address in the address manager. Since only the owner of the AddressManager\n     *         can directly modify addresses and the ProxyAdmin will own the AddressManager, this\n     *         gives the owner of the ProxyAdmin the ability to modify addresses directly.\n     *\n     * @param _name    Name to set within the AddressManager.\n     * @param _address Address to attach to the given name.\n     */\n    function setAddress(string memory _name, address _address) external onlyOwner {\n        addressManager.setAddress(_name, _address);\n    }\n\n    /**\n     * @custom:legacy\n     * @notice Set the upgrading status for the Chugsplash proxy type.\n     *\n     * @param _upgrading Whether or not the system is upgrading.\n     */\n    function setUpgrading(bool _upgrading) external onlyOwner {\n        upgrading = _upgrading;\n    }\n\n    /**\n     * @notice Updates the admin of the given proxy address.\n     *\n     * @param _proxy    Address of the proxy to update.\n     * @param _newAdmin Address of the new proxy admin.\n     */\n    function changeProxyAdmin(address payable _proxy, address _newAdmin) external onlyOwner {\n        ProxyType ptype = proxyType[_proxy];\n        if (ptype == ProxyType.ERC1967) {\n            Proxy(_proxy).changeAdmin(_newAdmin);\n        } else if (ptype == ProxyType.CHUGSPLASH) {\n            L1ChugSplashProxy(_proxy).setOwner(_newAdmin);\n        } else if (ptype == ProxyType.RESOLVED) {\n            addressManager.transferOwnership(_newAdmin);\n        } else {\n            revert(\"ProxyAdmin: unknown proxy type\");\n        }\n    }\n\n    /**\n     * @notice Changes a proxy's implementation contract and delegatecalls the new implementation\n     *         with some given data. Useful for atomic upgrade-and-initialize calls.\n     *\n     * @param _proxy          Address of the proxy to upgrade.\n     * @param _implementation Address of the new implementation address.\n     * @param _data           Data to trigger the new implementation with.\n     */\n    function upgradeAndCall(\n        address payable _proxy,\n        address _implementation,\n        bytes memory _data\n    ) external payable onlyOwner {\n        ProxyType ptype = proxyType[_proxy];\n        if (ptype == ProxyType.ERC1967) {\n            Proxy(_proxy).upgradeToAndCall{ value: msg.value }(_implementation, _data);\n        } else {\n            // reverts if proxy type is unknown\n            upgrade(_proxy, _implementation);\n            (bool success, ) = _proxy.call{ value: msg.value }(_data);\n            require(success, \"ProxyAdmin: call to proxy after upgrade failed\");\n        }\n    }\n\n    /**\n     * @custom:legacy\n     * @notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.\n     *\n     * @return Whether or not there is an upgrade going on. May not actually tell you whether an\n     *         upgrade is going on, since we don't currently plan to use this variable for anything\n     *         other than a legacy indicator to fix a UX bug in the ChugSplash proxy.\n     */\n    function isUpgrading() external view returns (bool) {\n        return upgrading;\n    }\n\n    /**\n     * @notice Returns the implementation of the given proxy address.\n     *\n     * @param _proxy Address of the proxy to get the implementation of.\n     *\n     * @return Address of the implementation of the proxy.\n     */\n    function getProxyImplementation(address _proxy) external view returns (address) {\n        ProxyType ptype = proxyType[_proxy];\n        if (ptype == ProxyType.ERC1967) {\n            return IStaticERC1967Proxy(_proxy).implementation();\n        } else if (ptype == ProxyType.CHUGSPLASH) {\n            return IStaticL1ChugSplashProxy(_proxy).getImplementation();\n        } else if (ptype == ProxyType.RESOLVED) {\n            return addressManager.getAddress(implementationName[_proxy]);\n        } else {\n            revert(\"ProxyAdmin: unknown proxy type\");\n        }\n    }\n\n    /**\n     * @notice Returns the admin of the given proxy address.\n     *\n     * @param _proxy Address of the proxy to get the admin of.\n     *\n     * @return Address of the admin of the proxy.\n     */\n    function getProxyAdmin(address payable _proxy) external view returns (address) {\n        ProxyType ptype = proxyType[_proxy];\n        if (ptype == ProxyType.ERC1967) {\n            return IStaticERC1967Proxy(_proxy).admin();\n        } else if (ptype == ProxyType.CHUGSPLASH) {\n            return IStaticL1ChugSplashProxy(_proxy).getOwner();\n        } else if (ptype == ProxyType.RESOLVED) {\n            return addressManager.owner();\n        } else {\n            revert(\"ProxyAdmin: unknown proxy type\");\n        }\n    }\n\n    /**\n     * @notice Changes a proxy's implementation contract.\n     *\n     * @param _proxy          Address of the proxy to upgrade.\n     * @param _implementation Address of the new implementation address.\n     */\n    function upgrade(address payable _proxy, address _implementation) public onlyOwner {\n        ProxyType ptype = proxyType[_proxy];\n        if (ptype == ProxyType.ERC1967) {\n            Proxy(_proxy).upgradeTo(_implementation);\n        } else if (ptype == ProxyType.CHUGSPLASH) {\n            L1ChugSplashProxy(_proxy).setStorage(\n                // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n                0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc,\n                bytes32(uint256(uint160(_implementation)))\n            );\n        } else if (ptype == ProxyType.RESOLVED) {\n            string memory name = implementationName[_proxy];\n            addressManager.setAddress(name, _implementation);\n        } else {\n            // It should not be possible to retrieve a ProxyType value which is not matched by\n            // one of the previous conditions.\n            assert(false);\n        }\n    }\n}\n"
    },
    "@rari-capital/solmate/src/auth/Owned.sol": {
      "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol)\nabstract contract Owned {\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event OwnerUpdated(address indexed user, address indexed newOwner);\n\n    /*//////////////////////////////////////////////////////////////\n                            OWNERSHIP STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    address public owner;\n\n    modifier onlyOwner() virtual {\n        require(msg.sender == owner, \"UNAUTHORIZED\");\n\n        _;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                               CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    constructor(address _owner) {\n        owner = _owner;\n\n        emit OwnerUpdated(address(0), _owner);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                             OWNERSHIP LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function setOwner(address newOwner) public virtual onlyOwner {\n        owner = newOwner;\n\n        emit OwnerUpdated(msg.sender, newOwner);\n    }\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Proxy\n * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or\n *         if the caller is address(0), meaning that the call originated from an off-chain\n *         simulation.\n */\ncontract Proxy {\n    /**\n     * @notice The storage slot that holds the address of the implementation.\n     *         bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n     */\n    bytes32 internal constant IMPLEMENTATION_KEY =\n        0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @notice The storage slot that holds the address of the owner.\n     *         bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n     */\n    bytes32 internal constant OWNER_KEY =\n        0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @notice An event that is emitted each time the implementation is changed. This event is part\n     *         of the EIP-1967 specification.\n     *\n     * @param implementation The address of the implementation contract\n     */\n    event Upgraded(address indexed implementation);\n\n    /**\n     * @notice An event that is emitted each time the owner is upgraded. This event is part of the\n     *         EIP-1967 specification.\n     *\n     * @param previousAdmin The previous owner of the contract\n     * @param newAdmin      The new owner of the contract\n     */\n    event AdminChanged(address previousAdmin, address newAdmin);\n\n    /**\n     * @notice A modifier that reverts if not called by the owner or by address(0) to allow\n     *         eth_call to interact with this proxy without needing to use low-level storage\n     *         inspection. We assume that nobody is able to trigger calls from address(0) during\n     *         normal EVM execution.\n     */\n    modifier proxyCallIfNotAdmin() {\n        if (msg.sender == _getAdmin() || msg.sender == address(0)) {\n            _;\n        } else {\n            // This WILL halt the call frame on completion.\n            _doProxyCall();\n        }\n    }\n\n    /**\n     * @notice Sets the initial admin during contract deployment. Admin address is stored at the\n     *         EIP-1967 admin storage slot so that accidental storage collision with the\n     *         implementation is not possible.\n     *\n     * @param _admin Address of the initial contract admin. Admin as the ability to access the\n     *               transparent proxy interface.\n     */\n    constructor(address _admin) {\n        _changeAdmin(_admin);\n    }\n\n    // slither-disable-next-line locked-ether\n    receive() external payable {\n        // Proxy call by default.\n        _doProxyCall();\n    }\n\n    // slither-disable-next-line locked-ether\n    fallback() external payable {\n        // Proxy call by default.\n        _doProxyCall();\n    }\n\n    /**\n     * @notice Set the implementation contract address. The code at the given address will execute\n     *         when this contract is called.\n     *\n     * @param _implementation Address of the implementation contract.\n     */\n    function upgradeTo(address _implementation) external proxyCallIfNotAdmin {\n        _setImplementation(_implementation);\n    }\n\n    /**\n     * @notice Set the implementation and call a function in a single transaction. Useful to ensure\n     *         atomic execution of initialization-based upgrades.\n     *\n     * @param _implementation Address of the implementation contract.\n     * @param _data           Calldata to delegatecall the new implementation with.\n     */\n    function upgradeToAndCall(address _implementation, bytes calldata _data)\n        external\n        payable\n        proxyCallIfNotAdmin\n        returns (bytes memory)\n    {\n        _setImplementation(_implementation);\n        (bool success, bytes memory returndata) = _implementation.delegatecall(_data);\n        require(success, \"Proxy: delegatecall to new implementation contract failed\");\n        return returndata;\n    }\n\n    /**\n     * @notice Changes the owner of the proxy contract. Only callable by the owner.\n     *\n     * @param _admin New owner of the proxy contract.\n     */\n    function changeAdmin(address _admin) external proxyCallIfNotAdmin {\n        _changeAdmin(_admin);\n    }\n\n    /**\n     * @notice Gets the owner of the proxy contract.\n     *\n     * @return Owner address.\n     */\n    function admin() external proxyCallIfNotAdmin returns (address) {\n        return _getAdmin();\n    }\n\n    /**\n     * @notice Queries the implementation address.\n     *\n     * @return Implementation address.\n     */\n    function implementation() external proxyCallIfNotAdmin returns (address) {\n        return _getImplementation();\n    }\n\n    /**\n     * @notice Sets the implementation address.\n     *\n     * @param _implementation New implementation address.\n     */\n    function _setImplementation(address _implementation) internal {\n        assembly {\n            sstore(IMPLEMENTATION_KEY, _implementation)\n        }\n        emit Upgraded(_implementation);\n    }\n\n    /**\n     * @notice Changes the owner of the proxy contract.\n     *\n     * @param _admin New owner of the proxy contract.\n     */\n    function _changeAdmin(address _admin) internal {\n        address previous = _getAdmin();\n        assembly {\n            sstore(OWNER_KEY, _admin)\n        }\n        emit AdminChanged(previous, _admin);\n    }\n\n    /**\n     * @notice Performs the proxy call via a delegatecall.\n     */\n    function _doProxyCall() internal {\n        address impl = _getImplementation();\n        require(impl != address(0), \"Proxy: implementation not initialized\");\n\n        assembly {\n            // Copy calldata into memory at 0x0....calldatasize.\n            calldatacopy(0x0, 0x0, calldatasize())\n\n            // Perform the delegatecall, make sure to pass all available gas.\n            let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)\n\n            // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n            // overwrite the calldata that we just copied into memory but that doesn't really\n            // matter because we'll be returning in a second anyway.\n            returndatacopy(0x0, 0x0, returndatasize())\n\n            // Success == 0 means a revert. We'll revert too and pass the data up.\n            if iszero(success) {\n                revert(0x0, returndatasize())\n            }\n\n            // Otherwise we'll just return and pass the data up.\n            return(0x0, returndatasize())\n        }\n    }\n\n    /**\n     * @notice Queries the implementation address.\n     *\n     * @return Implementation address.\n     */\n    function _getImplementation() internal view returns (address) {\n        address impl;\n        assembly {\n            impl := sload(IMPLEMENTATION_KEY)\n        }\n        return impl;\n    }\n\n    /**\n     * @notice Queries the owner of the proxy contract.\n     *\n     * @return Owner address.\n     */\n    function _getAdmin() internal view returns (address) {\n        address owner;\n        assembly {\n            owner := sload(OWNER_KEY)\n        }\n        return owner;\n    }\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/legacy/L1ChugSplashProxy.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title IL1ChugSplashDeployer\n */\ninterface IL1ChugSplashDeployer {\n    function isUpgrading() external view returns (bool);\n}\n\n/**\n * @custom:legacy\n * @title L1ChugSplashProxy\n * @notice Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added\n *         functions `setCode` and `setStorage` for changing the code or storage of the contract.\n *\n *         Note for future developers: do NOT make anything in this contract 'public' unless you\n *         know what you're doing. Anything public can potentially have a function signature that\n *         conflicts with a signature attached to the implementation contract. Public functions\n *         SHOULD always have the `proxyCallIfNotOwner` modifier unless there's some *really* good\n *         reason not to have that modifier. And there almost certainly is not a good reason to not\n *         have that modifier. Beware!\n */\ncontract L1ChugSplashProxy {\n    /**\n     * @notice \"Magic\" prefix. When prepended to some arbitrary bytecode and used to create a\n     *         contract, the appended bytecode will be deployed as given.\n     */\n    bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;\n\n    /**\n     * @notice bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n     */\n    bytes32 internal constant IMPLEMENTATION_KEY =\n        0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @notice bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n     */\n    bytes32 internal constant OWNER_KEY =\n        0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @notice Blocks a function from being called when the parent signals that the system should\n     *         be paused via an isUpgrading function.\n     */\n    modifier onlyWhenNotPaused() {\n        address owner = _getOwner();\n\n        // We do a low-level call because there's no guarantee that the owner actually *is* an\n        // L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and\n        // it turns out that it isn't the right type of contract.\n        (bool success, bytes memory returndata) = owner.staticcall(\n            abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector)\n        );\n\n        // If the call was unsuccessful then we assume that there's no \"isUpgrading\" method and we\n        // can just continue as normal. We also expect that the return value is exactly 32 bytes\n        // long. If this isn't the case then we can safely ignore the result.\n        if (success && returndata.length == 32) {\n            // Although the expected value is a *boolean*, it's safer to decode as a uint256 in the\n            // case that the isUpgrading function returned something other than 0 or 1. But we only\n            // really care about the case where this value is 0 (= false).\n            uint256 ret = abi.decode(returndata, (uint256));\n            require(ret == 0, \"L1ChugSplashProxy: system is currently being upgraded\");\n        }\n\n        _;\n    }\n\n    /**\n     * @notice Makes a proxy call instead of triggering the given function when the caller is\n     *         either the owner or the zero address. Caller can only ever be the zero address if\n     *         this function is being called off-chain via eth_call, which is totally fine and can\n     *         be convenient for client-side tooling. Avoids situations where the proxy and\n     *         implementation share a sighash and the proxy function ends up being called instead\n     *         of the implementation one.\n     *\n     *         Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If\n     *         there's a way for someone to send a transaction with msg.sender == address(0) in any\n     *         real context then we have much bigger problems. Primary reason to include this\n     *         additional allowed sender is because the owner address can be changed dynamically\n     *         and we do not want clients to have to keep track of the current owner in order to\n     *         make an eth_call that doesn't trigger the proxied contract.\n     */\n    // slither-disable-next-line incorrect-modifier\n    modifier proxyCallIfNotOwner() {\n        if (msg.sender == _getOwner() || msg.sender == address(0)) {\n            _;\n        } else {\n            // This WILL halt the call frame on completion.\n            _doProxyCall();\n        }\n    }\n\n    /**\n     * @param _owner Address of the initial contract owner.\n     */\n    constructor(address _owner) {\n        _setOwner(_owner);\n    }\n\n    // slither-disable-next-line locked-ether\n    receive() external payable {\n        // Proxy call by default.\n        _doProxyCall();\n    }\n\n    // slither-disable-next-line locked-ether\n    fallback() external payable {\n        // Proxy call by default.\n        _doProxyCall();\n    }\n\n    /**\n     * @notice Sets the code that should be running behind this proxy.\n     *\n     *         Note: This scheme is a bit different from the standard proxy scheme where one would\n     *         typically deploy the code separately and then set the implementation address. We're\n     *         doing it this way because it gives us a lot more freedom on the client side. Can\n     *         only be triggered by the contract owner.\n     *\n     * @param _code New contract code to run inside this contract.\n     */\n    function setCode(bytes memory _code) external proxyCallIfNotOwner {\n        // Get the code hash of the current implementation.\n        address implementation = _getImplementation();\n\n        // If the code hash matches the new implementation then we return early.\n        if (keccak256(_code) == _getAccountCodeHash(implementation)) {\n            return;\n        }\n\n        // Create the deploycode by appending the magic prefix.\n        bytes memory deploycode = abi.encodePacked(DEPLOY_CODE_PREFIX, _code);\n\n        // Deploy the code and set the new implementation address.\n        address newImplementation;\n        assembly {\n            newImplementation := create(0x0, add(deploycode, 0x20), mload(deploycode))\n        }\n\n        // Check that the code was actually deployed correctly. I'm not sure if you can ever\n        // actually fail this check. Should only happen if the contract creation from above runs\n        // out of gas but this parent execution thread does NOT run out of gas. Seems like we\n        // should be doing this check anyway though.\n        require(\n            _getAccountCodeHash(newImplementation) == keccak256(_code),\n            \"L1ChugSplashProxy: code was not correctly deployed\"\n        );\n\n        _setImplementation(newImplementation);\n    }\n\n    /**\n     * @notice Modifies some storage slot within the proxy contract. Gives us a lot of power to\n     *         perform upgrades in a more transparent way. Only callable by the owner.\n     *\n     * @param _key   Storage key to modify.\n     * @param _value New value for the storage key.\n     */\n    function setStorage(bytes32 _key, bytes32 _value) external proxyCallIfNotOwner {\n        assembly {\n            sstore(_key, _value)\n        }\n    }\n\n    /**\n     * @notice Changes the owner of the proxy contract. Only callable by the owner.\n     *\n     * @param _owner New owner of the proxy contract.\n     */\n    function setOwner(address _owner) external proxyCallIfNotOwner {\n        _setOwner(_owner);\n    }\n\n    /**\n     * @notice Queries the owner of the proxy contract. Can only be called by the owner OR by\n     *         making an eth_call and setting the \"from\" address to address(0).\n     *\n     * @return Owner address.\n     */\n    function getOwner() external proxyCallIfNotOwner returns (address) {\n        return _getOwner();\n    }\n\n    /**\n     * @notice Queries the implementation address. Can only be called by the owner OR by making an\n     *         eth_call and setting the \"from\" address to address(0).\n     *\n     * @return Implementation address.\n     */\n    function getImplementation() external proxyCallIfNotOwner returns (address) {\n        return _getImplementation();\n    }\n\n    /**\n     * @notice Sets the implementation address.\n     *\n     * @param _implementation New implementation address.\n     */\n    function _setImplementation(address _implementation) internal {\n        assembly {\n            sstore(IMPLEMENTATION_KEY, _implementation)\n        }\n    }\n\n    /**\n     * @notice Changes the owner of the proxy contract.\n     *\n     * @param _owner New owner of the proxy contract.\n     */\n    function _setOwner(address _owner) internal {\n        assembly {\n            sstore(OWNER_KEY, _owner)\n        }\n    }\n\n    /**\n     * @notice Performs the proxy call via a delegatecall.\n     */\n    function _doProxyCall() internal onlyWhenNotPaused {\n        address implementation = _getImplementation();\n\n        require(implementation != address(0), \"L1ChugSplashProxy: implementation is not set yet\");\n\n        assembly {\n            // Copy calldata into memory at 0x0....calldatasize.\n            calldatacopy(0x0, 0x0, calldatasize())\n\n            // Perform the delegatecall, make sure to pass all available gas.\n            let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)\n\n            // Copy returndata into memory at 0x0....returndatasize. Note that this *will*\n            // overwrite the calldata that we just copied into memory but that doesn't really\n            // matter because we'll be returning in a second anyway.\n            returndatacopy(0x0, 0x0, returndatasize())\n\n            // Success == 0 means a revert. We'll revert too and pass the data up.\n            if iszero(success) {\n                revert(0x0, returndatasize())\n            }\n\n            // Otherwise we'll just return and pass the data up.\n            return(0x0, returndatasize())\n        }\n    }\n\n    /**\n     * @notice Queries the implementation address.\n     *\n     * @return Implementation address.\n     */\n    function _getImplementation() internal view returns (address) {\n        address implementation;\n        assembly {\n            implementation := sload(IMPLEMENTATION_KEY)\n        }\n        return implementation;\n    }\n\n    /**\n     * @notice Queries the owner of the proxy contract.\n     *\n     * @return Owner address.\n     */\n    function _getOwner() internal view returns (address) {\n        address owner;\n        assembly {\n            owner := sload(OWNER_KEY)\n        }\n        return owner;\n    }\n\n    /**\n     * @notice Gets the code hash for a given account.\n     *\n     * @param _account Address of the account to get a code hash for.\n     *\n     * @return Code hash for the account.\n     */\n    function _getAccountCodeHash(address _account) internal view returns (bytes32) {\n        bytes32 codeHash;\n        assembly {\n            codeHash := extcodehash(_account)\n        }\n        return codeHash;\n    }\n}\n"
    },
    "contracts/testing/helpers/ExternalContractCompiler.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ProxyAdmin } from \"@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol\";\nimport { Proxy } from \"@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol\";\n\n/**\n * Just exists so we can compile external contracts.\n */\ncontract ExternalContractCompiler {\n\n}\n"
    },
    "contracts/testing/helpers/TestERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\n\ncontract TestERC721 is ERC721 {\n    constructor() ERC721(\"TEST\", \"TST\") {}\n\n    function mint(address to, uint256 tokenId) public {\n        _mint(to, tokenId);\n    }\n\n    function tokenURI(uint256) public pure virtual override returns (string memory) {}\n}\n"
    },
    "@rari-capital/solmate/src/tokens/ERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721 {\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event Transfer(address indexed from, address indexed to, uint256 indexed id);\n\n    event Approval(address indexed owner, address indexed spender, uint256 indexed id);\n\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /*//////////////////////////////////////////////////////////////\n                         METADATA STORAGE/LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    string public name;\n\n    string public symbol;\n\n    function tokenURI(uint256 id) public view virtual returns (string memory);\n\n    /*//////////////////////////////////////////////////////////////\n                      ERC721 BALANCE/OWNER STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    mapping(uint256 => address) internal _ownerOf;\n\n    mapping(address => uint256) internal _balanceOf;\n\n    function ownerOf(uint256 id) public view virtual returns (address owner) {\n        require((owner = _ownerOf[id]) != address(0), \"NOT_MINTED\");\n    }\n\n    function balanceOf(address owner) public view virtual returns (uint256) {\n        require(owner != address(0), \"ZERO_ADDRESS\");\n\n        return _balanceOf[owner];\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                         ERC721 APPROVAL STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    mapping(uint256 => address) public getApproved;\n\n    mapping(address => mapping(address => bool)) public isApprovedForAll;\n\n    /*//////////////////////////////////////////////////////////////\n                               CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    constructor(string memory _name, string memory _symbol) {\n        name = _name;\n        symbol = _symbol;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                              ERC721 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function approve(address spender, uint256 id) public virtual {\n        address owner = _ownerOf[id];\n\n        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], \"NOT_AUTHORIZED\");\n\n        getApproved[id] = spender;\n\n        emit Approval(owner, spender, id);\n    }\n\n    function setApprovalForAll(address operator, bool approved) public virtual {\n        isApprovedForAll[msg.sender][operator] = approved;\n\n        emit ApprovalForAll(msg.sender, operator, approved);\n    }\n\n    function transferFrom(\n        address from,\n        address to,\n        uint256 id\n    ) public virtual {\n        require(from == _ownerOf[id], \"WRONG_FROM\");\n\n        require(to != address(0), \"INVALID_RECIPIENT\");\n\n        require(\n            msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],\n            \"NOT_AUTHORIZED\"\n        );\n\n        // Underflow of the sender's balance is impossible because we check for\n        // ownership above and the recipient's balance can't realistically overflow.\n        unchecked {\n            _balanceOf[from]--;\n\n            _balanceOf[to]++;\n        }\n\n        _ownerOf[id] = to;\n\n        delete getApproved[id];\n\n        emit Transfer(from, to, id);\n    }\n\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id\n    ) public virtual {\n        transferFrom(from, to, id);\n\n        if (to.code.length != 0)\n            require(\n                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, \"\") ==\n                    ERC721TokenReceiver.onERC721Received.selector,\n                \"UNSAFE_RECIPIENT\"\n            );\n    }\n\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        bytes calldata data\n    ) public virtual {\n        transferFrom(from, to, id);\n\n        if (to.code.length != 0)\n            require(\n                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==\n                    ERC721TokenReceiver.onERC721Received.selector,\n                \"UNSAFE_RECIPIENT\"\n            );\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                              ERC165 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return\n            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165\n            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721\n            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        INTERNAL MINT/BURN LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function _mint(address to, uint256 id) internal virtual {\n        require(to != address(0), \"INVALID_RECIPIENT\");\n\n        require(_ownerOf[id] == address(0), \"ALREADY_MINTED\");\n\n        // Counter overflow is incredibly unrealistic.\n        unchecked {\n            _balanceOf[to]++;\n        }\n\n        _ownerOf[id] = to;\n\n        emit Transfer(address(0), to, id);\n    }\n\n    function _burn(uint256 id) internal virtual {\n        address owner = _ownerOf[id];\n\n        require(owner != address(0), \"NOT_MINTED\");\n\n        // Ownership check above ensures no underflow.\n        unchecked {\n            _balanceOf[owner]--;\n        }\n\n        delete _ownerOf[id];\n\n        delete getApproved[id];\n\n        emit Transfer(owner, address(0), id);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        INTERNAL SAFE MINT LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function _safeMint(address to, uint256 id) internal virtual {\n        _mint(to, id);\n\n        if (to.code.length != 0)\n            require(\n                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, \"\") ==\n                    ERC721TokenReceiver.onERC721Received.selector,\n                \"UNSAFE_RECIPIENT\"\n            );\n    }\n\n    function _safeMint(\n        address to,\n        uint256 id,\n        bytes memory data\n    ) internal virtual {\n        _mint(to, id);\n\n        if (to.code.length != 0)\n            require(\n                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==\n                    ERC721TokenReceiver.onERC721Received.selector,\n                \"UNSAFE_RECIPIENT\"\n            );\n    }\n}\n\n/// @notice A generic interface for a contract which properly accepts ERC721 tokens.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)\nabstract contract ERC721TokenReceiver {\n    function onERC721Received(\n        address,\n        address,\n        uint256,\n        bytes calldata\n    ) external virtual returns (bytes4) {\n        return ERC721TokenReceiver.onERC721Received.selector;\n    }\n}\n"
    },
    "contracts/testing/helpers/TestERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\n\ncontract TestERC20 is ERC20 {\n    constructor() ERC20(\"TEST\", \"TST\", 18) {}\n\n    function mint(address to, uint256 value) public {\n        _mint(to, value);\n    }\n}\n"
    },
    "@rari-capital/solmate/src/tokens/ERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n    /*//////////////////////////////////////////////////////////////\n                            METADATA STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    string public name;\n\n    string public symbol;\n\n    uint8 public immutable decimals;\n\n    /*//////////////////////////////////////////////////////////////\n                              ERC20 STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 public totalSupply;\n\n    mapping(address => uint256) public balanceOf;\n\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    /*//////////////////////////////////////////////////////////////\n                            EIP-2612 STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 internal immutable INITIAL_CHAIN_ID;\n\n    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n    mapping(address => uint256) public nonces;\n\n    /*//////////////////////////////////////////////////////////////\n                               CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    constructor(\n        string memory _name,\n        string memory _symbol,\n        uint8 _decimals\n    ) {\n        name = _name;\n        symbol = _symbol;\n        decimals = _decimals;\n\n        INITIAL_CHAIN_ID = block.chainid;\n        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                               ERC20 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function approve(address spender, uint256 amount) public virtual returns (bool) {\n        allowance[msg.sender][spender] = amount;\n\n        emit Approval(msg.sender, spender, amount);\n\n        return true;\n    }\n\n    function transfer(address to, uint256 amount) public virtual returns (bool) {\n        balanceOf[msg.sender] -= amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(msg.sender, to, amount);\n\n        return true;\n    }\n\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) public virtual returns (bool) {\n        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n        balanceOf[from] -= amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        return true;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                             EIP-2612 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) public virtual {\n        require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n        // Unchecked because the only math done is incrementing\n        // the owner's nonce which cannot realistically overflow.\n        unchecked {\n            address recoveredAddress = ecrecover(\n                keccak256(\n                    abi.encodePacked(\n                        \"\\x19\\x01\",\n                        DOMAIN_SEPARATOR(),\n                        keccak256(\n                            abi.encode(\n                                keccak256(\n                                    \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n                                ),\n                                owner,\n                                spender,\n                                value,\n                                nonces[owner]++,\n                                deadline\n                            )\n                        )\n                    )\n                ),\n                v,\n                r,\n                s\n            );\n\n            require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n            allowance[recoveredAddress][spender] = value;\n        }\n\n        emit Approval(owner, spender, value);\n    }\n\n    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n    }\n\n    function computeDomainSeparator() internal view virtual returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n                    keccak256(bytes(name)),\n                    keccak256(\"1\"),\n                    block.chainid,\n                    address(this)\n                )\n            );\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        INTERNAL MINT/BURN LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function _mint(address to, uint256 amount) internal virtual {\n        totalSupply += amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(address(0), to, amount);\n    }\n\n    function _burn(address from, uint256 amount) internal virtual {\n        balanceOf[from] -= amount;\n\n        // Cannot underflow because a user's balance\n        // will never be larger than the total supply.\n        unchecked {\n            totalSupply -= amount;\n        }\n\n        emit Transfer(from, address(0), amount);\n    }\n}\n"
    },
    "contracts/L1/TeleportrWithdrawer.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AssetReceiver } from \"../universal/AssetReceiver.sol\";\n\n/**\n * @notice Stub interface for Teleportr.\n */\ninterface Teleportr {\n    function withdrawBalance() external;\n}\n\n/**\n * @title TeleportrWithdrawer\n * @notice The TeleportrWithdrawer is a simple contract capable of withdrawing funds from the\n *         TeleportrContract and sending them to some recipient address.\n */\ncontract TeleportrWithdrawer is AssetReceiver {\n    /**\n     * @notice Address of the Teleportr contract.\n     */\n    address public teleportr;\n\n    /**\n     * @notice Address that will receive Teleportr withdrawals.\n     */\n    address public recipient;\n\n    /**\n     * @notice Data to be sent to the recipient address.\n     */\n    bytes public data;\n\n    /**\n     * @param _owner Initial owner of the contract.\n     */\n    constructor(address _owner) AssetReceiver(_owner) {}\n\n    /**\n     * @notice Allows the owner to update the recipient address.\n     *\n     * @param _recipient New recipient address.\n     */\n    function setRecipient(address _recipient) external onlyOwner {\n        recipient = _recipient;\n    }\n\n    /**\n     * @notice Allows the owner to update the Teleportr contract address.\n     *\n     * @param _teleportr New Teleportr contract address.\n     */\n    function setTeleportr(address _teleportr) external onlyOwner {\n        teleportr = _teleportr;\n    }\n\n    /**\n     * @notice Allows the owner to update the data to be sent to the recipient address.\n     *\n     * @param _data New data to be sent to the recipient address.\n     */\n    function setData(bytes memory _data) external onlyOwner {\n        data = _data;\n    }\n\n    /**\n     * @notice Withdraws the full balance of the Teleportr contract to the recipient address.\n     *         Anyone is allowed to trigger this function since the recipient address cannot be\n     *         controlled by the msg.sender.\n     */\n    function withdrawFromTeleportr() external {\n        Teleportr(teleportr).withdrawBalance();\n        (bool success, ) = recipient.call{ value: address(this).balance }(data);\n        require(success, \"TeleportrWithdrawer: send failed\");\n    }\n}\n"
    },
    "contracts/universal/AssetReceiver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ERC20 } from \"@rari-capital/solmate/src/tokens/ERC20.sol\";\nimport { ERC721 } from \"@rari-capital/solmate/src/tokens/ERC721.sol\";\nimport { Transactor } from \"./Transactor.sol\";\n\n/**\n * @title AssetReceiver\n * @notice AssetReceiver is a minimal contract for receiving funds assets in the form of either\n * ETH, ERC20 tokens, or ERC721 tokens. Only the contract owner may withdraw the assets.\n */\ncontract AssetReceiver is Transactor {\n    /**\n     * @notice Emitted when ETH is received by this address.\n     *\n     * @param from   Address that sent ETH to this contract.\n     * @param amount Amount of ETH received.\n     */\n    event ReceivedETH(address indexed from, uint256 amount);\n\n    /**\n     * @notice Emitted when ETH is withdrawn from this address.\n     *\n     * @param withdrawer Address that triggered the withdrawal.\n     * @param recipient  Address that received the withdrawal.\n     * @param amount     ETH amount withdrawn.\n     */\n    event WithdrewETH(address indexed withdrawer, address indexed recipient, uint256 amount);\n\n    /**\n     * @notice Emitted when ERC20 tokens are withdrawn from this address.\n     *\n     * @param withdrawer Address that triggered the withdrawal.\n     * @param recipient  Address that received the withdrawal.\n     * @param asset      Address of the token being withdrawn.\n     * @param amount     ERC20 amount withdrawn.\n     */\n    event WithdrewERC20(\n        address indexed withdrawer,\n        address indexed recipient,\n        address indexed asset,\n        uint256 amount\n    );\n\n    /**\n     * @notice Emitted when ERC20 tokens are withdrawn from this address.\n     *\n     * @param withdrawer Address that triggered the withdrawal.\n     * @param recipient  Address that received the withdrawal.\n     * @param asset      Address of the token being withdrawn.\n     * @param id         Token ID being withdrawn.\n     */\n    event WithdrewERC721(\n        address indexed withdrawer,\n        address indexed recipient,\n        address indexed asset,\n        uint256 id\n    );\n\n    /**\n     * @param _owner Initial contract owner.\n     */\n    constructor(address _owner) Transactor(_owner) {}\n\n    /**\n     * @notice Make sure we can receive ETH.\n     */\n    receive() external payable {\n        emit ReceivedETH(msg.sender, msg.value);\n    }\n\n    /**\n     * @notice Withdraws full ETH balance to the recipient.\n     *\n     * @param _to Address to receive the ETH balance.\n     */\n    function withdrawETH(address payable _to) external onlyOwner {\n        withdrawETH(_to, address(this).balance);\n    }\n\n    /**\n     * @notice Withdraws partial ETH balance to the recipient.\n     *\n     * @param _to     Address to receive the ETH balance.\n     * @param _amount Amount of ETH to withdraw.\n     */\n    function withdrawETH(address payable _to, uint256 _amount) public onlyOwner {\n        // slither-disable-next-line reentrancy-unlimited-gas\n        (bool success, ) = _to.call{ value: _amount }(\"\");\n        emit WithdrewETH(msg.sender, _to, _amount);\n    }\n\n    /**\n     * @notice Withdraws full ERC20 balance to the recipient.\n     *\n     * @param _asset ERC20 token to withdraw.\n     * @param _to    Address to receive the ERC20 balance.\n     */\n    function withdrawERC20(ERC20 _asset, address _to) external onlyOwner {\n        withdrawERC20(_asset, _to, _asset.balanceOf(address(this)));\n    }\n\n    /**\n     * @notice Withdraws partial ERC20 balance to the recipient.\n     *\n     * @param _asset  ERC20 token to withdraw.\n     * @param _to     Address to receive the ERC20 balance.\n     * @param _amount Amount of ERC20 to withdraw.\n     */\n    function withdrawERC20(\n        ERC20 _asset,\n        address _to,\n        uint256 _amount\n    ) public onlyOwner {\n        // slither-disable-next-line unchecked-transfer\n        _asset.transfer(_to, _amount);\n        // slither-disable-next-line reentrancy-events\n        emit WithdrewERC20(msg.sender, _to, address(_asset), _amount);\n    }\n\n    /**\n     * @notice Withdraws ERC721 token to the recipient.\n     *\n     * @param _asset ERC721 token to withdraw.\n     * @param _to    Address to receive the ERC721 token.\n     * @param _id    Token ID of the ERC721 token to withdraw.\n     */\n    function withdrawERC721(\n        ERC721 _asset,\n        address _to,\n        uint256 _id\n    ) external onlyOwner {\n        _asset.transferFrom(address(this), _to, _id);\n        // slither-disable-next-line reentrancy-events\n        emit WithdrewERC721(msg.sender, _to, address(_asset), _id);\n    }\n}\n"
    },
    "contracts/universal/Transactor.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\n\n/**\n * @title Transactor\n * @notice Transactor is a minimal contract that can send transactions.\n */\ncontract Transactor is Owned {\n    /**\n     * @param _owner Initial contract owner.\n     */\n    constructor(address _owner) Owned(_owner) {}\n\n    /**\n     * Sends a CALL to a target address.\n     *\n     * @param _target Address to call.\n     * @param _data   Data to send with the call.\n     * @param _value  ETH value to send with the call.\n     *\n     * @return Boolean success value.\n     * @return Bytes data returned by the call.\n     */\n    function CALL(\n        address _target,\n        bytes memory _data,\n        uint256 _value\n    ) external payable onlyOwner returns (bool, bytes memory) {\n        return _target.call{ value: _value }(_data);\n    }\n\n    /**\n     * Sends a DELEGATECALL to a target address.\n     *\n     * @param _target Address to call.\n     * @param _data   Data to send with the call.\n     *\n     * @return Boolean success value.\n     * @return Bytes data returned by the call.\n     */\n    function DELEGATECALL(address _target, bytes memory _data)\n        external\n        payable\n        onlyOwner\n        returns (bool, bytes memory)\n    {\n        // slither-disable-next-line controlled-delegatecall\n        return _target.delegatecall(_data);\n    }\n}\n"
    },
    "contracts/L2/TeleportrDisburser.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title TeleportrDisburser\n */\ncontract TeleportrDisburser is Ownable {\n    /**\n     * @notice A struct holding the address and amount to disbursement.\n     */\n    struct Disbursement {\n        uint256 amount;\n        address addr;\n    }\n\n    /**\n     * @notice Total number of disbursements processed.\n     */\n    uint256 public totalDisbursements;\n\n    /**\n     * @notice Emitted any time the balance is withdrawn by the owner.\n     *\n     * @param owner   The current owner and recipient of the funds.\n     * @param balance The current contract balance paid to the owner.\n     */\n    event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n    /**\n     * @notice Emitted any time a disbursement is successfuly sent.\n     *\n     * @param depositId The unique sequence number identifying the deposit.\n     * @param to        The recipient of the disbursement.\n     * @param amount    The amount sent to the recipient.\n     */\n    event DisbursementSuccess(uint256 indexed depositId, address indexed to, uint256 amount);\n\n    /**\n     * @notice Emitted any time a disbursement fails to send.\n     *\n     * @param depositId The unique sequence number identifying the deposit.\n     * @param to        The intended recipient of the disbursement.\n     * @param amount    The amount intended to be sent to the recipient.\n     */\n    event DisbursementFailed(uint256 indexed depositId, address indexed to, uint256 amount);\n\n    /**\n     * @custom:semver 0.0.1\n     */\n    constructor() {\n        totalDisbursements = 0;\n    }\n\n    /**\n     * @notice Accepts a list of Disbursements and forwards the amount paid to the contract to each\n     *         recipient. Reverts if there are zero disbursements, the total amount to forward\n     *         differs from the amount sent in the transaction, or the _nextDepositId is\n     *         unexpected. Failed disbursements will not cause the method to revert, but will\n     *         instead be held by the contract and available for the owner to withdraw.\n     *\n     * @param _nextDepositId The depositId of the first Dispursement.\n     * @param _disbursements A list of Disbursements to process.\n     */\n    function disburse(uint256 _nextDepositId, Disbursement[] calldata _disbursements)\n        external\n        payable\n        onlyOwner\n    {\n        // Ensure there are disbursements to process.\n        uint256 _numDisbursements = _disbursements.length;\n        require(_numDisbursements > 0, \"No disbursements\");\n\n        // Ensure the _nextDepositId matches our expected value.\n        uint256 _depositId = totalDisbursements;\n        require(_depositId == _nextDepositId, \"Unexpected next deposit id\");\n        unchecked {\n            totalDisbursements += _numDisbursements;\n        }\n\n        // Ensure the amount sent in the transaction is equal to the sum of the\n        // disbursements.\n        uint256 _totalDisbursed = 0;\n        for (uint256 i = 0; i < _numDisbursements; i++) {\n            _totalDisbursed += _disbursements[i].amount;\n        }\n        require(_totalDisbursed == msg.value, \"Disbursement total != amount sent\");\n\n        // Process disbursements.\n        for (uint256 i = 0; i < _numDisbursements; i++) {\n            uint256 _amount = _disbursements[i].amount;\n            address _addr = _disbursements[i].addr;\n\n            // Deliver the dispursement amount to the receiver. If the\n            // disbursement fails, the amount will be kept by the contract\n            // rather than reverting to prevent blocking progress on other\n            // disbursements.\n\n            // slither-disable-next-line calls-loop,reentrancy-events\n            (bool success, ) = _addr.call{ value: _amount, gas: 2300 }(\"\");\n            if (success) emit DisbursementSuccess(_depositId, _addr, _amount);\n            else emit DisbursementFailed(_depositId, _addr, _amount);\n\n            unchecked {\n                _depositId += 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Sends the contract's current balance to the owner.\n     */\n    function withdrawBalance() external onlyOwner {\n        address _owner = owner();\n        uint256 balance = address(this).balance;\n        emit BalanceWithdrawn(_owner, balance);\n        payable(_owner).transfer(balance);\n    }\n}\n"
    },
    "contracts/L1/TeleportrDeposit.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @custom:attribution https://github.com/0xclem/teleportr\n * @title TeleportrDeposit\n * @notice A contract meant to manage deposits into Optimism's Teleportr custodial bridge. Deposits\n *         are rate limited to avoid a situation where too much ETH is flowing through this bridge\n *         and cannot be properly disbursed on L2. Inspired by 0xclem's original Teleportr system\n *         (https://github.com/0xclem/teleportr).\n */\ncontract TeleportrDeposit is Ownable {\n    /**\n     * @notice Minimum deposit amount (in wei).\n     */\n    uint256 public minDepositAmount;\n\n    /**\n     * @notice Maximum deposit amount (in wei).\n     */\n    uint256 public maxDepositAmount;\n\n    /**\n     * @notice Maximum balance this contract will hold before it starts rejecting deposits.\n     */\n    uint256 public maxBalance;\n\n    /**\n     * @notice Total number of deposits received.\n     */\n    uint256 public totalDeposits;\n\n    /**\n     * @notice Emitted any time the minimum deposit amount is set.\n     *\n     * @param previousAmount The previous minimum deposit amount.\n     * @param newAmount      The new minimum deposit amount.\n     */\n    event MinDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n    /**\n     * @notice Emitted any time the maximum deposit amount is set.\n     *\n     * @param previousAmount The previous maximum deposit amount.\n     * @param newAmount      The new maximum deposit amount.\n     */\n    event MaxDepositAmountSet(uint256 previousAmount, uint256 newAmount);\n\n    /**\n     * @notice Emitted any time the contract maximum balance is set.\n     *\n     * @param previousBalance The previous maximum contract balance.\n     * @param newBalance      The new maximum contract balance.\n     */\n    event MaxBalanceSet(uint256 previousBalance, uint256 newBalance);\n\n    /**\n     * @notice Emitted any time the balance is withdrawn by the owner.\n     *\n     * @param owner   The current owner and recipient of the funds.\n     * @param balance The current contract balance paid to the owner.\n     */\n    event BalanceWithdrawn(address indexed owner, uint256 balance);\n\n    /**\n     * @notice Emitted any time a successful deposit is received.\n     *\n     * @param depositId A unique sequencer number identifying the deposit.\n     * @param emitter   The sending address of the payer.\n     * @param amount    The amount deposited by the payer.\n     */\n    event EtherReceived(uint256 indexed depositId, address indexed emitter, uint256 indexed amount);\n\n    /**\n     * @custom:semver 0.0.1\n     *\n     * @param _minDepositAmount The initial minimum deposit amount.\n     * @param _maxDepositAmount The initial maximum deposit amount.\n     * @param _maxBalance       The initial maximum contract balance.\n     */\n    constructor(\n        uint256 _minDepositAmount,\n        uint256 _maxDepositAmount,\n        uint256 _maxBalance\n    ) {\n        minDepositAmount = _minDepositAmount;\n        maxDepositAmount = _maxDepositAmount;\n        maxBalance = _maxBalance;\n        totalDeposits = 0;\n        emit MinDepositAmountSet(0, _minDepositAmount);\n        emit MaxDepositAmountSet(0, _maxDepositAmount);\n        emit MaxBalanceSet(0, _maxBalance);\n    }\n\n    /**\n     * @notice Accepts deposits that will be disbursed to the sender's address on L2.\n     */\n    receive() external payable {\n        require(msg.value >= minDepositAmount, \"Deposit amount is too small\");\n        require(msg.value <= maxDepositAmount, \"Deposit amount is too big\");\n        require(address(this).balance <= maxBalance, \"Contract max balance exceeded\");\n\n        emit EtherReceived(totalDeposits, msg.sender, msg.value);\n        unchecked {\n            totalDeposits += 1;\n        }\n    }\n\n    /**\n     * @notice Sends the contract's current balance to the owner.\n     */\n    function withdrawBalance() external onlyOwner {\n        address _owner = owner();\n        uint256 _balance = address(this).balance;\n        emit BalanceWithdrawn(_owner, _balance);\n        payable(_owner).transfer(_balance);\n    }\n\n    /**\n     * @notice Sets the minimum amount that can be deposited in a receive.\n     *\n     * @param _minDepositAmount The new minimum deposit amount.\n     */\n    function setMinAmount(uint256 _minDepositAmount) external onlyOwner {\n        emit MinDepositAmountSet(minDepositAmount, _minDepositAmount);\n        minDepositAmount = _minDepositAmount;\n    }\n\n    /**\n     * @notice Sets the maximum amount that can be deposited in a receive.\n     *\n     * @param _maxDepositAmount The new maximum deposit amount.\n     */\n    function setMaxAmount(uint256 _maxDepositAmount) external onlyOwner {\n        emit MaxDepositAmountSet(maxDepositAmount, _maxDepositAmount);\n        maxDepositAmount = _maxDepositAmount;\n    }\n\n    /**\n     * @notice Sets the maximum balance the contract can hold after a receive.\n     *\n     * @param _maxBalance The new maximum contract balance.\n     */\n    function setMaxBalance(uint256 _maxBalance) external onlyOwner {\n        emit MaxBalanceSet(maxBalance, _maxBalance);\n        maxBalance = _maxBalance;\n    }\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 10000
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "storageLayout",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    }
  }
}