{
  "language": "Solidity",
  "sources": {
    "contracts/L1/messaging/L1ERC721Bridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport {\n    CrossDomainEnabled\n} from \"@eth-optimism/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol\";\nimport {\n    OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { L2ERC721Bridge } from \"../../L2/messaging/L2ERC721Bridge.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 between Optimism and Ethereum. This contract\n *         acts as an escrow for ERC721 tokens deposted into L2.\n */\ncontract L1ERC721Bridge is CrossDomainEnabled, OwnableUpgradeable {\n    /**\n     * @notice Contract version number.\n     */\n    uint8 public constant VERSION = 1;\n\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 Address of the bridge on the other network.\n     */\n    address public otherBridge;\n\n    // Maps L1 token to L2 token to token ID to a boolean indicating if the token is deposited\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     * @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) CrossDomainEnabled(address(0)) {\n        initialize(_messenger, _otherBridge);\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    function initialize(address _messenger, address _otherBridge) public reinitializer(VERSION) {\n        messenger = _messenger;\n        otherBridge = _otherBridge;\n\n        // Initialize upgradable OZ contracts\n        __Ownable_init();\n    }\n\n    /**\n     * @notice Initiates a bridge of an NFT to the caller's account 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 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 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 check could be bypassed by a malicious\n        // contract via initcode, but it takes care of the user error we want to avoid.\n        require(!Address.isContract(msg.sender), \"L1ERC721Bridge: 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 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 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 bridgeERC721To(\n        address _localToken,\n        address _remoteToken,\n        address _to,\n        uint256 _tokenId,\n        uint32 _minGasLimit,\n        bytes calldata _extraData\n    ) external {\n        _initiateBridgeERC721(\n            _localToken,\n            _remoteToken,\n            msg.sender,\n            _to,\n            _tokenId,\n            _minGasLimit,\n            _extraData\n        );\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 onlyFromCrossDomainAccount(otherBridge) {\n        // Checks that the L1/L2 token pair has a token ID that is escrowed in the L1 Bridge\n        require(\n            deposits[_localToken][_remoteToken][_tokenId] == true,\n            \"Token ID is not escrowed in the L1 Bridge\"\n        );\n\n        deposits[_localToken][_remoteToken][_tokenId] = false;\n\n        // When a withdrawal is finalized on L1, the L1 Bridge transfers the NFT to the withdrawer\n        // slither-disable-next-line reentrancy-events\n        IERC721(_localToken).transferFrom(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     * @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 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 _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 {\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        sendCrossDomainMessage(otherBridge, _minGasLimit, message);\n        emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n    }\n}\n"
    },
    "@eth-optimism/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/* Interface Imports */\nimport { ICrossDomainMessenger } from \"./ICrossDomainMessenger.sol\";\n\n/**\n * @title CrossDomainEnabled\n * @dev Helper contract for contracts performing cross-domain communications\n *\n * Compiler used: defined by inheriting contract\n */\ncontract CrossDomainEnabled {\n    /*************\n     * Variables *\n     *************/\n\n    // Messenger contract used to send and recieve messages from the other domain.\n    address public messenger;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _messenger Address of the CrossDomainMessenger on the current layer.\n     */\n    constructor(address _messenger) {\n        messenger = _messenger;\n    }\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    /**\n     * Enforces that the modified function is only callable by a specific cross-domain account.\n     * @param _sourceDomainAccount The only account on the originating domain which is\n     *  authenticated to call this function.\n     */\n    modifier onlyFromCrossDomainAccount(address _sourceDomainAccount) {\n        require(\n            msg.sender == address(getCrossDomainMessenger()),\n            \"OVM_XCHAIN: messenger contract unauthenticated\"\n        );\n\n        require(\n            getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount,\n            \"OVM_XCHAIN: wrong sender of cross-domain message\"\n        );\n\n        _;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Gets the messenger, usually from storage. This function is exposed in case a child contract\n     * needs to override.\n     * @return The address of the cross-domain messenger contract which should be used.\n     */\n    function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) {\n        return ICrossDomainMessenger(messenger);\n    }\n\n    /**q\n     * Sends a message to an account on another domain\n     * @param _crossDomainTarget The intended recipient on the destination domain\n     * @param _message The data to send to the target (usually calldata to a function with\n     *  `onlyFromCrossDomainAccount()`)\n     * @param _gasLimit The gasLimit for the receipt of the message on the target domain.\n     */\n    function sendCrossDomainMessage(\n        address _crossDomainTarget,\n        uint32 _gasLimit,\n        bytes memory _message\n    ) internal {\n        // slither-disable-next-line reentrancy-events, reentrancy-benign\n        getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit);\n    }\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (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 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    /**\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/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"
    },
    "@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"
    },
    "contracts/L2/messaging/L2ERC721Bridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport {\n    CrossDomainEnabled\n} from \"@eth-optimism/contracts/contracts/libraries/bridge/CrossDomainEnabled.sol\";\nimport {\n    OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { L1ERC721Bridge } from \"../../L1/messaging/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../../universal/op-erc721/IOptimismMintableERC721.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 between Optimism and Ethereum. 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 */\ncontract L2ERC721Bridge is CrossDomainEnabled, OwnableUpgradeable {\n    /**\n     * @notice Contract version number.\n     */\n    uint8 public constant VERSION = 1;\n\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 Emitted when an ERC721 bridge from the other network fails.\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 ERC721BridgeFailed(\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 Address of the bridge on the other network.\n     */\n    address public otherBridge;\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) CrossDomainEnabled(address(0)) {\n        initialize(_messenger, _otherBridge);\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    function initialize(address _messenger, address _otherBridge) public reinitializer(VERSION) {\n        messenger = _messenger;\n        otherBridge = _otherBridge;\n\n        // Initialize upgradable OZ contracts\n        __Ownable_init();\n    }\n\n    /**\n     * @notice Initiates a bridge of an NFT to the caller's account on L1.\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 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 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 check could be bypassed by a malicious\n        // contract via initcode, but it takes care of the user error we want to avoid.\n        require(!Address.isContract(msg.sender), \"L2ERC721Bridge: 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 L1.\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 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 bridgeERC721To(\n        address _localToken,\n        address _remoteToken,\n        address _to,\n        uint256 _tokenId,\n        uint32 _minGasLimit,\n        bytes calldata _extraData\n    ) external {\n        _initiateBridgeERC721(\n            _localToken,\n            _remoteToken,\n            msg.sender,\n            _to,\n            _tokenId,\n            _minGasLimit,\n            _extraData\n        );\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 onlyFromCrossDomainAccount(otherBridge) {\n        // Check the target token is compliant and verify the deposited token on L1 matches the L2\n        // deposited token representation.\n        if (\n            // slither-disable-next-line reentrancy-events\n            ERC165Checker.supportsInterface(\n                _localToken,\n                type(IOptimismMintableERC721).interfaceId\n            ) && _remoteToken == IOptimismMintableERC721(_localToken).remoteToken()\n        ) {\n            // When a deposit is finalized, we give the NFT with the same tokenId to the account\n            // on L2.\n            // slither-disable-next-line reentrancy-events\n            IOptimismMintableERC721(_localToken).mint(_to, _tokenId);\n            // slither-disable-next-line reentrancy-events\n            emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n        } else {\n            // Either the L2 token which is being deposited-into disagrees about the correct address\n            // of its L1 token, or does not support the correct interface.\n            // This should only happen if there is a  malicious L2 token, or if a user somehow\n            // specified the wrong L2 token address to deposit into.\n            // In either case, we stop the process here and construct a withdrawal\n            // message so that users can get their NFT out in some cases.\n            // There is no way to prevent malicious token contracts altogether, but this does limit\n            // user error and mitigate some forms of malicious contract behavior.\n            bytes memory message = abi.encodeWithSelector(\n                L1ERC721Bridge.finalizeBridgeERC721.selector,\n                _remoteToken,\n                _localToken,\n                _to, // switched the _to and _from here to bounce back the deposit to the sender\n                _from,\n                _tokenId,\n                _extraData\n            );\n\n            // Send message up to L1 bridge\n            // slither-disable-next-line reentrancy-events\n            sendCrossDomainMessage(otherBridge, 0, message);\n\n            // slither-disable-next-line reentrancy-events\n            emit ERC721BridgeFailed(_localToken, _remoteToken, _from, _to, _tokenId, _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 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 _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 {\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        // 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        // 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        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        sendCrossDomainMessage(otherBridge, _minGasLimit, message);\n\n        // slither-disable-next-line reentrancy-events\n        emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n    }\n}\n"
    },
    "@eth-optimism/contracts/contracts/libraries/bridge/ICrossDomainMessenger.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title ICrossDomainMessenger\n */\ninterface ICrossDomainMessenger {\n    /**********\n     * Events *\n     **********/\n\n    event SentMessage(\n        address indexed target,\n        address sender,\n        bytes message,\n        uint256 messageNonce,\n        uint256 gasLimit\n    );\n    event RelayedMessage(bytes32 indexed msgHash);\n    event FailedRelayedMessage(bytes32 indexed msgHash);\n\n    /*************\n     * Variables *\n     *************/\n\n    function xDomainMessageSender() external view returns (address);\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Sends a cross domain message to the target messenger.\n     * @param _target Target contract address.\n     * @param _message Message to send to the target.\n     * @param _gasLimit Gas limit for the provided message.\n     */\n    function sendMessage(\n        address _target,\n        bytes calldata _message,\n        uint32 _gasLimit\n    ) external;\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.6.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 = _setInitializedVersion(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        bool isTopLevelCall = _setInitializedVersion(version);\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(version);\n        }\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        _setInitializedVersion(type(uint8).max);\n    }\n\n    function _setInitializedVersion(uint8 version) private returns (bool) {\n        // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n        // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n        // of initializers, because in other contexts the contract may have been reentered.\n        if (_initializing) {\n            require(\n                version == 1 && !AddressUpgradeable.isContract(address(this)),\n                \"Initializable: contract is already initialized\"\n            );\n            return false;\n        } else {\n            require(_initialized < version, \"Initializable: contract is already initialized\");\n            _initialized = version;\n            return true;\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.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 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\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/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.9;\n\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.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 IERC721 {\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 Address of the token on the remote domain.\n     */\n    function remoteToken() external returns (address);\n\n    /**\n     * @notice Address of the ERC721 bridge on this network.\n     */\n    function bridge() external returns (address);\n\n    /**\n     * @notice Mints some token ID for a user.\n     *\n     * @param _to      Address of the user to mint the token for.\n     * @param _tokenId Token ID to mint.\n     */\n    function mint(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"
    },
    "contracts/universal/op-erc721/OptimismMintableERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\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 ERC721, IOptimismMintableERC721 {\n    /**\n     * @inheritdoc IOptimismMintableERC721\n     */\n    address public remoteToken;\n\n    /**\n     * @inheritdoc IOptimismMintableERC721\n     */\n    address public 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 _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        address _remoteToken,\n        string memory _name,\n        string memory _symbol\n    ) ERC721(_name, _symbol) {\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)),\n                \"@\",\n                Strings.toString(block.chainid),\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 mint(address _to, uint256 _tokenId) external virtual onlyBridge {\n        _mint(_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(ERC721, 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/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/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/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"
    },
    "contracts/universal/op-erc721/OptimismMintableERC721Factory.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport {\n    OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { OptimismMintableERC721 } from \"./OptimismMintableERC721.sol\";\n\n/**\n * @title OptimismMintableERC721Factory\n * @notice Factory contract for creating OptimismMintableERC721 contracts.\n */\ncontract OptimismMintableERC721Factory is OwnableUpgradeable {\n    /**\n     * @notice Contract version number.\n     */\n    uint8 public constant VERSION = 1;\n\n    /**\n     * @notice Emitted whenever a new OptimismMintableERC721 contract is created.\n     *\n     * @param remoteToken Address of the token on the remote domain.\n     * @param localToken  Address of the token on the this domain.\n     */\n    event OptimismMintableERC721Created(address indexed remoteToken, address indexed localToken);\n\n    /**\n     * @notice Address of the ERC721 bridge on this network.\n     */\n    address public bridge;\n\n    /**\n     * @notice Tracks addresses created by this factory.\n     */\n    mapping(address => bool) public isStandardOptimismMintableERC721;\n\n    /**\n     * @param _bridge Address of the ERC721 bridge on this network.\n     */\n    constructor(address _bridge) {\n        initialize(_bridge);\n    }\n\n    /**\n     * @notice Initializes the factory.\n     *\n     * @param _bridge Address of the ERC721 bridge on this network.\n     */\n    function initialize(address _bridge) public reinitializer(VERSION) {\n        bridge = _bridge;\n\n        // Initialize upgradable OZ contracts\n        __Ownable_init();\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 createStandardOptimismMintableERC721(\n        address _remoteToken,\n        string memory _name,\n        string memory _symbol\n    ) external {\n        require(\n            _remoteToken != address(0),\n            \"OptimismMintableERC721Factory: L1 token address cannot be address(0)\"\n        );\n        require(\n            bridge != address(0),\n            \"OptimismMintableERC721Factory: bridge address must be initialized\"\n        );\n\n        OptimismMintableERC721 localToken = new OptimismMintableERC721(\n            bridge,\n            _remoteToken,\n            _name,\n            _symbol\n        );\n\n        isStandardOptimismMintableERC721[address(localToken)] = true;\n        emit OptimismMintableERC721Created(_remoteToken, address(localToken));\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * The default value of {decimals} is 18. To select a different value for\n     * {decimals} you should overload it.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the value {ERC20} uses, unless this function is\n     * overridden;\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) public virtual override returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, amount);\n        _transfer(from, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        uint256 currentAllowance = allowance(owner, spender);\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(owner, spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `sender` to `recipient`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     */\n    function _transfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {\n        require(from != address(0), \"ERC20: transfer from the zero address\");\n        require(to != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, amount);\n\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n        }\n        _balances[to] += amount;\n\n        emit Transfer(from, to, amount);\n\n        _afterTokenTransfer(from, to, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        _balances[account] += amount;\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n        }\n        _totalSupply -= amount;\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(\n        address owner,\n        address spender,\n        uint256 amount\n    ) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n     *\n     * Does not update the allowance amount in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Might emit an {Approval} event.\n     */\n    function _spendAllowance(\n        address owner,\n        address spender,\n        uint256 amount\n    ) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n            unchecked {\n                _approve(owner, spender, currentAllowance - amount);\n            }\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens 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 amount\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, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been 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 _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
    },
    "contracts/testing/helpers/TestERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestERC20 is ERC20 {\n    constructor() ERC20(\"TEST\", \"TST\") {}\n\n    function mint(address to, uint256 value) public {\n        _mint(to, value);\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/legacy/Lib_AddressManager.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* External Imports */\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Lib_AddressManager\n */\ncontract Lib_AddressManager is Ownable {\n    /**********\n     * Events *\n     **********/\n\n    event AddressSet(string indexed _name, address _newAddress, address _oldAddress);\n\n    /*************\n     * Variables *\n     *************/\n\n    mapping(bytes32 => address) private addresses;\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Changes the address associated with a particular name.\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     * Retrieves the address associated with a given name.\n     * @param _name Name to retrieve an address for.\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     * Internal Functions *\n     **********************/\n\n    /**\n     * Computes the hash of a name.\n     * @param _name Name to compute a hash for.\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"
    },
    "@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { Proxy } from \"./Proxy.sol\";\nimport { Owned } from \"@rari-capital/solmate/src/auth/Owned.sol\";\nimport { Lib_AddressManager } from \"../legacy/Lib_AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\n\n// Define static interfaces of these proxies so that we can easily\n// use staticcall on the getters we need.\ninterface IStatic_ERC1967Proxy {\n    function implementation() external view returns (address);\n\n    function admin() external view returns (address);\n}\n\ninterface IStatic_L1ChugSplashProxy {\n    function getImplementation() external view returns (address);\n\n    function getOwner() external view returns (address);\n}\n\n/**\n * @title ProxyAdmin\n * @dev 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 with\n *      the various types of proxies that have been deployed by Optimism.\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\n     *                                interface, this is the default.\n     * @custom:value Chugsplash       Represents the Chugsplash proxy interface,\n     *                                this is legacy.\n     * @custom:value ResolvedDelegate Represents the ResolvedDelegate proxy\n     *                                interface, this is legacy.\n     */\n    enum ProxyType {\n        ERC1967,\n        Chugsplash,\n        ResolvedDelegate\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 Lib_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     *         Lib_ResolvedDelegateProxy type.\n     */\n    Lib_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     * @notice Set the owner of the ProxyAdmin via constructor argument.\n     */\n    constructor(address owner) Owned(owner) {}\n\n    /**\n     * @notice\n     *\n     * @param _address   The address of the proxy.\n     * @param _type The type of the proxy.\n     */\n    function setProxyType(address _address, ProxyType _type) external onlyOwner {\n        proxyType[_address] = _type;\n    }\n\n    /**\n     * @notice Set the proxy type in the mapping. This needs to be kept up to date by the owner of\n     *         the contract.\n     *\n     * @param _address The address to be named.\n     * @param _name    The name of the address.\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 address manager. This is required to manage the legacy\n     *         `Lib_ResolvedDelegateProxy`.\n     *\n     * @param _address The address of the address manager.\n     */\n    function setAddressManager(Lib_AddressManager _address) external onlyOwner {\n        addressManager = _address;\n    }\n\n    /**\n     * @custom:legacy\n     * @notice Set an address in the address manager. This is required because only the owner of\n     *         the AddressManager can set the addresses in it.\n     *\n     * @param _name    The name of the address to set in the address manager.\n     * @param _address The address to set in the address manager.\n     */\n    function setAddress(string memory _name, address _address) external onlyOwner {\n        addressManager.setAddress(_name, _address);\n    }\n\n    /**\n     * @custom:legacy\n     * @notice Legacy function used by the old Chugsplash proxy to determine if an upgrade is\n     *         happening.\n     *\n     * @return Whether or not there is an upgrade going on\n     */\n    function isUpgrading() external view returns (bool) {\n        return upgrading;\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     * @dev Returns the current implementation of `proxy`.\n     *      This contract must be the admin of `proxy`.\n     *\n     * @param proxy The Proxy to return the implementation of.\n     * @return The address of the implementation.\n     */\n    function getProxyImplementation(Proxy proxy) external view returns (address) {\n        ProxyType proxyType = proxyType[address(proxy)];\n\n        if (proxyType == ProxyType.ERC1967) {\n            return IStatic_ERC1967Proxy(address(proxy)).implementation();\n        } else if (proxyType == ProxyType.Chugsplash) {\n            return IStatic_L1ChugSplashProxy(address(proxy)).getImplementation();\n        } else if (proxyType == ProxyType.ResolvedDelegate) {\n            return addressManager.getAddress(implementationName[address(proxy)]);\n        } else {\n            revert(\"ProxyAdmin: unknown proxy type\");\n        }\n    }\n\n    /**\n     * @dev Returns the current admin of `proxy`.\n     *      This contract must be the admin of `proxy`.\n     *\n     * @param proxy The Proxy to return the admin of.\n     * @return The address of the admin.\n     */\n    function getProxyAdmin(Proxy proxy) external view returns (address) {\n        ProxyType proxyType = proxyType[address(proxy)];\n\n        if (proxyType == ProxyType.ERC1967) {\n            return IStatic_ERC1967Proxy(address(proxy)).admin();\n        } else if (proxyType == ProxyType.Chugsplash) {\n            return IStatic_L1ChugSplashProxy(address(proxy)).getOwner();\n        } else if (proxyType == ProxyType.ResolvedDelegate) {\n            return addressManager.owner();\n        } else {\n            revert(\"ProxyAdmin: unknown proxy type\");\n        }\n    }\n\n    /**\n     * @dev Changes the admin of `proxy` to `newAdmin`. This contract must be the current admin\n     *      of `proxy`.\n     *\n     * @param proxy    The proxy that will have its admin updated.\n     * @param newAdmin The address of the admin to update to.\n     */\n    function changeProxyAdmin(Proxy proxy, address newAdmin) external onlyOwner {\n        ProxyType proxyType = proxyType[address(proxy)];\n\n        if (proxyType == ProxyType.ERC1967) {\n            proxy.changeAdmin(newAdmin);\n        } else if (proxyType == ProxyType.Chugsplash) {\n            L1ChugSplashProxy(payable(proxy)).setOwner(newAdmin);\n        } else if (proxyType == ProxyType.ResolvedDelegate) {\n            addressManager.transferOwnership(newAdmin);\n        } else {\n            revert(\"ProxyAdmin: unknown proxy type\");\n        }\n    }\n\n    /**\n     * @dev Upgrades `proxy` to `implementation`. This contract must be the admin of `proxy`.\n     *\n     * @param proxy          The address of the proxy.\n     * @param implementation The address of the implementation.\n     */\n    function upgrade(Proxy proxy, address implementation) public onlyOwner {\n        ProxyType proxyType = proxyType[address(proxy)];\n\n        if (proxyType == ProxyType.ERC1967) {\n            proxy.upgradeTo(implementation);\n        } else if (proxyType == ProxyType.Chugsplash) {\n            L1ChugSplashProxy(payable(proxy)).setStorage(\n                0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc,\n                bytes32(uint256(uint160(implementation)))\n            );\n        } else if (proxyType == ProxyType.ResolvedDelegate) {\n            string memory name = implementationName[address(proxy)];\n            addressManager.setAddress(name, implementation);\n        } else {\n            revert(\"ProxyAdmin: unknown proxy type\");\n        }\n    }\n\n    /**\n     * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation.\n     *      This contract must be the admin of `proxy`.\n     *\n     * @param proxy           The proxy to call.\n     * @param implementation  The implementation to upgrade the proxy to.\n     * @param data            The calldata to pass to the implementation.\n     */\n    function upgradeAndCall(\n        Proxy proxy,\n        address implementation,\n        bytes memory data\n    ) external payable onlyOwner {\n        ProxyType proxyType = proxyType[address(proxy)];\n\n        if (proxyType == ProxyType.ERC1967) {\n            proxy.upgradeToAndCall{ value: msg.value }(implementation, data);\n        } else {\n            // reverts if proxy type is unknown\n            upgrade(proxy, implementation);\n            (bool success, ) = address(proxy).call{ value: msg.value }(data);\n            require(success);\n        }\n    }\n}\n"
    },
    "@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Proxy\n * @notice Proxy is a transparent proxy that passes through the call\n *         if the caller is the owner or if the caller is `address(0)`,\n *         meaning that the call originated from an offchain simulation.\n */\ncontract Proxy {\n    /**\n     * @notice An event that is emitted each time the implementation is changed.\n     *         This event is part of the EIP 1967 spec.\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.\n     *         This event is part of the EIP 1967 spec.\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 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 set the initial owner during contract deployment. The\n     *         owner is stored at the eip1967 owner storage slot so that\n     *         storage collision with the implementation is not possible.\n     *\n     * @param _admin Address of the initial contract owner. The owner has\n     *               the ability to access the transparent proxy interface.\n     */\n    constructor(address _admin) {\n        _changeAdmin(_admin);\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 A modifier that reverts if not called by the owner\n     *         or by `address(0)` to allow `eth_call` to interact\n     *         with the proxy without needing to use low level storage\n     *         inspection. It is assumed that nobody controls the private\n     *         key for `address(0)`.\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 Set the implementation contract address. The code at this\n     *         address will execute when this contract is called.\n     *\n     * @param _implementation The 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\n     *         transaction. This is useful to ensure atomic `initialize()`\n     *         based upgrades.\n     *\n     * @param _implementation The address of the implementation contract\n     * @param _data           The calldata to delegatecall the new\n     *                        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);\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 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 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 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    /**\n     * @notice Performs the proxy call via a delegatecall.\n     */\n    function _doProxyCall() internal {\n        address implementation = _getImplementation();\n\n        require(implementation != 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(), 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"
    },
    "@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/legacy/L1ChugSplashProxy.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title iL1ChugSplashDeployer\n */\ninterface iL1ChugSplashDeployer {\n    function isUpgrading() external view returns (bool);\n}\n\n/**\n * @title L1ChugSplashProxy\n * @dev 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. Nifty!\n *\n * Note for future developers: do NOT make anything in this contract 'public' unless you know what\n * you're doing. Anything public can potentially have a function signature that conflicts with a\n * signature attached to the implementation contract. Public functions SHOULD always have the\n * 'proxyCallIfNotOwner' modifier unless there's some *really* good reason not to have that\n * modifier. And there almost certainly is not a good reason to not have that modifier. Beware!\n */\ncontract L1ChugSplashProxy {\n    /*************\n     * Constants *\n     *************/\n\n    // \"Magic\" prefix. When prepended to some arbitrary bytecode and used to create a contract, the\n    // appended bytecode will be deployed as given.\n    bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;\n\n    // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n    bytes32 internal constant IMPLEMENTATION_KEY =\n        0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    // bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\n    bytes32 internal constant OWNER_KEY =\n        0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _owner Address of the initial contract owner.\n     */\n    constructor(address _owner) {\n        _setOwner(_owner);\n    }\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    /**\n     * Blocks a function from being called when the parent signals that the system should be paused\n     * 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     * Makes a proxy call instead of triggering the given function when the caller is either the\n     * owner or the zero address. Caller can only ever be the zero address if this function is\n     * being called off-chain via eth_call, which is totally fine and can be convenient for\n     * client-side tooling. Avoids situations where the proxy and implementation share a sighash\n     * and the proxy function ends up being called instead of the implementation one.\n     *\n     * Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If there's a\n     * way for someone to send a transaction with msg.sender == address(0) in any real context then\n     * we have much bigger problems. Primary reason to include this additional allowed sender is\n     * because the owner address can be changed dynamically and we do not want clients to have to\n     * keep track of the current owner in order to make an eth_call that doesn't trigger the\n     * 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     * Fallback Function *\n     *********************/\n\n    // slither-disable-next-line locked-ether\n    fallback() external payable {\n        // Proxy call by default.\n        _doProxyCall();\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Sets the code that should be running behind this proxy. Note that this scheme is a bit\n     * different from the standard proxy scheme where one would typically deploy the code\n     * separately and then set the implementation address. We're doing it this way because it gives\n     * us a lot more freedom on the client side. Can only be triggered by the contract owner.\n     * @param _code New contract code to run inside this contract.\n     */\n    // slither-disable-next-line external-function\n    function setCode(bytes memory _code) public 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     * Modifies some storage slot within the proxy contract. Gives us a lot of power to perform\n     * upgrades in a more transparent way. Only callable by the owner.\n     * @param _key Storage key to modify.\n     * @param _value New value for the storage key.\n     */\n    // slither-disable-next-line external-function\n    function setStorage(bytes32 _key, bytes32 _value) public proxyCallIfNotOwner {\n        assembly {\n            sstore(_key, _value)\n        }\n    }\n\n    /**\n     * Changes the owner of the proxy contract. Only callable by the owner.\n     * @param _owner New owner of the proxy contract.\n     */\n    // slither-disable-next-line external-function\n    function setOwner(address _owner) public proxyCallIfNotOwner {\n        _setOwner(_owner);\n    }\n\n    /**\n     * Queries the owner of the proxy contract. Can only be called by the owner OR by making an\n     * eth_call and setting the \"from\" address to address(0).\n     * @return Owner address.\n     */\n    // slither-disable-next-line external-function\n    function getOwner() public proxyCallIfNotOwner returns (address) {\n        return _getOwner();\n    }\n\n    /**\n     * 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     * @return Implementation address.\n     */\n    // slither-disable-next-line external-function\n    function getImplementation() public proxyCallIfNotOwner returns (address) {\n        return _getImplementation();\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Sets the implementation address.\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     * Queries the implementation address.\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     * Changes the owner of the proxy contract.\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     * Queries the owner of the proxy contract.\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     * Gets the code hash for a given account.\n     * @param _account Address of the account to get a code hash for.\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    /**\n     * 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"
    },
    "contracts/universal/Transactor.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\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 _gas Amount of gas to send with the call.\n     * @param _value ETH value to send with the call.\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 _gas,\n        uint256 _value\n    ) external payable onlyOwner returns (bool, bytes memory) {\n        return _target.call{ gas: _gas, 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     * @param _gas Amount of gas to send with the call.\n     * @return Boolean success value.\n     * @return Bytes data returned by the call.\n     */\n    function DELEGATECALL(\n        address _target,\n        bytes memory _data,\n        uint256 _gas\n    ) external payable onlyOwner returns (bool, bytes memory) {\n        // slither-disable-next-line controlled-delegatecall\n        return _target.delegatecall{ gas: _gas }(_data);\n    }\n}\n"
    },
    "contracts/universal/AssetReceiver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\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     * Emitted when ETH is received by this address.\n     */\n    event ReceivedETH(address indexed from, uint256 amount);\n\n    /**\n     * Emitted when ETH is withdrawn from this address.\n     */\n    event WithdrewETH(address indexed withdrawer, address indexed recipient, uint256 amount);\n\n    /**\n     * Emitted when ERC20 tokens are withdrawn from this address.\n     */\n    event WithdrewERC20(\n        address indexed withdrawer,\n        address indexed recipient,\n        address indexed asset,\n        uint256 amount\n    );\n\n    /**\n     * Emitted when ERC721 tokens are withdrawn from this address.\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     * Make sure we can receive ETH.\n     */\n    receive() external payable {\n        emit ReceivedETH(msg.sender, msg.value);\n    }\n\n    /**\n     * 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     * 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        _to.transfer(_amount);\n        emit WithdrewETH(msg.sender, _to, _amount);\n    }\n\n    /**\n     * 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     * 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     * 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"
    },
    "@rari-capital/solmate/src/tokens/ERC20.sol": {
      "content": "// SPDX-License-Identifier: AGPL-3.0-only\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"
    },
    "@rari-capital/solmate/src/tokens/ERC721.sol": {
      "content": "// SPDX-License-Identifier: AGPL-3.0-only\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        require(\n            to.code.length == 0 ||\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        require(\n            to.code.length == 0 ||\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        require(\n            to.code.length == 0 ||\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        require(\n            to.code.length == 0 ||\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/universal/TeleportrWithdrawer.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { AssetReceiver } from \"./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/drippie/Drippie.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { AssetReceiver } from \"../AssetReceiver.sol\";\nimport { IDripCheck } from \"./IDripCheck.sol\";\n\n/**\n * @title Drippie\n * @notice Drippie is a system for managing automated contract interactions. A specific interaction\n * is called a \"drip\" and can be executed according to some condition (called a dripcheck) and an\n * execution interval. Drips cannot be executed faster than the execution interval. Drips can\n * trigger arbitrary contract calls where the calling contract is this contract address. Drips can\n * also send ETH value, which makes them ideal for keeping addresses sufficiently funded with ETH.\n * Drippie is designed to be connected with smart contract automation services so that drips can be\n * executed automatically. However, Drippie is specifically designed to be separated from these\n * services so that trust assumptions are better compartmentalized.\n */\ncontract Drippie is AssetReceiver {\n    /**\n     * Enum representing different status options for a given drip.\n     */\n    enum DripStatus {\n        NONE,\n        ACTIVE,\n        PAUSED,\n        ARCHIVED\n    }\n\n    /**\n     * Represents a drip action.\n     */\n    struct DripAction {\n        address payable target;\n        bytes data;\n        uint256 value;\n    }\n\n    /**\n     * Represents the configuration for a given drip.\n     */\n    struct DripConfig {\n        uint256 interval;\n        IDripCheck dripcheck;\n        bytes checkparams;\n        DripAction[] actions;\n    }\n\n    /**\n     * Represents the state of an active drip.\n     */\n    struct DripState {\n        DripStatus status;\n        DripConfig config;\n        uint256 last;\n        uint256 count;\n    }\n\n    /**\n     * Emitted when a new drip is created.\n     */\n    event DripCreated(\n        // Emit name twice because indexed version is hashed.\n        string indexed nameref,\n        string name,\n        DripConfig config\n    );\n\n    /**\n     * Emitted when a drip status is updated.\n     */\n    event DripStatusUpdated(\n        // Emit name twice because indexed version is hashed.\n        string indexed nameref,\n        string name,\n        DripStatus status\n    );\n\n    /**\n     * Emitted when a drip is executed.\n     */\n    event DripExecuted(\n        // Emit name twice because indexed version is hashed.\n        string indexed nameref,\n        string name,\n        address executor,\n        uint256 timestamp\n    );\n\n    /**\n     * Maps from drip names to drip states.\n     */\n    mapping(string => DripState) public drips;\n\n    /**\n     * @param _owner Initial contract owner.\n     */\n    constructor(address _owner) AssetReceiver(_owner) {}\n\n    /**\n     * Creates a new drip with the given name and configuration. Once created, drips cannot be\n     * modified in any way (this is a security measure). If you want to update a drip, simply pause\n     * (and potentially archive) the existing drip and create a new one.\n     *\n     * @param _name Name of the drip.\n     * @param _config Configuration for the drip.\n     */\n    function create(string memory _name, DripConfig memory _config) external onlyOwner {\n        // Make sure this drip doesn't already exist. We *must* guarantee that no other function\n        // will ever set the status of a drip back to NONE after it's been created. This is why\n        // archival is a separate status.\n        require(\n            drips[_name].status == DripStatus.NONE,\n            \"Drippie: drip with that name already exists\"\n        );\n\n        // We initialize this way because Solidity won't let us copy arrays into storage yet.\n        DripState storage state = drips[_name];\n        state.status = DripStatus.PAUSED;\n        state.config.interval = _config.interval;\n        state.config.dripcheck = _config.dripcheck;\n        state.config.checkparams = _config.checkparams;\n\n        // Solidity doesn't let us copy arrays into storage, so we push each array one by one.\n        for (uint256 i = 0; i < _config.actions.length; i++) {\n            state.config.actions.push(_config.actions[i]);\n        }\n\n        // Tell the world!\n        emit DripCreated(_name, _name, _config);\n    }\n\n    /**\n     * Sets the status for a given drip. The behavior of this function depends on the status that\n     * the user is trying to set. A drip can always move between ACTIVE and PAUSED, but it can\n     * never move back to NONE and once ARCHIVED, it can never move back to ACTIVE or PAUSED.\n     *\n     * @param _name Name of the drip to update.\n     * @param _status New drip status.\n     */\n    function status(string memory _name, DripStatus _status) external onlyOwner {\n        // Make sure we can never set drip status back to NONE. A simple security measure to\n        // prevent accidental overwrites if this code is ever updated down the line.\n        require(\n            _status != DripStatus.NONE,\n            \"Drippie: drip status can never be set back to NONE after creation\"\n        );\n\n        // Make sure the drip in question actually exists. Not strictly necessary but there doesn't\n        // seem to be any clear reason why you would want to do this, and it may save some gas in\n        // the case of a front-end bug.\n        require(\n            drips[_name].status != DripStatus.NONE,\n            \"Drippie: drip with that name does not exist\"\n        );\n\n        // Once a drip has been archived, it cannot be un-archived. This is, after all, the entire\n        // point of archiving a drip.\n        require(\n            drips[_name].status != DripStatus.ARCHIVED,\n            \"Drippie: drip with that name has been archived\"\n        );\n\n        // Although not strictly necessary, we make sure that the status here is actually changing.\n        // This may save the client some gas if there's a front-end bug and the user accidentally\n        // tries to \"change\" the status to the same value as before.\n        require(\n            drips[_name].status != _status,\n            \"Drippie: cannot set drip status to same status as before\"\n        );\n\n        // If the user is trying to archive this drip, make sure the drip has been paused. We do\n        // not allow users to archive active drips so that the effects of this action are more\n        // abundantly clear.\n        if (_status == DripStatus.ARCHIVED) {\n            require(\n                drips[_name].status == DripStatus.PAUSED,\n                \"Drippie: drip must be paused to be archived\"\n            );\n        }\n\n        // If we made it here then we can safely update the status.\n        drips[_name].status = _status;\n        emit DripStatusUpdated(_name, _name, drips[_name].status);\n    }\n\n    /**\n     * Checks if a given drip is executable.\n     *\n     * @param _name Drip to check.\n     * @return True if the drip is executable, false otherwise.\n     */\n    function executable(string memory _name) public view returns (bool) {\n        DripState storage state = drips[_name];\n\n        // Only allow active drips to be executed, an obvious security measure.\n        require(\n            state.status == DripStatus.ACTIVE,\n            \"Drippie: selected drip does not exist or is not currently active\"\n        );\n\n        // Don't drip if the drip interval has not yet elapsed since the last time we dripped. This\n        // is a safety measure that prevents a malicious recipient from, e.g., spending all of\n        // their funds and repeatedly requesting new drips. Limits the potential impact of a\n        // compromised recipient to just a single drip interval, after which the drip can be paused\n        // by the owner address.\n        require(\n            state.last + state.config.interval <= block.timestamp,\n            \"Drippie: drip interval has not elapsed since last drip\"\n        );\n\n        // Make sure we're allowed to execute this drip.\n        require(\n            state.config.dripcheck.check(state.config.checkparams),\n            \"Drippie: dripcheck failed so drip is not yet ready to be triggered\"\n        );\n\n        // Alright, we're good to execute.\n        return true;\n    }\n\n    /**\n     * Triggers a drip. This function is deliberately left as a public function because the\n     * assumption being made here is that setting the drip to ACTIVE is an affirmative signal that\n     * the drip should be executable according to the drip parameters, drip check, and drip\n     * interval. Note that drip parameters are read entirely from the state and are not supplied as\n     * user input, so there should not be any way for a non-authorized user to influence the\n     * behavior of the drip.\n     *\n     * @param _name Name of the drip to trigger.\n     */\n    function drip(string memory _name) external {\n        DripState storage state = drips[_name];\n\n        // Make sure the drip can be executed.\n        require(\n            executable(_name) == true,\n            \"Drippie: drip cannot be executed at this time, try again later\"\n        );\n\n        // Update the last execution time for this drip before the call. Note that it's entirely\n        // possible for a drip to be executed multiple times per block or even multiple times\n        // within the same transaction (via re-entrancy) if the drip interval is set to zero. Users\n        // should set a drip interval of 1 if they'd like the drip to be executed only once per\n        // block (since this will then prevent re-entrancy).\n        state.last = block.timestamp;\n\n        // Execute each action in the drip. We allow drips to have multiple actions because there\n        // are scenarios in which a contract must do multiple things atomically. For example, the\n        // contract may need to withdraw ETH from one account and then deposit that ETH into\n        // another account within the same transaction.\n        uint256 len = state.config.actions.length;\n        for (uint256 i = 0; i < len; i++) {\n            // Must be marked as \"storage\" because copying structs into memory is not yet supported\n            // by Solidity. Won't significantly reduce gas costs but at least makes it easier to\n            // read what the rest of this section is doing.\n            DripAction storage action = state.config.actions[i];\n\n            // Actually execute the action. We could use ExcessivelySafeCall here but not strictly\n            // necessary (worst case, a drip gets bricked IFF the target is malicious, doubt this\n            // will ever happen in practice). Could save a marginal amount of gas to ignore the\n            // returndata.\n            // slither-disable-next-line calls-loop\n            (bool success, ) = action.target.call{ value: action.value }(action.data);\n\n            // Generally should not happen, but could if there's a misconfiguration (e.g., passing\n            // the wrong data to the target contract), the recipient is not payable, or\n            // insufficient gas was supplied to this transaction. We revert so the drip can be\n            // fixed and triggered again later. Means we cannot emit an event to alert of the\n            // failure, but can reasonably be detected by off-chain services even without an event.\n            // Note that this forces the drip executor to supply sufficient gas to the call\n            // (assuming there is some sufficient gas limit that exists, otherwise the drip will\n            // not execute).\n            require(\n                success,\n                \"Drippie: drip was unsuccessful, please check your configuration for mistakes\"\n            );\n        }\n\n        state.count++;\n        emit DripExecuted(_name, _name, msg.sender, block.timestamp);\n    }\n}\n"
    },
    "contracts/universal/drippie/IDripCheck.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface IDripCheck {\n    // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\n    // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\n    // possible to easily encode parameters on the client side. Solidity does not support generics\n    // so it's not possible to do this with explicit typing.\n\n    function check(bytes memory _params) external view returns (bool);\n}\n"
    },
    "contracts/universal/drippie/dripchecks/CheckTrue.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { IDripCheck } from \"../IDripCheck.sol\";\n\n/**\n * @title CheckTrue\n * @notice DripCheck that always returns true.\n */\ncontract CheckTrue is IDripCheck {\n    function check(bytes memory) external pure returns (bool) {\n        return true;\n    }\n}\n"
    },
    "contracts/universal/drippie/dripchecks/CheckGelatoLow.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { IDripCheck } from \"../IDripCheck.sol\";\n\ninterface IGelatoTreasury {\n    function userTokenBalance(address _user, address _token) external view returns (uint256);\n}\n\n/**\n * @title CheckGelatoLow\n * @notice DripCheck for checking if an account's Gelato ETH balance is below some threshold.\n */\ncontract CheckGelatoLow is IDripCheck {\n    event _EventToExposeStructInABI__Params(Params params);\n    struct Params {\n        address treasury;\n        uint256 threshold;\n        address recipient;\n    }\n\n    function check(bytes memory _params) external view returns (bool) {\n        Params memory params = abi.decode(_params, (Params));\n\n        // Check GelatoTreasury ETH balance is below threshold.\n        return\n            IGelatoTreasury(params.treasury).userTokenBalance(\n                params.recipient,\n                // Gelato represents ETH as 0xeeeee....eeeee\n                0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\n            ) < params.threshold;\n    }\n}\n"
    },
    "contracts/universal/drippie/dripchecks/CheckBalanceLow.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { IDripCheck } from \"../IDripCheck.sol\";\n\n/**\n * @title CheckBalanceLow\n * @notice DripCheck for checking if an account's balance is below a given threshold.\n */\ncontract CheckBalanceLow is IDripCheck {\n    event _EventToExposeStructInABI__Params(Params params);\n    struct Params {\n        address target;\n        uint256 threshold;\n    }\n\n    function check(bytes memory _params) external view returns (bool) {\n        Params memory params = abi.decode(_params, (Params));\n\n        // Check target ETH balance is below threshold.\n        return params.target.balance < params.threshold;\n    }\n}\n"
    },
    "contracts/universal/drippie/dripchecks/CheckBalanceHigh.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { IDripCheck } from \"../IDripCheck.sol\";\n\n/**\n * @title CheckBalanceHigh\n * @notice DripCheck for checking if an account's balance is above a given threshold.\n */\ncontract CheckBalanceHigh is IDripCheck {\n    event _EventToExposeStructInABI__Params(Params params);\n    struct Params {\n        address target;\n        uint256 threshold;\n    }\n\n    function check(bytes memory _params) external view returns (bool) {\n        Params memory params = abi.decode(_params, (Params));\n\n        // Check target balance is above threshold.\n        return params.target.balance > params.threshold;\n    }\n}\n"
    },
    "contracts/testing/helpers/ExternalContractCompiler.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\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.9;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/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"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 10000
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "storageLayout",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    }
  }
}