{
  "language": "Solidity",
  "sources": {
    "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n     * initialization step. This is essential to configure modules that are added through upgrades and that require\n     * initialization.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized < type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    function __Pausable_init() internal onlyInitializing {\n        __Pausable_init_unchained();\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        require(!paused(), \"Pausable: paused\");\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        require(paused(), \"Pausable: not paused\");\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        // On the first call to nonReentrant, _notEntered will be true\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n\n        _;\n\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n                /// @solidity memory-safe-assembly\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
    },
    "@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/access/Ownable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/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 Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
    },
    "@openzeppelin/contracts/proxy/utils/Initializable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n     * initialization step. This is essential to configure modules that are added through upgrades and that require\n     * initialization.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized < type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 `from` to `to`.\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/extensions/draft-IERC20Permit.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\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    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\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"
    },
    "@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/utils/SafeERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/Address.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary 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                /// @solidity memory-safe-assembly\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
    },
    "@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/ERC165Checker.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.2) (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        // prepare call\n        bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n\n        // perform static call\n        bool success;\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly {\n            success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\n            returnSize := returndatasize()\n            returnValue := mload(0x00)\n        }\n\n        return success && returnSize >= 0x20 && returnValue > 0;\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/math/Math.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a >= b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1);\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator,\n        Rounding rounding\n    ) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`.\n        // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.\n        // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.\n        // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a\n        // good first aproximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1;\n        uint256 x = a;\n        if (x >> 128 > 0) {\n            x >>= 128;\n            result <<= 64;\n        }\n        if (x >> 64 > 0) {\n            x >>= 64;\n            result <<= 32;\n        }\n        if (x >> 32 > 0) {\n            x >>= 32;\n            result <<= 16;\n        }\n        if (x >> 16 > 0) {\n            x >>= 16;\n            result <<= 8;\n        }\n        if (x >> 8 > 0) {\n            x >>= 8;\n            result <<= 4;\n        }\n        if (x >> 4 > 0) {\n            x >>= 4;\n            result <<= 2;\n        }\n        if (x >> 2 > 0) {\n            result <<= 1;\n        }\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = sqrt(a);\n        if (rounding == Rounding.Up && result * result < a) {\n            result += 1;\n        }\n        return result;\n    }\n}\n"
    },
    "contracts/chugsplash/interfaces/iL1ChugSplashDeployer.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"
    },
    "contracts/chugsplash/L1ChugSplashProxy.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { iL1ChugSplashDeployer } from \"./interfaces/iL1ChugSplashDeployer.sol\";\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    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    fallback() external payable {\n        // Proxy call by default.\n        _doProxyCall();\n    }\n\n    receive() 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    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    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    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    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    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/L1/cannon/interfaces/IMIPS.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {ISemver} from \"contracts/universal/ISemver.sol\";\nimport {IPreimageOracle} from \"./IPreimageOracle.sol\";\n\n/// @title IMIPS\n/// @notice Interface for the MIPS contract.\ninterface IMIPS is ISemver {\n    function oracle() external view returns (IPreimageOracle oracle_);\n\n    function step(bytes memory _stateData, bytes memory _proof, bytes32 _localContext) external returns (bytes32);\n}\n"
    },
    "contracts/L1/cannon/interfaces/IMIPS2.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {ISemver} from \"contracts/universal/ISemver.sol\";\n\n/// @title IMIPS2\n/// @notice Interface for the MIPS2 contract.\ninterface IMIPS2 is ISemver {\n    function step(bytes memory _stateData, bytes memory _proof, bytes32 _localContext) external returns (bytes32);\n}\n"
    },
    "contracts/L1/cannon/interfaces/IPreimageOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/// @title IPreimageOracle\n/// @notice Interface for a preimage oracle.\ninterface IPreimageOracle {\n    /// @notice Returns the length of the large preimage proposal challenge period.\n    /// @return challengePeriod_ The length of the challenge period in seconds.\n    function challengePeriod() external view returns (uint256 challengePeriod_);\n\n    /// @notice Reads a preimage from the oracle.\n    /// @param _key The key of the preimage to read.\n    /// @param _offset The offset of the preimage to read.\n    /// @return dat_ The preimage data.\n    /// @return datLen_ The length of the preimage data.\n    function readPreimage(bytes32 _key, uint256 _offset) external view returns (bytes32 dat_, uint256 datLen_);\n\n    /// @notice Loads of local data part into the preimage oracle.\n    /// @param _ident The identifier of the local data.\n    /// @param _localContext The local key context for the preimage oracle. Optionally, can be set as a constant\n    ///                      if the caller only requires one set of local keys.\n    /// @param _word The local data word.\n    /// @param _size The number of bytes in `_word` to load.\n    /// @param _partOffset The offset of the local data part to write to the oracle.\n    /// @dev The local data parts are loaded into the preimage oracle under the context\n    ///      of the caller - no other account can write to the caller's context\n    ///      specific data.\n    ///\n    ///      There are 5 local data identifiers:\n    ///      ┌────────────┬────────────────────────┐\n    ///      │ Identifier │      Data              │\n    ///      ├────────────┼────────────────────────┤\n    ///      │          1 │ L1 Head Hash (bytes32) │\n    ///      │          2 │ Output Root (bytes32)  │\n    ///      │          3 │ Root Claim (bytes32)   │\n    ///      │          4 │ L2 Block Number (u64)  │\n    ///      │          5 │ Chain ID (u64)         │\n    ///      └────────────┴────────────────────────┘\n    function loadLocalData(\n        uint256 _ident,\n        bytes32 _localContext,\n        bytes32 _word,\n        uint256 _size,\n        uint256 _partOffset\n    )\n    external\n    returns (bytes32 key_);\n\n    /// @notice Prepares a preimage to be read by keccak256 key, starting at the given offset and up to 32 bytes\n    ///         (clipped at preimage length, if out of data).\n    /// @param _partOffset The offset of the preimage to read.\n    /// @param _preimage The preimage data.\n    function loadKeccak256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external;\n\n    /// @notice Prepares a preimage to be read by sha256 key, starting at the given offset and up to 32 bytes\n    ///         (clipped at preimage length, if out of data).\n    /// @param _partOffset The offset of the preimage to read.\n    /// @param _preimage The preimage data.\n    function loadSha256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external;\n\n    /// @notice Verifies that `p(_z) = _y` given `_commitment` that corresponds to the polynomial `p(x)` and a KZG\n    //          proof. The value `y` is the pre-image, and the preimage key is `5 ++ keccak256(_commitment ++ z)[1:]`.\n    /// @param _z Big endian point value. Part of the preimage key.\n    /// @param _y Big endian point value. The preimage for the key.\n    /// @param _commitment The commitment to the polynomial. 48 bytes, part of the preimage key.\n    /// @param _proof The KZG proof, part of the preimage key.\n    /// @param _partOffset The offset of the preimage to store.\n    function loadBlobPreimagePart(\n        uint256 _z,\n        uint256 _y,\n        bytes calldata _commitment,\n        bytes calldata _proof,\n        uint256 _partOffset\n    )\n    external;\n\n    /// @notice Prepares a precompile result to be read by a precompile key for the specified offset.\n    ///         The precompile result data is a concatenation of the precompile call status byte and its return data.\n    ///         The preimage key is `6 ++ keccak256(precompile ++ input)[1:]`.\n    /// @param _partOffset The offset of the precompile result being loaded.\n    /// @param _precompile The precompile address\n    /// @param _requiredGas The gas required to fully execute an L1 precompile.\n    /// @param _input The input to the precompile call.\n    function loadPrecompilePreimagePart(\n        uint256 _partOffset,\n        address _precompile,\n        uint64 _requiredGas,\n        bytes calldata _input\n    )\n    external;\n}\n"
    },
    "contracts/L1/cannon/libraries/CannonErrors.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/// @notice Thrown when a passed part offset is out of bounds.\n    error PartOffsetOOB();\n\n/// @notice Thrown when insufficient gas is provided when loading precompile preimages.\n    error NotEnoughGas();\n\n/// @notice Thrown when a merkle proof fails to verify.\n    error InvalidProof();\n\n/// @notice Thrown when the prestate preimage doesn't match the claimed preimage.\n    error InvalidPreimage();\n\n/// @notice Thrown when a leaf with an invalid input size is added.\n    error InvalidInputSize();\n\n/// @notice Thrown when data is submitted out of order in a large preimage proposal.\n    error WrongStartingBlock();\n\n/// @notice Thrown when the pre and post states passed aren't contiguous.\n    error StatesNotContiguous();\n\n/// @notice Thrown when the permutation yields the expected result.\n    error PostStateMatches();\n\n/// @notice Thrown when the preimage is too large to fit in the tree.\n    error TreeSizeOverflow();\n\n/// @notice Thrown when the preimage proposal has already been finalized.\n    error AlreadyFinalized();\n\n/// @notice Thrown when the proposal has not matured past the challenge period.\n    error ActiveProposal();\n\n/// @notice Thrown when attempting to finalize a proposal that has been challenged.\n    error BadProposal();\n\n/// @notice Thrown when attempting to add leaves to a preimage proposal that has not been initialized.\n    error NotInitialized();\n\n/// @notice Thrown when attempting to re-initialize an existing large preimage proposal.\n    error AlreadyInitialized();\n\n/// @notice Thrown when the caller of a function is not an EOA.\n    error NotEOA();\n\n/// @notice Thrown when an insufficient bond is provided for a large preimage proposal.\n    error InsufficientBond();\n\n/// @notice Thrown when a bond transfer fails.\n    error BondTransferFailed();\n\n/// @notice Thrown when the value of the exited boolean is not 0 or 1.\n    error InvalidExitedValue();\n"
    },
    "contracts/L1/cannon/libraries/CannonTypes.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n    using LPPMetadataLib for LPPMetaData global;\n\n/// @notice Packed LPP metadata.\n/// ┌─────────────┬────────────────────────────────────────────┐\n/// │ Bit Offsets │                Description                 │\n/// ├─────────────┼────────────────────────────────────────────┤\n/// │ [0, 64)     │ Timestamp (Finalized - All data available) │\n/// │ [64, 96)    │ Part Offset                                │\n/// │ [96, 128)   │ Claimed Size                               │\n/// │ [128, 160)  │ Blocks Processed (Inclusive of Padding)    │\n/// │ [160, 192)  │ Bytes Processed (Non-inclusive of Padding) │\n/// │ [192, 256)  │ Countered                                  │\n/// └─────────────┴────────────────────────────────────────────┘\n    type LPPMetaData is bytes32;\n\n/// @notice LPP metadata UDT extension functions.\nlibrary LPPMetadataLib {\n    uint256 private constant U64_MASK = 0xFFFFFFFFFFFFFFFF;\n    uint256 private constant U32_MASK = 0xFFFFFFFF;\n\n    function setTimestamp(LPPMetaData _self, uint64 _timestamp) internal pure returns (LPPMetaData self_) {\n        assembly {\n            self_ := or(shl(192, _timestamp), and(_self, not(shl(192, U64_MASK))))\n        }\n    }\n\n    function setPartOffset(LPPMetaData _self, uint32 _partOffset) internal pure returns (LPPMetaData self_) {\n        assembly {\n            self_ := or(shl(160, _partOffset), and(_self, not(shl(160, U32_MASK))))\n        }\n    }\n\n    function setClaimedSize(LPPMetaData _self, uint32 _claimedSize) internal pure returns (LPPMetaData self_) {\n        assembly {\n            self_ := or(shl(128, _claimedSize), and(_self, not(shl(128, U32_MASK))))\n        }\n    }\n\n    function setBlocksProcessed(LPPMetaData _self, uint32 _blocksProcessed) internal pure returns (LPPMetaData self_) {\n        assembly {\n            self_ := or(shl(96, _blocksProcessed), and(_self, not(shl(96, U32_MASK))))\n        }\n    }\n\n    function setBytesProcessed(LPPMetaData _self, uint32 _bytesProcessed) internal pure returns (LPPMetaData self_) {\n        assembly {\n            self_ := or(shl(64, _bytesProcessed), and(_self, not(shl(64, U32_MASK))))\n        }\n    }\n\n    function setCountered(LPPMetaData _self, bool _countered) internal pure returns (LPPMetaData self_) {\n        assembly {\n            self_ := or(_countered, and(_self, not(U64_MASK)))\n        }\n    }\n\n    function timestamp(LPPMetaData _self) internal pure returns (uint64 timestamp_) {\n        assembly {\n            timestamp_ := shr(192, _self)\n        }\n    }\n\n    function partOffset(LPPMetaData _self) internal pure returns (uint64 partOffset_) {\n        assembly {\n            partOffset_ := and(shr(160, _self), U32_MASK)\n        }\n    }\n\n    function claimedSize(LPPMetaData _self) internal pure returns (uint32 claimedSize_) {\n        assembly {\n            claimedSize_ := and(shr(128, _self), U32_MASK)\n        }\n    }\n\n    function blocksProcessed(LPPMetaData _self) internal pure returns (uint32 blocksProcessed_) {\n        assembly {\n            blocksProcessed_ := and(shr(96, _self), U32_MASK)\n        }\n    }\n\n    function bytesProcessed(LPPMetaData _self) internal pure returns (uint32 bytesProcessed_) {\n        assembly {\n            bytesProcessed_ := and(shr(64, _self), U32_MASK)\n        }\n    }\n\n    function countered(LPPMetaData _self) internal pure returns (bool countered_) {\n        assembly {\n            countered_ := and(_self, U64_MASK)\n        }\n    }\n}\n"
    },
    "contracts/L1/cannon/libraries/MIPSInstructions.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {MIPSMemory} from \"./MIPSMemory.sol\";\nimport {MIPSState as st} from \"./MIPSState.sol\";\n\nlibrary MIPSInstructions {\n    /// @param _pc The program counter.\n    /// @param _memRoot The current memory root.\n    /// @param _insnProofOffset The calldata offset of the memory proof for the current instruction.\n    /// @return insn_ The current 32-bit instruction at the pc.\n    /// @return opcode_ The opcode value parsed from insn_.\n    /// @return fun_ The function value parsed from insn_.\n    function getInstructionDetails(\n        uint32 _pc,\n        bytes32 _memRoot,\n        uint256 _insnProofOffset\n    )\n    internal\n    pure\n    returns (uint32 insn_, uint32 opcode_, uint32 fun_)\n    {\n        unchecked {\n            insn_ = MIPSMemory.readMem(_memRoot, _pc, _insnProofOffset);\n            opcode_ = insn_ >> 26; // First 6-bits\n            fun_ = insn_ & 0x3f; // Last 6-bits\n\n            return (insn_, opcode_, fun_);\n        }\n    }\n\n    /// @notice Execute core MIPS step logic.\n    /// @notice _cpu The CPU scalar fields.\n    /// @notice _registers The CPU registers.\n    /// @notice _memRoot The current merkle root of the memory.\n    /// @notice _memProofOffset The offset in calldata specify where the memory merkle proof is located.\n    /// @param _insn The current 32-bit instruction at the pc.\n    /// @param _opcode The opcode value parsed from insn_.\n    /// @param _fun The function value parsed from insn_.\n    /// @return newMemRoot_ The updated merkle root of memory after any modifications, may be unchanged.\n    function execMipsCoreStepLogic(\n        st.CpuScalars memory _cpu,\n        uint32[32] memory _registers,\n        bytes32 _memRoot,\n        uint256 _memProofOffset,\n        uint32 _insn,\n        uint32 _opcode,\n        uint32 _fun\n    )\n    internal\n    pure\n    returns (bytes32 newMemRoot_)\n    {\n        unchecked {\n            newMemRoot_ = _memRoot;\n\n        // j-type j/jal\n            if (_opcode == 2 || _opcode == 3) {\n                // Take top 4 bits of the next PC (its 256 MB region), and concatenate with the 26-bit offset\n                uint32 target = (_cpu.nextPC & 0xF0000000) | (_insn & 0x03FFFFFF) << 2;\n                handleJump(_cpu, _registers, _opcode == 2 ? 0 : 31, target);\n                return newMemRoot_;\n            }\n\n        // register fetch\n            uint32 rs = 0; // source register 1 value\n            uint32 rt = 0; // source register 2 / temp value\n            uint32 rtReg = (_insn >> 16) & 0x1F;\n\n        // R-type or I-type (stores rt)\n            rs = _registers[(_insn >> 21) & 0x1F];\n            uint32 rdReg = rtReg;\n\n            if (_opcode == 0 || _opcode == 0x1c) {\n                // R-type (stores rd)\n                rt = _registers[rtReg];\n                rdReg = (_insn >> 11) & 0x1F;\n            } else if (_opcode < 0x20) {\n                // rt is SignExtImm\n                // don't sign extend for andi, ori, xori\n                if (_opcode == 0xC || _opcode == 0xD || _opcode == 0xe) {\n                    // ZeroExtImm\n                    rt = _insn & 0xFFFF;\n                } else {\n                    // SignExtImm\n                    rt = signExtend(_insn & 0xFFFF, 16);\n                }\n            } else if (_opcode >= 0x28 || _opcode == 0x22 || _opcode == 0x26) {\n                // store rt value with store\n                rt = _registers[rtReg];\n\n                // store actual rt with lwl and lwr\n                rdReg = rtReg;\n            }\n\n            if ((_opcode >= 4 && _opcode < 8) || _opcode == 1) {\n                handleBranch({\n                    _cpu: _cpu,\n                    _registers: _registers,\n                    _opcode: _opcode,\n                    _insn: _insn,\n                    _rtReg: rtReg,\n                    _rs: rs\n                });\n                return newMemRoot_;\n            }\n\n            uint32 storeAddr = 0xFF_FF_FF_FF;\n        // memory fetch (all I-type)\n        // we do the load for stores also\n            uint32 mem = 0;\n            if (_opcode >= 0x20) {\n                // M[R[rs]+SignExtImm]\n                rs += signExtend(_insn & 0xFFFF, 16);\n                uint32 addr = rs & 0xFFFFFFFC;\n                mem = MIPSMemory.readMem(_memRoot, addr, _memProofOffset);\n                if (_opcode >= 0x28 && _opcode != 0x30) {\n                    // store\n                    storeAddr = addr;\n                    // store opcodes don't write back to a register\n                    rdReg = 0;\n                }\n            }\n\n        // ALU\n        // Note: swr outputs more than 4 bytes without the mask 0xffFFffFF\n            uint32 val = executeMipsInstruction(_insn, _opcode, _fun, rs, rt, mem) & 0xffFFffFF;\n\n            if (_opcode == 0 && _fun >= 8 && _fun < 0x1c) {\n                if (_fun == 8 || _fun == 9) {\n                    // jr/jalr\n                    handleJump(_cpu, _registers, _fun == 8 ? 0 : rdReg, rs);\n                    return newMemRoot_;\n                }\n\n                if (_fun == 0xa) {\n                    // movz\n                    handleRd(_cpu, _registers, rdReg, rs, rt == 0);\n                    return newMemRoot_;\n                }\n                if (_fun == 0xb) {\n                    // movn\n                    handleRd(_cpu, _registers, rdReg, rs, rt != 0);\n                    return newMemRoot_;\n                }\n\n                // lo and hi registers\n                // can write back\n                if (_fun >= 0x10 && _fun < 0x1c) {\n                    handleHiLo({_cpu: _cpu, _registers: _registers, _fun: _fun, _rs: rs, _rt: rt, _storeReg: rdReg});\n\n                    return newMemRoot_;\n                }\n            }\n\n        // stupid sc, write a 1 to rt\n            if (_opcode == 0x38 && rtReg != 0) {\n                _registers[rtReg] = 1;\n            }\n\n        // write memory\n            if (storeAddr != 0xFF_FF_FF_FF) {\n                newMemRoot_ = MIPSMemory.writeMem(storeAddr, _memProofOffset, val);\n            }\n\n        // write back the value to destination register\n            handleRd(_cpu, _registers, rdReg, val, true);\n\n            return newMemRoot_;\n        }\n    }\n\n    /// @notice Execute an instruction.\n    function executeMipsInstruction(\n        uint32 _insn,\n        uint32 _opcode,\n        uint32 _fun,\n        uint32 _rs,\n        uint32 _rt,\n        uint32 _mem\n    )\n    internal\n    pure\n    returns (uint32 out_)\n    {\n        unchecked {\n            if (_opcode == 0 || (_opcode >= 8 && _opcode < 0xF)) {\n                assembly {\n                // transform ArithLogI to SPECIAL\n                    switch _opcode\n                    // addi\n                    case 0x8 {_fun := 0x20}\n                    // addiu\n                    case 0x9 {_fun := 0x21}\n                    // stli\n                    case 0xA {_fun := 0x2A}\n                    // sltiu\n                    case 0xB {_fun := 0x2B}\n                    // andi\n                    case 0xC {_fun := 0x24}\n                    // ori\n                    case 0xD {_fun := 0x25}\n                    // xori\n                    case 0xE {_fun := 0x26}\n                }\n\n                // sll\n                if (_fun == 0x00) {\n                    return _rt << ((_insn >> 6) & 0x1F);\n                }\n                    // srl\n                else if (_fun == 0x02) {\n                    return _rt >> ((_insn >> 6) & 0x1F);\n                }\n                    // sra\n                else if (_fun == 0x03) {\n                    uint32 shamt = (_insn >> 6) & 0x1F;\n                    return signExtend(_rt >> shamt, 32 - shamt);\n                }\n                    // sllv\n                else if (_fun == 0x04) {\n                    return _rt << (_rs & 0x1F);\n                }\n                    // srlv\n                else if (_fun == 0x6) {\n                    return _rt >> (_rs & 0x1F);\n                }\n                    // srav\n                else if (_fun == 0x07) {\n                    // shamt here is different than the typical shamt which comes from the\n                    // instruction itself, here it comes from the rs register\n                    uint32 shamt = _rs & 0x1F;\n                    return signExtend(_rt >> shamt, 32 - shamt);\n                }\n                    // functs in range [0x8, 0x1b] are handled specially by other functions\n                    // Explicitly enumerate each funct in range to reduce code diff against Go Vm\n                    // jr\n                else if (_fun == 0x08) {\n                    return _rs;\n                }\n                    // jalr\n                else if (_fun == 0x09) {\n                    return _rs;\n                }\n                    // movz\n                else if (_fun == 0x0a) {\n                    return _rs;\n                }\n                    // movn\n                else if (_fun == 0x0b) {\n                    return _rs;\n                }\n                    // syscall\n                else if (_fun == 0x0c) {\n                    return _rs;\n                }\n                    // 0x0d - break not supported\n                    // sync\n                else if (_fun == 0x0f) {\n                    return _rs;\n                }\n                    // mfhi\n                else if (_fun == 0x10) {\n                    return _rs;\n                }\n                    // mthi\n                else if (_fun == 0x11) {\n                    return _rs;\n                }\n                    // mflo\n                else if (_fun == 0x12) {\n                    return _rs;\n                }\n                    // mtlo\n                else if (_fun == 0x13) {\n                    return _rs;\n                }\n                    // mult\n                else if (_fun == 0x18) {\n                    return _rs;\n                }\n                    // multu\n                else if (_fun == 0x19) {\n                    return _rs;\n                }\n                    // div\n                else if (_fun == 0x1a) {\n                    return _rs;\n                }\n                    // divu\n                else if (_fun == 0x1b) {\n                    return _rs;\n                }\n                    // The rest includes transformed R-type arith imm instructions\n                    // add\n                else if (_fun == 0x20) {\n                    return (_rs + _rt);\n                }\n                    // addu\n                else if (_fun == 0x21) {\n                    return (_rs + _rt);\n                }\n                    // sub\n                else if (_fun == 0x22) {\n                    return (_rs - _rt);\n                }\n                    // subu\n                else if (_fun == 0x23) {\n                    return (_rs - _rt);\n                }\n                    // and\n                else if (_fun == 0x24) {\n                    return (_rs & _rt);\n                }\n                    // or\n                else if (_fun == 0x25) {\n                    return (_rs | _rt);\n                }\n                    // xor\n                else if (_fun == 0x26) {\n                    return (_rs ^ _rt);\n                }\n                    // nor\n                else if (_fun == 0x27) {\n                    return ~(_rs | _rt);\n                }\n                    // slti\n                else if (_fun == 0x2a) {\n                    return int32(_rs) < int32(_rt) ? 1 : 0;\n                }\n                    // sltiu\n                else if (_fun == 0x2b) {\n                    return _rs < _rt ? 1 : 0;\n                } else {\n                    revert(\"invalid instruction\");\n                }\n            } else {\n                // SPECIAL2\n                if (_opcode == 0x1C) {\n                    // mul\n                    if (_fun == 0x2) {\n                        return uint32(int32(_rs) * int32(_rt));\n                    }\n                        // clz, clo\n                    else if (_fun == 0x20 || _fun == 0x21) {\n                        if (_fun == 0x20) {\n                            _rs = ~_rs;\n                        }\n                        uint32 i = 0;\n                        while (_rs & 0x80000000 != 0) {\n                            i++;\n                            _rs <<= 1;\n                        }\n                        return i;\n                    }\n                }\n                    // lui\n                else if (_opcode == 0x0F) {\n                    return _rt << 16;\n                }\n                    // lb\n                else if (_opcode == 0x20) {\n                    return signExtend((_mem >> (24 - (_rs & 3) * 8)) & 0xFF, 8);\n                }\n                    // lh\n                else if (_opcode == 0x21) {\n                    return signExtend((_mem >> (16 - (_rs & 2) * 8)) & 0xFFFF, 16);\n                }\n                    // lwl\n                else if (_opcode == 0x22) {\n                    uint32 val = _mem << ((_rs & 3) * 8);\n                    uint32 mask = uint32(0xFFFFFFFF) << ((_rs & 3) * 8);\n                    return (_rt & ~mask) | val;\n                }\n                    // lw\n                else if (_opcode == 0x23) {\n                    return _mem;\n                }\n                    // lbu\n                else if (_opcode == 0x24) {\n                    return (_mem >> (24 - (_rs & 3) * 8)) & 0xFF;\n                }\n                    //  lhu\n                else if (_opcode == 0x25) {\n                    return (_mem >> (16 - (_rs & 2) * 8)) & 0xFFFF;\n                }\n                    //  lwr\n                else if (_opcode == 0x26) {\n                    uint32 val = _mem >> (24 - (_rs & 3) * 8);\n                    uint32 mask = uint32(0xFFFFFFFF) >> (24 - (_rs & 3) * 8);\n                    return (_rt & ~mask) | val;\n                }\n                    //  sb\n                else if (_opcode == 0x28) {\n                    uint32 val = (_rt & 0xFF) << (24 - (_rs & 3) * 8);\n                    uint32 mask = 0xFFFFFFFF ^ uint32(0xFF << (24 - (_rs & 3) * 8));\n                    return (_mem & mask) | val;\n                }\n                    //  sh\n                else if (_opcode == 0x29) {\n                    uint32 val = (_rt & 0xFFFF) << (16 - (_rs & 2) * 8);\n                    uint32 mask = 0xFFFFFFFF ^ uint32(0xFFFF << (16 - (_rs & 2) * 8));\n                    return (_mem & mask) | val;\n                }\n                    //  swl\n                else if (_opcode == 0x2a) {\n                    uint32 val = _rt >> ((_rs & 3) * 8);\n                    uint32 mask = uint32(0xFFFFFFFF) >> ((_rs & 3) * 8);\n                    return (_mem & ~mask) | val;\n                }\n                    //  sw\n                else if (_opcode == 0x2b) {\n                    return _rt;\n                }\n                    //  swr\n                else if (_opcode == 0x2e) {\n                    uint32 val = _rt << (24 - (_rs & 3) * 8);\n                    uint32 mask = uint32(0xFFFFFFFF) << (24 - (_rs & 3) * 8);\n                    return (_mem & ~mask) | val;\n                }\n                    // ll\n                else if (_opcode == 0x30) {\n                    return _mem;\n                }\n                    // sc\n                else if (_opcode == 0x38) {\n                    return _rt;\n                } else {\n                    revert(\"invalid instruction\");\n                }\n            }\n            revert(\"invalid instruction\");\n        }\n    }\n\n    /// @notice Extends the value leftwards with its most significant bit (sign extension).\n    function signExtend(uint32 _dat, uint32 _idx) internal pure returns (uint32 out_) {\n        unchecked {\n            bool isSigned = (_dat >> (_idx - 1)) != 0;\n            uint256 signed = ((1 << (32 - _idx)) - 1) << _idx;\n            uint256 mask = (1 << _idx) - 1;\n            return uint32(_dat & mask | (isSigned ? signed : 0));\n        }\n    }\n\n    /// @notice Handles a branch instruction, updating the MIPS state PC where needed.\n    /// @param _cpu Holds the state of cpu scalars pc, nextPC, hi, lo.\n    /// @param _registers Holds the current state of the cpu registers.\n    /// @param _opcode The opcode of the branch instruction.\n    /// @param _insn The instruction to be executed.\n    /// @param _rtReg The register to be used for the branch.\n    /// @param _rs The register to be compared with the branch register.\n    function handleBranch(\n        st.CpuScalars memory _cpu,\n        uint32[32] memory _registers,\n        uint32 _opcode,\n        uint32 _insn,\n        uint32 _rtReg,\n        uint32 _rs\n    )\n    internal\n    pure\n    {\n        unchecked {\n            bool shouldBranch = false;\n\n            if (_cpu.nextPC != _cpu.pc + 4) {\n                revert(\"branch in delay slot\");\n            }\n\n        // beq/bne: Branch on equal / not equal\n            if (_opcode == 4 || _opcode == 5) {\n                uint32 rt = _registers[_rtReg];\n                shouldBranch = (_rs == rt && _opcode == 4) || (_rs != rt && _opcode == 5);\n            }\n                // blez: Branches if instruction is less than or equal to zero\n            else if (_opcode == 6) {\n                shouldBranch = int32(_rs) <= 0;\n            }\n                // bgtz: Branches if instruction is greater than zero\n            else if (_opcode == 7) {\n                shouldBranch = int32(_rs) > 0;\n            }\n                // bltz/bgez: Branch on less than zero / greater than or equal to zero\n            else if (_opcode == 1) {\n                // regimm\n                uint32 rtv = ((_insn >> 16) & 0x1F);\n                if (rtv == 0) {\n                    shouldBranch = int32(_rs) < 0;\n                }\n                if (rtv == 1) {\n                    shouldBranch = int32(_rs) >= 0;\n                }\n            }\n\n        // Update the state's previous PC\n            uint32 prevPC = _cpu.pc;\n\n        // Execute the delay slot first\n            _cpu.pc = _cpu.nextPC;\n\n        // If we should branch, update the PC to the branch target\n        // Otherwise, proceed to the next instruction\n            if (shouldBranch) {\n                _cpu.nextPC = prevPC + 4 + (signExtend(_insn & 0xFFFF, 16) << 2);\n            } else {\n                _cpu.nextPC = _cpu.nextPC + 4;\n            }\n        }\n    }\n\n    /// @notice Handles HI and LO register instructions.\n    /// @param _cpu Holds the state of cpu scalars pc, nextPC, hi, lo.\n    /// @param _registers Holds the current state of the cpu registers.\n    /// @param _fun The function code of the instruction.\n    /// @param _rs The value of the RS register.\n    /// @param _rt The value of the RT register.\n    /// @param _storeReg The register to store the result in.\n    function handleHiLo(\n        st.CpuScalars memory _cpu,\n        uint32[32] memory _registers,\n        uint32 _fun,\n        uint32 _rs,\n        uint32 _rt,\n        uint32 _storeReg\n    )\n    internal\n    pure\n    {\n        unchecked {\n            uint32 val = 0;\n\n        // mfhi: Move the contents of the HI register into the destination\n            if (_fun == 0x10) {\n                val = _cpu.hi;\n            }\n                // mthi: Move the contents of the source into the HI register\n            else if (_fun == 0x11) {\n                _cpu.hi = _rs;\n            }\n                // mflo: Move the contents of the LO register into the destination\n            else if (_fun == 0x12) {\n                val = _cpu.lo;\n            }\n                // mtlo: Move the contents of the source into the LO register\n            else if (_fun == 0x13) {\n                _cpu.lo = _rs;\n            }\n                // mult: Multiplies `rs` by `rt` and stores the result in HI and LO registers\n            else if (_fun == 0x18) {\n                uint64 acc = uint64(int64(int32(_rs)) * int64(int32(_rt)));\n                _cpu.hi = uint32(acc >> 32);\n                _cpu.lo = uint32(acc);\n            }\n                // multu: Unsigned multiplies `rs` by `rt` and stores the result in HI and LO registers\n            else if (_fun == 0x19) {\n                uint64 acc = uint64(uint64(_rs) * uint64(_rt));\n                _cpu.hi = uint32(acc >> 32);\n                _cpu.lo = uint32(acc);\n            }\n                // div: Divides `rs` by `rt`.\n                // Stores the quotient in LO\n                // And the remainder in HI\n            else if (_fun == 0x1a) {\n                if (int32(_rt) == 0) {\n                    revert(\"MIPS: division by zero\");\n                }\n                _cpu.hi = uint32(int32(_rs) % int32(_rt));\n                _cpu.lo = uint32(int32(_rs) / int32(_rt));\n            }\n                // divu: Unsigned divides `rs` by `rt`.\n                // Stores the quotient in LO\n                // And the remainder in HI\n            else if (_fun == 0x1b) {\n                if (_rt == 0) {\n                    revert(\"MIPS: division by zero\");\n                }\n                _cpu.hi = _rs % _rt;\n                _cpu.lo = _rs / _rt;\n            }\n\n        // Store the result in the destination register, if applicable\n            if (_storeReg != 0) {\n                _registers[_storeReg] = val;\n            }\n\n        // Update the PC\n            _cpu.pc = _cpu.nextPC;\n            _cpu.nextPC = _cpu.nextPC + 4;\n        }\n    }\n\n    /// @notice Handles a jump instruction, updating the MIPS state PC where needed.\n    /// @param _cpu Holds the state of cpu scalars pc, nextPC, hi, lo.\n    /// @param _registers Holds the current state of the cpu registers.\n    /// @param _linkReg The register to store the link to the instruction after the delay slot instruction.\n    /// @param _dest The destination to jump to.\n    function handleJump(\n        st.CpuScalars memory _cpu,\n        uint32[32] memory _registers,\n        uint32 _linkReg,\n        uint32 _dest\n    )\n    internal\n    pure\n    {\n        unchecked {\n            if (_cpu.nextPC != _cpu.pc + 4) {\n                revert(\"jump in delay slot\");\n            }\n\n        // Update the next PC to the jump destination.\n            uint32 prevPC = _cpu.pc;\n            _cpu.pc = _cpu.nextPC;\n            _cpu.nextPC = _dest;\n\n        // Update the link-register to the instruction after the delay slot instruction.\n            if (_linkReg != 0) {\n                _registers[_linkReg] = prevPC + 8;\n            }\n        }\n    }\n\n    /// @notice Handles a storing a value into a register.\n    /// @param _cpu Holds the state of cpu scalars pc, nextPC, hi, lo.\n    /// @param _registers Holds the current state of the cpu registers.\n    /// @param _storeReg The register to store the value into.\n    /// @param _val The value to store.\n    /// @param _conditional Whether or not the store is conditional.\n    function handleRd(\n        st.CpuScalars memory _cpu,\n        uint32[32] memory _registers,\n        uint32 _storeReg,\n        uint32 _val,\n        bool _conditional\n    )\n    internal\n    pure\n    {\n        unchecked {\n        // The destination register must be valid.\n            require(_storeReg < 32, \"valid register\");\n\n        // Never write to reg 0, and it can be conditional (movz, movn).\n            if (_storeReg != 0 && _conditional) {\n                _registers[_storeReg] = _val;\n            }\n\n        // Update the PC.\n            _cpu.pc = _cpu.nextPC;\n            _cpu.nextPC = _cpu.nextPC + 4;\n        }\n    }\n}\n"
    },
    "contracts/L1/cannon/libraries/MIPSMemory.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nlibrary MIPSMemory {\n    /// @notice Reads a 32-bit value from memory.\n    /// @param _memRoot The current memory root\n    /// @param _addr The address to read from.\n    /// @param _proofOffset The offset of the memory proof in calldata.\n    /// @return out_ The hashed MIPS state.\n    function readMem(bytes32 _memRoot, uint32 _addr, uint256 _proofOffset) internal pure returns (uint32 out_) {\n        unchecked {\n            validateMemoryProofAvailability(_proofOffset);\n            assembly {\n            // Validate the address alignement.\n                if and(_addr, 3) {revert(0, 0)}\n\n            // Load the leaf value.\n                let leaf := calldataload(_proofOffset)\n                _proofOffset := add(_proofOffset, 32)\n\n            // Convenience function to hash two nodes together in scratch space.\n                function hashPair(a, b) -> h {\n                    mstore(0, a)\n                    mstore(32, b)\n                    h := keccak256(0, 64)\n                }\n\n            // Start with the leaf node.\n            // Work back up by combining with siblings, to reconstruct the root.\n                let path := shr(5, _addr)\n                let node := leaf\n                for {let i := 0} lt(i, 27) {i := add(i, 1)} {\n                    let sibling := calldataload(_proofOffset)\n                    _proofOffset := add(_proofOffset, 32)\n                    switch and(shr(i, path), 1)\n                    case 0 {node := hashPair(node, sibling)}\n                    case 1 {node := hashPair(sibling, node)}\n                }\n\n            // Verify the root matches.\n                if iszero(eq(node, _memRoot)) {\n                    mstore(0, 0x0badf00d)\n                    revert(0, 32)\n                }\n\n            // Bits to shift = (32 - 4 - (addr % 32)) * 8\n                let shamt := shl(3, sub(sub(32, 4), and(_addr, 31)))\n                out_ := and(shr(shamt, leaf), 0xFFffFFff)\n            }\n        }\n    }\n\n    /// @notice Writes a 32-bit value to memory.\n    ///         This function first overwrites the part of the leaf.\n    ///         Then it recomputes the memory merkle root.\n    /// @param _addr The address to write to.\n    /// @param _proofOffset The offset of the memory proof in calldata.\n    /// @param _val The value to write.\n    /// @return newMemRoot_ The new memory root after modification\n    function writeMem(uint32 _addr, uint256 _proofOffset, uint32 _val) internal pure returns (bytes32 newMemRoot_) {\n        unchecked {\n            validateMemoryProofAvailability(_proofOffset);\n            assembly {\n            // Validate the address alignement.\n                if and(_addr, 3) {revert(0, 0)}\n\n            // Load the leaf value.\n                let leaf := calldataload(_proofOffset)\n                let shamt := shl(3, sub(sub(32, 4), and(_addr, 31)))\n\n            // Mask out 4 bytes, and OR in the value\n                leaf := or(and(leaf, not(shl(shamt, 0xFFffFFff))), shl(shamt, _val))\n                _proofOffset := add(_proofOffset, 32)\n\n            // Convenience function to hash two nodes together in scratch space.\n                function hashPair(a, b) -> h {\n                    mstore(0, a)\n                    mstore(32, b)\n                    h := keccak256(0, 64)\n                }\n\n            // Start with the leaf node.\n            // Work back up by combining with siblings, to reconstruct the root.\n                let path := shr(5, _addr)\n                let node := leaf\n                for {let i := 0} lt(i, 27) {i := add(i, 1)} {\n                    let sibling := calldataload(_proofOffset)\n                    _proofOffset := add(_proofOffset, 32)\n                    switch and(shr(i, path), 1)\n                    case 0 {node := hashPair(node, sibling)}\n                    case 1 {node := hashPair(sibling, node)}\n                }\n\n                newMemRoot_ := node\n            }\n            return newMemRoot_;\n        }\n    }\n\n    /// @notice Computes the offset of a memory proof in the calldata.\n    /// @param _proofDataOffset The offset of the set of all memory proof data within calldata (proof.offset)\n    ///     Equal to the offset of the first memory proof (at _proofIndex 0).\n    /// @param _proofIndex The index of the proof in the calldata.\n    /// @return offset_ The offset of the memory proof at the given _proofIndex in the calldata.\n    function memoryProofOffset(uint256 _proofDataOffset, uint8 _proofIndex) internal pure returns (uint256 offset_) {\n        unchecked {\n        // A proof of 32 bit memory, with 32-byte leaf values, is (32-5)=27 bytes32 entries.\n        // And the leaf value itself needs to be encoded as well: (27 + 1) = 28 bytes32 entries.\n            offset_ = _proofDataOffset + (uint256(_proofIndex) * (28 * 32));\n            return offset_;\n        }\n    }\n\n    /// @notice Validates that enough calldata is available to hold a full memory proof at the given offset\n    /// @param _proofStartOffset The index of the first byte of the target memory proof in calldata\n    function validateMemoryProofAvailability(uint256 _proofStartOffset) internal pure {\n        unchecked {\n            uint256 s = 0;\n            assembly {\n                s := calldatasize()\n            }\n        // A memory proof consists of 28 bytes32 values - verify we have enough calldata\n            require(s >= (_proofStartOffset + 28 * 32), \"check that there is enough calldata\");\n        }\n    }\n}\n"
    },
    "contracts/L1/cannon/libraries/MIPSState.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nlibrary MIPSState {\n    struct CpuScalars {\n        uint32 pc;\n        uint32 nextPC;\n        uint32 lo;\n        uint32 hi;\n    }\n}\n"
    },
    "contracts/L1/cannon/libraries/MIPSSyscalls.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {MIPSMemory} from \"./MIPSMemory.sol\";\nimport {MIPSState as st} from \"./MIPSState.sol\";\nimport {IPreimageOracle} from \"../interfaces/IPreimageOracle.sol\";\nimport {PreimageKeyLib} from \"../PreimageKeyLib.sol\";\n\nlibrary MIPSSyscalls {\n    struct SysReadParams {\n        /// @param _a0 The file descriptor.\n        uint32 a0;\n        /// @param _a1 The memory location where data should be read to.\n        uint32 a1;\n        /// @param _a2 The number of bytes to read from the file\n        uint32 a2;\n        /// @param _preimageKey The key of the preimage to read.\n        bytes32 preimageKey;\n        /// @param _preimageOffset The offset of the preimage to read.\n        uint32 preimageOffset;\n        /// @param _localContext The local context for the preimage key.\n        bytes32 localContext;\n        /// @param _oracle The address of the preimage oracle.\n        IPreimageOracle oracle;\n        /// @param _proofOffset The offset of the memory proof in calldata.\n        uint256 proofOffset;\n        /// @param _memRoot The current memory root.\n        bytes32 memRoot;\n    }\n\n    uint32 internal constant SYS_MMAP = 4090;\n    uint32 internal constant SYS_BRK = 4045;\n    uint32 internal constant SYS_CLONE = 4120;\n    uint32 internal constant SYS_EXIT_GROUP = 4246;\n    uint32 internal constant SYS_READ = 4003;\n    uint32 internal constant SYS_WRITE = 4004;\n    uint32 internal constant SYS_FCNTL = 4055;\n    uint32 internal constant SYS_EXIT = 4001;\n    uint32 internal constant SYS_SCHED_YIELD = 4162;\n    uint32 internal constant SYS_GETTID = 4222;\n    uint32 internal constant SYS_FUTEX = 4238;\n    uint32 internal constant SYS_OPEN = 4005;\n    uint32 internal constant SYS_NANOSLEEP = 4166;\n    // unused syscalls\n    uint32 internal constant SYS_CLOCK_GETTIME = 4263;\n    uint32 internal constant SYS_GET_AFFINITY = 4240;\n    uint32 internal constant SYS_GETAFFINITY = 4240;\n    uint32 internal constant SYS_MADVISE = 4218;\n    uint32 internal constant SYS_RTSIGPROCMASK = 4195;\n    uint32 internal constant SYS_SIGALTSTACK = 4206;\n    uint32 internal constant SYS_RTSIGACTION = 4194;\n    uint32 internal constant SYS_PRLIMIT64 = 4338;\n    uint32 internal constant SYS_CLOSE = 4006;\n    uint32 internal constant SYS_PREAD64 = 4200;\n    uint32 internal constant SYS_FSTAT64 = 4215;\n    uint32 internal constant SYS_OPENAT = 4288;\n    uint32 internal constant SYS_READLINK = 4085;\n    uint32 internal constant SYS_READLINKAT = 4298;\n    uint32 internal constant SYS_IOCTL = 4054;\n    uint32 internal constant SYS_EPOLLCREATE1 = 4326;\n    uint32 internal constant SYS_PIPE2 = 4328;\n    uint32 internal constant SYS_EPOLLCTL = 4249;\n    uint32 internal constant SYS_EPOLLPWAIT = 4313;\n    uint32 internal constant SYS_GETRANDOM = 4353;\n    uint32 internal constant SYS_UNAME = 4122;\n    uint32 internal constant SYS_STAT64 = 4213;\n    uint32 internal constant SYS_GETUID = 4024;\n    uint32 internal constant SYS_GETGID = 4047;\n    uint32 internal constant SYS_LLSEEK = 4140;\n    uint32 internal constant SYS_MINCORE = 4217;\n    uint32 internal constant SYS_TGKILL = 4266;\n    // profiling-related syscalls - ignored\n    uint32 internal constant SYS_SETITIMER = 4104;\n    uint32 internal constant SYS_TIMERCREATE = 4257;\n    uint32 internal constant SYS_TIMERSETTIME = 4258;\n    uint32 internal constant SYS_TIMERDELETE = 4261;\n    uint32 internal constant SYS_CLOCKGETTIME = 4263;\n    uint32 internal constant SYS_MUNMAP = 4091;\n\n    uint32 internal constant FD_STDIN = 0;\n    uint32 internal constant FD_STDOUT = 1;\n    uint32 internal constant FD_STDERR = 2;\n    uint32 internal constant FD_HINT_READ = 3;\n    uint32 internal constant FD_HINT_WRITE = 4;\n    uint32 internal constant FD_PREIMAGE_READ = 5;\n    uint32 internal constant FD_PREIMAGE_WRITE = 6;\n\n    uint32 internal constant SYS_ERROR_SIGNAL = 0xFF_FF_FF_FF;\n    uint32 internal constant EBADF = 0x9;\n    uint32 internal constant EINVAL = 0x16;\n    uint32 internal constant EAGAIN = 0xb;\n    uint32 internal constant ETIMEDOUT = 0x91;\n\n    uint32 internal constant FUTEX_WAIT_PRIVATE = 128;\n    uint32 internal constant FUTEX_WAKE_PRIVATE = 129;\n    uint32 internal constant FUTEX_TIMEOUT_STEPS = 10000;\n    uint64 internal constant FUTEX_NO_TIMEOUT = type(uint64).max;\n    uint32 internal constant FUTEX_EMPTY_ADDR = 0xFF_FF_FF_FF;\n\n    uint32 internal constant SCHED_QUANTUM = 100_000;\n    /// @notice Start of the data segment.\n    uint32 internal constant PROGRAM_BREAK = 0x40000000;\n    uint32 internal constant HEAP_END = 0x60000000;\n\n    // SYS_CLONE flags\n    uint32 internal constant CLONE_VM = 0x100;\n    uint32 internal constant CLONE_FS = 0x200;\n    uint32 internal constant CLONE_FILES = 0x400;\n    uint32 internal constant CLONE_SIGHAND = 0x800;\n    uint32 internal constant CLONE_PTRACE = 0x2000;\n    uint32 internal constant CLONE_VFORK = 0x4000;\n    uint32 internal constant CLONE_PARENT = 0x8000;\n    uint32 internal constant CLONE_THREAD = 0x10000;\n    uint32 internal constant CLONE_NEWNS = 0x20000;\n    uint32 internal constant CLONE_SYSVSEM = 0x40000;\n    uint32 internal constant CLONE_SETTLS = 0x80000;\n    uint32 internal constant CLONE_PARENTSETTID = 0x100000;\n    uint32 internal constant CLONE_CHILDCLEARTID = 0x200000;\n    uint32 internal constant CLONE_UNTRACED = 0x800000;\n    uint32 internal constant CLONE_CHILDSETTID = 0x1000000;\n    uint32 internal constant CLONE_STOPPED = 0x2000000;\n    uint32 internal constant CLONE_NEWUTS = 0x4000000;\n    uint32 internal constant CLONE_NEWIPC = 0x8000000;\n    uint32 internal constant VALID_SYS_CLONE_FLAGS =\n    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | CLONE_THREAD;\n\n    /// @notice Extract syscall num and arguments from registers.\n    /// @param _registers The cpu registers.\n    /// @return sysCallNum_ The syscall number.\n    /// @return a0_ The first argument available to the syscall operation.\n    /// @return a1_ The second argument available to the syscall operation.\n    /// @return a2_ The third argument available to the syscall operation.\n    /// @return a3_ The fourth argument available to the syscall operation.\n    function getSyscallArgs(uint32[32] memory _registers)\n    internal\n    pure\n    returns (uint32 sysCallNum_, uint32 a0_, uint32 a1_, uint32 a2_, uint32 a3_)\n    {\n        unchecked {\n            sysCallNum_ = _registers[2];\n\n            a0_ = _registers[4];\n            a1_ = _registers[5];\n            a2_ = _registers[6];\n            a3_ = _registers[7];\n\n            return (sysCallNum_, a0_, a1_, a2_, a3_);\n        }\n    }\n\n    /// @notice Like a Linux mmap syscall. Allocates a page from the heap.\n    /// @param _a0 The address for the new mapping\n    /// @param _a1 The size of the new mapping\n    /// @param _heap The current value of the heap pointer\n    /// @return v0_ The address of the new mapping\n    /// @return v1_ Unused error code (0)\n    /// @return newHeap_ The new value for the heap, may be unchanged\n    function handleSysMmap(\n        uint32 _a0,\n        uint32 _a1,\n        uint32 _heap\n    )\n    internal\n    pure\n    returns (uint32 v0_, uint32 v1_, uint32 newHeap_)\n    {\n        unchecked {\n            v1_ = uint32(0);\n            newHeap_ = _heap;\n\n            uint32 sz = _a1;\n            if (sz & 4095 != 0) {\n                // adjust size to align with page size\n                sz += 4096 - (sz & 4095);\n            }\n            if (_a0 == 0) {\n                v0_ = _heap;\n                newHeap_ += sz;\n                // Fail if new heap exceeds memory limit, newHeap overflows to low memory, or sz overflows\n                if (newHeap_ > HEAP_END || newHeap_ < _heap || sz < _a1) {\n                    v0_ = SYS_ERROR_SIGNAL;\n                    v1_ = EINVAL;\n                    return (v0_, v1_, _heap);\n                }\n            } else {\n                v0_ = _a0;\n            }\n\n            return (v0_, v1_, newHeap_);\n        }\n    }\n\n    /// @notice Like a Linux read syscall. Splits unaligned reads into aligned reads.\n    ///         Args are provided as a struct to reduce stack pressure.\n    /// @return v0_ The number of bytes read, -1 on error.\n    /// @return v1_ The error code, 0 if there is no error.\n    /// @return newPreimageOffset_ The new value for the preimage offset.\n    /// @return newMemRoot_ The new memory root.\n    function handleSysRead(SysReadParams memory _args)\n    internal\n    view\n    returns (uint32 v0_, uint32 v1_, uint32 newPreimageOffset_, bytes32 newMemRoot_)\n    {\n        unchecked {\n            v0_ = uint32(0);\n            v1_ = uint32(0);\n            newMemRoot_ = _args.memRoot;\n            newPreimageOffset_ = _args.preimageOffset;\n\n        // args: _a0 = fd, _a1 = addr, _a2 = count\n        // returns: v0_ = read, v1_ = err code\n            if (_args.a0 == FD_STDIN) {\n                // Leave v0_ and v1_ zero: read nothing, no error\n            }\n                // pre-image oracle read\n            else if (_args.a0 == FD_PREIMAGE_READ) {\n                // verify proof is correct, and get the existing memory.\n                // mask the addr to align it to 4 bytes\n                uint32 mem = MIPSMemory.readMem(_args.memRoot, _args.a1 & 0xFFffFFfc, _args.proofOffset);\n                // If the preimage key is a local key, localize it in the context of the caller.\n                if (uint8(_args.preimageKey[0]) == 1) {\n                    _args.preimageKey = PreimageKeyLib.localize(_args.preimageKey, _args.localContext);\n                }\n                (bytes32 dat, uint256 datLen) = _args.oracle.readPreimage(_args.preimageKey, _args.preimageOffset);\n\n                // Transform data for writing to memory\n                // We use assembly for more precise ops, and no var count limit\n                uint32 a1 = _args.a1;\n                uint32 a2 = _args.a2;\n                assembly {\n                    let alignment := and(a1, 3) // the read might not start at an aligned address\n                    let space := sub(4, alignment) // remaining space in memory word\n                    if lt(space, datLen) {datLen := space} // if less space than data, shorten data\n                    if lt(a2, datLen) {datLen := a2} // if requested to read less, read less\n                    dat := shr(sub(256, mul(datLen, 8)), dat) // right-align data\n                    dat := shl(mul(sub(sub(4, datLen), alignment), 8), dat) // position data to insert into memory\n                // word\n                    let mask := sub(shl(mul(sub(4, alignment), 8), 1), 1) // mask all bytes after start\n                    let suffixMask := sub(shl(mul(sub(sub(4, alignment), datLen), 8), 1), 1) // mask of all bytes\n                // starting from end, maybe none\n                    mask := and(mask, not(suffixMask)) // reduce mask to just cover the data we insert\n                    mem := or(and(mem, not(mask)), dat) // clear masked part of original memory, and insert data\n                }\n\n                // Write memory back\n                newMemRoot_ = MIPSMemory.writeMem(_args.a1 & 0xFFffFFfc, _args.proofOffset, mem);\n                newPreimageOffset_ += uint32(datLen);\n                v0_ = uint32(datLen);\n            }\n                // hint response\n            else if (_args.a0 == FD_HINT_READ) {\n                // Don't read into memory, just say we read it all\n                // The result is ignored anyway\n                v0_ = _args.a2;\n            } else {\n                v0_ = 0xFFffFFff;\n                v1_ = EBADF;\n            }\n\n            return (v0_, v1_, newPreimageOffset_, newMemRoot_);\n        }\n    }\n\n    /// @notice Like a Linux write syscall. Splits unaligned writes into aligned writes.\n    /// @param _a0 The file descriptor.\n    /// @param _a1 The memory address to read from.\n    /// @param _a2 The number of bytes to read.\n    /// @param _preimageKey The current preimaageKey.\n    /// @param _preimageOffset The current preimageOffset.\n    /// @param _proofOffset The offset of the memory proof in calldata.\n    /// @param _memRoot The current memory root.\n    /// @return v0_ The number of bytes written, or -1 on error.\n    /// @return v1_ The error code, or 0 if empty.\n    /// @return newPreimageKey_ The new preimageKey.\n    /// @return newPreimageOffset_ The new preimageOffset.\n    function handleSysWrite(\n        uint32 _a0,\n        uint32 _a1,\n        uint32 _a2,\n        bytes32 _preimageKey,\n        uint32 _preimageOffset,\n        uint256 _proofOffset,\n        bytes32 _memRoot\n    )\n    internal\n    pure\n    returns (uint32 v0_, uint32 v1_, bytes32 newPreimageKey_, uint32 newPreimageOffset_)\n    {\n        unchecked {\n        // args: _a0 = fd, _a1 = addr, _a2 = count\n        // returns: v0_ = written, v1_ = err code\n            v0_ = uint32(0);\n            v1_ = uint32(0);\n            newPreimageKey_ = _preimageKey;\n            newPreimageOffset_ = _preimageOffset;\n\n            if (_a0 == FD_STDOUT || _a0 == FD_STDERR || _a0 == FD_HINT_WRITE) {\n                v0_ = _a2; // tell program we have written everything\n            }\n                // pre-image oracle\n            else if (_a0 == FD_PREIMAGE_WRITE) {\n                // mask the addr to align it to 4 bytes\n                uint32 mem = MIPSMemory.readMem(_memRoot, _a1 & 0xFFffFFfc, _proofOffset);\n                bytes32 key = _preimageKey;\n\n                // Construct pre-image key from memory\n                // We use assembly for more precise ops, and no var count limit\n                assembly {\n                    let alignment := and(_a1, 3) // the read might not start at an aligned address\n                    let space := sub(4, alignment) // remaining space in memory word\n                    if lt(space, _a2) {_a2 := space} // if less space than data, shorten data\n                    key := shl(mul(_a2, 8), key) // shift key, make space for new info\n                    let mask := sub(shl(mul(_a2, 8), 1), 1) // mask for extracting value from memory\n                    mem := and(shr(mul(sub(space, _a2), 8), mem), mask) // align value to right, mask it\n                    key := or(key, mem) // insert into key\n                }\n\n                // Write pre-image key to oracle\n                newPreimageKey_ = key;\n                newPreimageOffset_ = 0; // reset offset, to read new pre-image data from the start\n                v0_ = _a2;\n            } else {\n                v0_ = 0xFFffFFff;\n                v1_ = EBADF;\n            }\n\n            return (v0_, v1_, newPreimageKey_, newPreimageOffset_);\n        }\n    }\n\n    /// @notice Like Linux fcntl (file control) syscall, but only supports minimal file-descriptor control commands, to\n    /// retrieve the file-descriptor R/W flags.\n    /// @param _a0 The file descriptor.\n    /// @param _a1 The control command.\n    /// @param v0_ The file status flag (only supported command is F_GETFL), or -1 on error.\n    /// @param v1_ An error number, or 0 if there is no error.\n    function handleSysFcntl(uint32 _a0, uint32 _a1) internal pure returns (uint32 v0_, uint32 v1_) {\n        unchecked {\n            v0_ = uint32(0);\n            v1_ = uint32(0);\n\n        // args: _a0 = fd, _a1 = cmd\n            if (_a1 == 1) {\n                // F_GETFD: get file descriptor flags\n                if (\n                    _a0 == FD_STDIN || _a0 == FD_STDOUT || _a0 == FD_STDERR || _a0 == FD_PREIMAGE_READ\n                    || _a0 == FD_HINT_READ || _a0 == FD_PREIMAGE_WRITE || _a0 == FD_HINT_WRITE\n                ) {\n                    v0_ = 0; // No flags set\n                } else {\n                    v0_ = 0xFFffFFff;\n                    v1_ = EBADF;\n                }\n            } else if (_a1 == 3) {\n                // F_GETFL: get file descriptor flags\n                if (_a0 == FD_STDIN || _a0 == FD_PREIMAGE_READ || _a0 == FD_HINT_READ) {\n                    v0_ = 0; // O_RDONLY\n                } else if (_a0 == FD_STDOUT || _a0 == FD_STDERR || _a0 == FD_PREIMAGE_WRITE || _a0 == FD_HINT_WRITE) {\n                    v0_ = 1; // O_WRONLY\n                } else {\n                    v0_ = 0xFFffFFff;\n                    v1_ = EBADF;\n                }\n            } else {\n                v0_ = 0xFFffFFff;\n                v1_ = EINVAL; // cmd not recognized by this kernel\n            }\n\n            return (v0_, v1_);\n        }\n    }\n\n    function handleSyscallUpdates(\n        st.CpuScalars memory _cpu,\n        uint32[32] memory _registers,\n        uint32 _v0,\n        uint32 _v1\n    )\n    internal\n    pure\n    {\n        unchecked {\n        // Write the results back to the state registers\n            _registers[2] = _v0;\n            _registers[7] = _v1;\n\n        // Update the PC and nextPC\n            _cpu.pc = _cpu.nextPC;\n            _cpu.nextPC = _cpu.nextPC + 4;\n        }\n    }\n}\n"
    },
    "contracts/L1/cannon/MIPS.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {ISemver} from \"../../universal/ISemver.sol\";\nimport {IPreimageOracle} from \"./interfaces/IPreimageOracle.sol\";\nimport {PreimageKeyLib} from \"./PreimageKeyLib.sol\";\nimport {MIPSInstructions as ins} from \"./libraries/MIPSInstructions.sol\";\nimport {MIPSSyscalls as sys} from \"./libraries/MIPSSyscalls.sol\";\nimport {MIPSState as st} from \"./libraries/MIPSState.sol\";\nimport {MIPSMemory} from \"./libraries/MIPSMemory.sol\";\n\n/// @title MIPS\n/// @notice The MIPS contract emulates a single MIPS instruction.\n///         Note that delay slots are isolated instructions:\n///         the nextPC in the state pre-schedules where the VM jumps next.\n///         The Step input is a packed VM state, with binary-merkle-tree\n///         witness data for memory reads/writes.\n///         The Step outputs a keccak256 hash of the packed VM State,\n///         and logs the resulting state for offchain usage.\n/// @dev https://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_Green_Sheet.pdf\n/// @dev https://www.cs.cmu.edu/afs/cs/academic/class/15740-f97/public/doc/mips-isa.pdf\n///      (page A-177)\n/// @dev https://uweb.engr.arizona.edu/~ece369/Resources/spim/MIPSReference.pdf\n/// @dev https://en.wikibooks.org/wiki/MIPS_Assembly/Instruction_Formats\n/// @dev https://github.com/golang/go/blob/master/src/syscall/zerrors_linux_mips.go\n///      MIPS linux kernel errors used by Go runtime\ncontract MIPS is ISemver {\n    /// @notice Stores the VM state.\n    ///         Total state size: 32 + 32 + 6 * 4 + 1 + 1 + 8 + 32 * 4 = 226 bytes\n    ///         If nextPC != pc + 4, then the VM is executing a branch/jump delay slot.\n    struct State {\n        bytes32 memRoot;\n        bytes32 preimageKey;\n        uint32 preimageOffset;\n        uint32 pc;\n        uint32 nextPC;\n        uint32 lo;\n        uint32 hi;\n        uint32 heap;\n        uint8 exitCode;\n        bool exited;\n        uint64 step;\n        uint32[32] registers;\n    }\n\n    /// @notice The semantic version of the MIPS contract.\n    /// @custom:semver 1.1.0-rc.1\n    string public constant version = \"1.1.0-rc.1\";\n\n    /// @notice The preimage oracle contract.\n    IPreimageOracle internal immutable ORACLE;\n\n    // The offset of the start of proof calldata (_proof.offset) in the step() function\n    uint256 internal constant STEP_PROOF_OFFSET = 420;\n\n    /// @param _oracle The address of the preimage oracle contract.\n    constructor(IPreimageOracle _oracle) {\n        ORACLE = _oracle;\n    }\n\n    /// @notice Getter for the pre-image oracle contract.\n    /// @return oracle_ The IPreimageOracle contract.\n    function oracle() external view returns (IPreimageOracle oracle_) {\n        oracle_ = ORACLE;\n    }\n\n    /// @notice Computes the hash of the MIPS state.\n    /// @return out_ The hashed MIPS state.\n    function outputState() internal returns (bytes32 out_) {\n        assembly {\n        // copies 'size' bytes, right-aligned in word at 'from', to 'to', incl. trailing data\n            function copyMem(from, to, size) -> fromOut, toOut {\n                mstore(to, mload(add(from, sub(32, size))))\n                fromOut := add(from, 32)\n                toOut := add(to, size)\n            }\n\n        // From points to the MIPS State\n            let from := 0x80\n\n        // Copy to the free memory pointer\n            let start := mload(0x40)\n            let to := start\n\n        // Copy state to free memory\n            from, to := copyMem(from, to, 32) // memRoot\n            from, to := copyMem(from, to, 32) // preimageKey\n            from, to := copyMem(from, to, 4) // preimageOffset\n            from, to := copyMem(from, to, 4) // pc\n            from, to := copyMem(from, to, 4) // nextPC\n            from, to := copyMem(from, to, 4) // lo\n            from, to := copyMem(from, to, 4) // hi\n            from, to := copyMem(from, to, 4) // heap\n            let exitCode := mload(from)\n            from, to := copyMem(from, to, 1) // exitCode\n            let exited := mload(from)\n            from, to := copyMem(from, to, 1) // exited\n            from, to := copyMem(from, to, 8) // step\n            from := add(from, 32) // offset to registers\n\n        // Verify that the value of exited is valid (0 or 1)\n            if gt(exited, 1) {\n            // revert InvalidExitedValue();\n                let ptr := mload(0x40)\n                mstore(ptr, shl(224, 0x0136cc76))\n                revert(ptr, 0x04)\n            }\n\n        // Copy registers\n            for {let i := 0} lt(i, 32) {i := add(i, 1)} {from, to := copyMem(from, to, 4)}\n\n        // Clean up end of memory\n            mstore(to, 0)\n\n        // Log the resulting MIPS state, for debugging\n            log0(start, sub(to, start))\n\n        // Determine the VM status\n            let status := 0\n            switch exited\n            case 1 {\n                switch exitCode\n                // VMStatusValid\n                case 0 {status := 0}\n                // VMStatusInvalid\n                case 1 {status := 1}\n                // VMStatusPanic\n                default {status := 2}\n            }\n            // VMStatusUnfinished\n            default {status := 3}\n\n        // Compute the hash of the resulting MIPS state and set the status byte\n            out_ := keccak256(start, sub(to, start))\n            out_ := or(and(not(shl(248, 0xFF)), out_), shl(248, status))\n        }\n    }\n\n    /// @notice Handles a syscall.\n    /// @param _localContext The local key context for the preimage oracle.\n    /// @return out_ The hashed MIPS state.\n    function handleSyscall(bytes32 _localContext) internal returns (bytes32 out_) {\n        unchecked {\n        // Load state from memory\n            State memory state;\n            assembly {\n                state := 0x80\n            }\n\n        // Load the syscall numbers and args from the registers\n            (uint32 syscall_no, uint32 a0, uint32 a1, uint32 a2,) = sys.getSyscallArgs(state.registers);\n\n            uint32 v0 = 0;\n            uint32 v1 = 0;\n\n            if (syscall_no == sys.SYS_MMAP) {\n                (v0, v1, state.heap) = sys.handleSysMmap(a0, a1, state.heap);\n            } else if (syscall_no == sys.SYS_BRK) {\n                // brk: Returns a fixed address for the program break at 0x40000000\n                v0 = sys.PROGRAM_BREAK;\n            } else if (syscall_no == sys.SYS_CLONE) {\n                // clone (not supported) returns 1\n                v0 = 1;\n            } else if (syscall_no == sys.SYS_EXIT_GROUP) {\n                // exit group: Sets the Exited and ExitCode states to true and argument 0.\n                state.exited = true;\n                state.exitCode = uint8(a0);\n                return outputState();\n            } else if (syscall_no == sys.SYS_READ) {\n                sys.SysReadParams memory args = sys.SysReadParams({\n                    a0: a0,\n                    a1: a1,\n                    a2: a2,\n                    preimageKey: state.preimageKey,\n                    preimageOffset: state.preimageOffset,\n                    localContext: _localContext,\n                    oracle: ORACLE,\n                    proofOffset: MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1),\n                    memRoot: state.memRoot\n                });\n                (v0, v1, state.preimageOffset, state.memRoot) = sys.handleSysRead(args);\n            } else if (syscall_no == sys.SYS_WRITE) {\n                (v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({\n                    _a0: a0,\n                    _a1: a1,\n                    _a2: a2,\n                    _preimageKey: state.preimageKey,\n                    _preimageOffset: state.preimageOffset,\n                    _proofOffset: MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1),\n                    _memRoot: state.memRoot\n                });\n            } else if (syscall_no == sys.SYS_FCNTL) {\n                (v0, v1) = sys.handleSysFcntl(a0, a1);\n            }\n\n            st.CpuScalars memory cpu = getCpuScalars(state);\n            sys.handleSyscallUpdates(cpu, state.registers, v0, v1);\n            setStateCpuScalars(state, cpu);\n\n            out_ = outputState();\n        }\n    }\n\n    /// @notice Executes a single step of the vm.\n    ///         Will revert if any required input state is missing.\n    /// @param _stateData The encoded state witness data.\n    /// @param _proof The encoded proof data for leaves within the MIPS VM's memory.\n    /// @param _localContext The local key context for the preimage oracle. Optional, can be set as a constant\n    ///                      if the caller only requires one set of local keys.\n    function step(bytes calldata _stateData, bytes calldata _proof, bytes32 _localContext) public returns (bytes32) {\n        unchecked {\n            State memory state;\n\n        // Packed calldata is ~6 times smaller than state size\n            assembly {\n                if iszero(eq(state, 0x80)) {\n                // expected state mem offset check\n                    revert(0, 0)\n                }\n                if iszero(eq(mload(0x40), shl(5, 48))) {\n                // expected memory check\n                    revert(0, 0)\n                }\n                if iszero(eq(_stateData.offset, 132)) {\n                // 32*4+4=132 expected state data offset\n                    revert(0, 0)\n                }\n                if iszero(eq(_proof.offset, STEP_PROOF_OFFSET)) {\n                // 132+32+256=420 expected proof offset\n                    revert(0, 0)\n                }\n\n                function putField(callOffset, memOffset, size) -> callOffsetOut, memOffsetOut {\n                // calldata is packed, thus starting left-aligned, shift-right to pad and right-align\n                    let w := shr(shl(3, sub(32, size)), calldataload(callOffset))\n                    mstore(memOffset, w)\n                    callOffsetOut := add(callOffset, size)\n                    memOffsetOut := add(memOffset, 32)\n                }\n\n            // Unpack state from calldata into memory\n                let c := _stateData.offset // calldata offset\n                let m := 0x80 // mem offset\n                c, m := putField(c, m, 32) // memRoot\n                c, m := putField(c, m, 32) // preimageKey\n                c, m := putField(c, m, 4) // preimageOffset\n                c, m := putField(c, m, 4) // pc\n                c, m := putField(c, m, 4) // nextPC\n                c, m := putField(c, m, 4) // lo\n                c, m := putField(c, m, 4) // hi\n                c, m := putField(c, m, 4) // heap\n                c, m := putField(c, m, 1) // exitCode\n                c, m := putField(c, m, 1) // exited\n                let exited := mload(sub(m, 32))\n                c, m := putField(c, m, 8) // step\n\n            // Verify that the value of exited is valid (0 or 1)\n                if gt(exited, 1) {\n                // revert InvalidExitedValue();\n                    let ptr := mload(0x40)\n                    mstore(ptr, shl(224, 0x0136cc76))\n                    revert(ptr, 0x04)\n                }\n\n            // Compiler should have done this already\n                if iszero(eq(mload(m), add(m, 32))) {\n                // expected registers offset check\n                    revert(0, 0)\n                }\n\n            // Unpack register calldata into memory\n                m := add(m, 32)\n                for {let i := 0} lt(i, 32) {i := add(i, 1)} {c, m := putField(c, m, 4)}\n            }\n\n        // Don't change state once exited\n            if (state.exited) {\n                return outputState();\n            }\n\n            state.step += 1;\n\n        // instruction fetch\n            uint256 insnProofOffset = MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 0);\n            (uint32 insn, uint32 opcode, uint32 fun) =\n                                ins.getInstructionDetails(state.pc, state.memRoot, insnProofOffset);\n\n        // Handle syscall separately\n        // syscall (can read and write)\n            if (opcode == 0 && fun == 0xC) {\n                return handleSyscall(_localContext);\n            }\n\n        // Exec the rest of the step logic\n            st.CpuScalars memory cpu = getCpuScalars(state);\n            (state.memRoot) = ins.execMipsCoreStepLogic({\n                _cpu: cpu,\n                _registers: state.registers,\n                _memRoot: state.memRoot,\n                _memProofOffset: MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1),\n                _insn: insn,\n                _opcode: opcode,\n                _fun: fun\n            });\n            setStateCpuScalars(state, cpu);\n\n            return outputState();\n        }\n    }\n\n    function getCpuScalars(State memory _state) internal pure returns (st.CpuScalars memory) {\n        return st.CpuScalars({pc: _state.pc, nextPC: _state.nextPC, lo: _state.lo, hi: _state.hi});\n    }\n\n    function setStateCpuScalars(State memory _state, st.CpuScalars memory _cpu) internal pure {\n        _state.pc = _cpu.pc;\n        _state.nextPC = _cpu.nextPC;\n        _state.lo = _cpu.lo;\n        _state.hi = _cpu.hi;\n    }\n}\n"
    },
    "contracts/L1/cannon/MIPS2.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {VMStatuses} from \"../dispute/lib/Types.sol\";\nimport {ISemver} from \"../../universal/ISemver.sol\";\nimport {IPreimageOracle} from \"./interfaces/IPreimageOracle.sol\";\nimport {MIPSMemory} from \"./libraries/MIPSMemory.sol\";\nimport {MIPSSyscalls as sys} from \"./libraries/MIPSSyscalls.sol\";\nimport {MIPSState as st} from \"./libraries/MIPSState.sol\";\nimport {MIPSInstructions as ins} from \"./libraries/MIPSInstructions.sol\";\n\n/// @title MIPS2\n/// @notice The MIPS2 contract emulates a single MIPS instruction.\n///         It differs from MIPS.sol in that it supports multi-threading.\ncontract MIPS2 is ISemver {\n    /// @notice The thread context.\n    ///         Total state size: 4 + 1 + 1 + 4 + 4 + 8 + 4 + 4 + 4 + 4 + 32 * 4 = 166 bytes\n    struct ThreadState {\n        // metadata\n        uint32 threadID;\n        uint8 exitCode;\n        bool exited;\n        // state\n        uint32 futexAddr;\n        uint32 futexVal;\n        uint64 futexTimeoutStep;\n        uint32 pc;\n        uint32 nextPC;\n        uint32 lo;\n        uint32 hi;\n        uint32[32] registers;\n    }\n\n    /// @notice Stores the VM state.\n    ///         Total state size: 32 + 32 + 4 + 4 + 1 + 1 + 8 + 8 + 4 + 1 + 32 + 32 + 4 = 163 bytes\n    ///         If nextPC != pc + 4, then the VM is executing a branch/jump delay slot.\n    struct State {\n        bytes32 memRoot;\n        bytes32 preimageKey;\n        uint32 preimageOffset;\n        uint32 heap;\n        uint8 exitCode;\n        bool exited;\n        uint64 step;\n        uint64 stepsSinceLastContextSwitch;\n        uint32 wakeup;\n        bool traverseRight;\n        bytes32 leftThreadStack;\n        bytes32 rightThreadStack;\n        uint32 nextThreadID;\n    }\n\n    /// @notice The semantic version of the MIPS2 contract.\n    /// @custom:semver 1.0.0-beta.4\n    string public constant version = \"1.0.0-beta.4\";\n\n    /// @notice The preimage oracle contract.\n    IPreimageOracle internal immutable ORACLE;\n\n    // The offset of the start of proof calldata (_threadWitness.offset) in the step() function\n    uint256 internal constant THREAD_PROOF_OFFSET = 356;\n\n    // The offset of the start of proof calldata (_memProof.offset) in the step() function\n    uint256 internal constant MEM_PROOF_OFFSET = THREAD_PROOF_OFFSET + 166 + 32;\n\n    // The empty thread root - keccak256(bytes32(0) ++ bytes32(0))\n    bytes32 internal constant EMPTY_THREAD_ROOT = hex\"ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5\";\n\n    // State memory offset allocated during step\n    uint256 internal constant STATE_MEM_OFFSET = 0x80;\n\n    // ThreadState memory offset allocated during step\n    uint256 internal constant TC_MEM_OFFSET = 0x220;\n\n    /// @param _oracle The address of the preimage oracle contract.\n    constructor(IPreimageOracle _oracle) {\n        ORACLE = _oracle;\n    }\n\n    /// @notice Executes a single step of the multi-threaded vm.\n    ///         Will revert if any required input state is missing.\n    /// @param _stateData The encoded state witness data.\n    /// @param _proof The encoded proof data: <<thread_context, inner_root>, <memory proof>.\n    ///               Contains the thread context witness and the memory proof data for leaves within the MIPS VM's\n    /// memory.\n    ///               The thread context witness is a packed tuple of the thread context and the immediate inner root of\n    /// the current thread stack.\n    /// @param _localContext The local key context for the preimage oracle. Optional, can be set as a constant\n    ///                      if the caller only requires one set of local keys.\n    function step(bytes calldata _stateData, bytes calldata _proof, bytes32 _localContext) public returns (bytes32) {\n        unchecked {\n            State memory state;\n            ThreadState memory thread;\n\n            assembly {\n                if iszero(eq(state, STATE_MEM_OFFSET)) {\n                // expected state mem offset check\n                    revert(0, 0)\n                }\n                if iszero(eq(thread, TC_MEM_OFFSET)) {\n                // expected thread mem offset check\n                    revert(0, 0)\n                }\n                if iszero(eq(mload(0x40), shl(5, 60))) {\n                // 4 + 13 state slots + 43 thread slots = 60 expected memory check\n                    revert(0, 0)\n                }\n                if iszero(eq(_stateData.offset, 132)) {\n                // 32*4+4=132 expected state data offset\n                    revert(0, 0)\n                }\n                if iszero(eq(_proof.offset, THREAD_PROOF_OFFSET)) {\n                // _stateData.offset+192+32=356 expected thread proof offset\n                    revert(0, 0)\n                }\n\n                function putField(callOffset, memOffset, size) -> callOffsetOut, memOffsetOut {\n                // calldata is packed, thus starting left-aligned, shift-right to pad and right-align\n                    let w := shr(shl(3, sub(32, size)), calldataload(callOffset))\n                    mstore(memOffset, w)\n                    callOffsetOut := add(callOffset, size)\n                    memOffsetOut := add(memOffset, 32)\n                }\n\n            // Unpack state from calldata into memory\n                let c := _stateData.offset // calldata offset\n                let m := STATE_MEM_OFFSET // mem offset\n                c, m := putField(c, m, 32) // memRoot\n                c, m := putField(c, m, 32) // preimageKey\n                c, m := putField(c, m, 4) // preimageOffset\n                c, m := putField(c, m, 4) // heap\n                c, m := putField(c, m, 1) // exitCode\n                c, m := putField(c, m, 1) // exited\n                c, m := putField(c, m, 8) // step\n                c, m := putField(c, m, 8) // stepsSinceLastContextSwitch\n                c, m := putField(c, m, 4) // wakeup\n                c, m := putField(c, m, 1) // traverseRight\n                c, m := putField(c, m, 32) // leftThreadStack\n                c, m := putField(c, m, 32) // rightThreadStack\n                c, m := putField(c, m, 4) // nextThreadID\n            }\n\n            if (state.exited) {\n                // thread state is unchanged\n                return outputState();\n            }\n\n            if (state.leftThreadStack == EMPTY_THREAD_ROOT && state.rightThreadStack == EMPTY_THREAD_ROOT) {\n                revert(\"MIPS2: illegal vm state\");\n            }\n\n            state.step += 1;\n\n            setThreadStateFromCalldata(thread);\n            validateCalldataThreadWitness(state, thread);\n\n        // Search for the first thread blocked by the wakeup call, if wakeup is set\n        // Don't allow regular execution until we resolved if we have woken up any thread.\n            if (state.wakeup != sys.FUTEX_EMPTY_ADDR) {\n                if (state.wakeup == thread.futexAddr) {\n                    // completed wake traverssal\n                    // resume execution on woken up thread\n                    state.wakeup = sys.FUTEX_EMPTY_ADDR;\n                    return outputState();\n                } else {\n                    bool traversingRight = state.traverseRight;\n                    bool changedDirections = preemptThread(state, thread);\n                    if (traversingRight && changedDirections) {\n                        // then we've completed wake traversal\n                        // resume thread execution\n                        state.wakeup = sys.FUTEX_EMPTY_ADDR;\n                    }\n                    return outputState();\n                }\n            }\n\n            if (thread.exited) {\n                popThread(state);\n                return outputState();\n            }\n\n        // check if thread is blocked on a futex\n            if (thread.futexAddr != sys.FUTEX_EMPTY_ADDR) {\n                // if set, then check futex\n                // check timeout first\n                if (state.step > thread.futexTimeoutStep) {\n                    // timeout! Allow execution\n                    return onWaitComplete(state, thread, true);\n                } else {\n                    uint32 mem = MIPSMemory.readMem(\n                        state.memRoot, thread.futexAddr & 0xFFffFFfc, MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1)\n                    );\n                    if (thread.futexVal == mem) {\n                        // still got expected value, continue sleeping, try next thread.\n                        preemptThread(state, thread);\n                        return outputState();\n                    } else {\n                        // wake thread up, the value at its address changed!\n                        // Userspace can turn thread back to sleep if it was too sporadic.\n                        return onWaitComplete(state, thread, false);\n                    }\n                }\n            }\n\n            if (state.stepsSinceLastContextSwitch == sys.SCHED_QUANTUM) {\n                preemptThread(state, thread);\n                return outputState();\n            }\n            state.stepsSinceLastContextSwitch += 1;\n\n        // instruction fetch\n            uint256 insnProofOffset = MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 0);\n            (uint32 insn, uint32 opcode, uint32 fun) =\n                                ins.getInstructionDetails(thread.pc, state.memRoot, insnProofOffset);\n\n        // Handle syscall separately\n        // syscall (can read and write)\n            if (opcode == 0 && fun == 0xC) {\n                return handleSyscall(_localContext);\n            }\n\n        // Exec the rest of the step logic\n            st.CpuScalars memory cpu = getCpuScalars(thread);\n            (state.memRoot) = ins.execMipsCoreStepLogic({\n                _cpu: cpu,\n                _registers: thread.registers,\n                _memRoot: state.memRoot,\n                _memProofOffset: MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1),\n                _insn: insn,\n                _opcode: opcode,\n                _fun: fun\n            });\n            setStateCpuScalars(thread, cpu);\n            updateCurrentThreadRoot();\n            return outputState();\n        }\n    }\n\n    function handleSyscall(bytes32 _localContext) internal returns (bytes32 out_) {\n        unchecked {\n        // Load state from memory offsets to reduce stack pressure\n            State memory state;\n            ThreadState memory thread;\n            assembly {\n                state := STATE_MEM_OFFSET\n                thread := TC_MEM_OFFSET\n            }\n\n        // Load the syscall numbers and args from the registers\n            (uint32 syscall_no, uint32 a0, uint32 a1, uint32 a2, uint32 a3) = sys.getSyscallArgs(thread.registers);\n        // Syscalls that are unimplemented but known return with v0=0 and v1=0\n            uint32 v0 = 0;\n            uint32 v1 = 0;\n\n            if (syscall_no == sys.SYS_MMAP) {\n                (v0, v1, state.heap) = sys.handleSysMmap(a0, a1, state.heap);\n            } else if (syscall_no == sys.SYS_BRK) {\n                // brk: Returns a fixed address for the program break at 0x40000000\n                v0 = sys.PROGRAM_BREAK;\n            } else if (syscall_no == sys.SYS_CLONE) {\n                if (sys.VALID_SYS_CLONE_FLAGS != a0) {\n                    state.exited = true;\n                    state.exitCode = VMStatuses.PANIC.raw();\n                    return outputState();\n                }\n                v0 = state.nextThreadID;\n                v1 = 0;\n                ThreadState memory newThread;\n                newThread.threadID = state.nextThreadID;\n                newThread.exitCode = 0;\n                newThread.exited = false;\n                newThread.futexAddr = sys.FUTEX_EMPTY_ADDR;\n                newThread.futexVal = 0;\n                newThread.futexTimeoutStep = 0;\n                newThread.pc = thread.nextPC;\n                newThread.nextPC = thread.nextPC + 4;\n                newThread.lo = thread.lo;\n                newThread.hi = thread.hi;\n                for (uint256 i; i < 32; i++) {\n                    newThread.registers[i] = thread.registers[i];\n                }\n                newThread.registers[29] = a1; // set stack pointer\n                // the child will perceive a 0 value as returned value instead, and no error\n                newThread.registers[2] = 0;\n                newThread.registers[7] = 0;\n                state.nextThreadID++;\n\n                // Preempt this thread for the new one. But not before updating PCs\n                st.CpuScalars memory cpu0 = getCpuScalars(thread);\n                sys.handleSyscallUpdates(cpu0, thread.registers, v0, v1);\n                setStateCpuScalars(thread, cpu0);\n                updateCurrentThreadRoot();\n                pushThread(state, newThread);\n                return outputState();\n            } else if (syscall_no == sys.SYS_EXIT_GROUP) {\n                // exit group: Sets the Exited and ExitCode states to true and argument 0.\n                state.exited = true;\n                state.exitCode = uint8(a0);\n                updateCurrentThreadRoot();\n                return outputState();\n            } else if (syscall_no == sys.SYS_READ) {\n                sys.SysReadParams memory args = sys.SysReadParams({\n                    a0: a0,\n                    a1: a1,\n                    a2: a2,\n                    preimageKey: state.preimageKey,\n                    preimageOffset: state.preimageOffset,\n                    localContext: _localContext,\n                    oracle: ORACLE,\n                    proofOffset: MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1),\n                    memRoot: state.memRoot\n                });\n                (v0, v1, state.preimageOffset, state.memRoot) = sys.handleSysRead(args);\n            } else if (syscall_no == sys.SYS_WRITE) {\n                (v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({\n                    _a0: a0,\n                    _a1: a1,\n                    _a2: a2,\n                    _preimageKey: state.preimageKey,\n                    _preimageOffset: state.preimageOffset,\n                    _proofOffset: MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1),\n                    _memRoot: state.memRoot\n                });\n            } else if (syscall_no == sys.SYS_FCNTL) {\n                (v0, v1) = sys.handleSysFcntl(a0, a1);\n            } else if (syscall_no == sys.SYS_GETTID) {\n                v0 = thread.threadID;\n                v1 = 0;\n            } else if (syscall_no == sys.SYS_EXIT) {\n                thread.exited = true;\n                thread.exitCode = uint8(a0);\n                if (lastThreadRemaining(state)) {\n                    state.exited = true;\n                    state.exitCode = uint8(a0);\n                }\n                updateCurrentThreadRoot();\n                return outputState();\n            } else if (syscall_no == sys.SYS_FUTEX) {\n                // args: a0 = addr, a1 = op, a2 = val, a3 = timeout\n                if (a1 == sys.FUTEX_WAIT_PRIVATE) {\n                    thread.futexAddr = a0;\n                    uint32 mem = MIPSMemory.readMem(\n                        state.memRoot, a0 & 0xFFffFFfc, MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1)\n                    );\n                    if (mem != a2) {\n                        v0 = sys.SYS_ERROR_SIGNAL;\n                        v1 = sys.EAGAIN;\n                    } else {\n                        thread.futexVal = a2;\n                        thread.futexTimeoutStep = a3 == 0 ? sys.FUTEX_NO_TIMEOUT : state.step + sys.FUTEX_TIMEOUT_STEPS;\n                        // Leave cpu scalars as-is. This instruction will be completed by `onWaitComplete`\n                        updateCurrentThreadRoot();\n                        return outputState();\n                    }\n                } else if (a1 == sys.FUTEX_WAKE_PRIVATE) {\n                    // Trigger thread traversal starting from the left stack until we find one waiting on the wakeup\n                    // address\n                    state.wakeup = a0;\n                    // Don't indicate to the program that we've woken up a waiting thread, as there are no guarantees.\n                    // The woken up thread should indicate this in userspace.\n                    v0 = 0;\n                    v1 = 0;\n                    st.CpuScalars memory cpu0 = getCpuScalars(thread);\n                    sys.handleSyscallUpdates(cpu0, thread.registers, v0, v1);\n                    setStateCpuScalars(thread, cpu0);\n                    preemptThread(state, thread);\n                    state.traverseRight = state.leftThreadStack == EMPTY_THREAD_ROOT;\n                    return outputState();\n                } else {\n                    v0 = sys.SYS_ERROR_SIGNAL;\n                    v1 = sys.EINVAL;\n                }\n            } else if (syscall_no == sys.SYS_SCHED_YIELD || syscall_no == sys.SYS_NANOSLEEP) {\n                v0 = 0;\n                v1 = 0;\n                st.CpuScalars memory cpu0 = getCpuScalars(thread);\n                sys.handleSyscallUpdates(cpu0, thread.registers, v0, v1);\n                setStateCpuScalars(thread, cpu0);\n                preemptThread(state, thread);\n                return outputState();\n            } else if (syscall_no == sys.SYS_OPEN) {\n                v0 = sys.SYS_ERROR_SIGNAL;\n                v1 = sys.EBADF;\n            } else if (syscall_no == sys.SYS_CLOCK_GETTIME) {\n                // ignored\n            } else if (syscall_no == sys.SYS_GET_AFFINITY) {\n                // ignored\n            } else if (syscall_no == sys.SYS_MADVISE) {\n                // ignored\n            } else if (syscall_no == sys.SYS_RTSIGPROCMASK) {\n                // ignored\n            } else if (syscall_no == sys.SYS_SIGALTSTACK) {\n                // ignored\n            } else if (syscall_no == sys.SYS_RTSIGACTION) {\n                // ignored\n            } else if (syscall_no == sys.SYS_PRLIMIT64) {\n                // ignored\n            } else if (syscall_no == sys.SYS_CLOSE) {\n                // ignored\n            } else if (syscall_no == sys.SYS_PREAD64) {\n                // ignored\n            } else if (syscall_no == sys.SYS_FSTAT64) {\n                // ignored\n            } else if (syscall_no == sys.SYS_OPENAT) {\n                // ignored\n            } else if (syscall_no == sys.SYS_READLINK) {\n                // ignored\n            } else if (syscall_no == sys.SYS_READLINKAT) {\n                // ignored\n            } else if (syscall_no == sys.SYS_IOCTL) {\n                // ignored\n            } else if (syscall_no == sys.SYS_EPOLLCREATE1) {\n                // ignored\n            } else if (syscall_no == sys.SYS_PIPE2) {\n                // ignored\n            } else if (syscall_no == sys.SYS_EPOLLCTL) {\n                // ignored\n            } else if (syscall_no == sys.SYS_EPOLLPWAIT) {\n                // ignored\n            } else if (syscall_no == sys.SYS_GETRANDOM) {\n                // ignored\n            } else if (syscall_no == sys.SYS_UNAME) {\n                // ignored\n            } else if (syscall_no == sys.SYS_STAT64) {\n                // ignored\n            } else if (syscall_no == sys.SYS_GETUID) {\n                // ignored\n            } else if (syscall_no == sys.SYS_GETGID) {\n                // ignored\n            } else if (syscall_no == sys.SYS_LLSEEK) {\n                // ignored\n            } else if (syscall_no == sys.SYS_MINCORE) {\n                // ignored\n            } else if (syscall_no == sys.SYS_TGKILL) {\n                // ignored\n            } else if (syscall_no == sys.SYS_SETITIMER) {\n                // ignored\n            } else if (syscall_no == sys.SYS_TIMERCREATE) {\n                // ignored\n            } else if (syscall_no == sys.SYS_TIMERSETTIME) {\n                // ignored\n            } else if (syscall_no == sys.SYS_TIMERDELETE) {\n                // ignored\n            } else if (syscall_no == sys.SYS_CLOCKGETTIME) {\n                // ignored\n            } else if (syscall_no == sys.SYS_MUNMAP) {\n                // ignored\n            } else {\n                revert(\"MIPS2: unimplemented syscall\");\n            }\n\n            st.CpuScalars memory cpu = getCpuScalars(thread);\n            sys.handleSyscallUpdates(cpu, thread.registers, v0, v1);\n            setStateCpuScalars(thread, cpu);\n\n            updateCurrentThreadRoot();\n            out_ = outputState();\n        }\n    }\n\n    /// @notice Computes the hash of the MIPS state.\n    /// @return out_ The hashed MIPS state.\n    function outputState() internal returns (bytes32 out_) {\n        assembly {\n        // copies 'size' bytes, right-aligned in word at 'from', to 'to', incl. trailing data\n            function copyMem(from, to, size) -> fromOut, toOut {\n                mstore(to, mload(add(from, sub(32, size))))\n                fromOut := add(from, 32)\n                toOut := add(to, size)\n            }\n\n        // From points to the MIPS State\n            let from := STATE_MEM_OFFSET\n\n        // Copy to the free memory pointer\n            let start := mload(0x40)\n            let to := start\n\n        // Copy state to free memory\n            from, to := copyMem(from, to, 32) // memRoot\n            from, to := copyMem(from, to, 32) // preimageKey\n            from, to := copyMem(from, to, 4) // preimageOffset\n            from, to := copyMem(from, to, 4) // heap\n            let exitCode := mload(from)\n            from, to := copyMem(from, to, 1) // exitCode\n            let exited := mload(from)\n            from, to := copyMem(from, to, 1) // exited\n            from, to := copyMem(from, to, 8) // step\n            from, to := copyMem(from, to, 8) // stepsSinceLastContextSwitch\n            from, to := copyMem(from, to, 4) // wakeup\n            from, to := copyMem(from, to, 1) // traverseRight\n            from, to := copyMem(from, to, 32) // leftThreadStack\n            from, to := copyMem(from, to, 32) // rightThreadStack\n            from, to := copyMem(from, to, 4) // nextThreadID\n\n        // Clean up end of memory\n            mstore(to, 0)\n\n        // Log the resulting MIPS state, for debugging\n            log0(start, sub(to, start))\n\n        // Determine the VM status\n            let status := 0\n            switch exited\n            case 1 {\n                switch exitCode\n                // VMStatusValid\n                case 0 {status := 0}\n                // VMStatusInvalid\n                case 1 {status := 1}\n                // VMStatusPanic\n                default {status := 2}\n            }\n            // VMStatusUnfinished\n            default {status := 3}\n\n        // Compute the hash of the resulting MIPS state and set the status byte\n            out_ := keccak256(start, sub(to, start))\n            out_ := or(and(not(shl(248, 0xFF)), out_), shl(248, status))\n        }\n    }\n\n    /// @notice Updates the current thread stack root via inner thread root in calldata\n    function updateCurrentThreadRoot() internal pure {\n        State memory state;\n        ThreadState memory thread;\n        assembly {\n            state := STATE_MEM_OFFSET\n            thread := TC_MEM_OFFSET\n        }\n        bytes32 updatedRoot = computeThreadRoot(loadCalldataInnerThreadRoot(), thread);\n        if (state.traverseRight) {\n            state.rightThreadStack = updatedRoot;\n        } else {\n            state.leftThreadStack = updatedRoot;\n        }\n    }\n\n    /// @notice Completes the FUTEX_WAIT syscall.\n    function onWaitComplete(\n        State memory _state,\n        ThreadState memory _thread,\n        bool _isTimedOut\n    )\n    internal\n    returns (bytes32 out_)\n    {\n        // Clear the futex state\n        _thread.futexAddr = sys.FUTEX_EMPTY_ADDR;\n        _thread.futexVal = 0;\n        _thread.futexTimeoutStep = 0;\n\n        // Complete the FUTEX_WAIT syscall\n        uint32 v0 = _isTimedOut ? sys.SYS_ERROR_SIGNAL : 0;\n        // set errno\n        uint32 v1 = _isTimedOut ? sys.ETIMEDOUT : 0;\n        st.CpuScalars memory cpu = getCpuScalars(_thread);\n        sys.handleSyscallUpdates(cpu, _thread.registers, v0, v1);\n        setStateCpuScalars(_thread, cpu);\n\n        _state.wakeup = sys.FUTEX_EMPTY_ADDR;\n        updateCurrentThreadRoot();\n        out_ = outputState();\n    }\n\n    /// @notice Preempts the current thread for another and updates the VM state.\n    ///         It reads the inner thread root from calldata to update the current thread stack root.\n    function preemptThread(\n        State memory _state,\n        ThreadState memory _thread\n    )\n    internal\n    pure\n    returns (bool _changedDirections)\n    {\n        // pop thread from the current stack and push to the other stack\n        if (_state.traverseRight) {\n            require(_state.rightThreadStack != EMPTY_THREAD_ROOT, \"empty right thread stack\");\n            _state.rightThreadStack = loadCalldataInnerThreadRoot();\n            _state.leftThreadStack = computeThreadRoot(_state.leftThreadStack, _thread);\n        } else {\n            require(_state.leftThreadStack != EMPTY_THREAD_ROOT, \"empty left thread stack\");\n            _state.leftThreadStack = loadCalldataInnerThreadRoot();\n            _state.rightThreadStack = computeThreadRoot(_state.rightThreadStack, _thread);\n        }\n        bytes32 current = _state.traverseRight ? _state.rightThreadStack : _state.leftThreadStack;\n        if (current == EMPTY_THREAD_ROOT) {\n            _state.traverseRight = !_state.traverseRight;\n            _changedDirections = true;\n        }\n        _state.stepsSinceLastContextSwitch = 0;\n    }\n\n    /// @notice Pushes a thread to the current thread stack.\n    function pushThread(State memory _state, ThreadState memory _thread) internal pure {\n        if (_state.traverseRight) {\n            _state.rightThreadStack = computeThreadRoot(_state.rightThreadStack, _thread);\n        } else {\n            _state.leftThreadStack = computeThreadRoot(_state.leftThreadStack, _thread);\n        }\n        _state.stepsSinceLastContextSwitch = 0;\n    }\n\n    /// @notice Removes the current thread from the stack.\n    function popThread(State memory _state) internal pure {\n        if (_state.traverseRight) {\n            _state.rightThreadStack = loadCalldataInnerThreadRoot();\n        } else {\n            _state.leftThreadStack = loadCalldataInnerThreadRoot();\n        }\n        bytes32 current = _state.traverseRight ? _state.rightThreadStack : _state.leftThreadStack;\n        if (current == EMPTY_THREAD_ROOT) {\n            _state.traverseRight = !_state.traverseRight;\n        }\n        _state.stepsSinceLastContextSwitch = 0;\n    }\n\n    /// @notice Returns true if the number of threads is 1\n    function lastThreadRemaining(State memory _state) internal pure returns (bool out_) {\n        bytes32 inactiveStack = _state.traverseRight ? _state.leftThreadStack : _state.rightThreadStack;\n        bool currentStackIsAlmostEmpty = loadCalldataInnerThreadRoot() == EMPTY_THREAD_ROOT;\n        return inactiveStack == EMPTY_THREAD_ROOT && currentStackIsAlmostEmpty;\n    }\n\n    function computeThreadRoot(bytes32 _currentRoot, ThreadState memory _thread) internal pure returns (bytes32 _out) {\n        // w_i = hash(w_0 ++ hash(thread))\n        bytes32 threadRoot = outputThreadState(_thread);\n        _out = keccak256(abi.encodePacked(_currentRoot, threadRoot));\n    }\n\n    function outputThreadState(ThreadState memory _thread) internal pure returns (bytes32 out_) {\n        assembly {\n        // copies 'size' bytes, right-aligned in word at 'from', to 'to', incl. trailing data\n            function copyMem(from, to, size) -> fromOut, toOut {\n                mstore(to, mload(add(from, sub(32, size))))\n                fromOut := add(from, 32)\n                toOut := add(to, size)\n            }\n\n        // From points to the ThreadState\n            let from := _thread\n\n        // Copy to the free memory pointer\n            let start := mload(0x40)\n            let to := start\n\n        // Copy state to free memory\n            from, to := copyMem(from, to, 4) // threadID\n            from, to := copyMem(from, to, 1) // exitCode\n            from, to := copyMem(from, to, 1) // exited\n            from, to := copyMem(from, to, 4) // futexAddr\n            from, to := copyMem(from, to, 4) // futexVal\n            from, to := copyMem(from, to, 8) // futexTimeoutStep\n            from, to := copyMem(from, to, 4) // pc\n            from, to := copyMem(from, to, 4) // nextPC\n            from, to := copyMem(from, to, 4) // lo\n            from, to := copyMem(from, to, 4) // hi\n            from := mload(from) // offset to registers\n        // Copy registers\n            for {let i := 0} lt(i, 32) {i := add(i, 1)} {from, to := copyMem(from, to, 4)}\n\n        // Clean up end of memory\n            mstore(to, 0)\n\n        // Compute the hash of the resulting ThreadState\n            out_ := keccak256(start, sub(to, start))\n        }\n    }\n\n    function getCpuScalars(ThreadState memory _tc) internal pure returns (st.CpuScalars memory cpu_) {\n        cpu_ = st.CpuScalars({pc: _tc.pc, nextPC: _tc.nextPC, lo: _tc.lo, hi: _tc.hi});\n    }\n\n    function setStateCpuScalars(ThreadState memory _tc, st.CpuScalars memory _cpu) internal pure {\n        _tc.pc = _cpu.pc;\n        _tc.nextPC = _cpu.nextPC;\n        _tc.lo = _cpu.lo;\n        _tc.hi = _cpu.hi;\n    }\n\n    /// @notice Validates the thread witness in calldata against the current thread.\n    function validateCalldataThreadWitness(State memory _state, ThreadState memory _thread) internal pure {\n        bytes32 witnessRoot = computeThreadRoot(loadCalldataInnerThreadRoot(), _thread);\n        bytes32 expectedRoot = _state.traverseRight ? _state.rightThreadStack : _state.leftThreadStack;\n        require(expectedRoot == witnessRoot, \"invalid thread witness\");\n    }\n\n    /// @notice Sets the thread context from calldata.\n    function setThreadStateFromCalldata(ThreadState memory _thread) internal pure {\n        uint256 s = 0;\n        assembly {\n            s := calldatasize()\n        }\n        // verify we have enough calldata\n        require(s >= (THREAD_PROOF_OFFSET + 166), \"insufficient calldata for thread witness\");\n\n        unchecked {\n            assembly {\n                function putField(callOffset, memOffset, size) -> callOffsetOut, memOffsetOut {\n                // calldata is packed, thus starting left-aligned, shift-right to pad and right-align\n                    let w := shr(shl(3, sub(32, size)), calldataload(callOffset))\n                    mstore(memOffset, w)\n                    callOffsetOut := add(callOffset, size)\n                    memOffsetOut := add(memOffset, 32)\n                }\n\n                let c := THREAD_PROOF_OFFSET\n                let m := _thread\n                c, m := putField(c, m, 4) // threadID\n                c, m := putField(c, m, 1) // exitCode\n                c, m := putField(c, m, 1) // exited\n                c, m := putField(c, m, 4) // futexAddr\n                c, m := putField(c, m, 4) // futexVal\n                c, m := putField(c, m, 8) // futexTimeoutStep\n                c, m := putField(c, m, 4) // pc\n                c, m := putField(c, m, 4) // nextPC\n                c, m := putField(c, m, 4) // lo\n                c, m := putField(c, m, 4) // hi\n                m := mload(m) // offset to registers\n            // Unpack register calldata into memory\n                for {let i := 0} lt(i, 32) {i := add(i, 1)} {c, m := putField(c, m, 4)}\n            }\n        }\n    }\n\n    /// @notice Loads the inner root for the current thread hash onion from calldata.\n    function loadCalldataInnerThreadRoot() internal pure returns (bytes32 innerThreadRoot_) {\n        uint256 s = 0;\n        assembly {\n            s := calldatasize()\n            innerThreadRoot_ := calldataload(add(THREAD_PROOF_OFFSET, 166))\n        }\n        // verify we have enough calldata\n        require(s >= (THREAD_PROOF_OFFSET + 198), \"insufficient calldata for thread witness\"); // 166 + 32\n    }\n}\n"
    },
    "contracts/L1/cannon/PreimageKeyLib.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/// @title PreimageKeyLib\n/// @notice Shared utilities for localizing local keys in the preimage oracle.\nlibrary PreimageKeyLib {\n    /// @notice Generates a context-specific local key for the given local data identifier.\n    /// @dev See `localize` for a description of the localization operation.\n    /// @param _ident The identifier of the local data. [0, 32) bytes in size.\n    /// @param _localContext The local context for the key.\n    /// @return key_ The context-specific local key.\n    function localizeIdent(uint256 _ident, bytes32 _localContext) internal view returns (bytes32 key_) {\n        assembly {\n        // Set the type byte in the given identifier to `1` (Local). We only care about\n        // the [1, 32) bytes in this value.\n            key_ := or(shl(248, 1), and(_ident, not(shl(248, 0xFF))))\n        }\n        // Localize the key with the given local context.\n        key_ = localize(key_, _localContext);\n    }\n\n    /// @notice Localizes a given local data key for the caller's context.\n    /// @dev The localization operation is defined as:\n    ///      localize(k) = H(k .. sender .. local_context) & ~(0xFF << 248) | (0x01 << 248)\n    ///      where H is the Keccak-256 hash function.\n    /// @param _key The local data key to localize.\n    /// @param _localContext The local context for the key.\n    /// @return localizedKey_ The localized local data key.\n    function localize(bytes32 _key, bytes32 _localContext) internal view returns (bytes32 localizedKey_) {\n        assembly {\n        // Grab the current free memory pointer to restore later.\n            let ptr := mload(0x40)\n        // Store the local data key and caller next to each other in memory for hashing.\n            mstore(0, _key)\n            mstore(0x20, caller())\n            mstore(0x40, _localContext)\n        // Localize the key with the above `localize` operation.\n            localizedKey_ := or(and(keccak256(0, 0x60), not(shl(248, 0xFF))), shl(248, 1))\n        // Restore the free memory pointer.\n            mstore(0x40, ptr)\n        }\n    }\n\n    /// @notice Computes and returns the key for a global keccak pre-image.\n    /// @param _preimage The pre-image.\n    /// @return key_ The pre-image key.\n    function keccak256PreimageKey(bytes memory _preimage) internal pure returns (bytes32 key_) {\n        assembly {\n        // Grab the size of the `_preimage`\n            let size := mload(_preimage)\n\n        // Compute the pre-image keccak256 hash (aka the pre-image key)\n            let h := keccak256(add(_preimage, 0x20), size)\n\n        // Mask out prefix byte, replace with type 2 byte\n            key_ := or(and(h, not(shl(248, 0xFF))), shl(248, 2))\n        }\n    }\n}\n"
    },
    "contracts/L1/cannon/PreimageOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {IPreimageOracle} from \"./interfaces/IPreimageOracle.sol\";\nimport {ISemver} from \"contracts/universal/ISemver.sol\";\nimport {PreimageKeyLib} from \"./PreimageKeyLib.sol\";\nimport {LibKeccak} from \"contracts/libraries/crypto/LibKeccak.sol\";\nimport \"contracts/L1/cannon/libraries/CannonErrors.sol\";\nimport \"contracts/L1/cannon/libraries/CannonTypes.sol\";\n\n/// @title PreimageOracle\n/// @notice A contract for storing permissioned pre-images.\n/// @custom:attribution Solady <https://github.com/Vectorized/solady/blob/main/src/utils/MerkleProofLib.sol#L13-L43>\n/// @custom:attribution Beacon Deposit Contract <0x00000000219ab540356cbb839cbe05303d7705fa>\ncontract PreimageOracle is IPreimageOracle, ISemver {\n    ////////////////////////////////////////////////////////////////\n    //                   Constants & Immutables                   //\n    ////////////////////////////////////////////////////////////////\n\n    /// @notice The duration of the large preimage proposal challenge period.\n    uint256 internal immutable CHALLENGE_PERIOD;\n    /// @notice The minimum size of a preimage that can be proposed in the large preimage path.\n    uint256 internal immutable MIN_LPP_SIZE_BYTES;\n    /// @notice The minimum bond size for large preimage proposals.\n    uint256 public constant MIN_BOND_SIZE = 0.25 ether;\n    /// @notice The depth of the keccak256 merkle tree. Supports up to 65,536 keccak blocks, or ~8.91MB preimages.\n    uint256 public constant KECCAK_TREE_DEPTH = 16;\n    /// @notice The maximum number of keccak blocks that can fit into the merkle tree.\n    uint256 public constant MAX_LEAF_COUNT = 2 ** KECCAK_TREE_DEPTH - 1;\n    /// @notice The reserved gas for precompile call setup.\n    uint256 public constant PRECOMPILE_CALL_RESERVED_GAS = 100_000;\n\n    /// @notice The semantic version of the Preimage Oracle contract.\n    /// @custom:semver 1.1.2-rc.1\n    string public constant version = \"1.1.2-rc.1\";\n\n    ////////////////////////////////////////////////////////////////\n    //                 Authorized Preimage Parts                  //\n    ////////////////////////////////////////////////////////////////\n\n    /// @notice Mapping of pre-image keys to pre-image lengths.\n    mapping(bytes32 => uint256) public preimageLengths;\n    /// @notice Mapping of pre-image keys to pre-image offsets to pre-image parts.\n    mapping(bytes32 => mapping(uint256 => bytes32)) public preimageParts;\n    /// @notice Mapping of pre-image keys to pre-image part offsets to preimage preparedness.\n    mapping(bytes32 => mapping(uint256 => bool)) public preimagePartOk;\n\n    ////////////////////////////////////////////////////////////////\n    //                  Large Preimage Proposals                  //\n    ////////////////////////////////////////////////////////////////\n\n    /// @notice A raw leaf of the large preimage proposal merkle tree.\n    struct Leaf {\n        /// @notice The input absorbed for the block, exactly 136 bytes.\n        bytes input;\n        /// @notice The index of the block in the absorption process.\n        uint256 index;\n        /// @notice The hash of the internal state after absorbing the input.\n        bytes32 stateCommitment;\n    }\n\n    /// @notice Unpacked keys for large preimage proposals.\n    struct LargePreimageProposalKeys {\n        /// @notice The claimant of the large preimage proposal.\n        address claimant;\n        /// @notice The UUID of the large preimage proposal.\n        uint256 uuid;\n    }\n\n    /// @notice Static padding hashes. These values are persisted in storage, but are entirely immutable\n    ///         after the constructor's execution.\n    bytes32[KECCAK_TREE_DEPTH] public zeroHashes;\n    /// @notice Append-only array of large preimage proposals for off-chain reference.\n    LargePreimageProposalKeys[] public proposals;\n    /// @notice Mapping of claimants to proposal UUIDs to the current branch path of the merkleization process.\n    mapping(address => mapping(uint256 => bytes32[KECCAK_TREE_DEPTH])) public proposalBranches;\n    /// @notice Mapping of claimants to proposal UUIDs to the timestamp of creation of the proposal as well as the\n    /// challenged status.\n    mapping(address => mapping(uint256 => LPPMetaData)) public proposalMetadata;\n    /// @notice Mapping of claimants to proposal UUIDs to bond amounts.\n    mapping(address => mapping(uint256 => uint256)) public proposalBonds;\n    /// @notice Mapping of claimants to proposal UUIDs to the preimage part picked up during the absorbtion process.\n    mapping(address => mapping(uint256 => bytes32)) public proposalParts;\n    /// @notice Mapping of claimants to proposal UUIDs to blocks which leaves were added to the merkle tree.\n    mapping(address => mapping(uint256 => uint64[])) public proposalBlocks;\n\n    ////////////////////////////////////////////////////////////////\n    //                        Constructor                         //\n    ////////////////////////////////////////////////////////////////\n\n    constructor(uint256 _minProposalSize, uint256 _challengePeriod) {\n        MIN_LPP_SIZE_BYTES = _minProposalSize;\n        CHALLENGE_PERIOD = _challengePeriod;\n\n        // Make sure challenge period fits within uint64 so that it can safely be used within the\n        // FaultDisputeGame contract to compute clock extensions. Adding this check is simpler than\n        // changing the existing contract ABI.\n        require(_challengePeriod <= type(uint64).max, \"challenge period too large\");\n\n        // Compute hashes in empty sparse Merkle tree. The first hash is not set, and kept as zero as the identity.\n        for (uint256 height = 0; height < KECCAK_TREE_DEPTH - 1; height++) {\n            zeroHashes[height + 1] = keccak256(abi.encodePacked(zeroHashes[height], zeroHashes[height]));\n        }\n    }\n\n    ////////////////////////////////////////////////////////////////\n    //             Standard Preimage Route (External)             //\n    ////////////////////////////////////////////////////////////////\n\n    /// @inheritdoc IPreimageOracle\n    function readPreimage(bytes32 _key, uint256 _offset) external view returns (bytes32 dat_, uint256 datLen_) {\n        require(preimagePartOk[_key][_offset], \"pre-image must exist\");\n\n        // Calculate the length of the pre-image data\n        // Add 8 for the length-prefix part\n        datLen_ = 32;\n        uint256 length = preimageLengths[_key];\n        if (_offset + 32 >= length + 8) {\n            datLen_ = length + 8 - _offset;\n        }\n\n        // Retrieve the pre-image data\n        dat_ = preimageParts[_key][_offset];\n    }\n\n    /// @inheritdoc IPreimageOracle\n    function loadLocalData(\n        uint256 _ident,\n        bytes32 _localContext,\n        bytes32 _word,\n        uint256 _size,\n        uint256 _partOffset\n    )\n    external\n    returns (bytes32 key_)\n    {\n        // Compute the localized key from the given local identifier.\n        key_ = PreimageKeyLib.localizeIdent(_ident, _localContext);\n\n        // Revert if the given part offset is not within bounds.\n        if (_partOffset >= _size + 8 || _size > 32) {\n            revert PartOffsetOOB();\n        }\n\n        // Prepare the local data part at the given offset\n        bytes32 part;\n        assembly {\n        // Clean the memory in [0x20, 0x40)\n            mstore(0x20, 0x00)\n\n        // Store the full local data in scratch space.\n            mstore(0x00, shl(192, _size))\n            mstore(0x08, _word)\n\n        // Prepare the local data part at the requested offset.\n            part := mload(_partOffset)\n        }\n\n        // Store the first part with `_partOffset`.\n        preimagePartOk[key_][_partOffset] = true;\n        preimageParts[key_][_partOffset] = part;\n        // Assign the length of the preimage at the localized key.\n        preimageLengths[key_] = _size;\n    }\n\n    /// @inheritdoc IPreimageOracle\n    function loadKeccak256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external {\n        uint256 size;\n        bytes32 key;\n        bytes32 part;\n        assembly {\n        // len(sig) + len(partOffset) + len(preimage offset) = 4 + 32 + 32 = 0x44\n            size := calldataload(0x44)\n\n        // revert if part offset >= size+8 (i.e. parts must be within bounds)\n            if iszero(lt(_partOffset, add(size, 8))) {\n            // Store \"PartOffsetOOB()\"\n                mstore(0x00, 0xfe254987)\n            // Revert with \"PartOffsetOOB()\"\n                revert(0x1c, 0x04)\n            }\n        // we leave solidity slots 0x40 and 0x60 untouched, and everything after as scratch-memory.\n            let ptr := 0x80\n        // put size as big-endian uint64 at start of pre-image\n            mstore(ptr, shl(192, size))\n            ptr := add(ptr, 0x08)\n        // copy preimage payload into memory so we can hash and read it.\n            calldatacopy(ptr, _preimage.offset, size)\n        // Note that it includes the 8-byte big-endian uint64 length prefix.\n        // this will be zero-padded at the end, since memory at end is clean.\n            part := mload(add(sub(ptr, 0x08), _partOffset))\n            let h := keccak256(ptr, size) // compute preimage keccak256 hash\n        // mask out prefix byte, replace with type 2 byte\n            key := or(and(h, not(shl(248, 0xFF))), shl(248, 0x02))\n        }\n        preimagePartOk[key][_partOffset] = true;\n        preimageParts[key][_partOffset] = part;\n        preimageLengths[key] = size;\n    }\n\n    /// @inheritdoc IPreimageOracle\n    function loadSha256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external {\n        uint256 size;\n        bytes32 key;\n        bytes32 part;\n        assembly {\n        // len(sig) + len(partOffset) + len(preimage offset) = 4 + 32 + 32 = 0x44\n            size := calldataload(0x44)\n\n        // revert if part offset >= size+8 (i.e. parts must be within bounds)\n            if iszero(lt(_partOffset, add(size, 8))) {\n            // Store \"PartOffsetOOB()\"\n                mstore(0, 0xfe254987)\n            // Revert with \"PartOffsetOOB()\"\n                revert(0x1c, 4)\n            }\n        // we leave solidity slots 0x40 and 0x60 untouched,\n        // and everything after as scratch-memory.\n            let ptr := 0x80\n        // put size as big-endian uint64 at start of pre-image\n            mstore(ptr, shl(192, size))\n            ptr := add(ptr, 8)\n        // copy preimage payload into memory so we can hash and read it.\n            calldatacopy(ptr, _preimage.offset, size)\n        // Note that it includes the 8-byte big-endian uint64 length prefix.\n        // this will be zero-padded at the end, since memory at end is clean.\n            part := mload(add(sub(ptr, 8), _partOffset))\n\n        // compute SHA2-256 hash with pre-compile\n            let success :=\n            staticcall(\n                gas(), // Forward all available gas\n                0x02, // Address of SHA-256 precompile\n                ptr, // Start of input data in memory\n                size, // Size of input data\n                0, // Store output in scratch memory\n                0x20 // Output is always 32 bytes\n            )\n        // Check if the staticcall succeeded\n            if iszero(success) {revert(0, 0)}\n            let h := mload(0) // get return data\n        // mask out prefix byte, replace with type 4 byte\n            key := or(and(h, not(shl(248, 0xFF))), shl(248, 4))\n        }\n        preimagePartOk[key][_partOffset] = true;\n        preimageParts[key][_partOffset] = part;\n        preimageLengths[key] = size;\n    }\n\n    /// @inheritdoc IPreimageOracle\n    function loadBlobPreimagePart(\n        uint256 _z,\n        uint256 _y,\n        bytes calldata _commitment,\n        bytes calldata _proof,\n        uint256 _partOffset\n    )\n    external\n    {\n        bytes32 key;\n        bytes32 part;\n        assembly {\n        // Compute the versioned hash. The SHA2 hash of the 48 byte commitment is masked with the version byte,\n        // which is currently 1. https://eips.ethereum.org/EIPS/eip-4844#parameters\n        // SAFETY: We're only reading 48 bytes from `_commitment` into scratch space, so we're not reading into the\n        //         free memory ptr region. Since the exact number of btyes that is copied into scratch space is\n        //         the same size as the hash input, there's no concern of dirty memory being read into the hash\n        //         input.\n            calldatacopy(0x00, _commitment.offset, 0x30)\n            let success := staticcall(gas(), 0x02, 0x00, 0x30, 0x00, 0x20)\n            if iszero(success) {\n            // Store the \"ShaFailed()\" error selector.\n                mstore(0x00, 0xf9112969)\n            // revert with \"ShaFailed()\"\n                revert(0x1C, 0x04)\n            }\n        // Set the `VERSIONED_HASH_VERSION_KZG` byte = 1 in the high-order byte of the hash.\n            let versionedHash := or(and(mload(0x00), not(shl(248, 0xFF))), shl(248, 0x01))\n\n        // we leave solidity slots 0x40 and 0x60 untouched, and everything after as scratch-memory.\n            let ptr := 0x80\n\n        // Load the inputs for the point evaluation precompile into memory. The inputs to the point evaluation\n        // precompile are packed, and not supposed to be ABI-encoded.\n            mstore(ptr, versionedHash)\n            mstore(add(ptr, 0x20), _z)\n            mstore(add(ptr, 0x40), _y)\n            calldatacopy(add(ptr, 0x60), _commitment.offset, 0x30)\n            calldatacopy(add(ptr, 0x90), _proof.offset, 0x30)\n\n        // Verify the KZG proof by calling the point evaluation precompile. If the proof is invalid, the precompile\n        // will revert.\n            success :=\n            staticcall(\n                gas(), // forward all gas\n                0x0A, // point evaluation precompile address\n                ptr, // input ptr\n                0xC0, // input size = 192 bytes\n                0x00, // output ptr\n                0x00 // output size\n            )\n            if iszero(success) {\n            // Store the \"InvalidProof()\" error selector.\n                mstore(0x00, 0x09bde339)\n            // revert with \"InvalidProof()\"\n                revert(0x1C, 0x04)\n            }\n\n        // revert if part offset >= 32+8 (i.e. parts must be within bounds)\n            if iszero(lt(_partOffset, 0x28)) {\n            // Store \"PartOffsetOOB()\"\n                mstore(0x00, 0xfe254987)\n            // Revert with \"PartOffsetOOB()\"\n                revert(0x1C, 0x04)\n            }\n        // Clean the word at `ptr + 0x28` to ensure that data out of bounds of the preimage is zero, if the part\n        // offset requires a partial read.\n            mstore(add(ptr, 0x28), 0x00)\n        // put size (32) as a big-endian uint64 at start of pre-image\n            mstore(ptr, shl(192, 0x20))\n        // copy preimage payload into memory so we can hash and read it.\n            mstore(add(ptr, 0x08), _y)\n        // Note that it includes the 8-byte big-endian uint64 length prefix. This will be zero-padded at the end,\n        // since memory at end is guaranteed to be clean.\n            part := mload(add(ptr, _partOffset))\n\n        // Compute the key: `keccak256(commitment ++ z)`. Since the exact number of btyes that is copied into\n        // scratch space is the same size as the hash input, there's no concern of dirty memory being read into\n        // the hash input.\n            calldatacopy(ptr, _commitment.offset, 0x30)\n            mstore(add(ptr, 0x30), _z)\n            let h := keccak256(ptr, 0x50)\n        // mask out prefix byte, replace with type 5 byte\n            key := or(and(h, not(shl(248, 0xFF))), shl(248, 0x05))\n        }\n        preimagePartOk[key][_partOffset] = true;\n        preimageParts[key][_partOffset] = part;\n        preimageLengths[key] = 32;\n    }\n\n    /// @inheritdoc IPreimageOracle\n    function loadPrecompilePreimagePart(\n        uint256 _partOffset,\n        address _precompile,\n        uint64 _requiredGas,\n        bytes calldata _input\n    )\n    external\n    {\n        bytes32 res;\n        bytes32 key;\n        bytes32 part;\n        uint256 size;\n        assembly {\n        // we leave solidity slots 0x40 and 0x60 untouched, and everything after as scratch-memory.\n            let ptr := 0x80\n\n        // copy precompile address, requiredGas, and input into memory to compute the key\n            mstore(ptr, shl(96, _precompile))\n            mstore(add(ptr, 20), shl(192, _requiredGas))\n            calldatacopy(add(28, ptr), _input.offset, _input.length)\n        // compute the hash\n            let h := keccak256(ptr, add(28, _input.length))\n        // mask out prefix byte, replace with type 6 byte\n            key := or(and(h, not(shl(248, 0xFF))), shl(248, 0x06))\n\n        // Check if the precompile call has at least the required gas.\n        // This assumes there are no further memory expansion costs until after the staticall on the precompile\n        // Also assumes that the gas expended in setting up the staticcall is less than PRECOMPILE_CALL_RESERVED_GAS\n        // require(gas() >= (requiredGas * 64 / 63) + reservedGas)\n            if lt(mul(gas(), 63), add(mul(_requiredGas, 64), mul(PRECOMPILE_CALL_RESERVED_GAS, 63))) {\n            // Store \"NotEnoughGas()\"\n                mstore(0, 0xdd629f86)\n                revert(0x1c, 4)\n            }\n\n        // Call the precompile to get the result.\n        // SAFETY: Given the above gas check, the staticall cannot fail due to insufficient gas.\n            res :=\n            staticcall(\n                gas(), // forward all gas\n                _precompile,\n                add(28, ptr), // input ptr\n                _input.length,\n                0x0, // Unused as we don't copy anything\n                0x00 // don't copy anything\n            )\n\n            size := add(1, returndatasize())\n        // revert if part offset >= size+8 (i.e. parts must be within bounds)\n            if iszero(lt(_partOffset, add(size, 8))) {\n            // Store \"PartOffsetOOB()\"\n                mstore(0, 0xfe254987)\n            // Revert with \"PartOffsetOOB()\"\n                revert(0x1c, 4)\n            }\n\n        // Reuse the `ptr` to store the preimage part: <sizePrefix ++ precompileStatus ++ returrnData>\n        // put size as big-endian uint64 at start of pre-image\n            mstore(ptr, shl(192, size))\n            ptr := add(ptr, 0x08)\n\n        // write precompile result status to the first byte of `ptr`\n            mstore8(ptr, res)\n        // write precompile return data to the rest of `ptr`\n            returndatacopy(add(ptr, 0x01), 0x0, returndatasize())\n\n        // compute part given ofset\n            part := mload(add(sub(ptr, 0x08), _partOffset))\n        }\n        preimagePartOk[key][_partOffset] = true;\n        preimageParts[key][_partOffset] = part;\n        preimageLengths[key] = size;\n    }\n\n    ////////////////////////////////////////////////////////////////\n    //            Large Preimage Proposals (External)             //\n    ////////////////////////////////////////////////////////////////\n\n    /// @notice Returns the length of the `proposals` array\n    function proposalCount() external view returns (uint256 count_) {\n        count_ = proposals.length;\n    }\n\n    /// @notice Returns the length of the array with the block numbers of `addLeavesLPP` calls for a given large\n    ///         preimage proposal.\n    function proposalBlocksLen(address _claimant, uint256 _uuid) external view returns (uint256 len_) {\n        len_ = proposalBlocks[_claimant][_uuid].length;\n    }\n\n    /// @notice Returns the length of the large preimage proposal challenge period.\n    function challengePeriod() external view returns (uint256 challengePeriod_) {\n        challengePeriod_ = CHALLENGE_PERIOD;\n    }\n\n    /// @notice Returns the minimum size (in bytes) of a large preimage proposal.\n    function minProposalSize() external view returns (uint256 minProposalSize_) {\n        minProposalSize_ = MIN_LPP_SIZE_BYTES;\n    }\n\n    /// @notice Initialize a large preimage proposal. Must be called before adding any leaves.\n    function initLPP(uint256 _uuid, uint32 _partOffset, uint32 _claimedSize) external payable {\n        // The bond provided must be at least `MIN_BOND_SIZE`.\n        if (msg.value < MIN_BOND_SIZE) revert InsufficientBond();\n\n        // The caller of `addLeavesLPP` must be an EOA, so that the call inputs are always available in block bodies.\n        if (msg.sender != tx.origin) revert NotEOA();\n\n        // The part offset must be within the bounds of the claimed size + 8.\n        if (_partOffset >= _claimedSize + 8) revert PartOffsetOOB();\n\n        // The claimed size must be at least `MIN_LPP_SIZE_BYTES`.\n        if (_claimedSize < MIN_LPP_SIZE_BYTES) revert InvalidInputSize();\n\n        // Initialize the proposal metadata.\n        LPPMetaData metaData = proposalMetadata[msg.sender][_uuid];\n\n        // Revert if the proposal has already been initialized. 0-size preimages are *not* allowed.\n        if (metaData.claimedSize() != 0) revert AlreadyInitialized();\n\n        proposalMetadata[msg.sender][_uuid] = metaData.setPartOffset(_partOffset).setClaimedSize(_claimedSize);\n        proposals.push(LargePreimageProposalKeys(msg.sender, _uuid));\n\n        // Assign the bond to the proposal.\n        proposalBonds[msg.sender][_uuid] = msg.value;\n    }\n\n    /// @notice Adds a contiguous list of keccak state matrices to the merkle tree.\n    function addLeavesLPP(\n        uint256 _uuid,\n        uint256 _inputStartBlock,\n        bytes calldata _input,\n        bytes32[] calldata _stateCommitments,\n        bool _finalize\n    )\n    external\n    {\n        // If we're finalizing, pad the input for the submitter. If not, copy the input into memory verbatim.\n        bytes memory input;\n        if (_finalize) {\n            input = LibKeccak.pad(_input);\n        } else {\n            input = _input;\n        }\n\n        // Pull storage variables onto the stack / into memory for operations.\n        bytes32[KECCAK_TREE_DEPTH] memory branch = proposalBranches[msg.sender][_uuid];\n        LPPMetaData metaData = proposalMetadata[msg.sender][_uuid];\n        uint256 blocksProcessed = metaData.blocksProcessed();\n\n        // The caller of `addLeavesLPP` must be an EOA.\n        // Note: This check may break if EIPs like EIP-3074 are introduced. We may query the data in the logs if this\n        // is the case.\n        if (msg.sender != tx.origin) revert NotEOA();\n\n        // Revert if the proposal has not been initialized. 0-size preimages are *not* allowed.\n        if (metaData.claimedSize() == 0) revert NotInitialized();\n\n        // Revert if the proposal has already been finalized. No leaves can be added after this point.\n        if (metaData.timestamp() != 0) revert AlreadyFinalized();\n\n        // Revert if the starting block is not the next block to be added. This is to aid submitters in ensuring that\n        // they don't corrupt an in-progress proposal by submitting input out of order.\n        if (blocksProcessed != _inputStartBlock) revert WrongStartingBlock();\n\n        // Attempt to extract the preimage part from the input data, if the part offset is present in the current\n        // chunk of input. This function has side effects, and will persist the preimage part to the caller's large\n        // preimage proposal storage if the part offset is present in the input data.\n        _extractPreimagePart(_input, _uuid, _finalize, metaData);\n\n        assembly {\n            let inputLen := mload(input)\n            let inputPtr := add(input, 0x20)\n\n        // The input length must be a multiple of 136 bytes\n        // The input length / 136 must be equal to the number of state commitments.\n            if or(mod(inputLen, 136), iszero(eq(_stateCommitments.length, div(inputLen, 136)))) {\n            // Store \"InvalidInputSize()\" error selector\n                mstore(0x00, 0x7b1daf1)\n                revert(0x1C, 0x04)\n            }\n\n        // Allocate a hashing buffer the size of the leaf preimage.\n            let hashBuf := mload(0x40)\n            mstore(0x40, add(hashBuf, 0xC8))\n\n            for {let i := 0} lt(i, inputLen) {i := add(i, 136)} {\n            // Copy the leaf preimage into the hashing buffer.\n                let inputStartPtr := add(inputPtr, i)\n                mstore(hashBuf, mload(inputStartPtr))\n                mstore(add(hashBuf, 0x20), mload(add(inputStartPtr, 0x20)))\n                mstore(add(hashBuf, 0x40), mload(add(inputStartPtr, 0x40)))\n                mstore(add(hashBuf, 0x60), mload(add(inputStartPtr, 0x60)))\n                mstore(add(hashBuf, 0x80), mload(add(inputStartPtr, 0x80)))\n                mstore(add(hashBuf, 136), blocksProcessed)\n                mstore(add(hashBuf, 168), calldataload(add(_stateCommitments.offset, shl(0x05, div(i, 136)))))\n\n            // Hash the leaf preimage to get the node to add.\n                let node := keccak256(hashBuf, 0xC8)\n\n            // Increment the number of blocks processed.\n                blocksProcessed := add(blocksProcessed, 0x01)\n\n            // Add the node to the tree.\n                let size := blocksProcessed\n                for {let height := 0x00} lt(height, shl(0x05, KECCAK_TREE_DEPTH)) {height := add(height, 0x20)} {\n                    if and(size, 0x01) {\n                        mstore(add(branch, height), node)\n                        break\n                    }\n\n                // Hash the node at `height` in the branch and the node together.\n                    mstore(0x00, mload(add(branch, height)))\n                    mstore(0x20, node)\n                    node := keccak256(0x00, 0x40)\n                    size := shr(0x01, size)\n                }\n            }\n        }\n\n        // Do not allow for posting preimages larger than the merkle tree can support. The incremental merkle tree\n        // algorithm only supports 2**height - 1 leaves, the right most leaf must always be kept empty.\n        // Reference: https://daejunpark.github.io/papers/deposit.pdf - Page 10, Section 5.1.\n        if (blocksProcessed > MAX_LEAF_COUNT) revert TreeSizeOverflow();\n\n        // Update the proposal metadata to include the number of blocks processed and total bytes processed.\n        metaData = metaData.setBlocksProcessed(uint32(blocksProcessed)).setBytesProcessed(\n            uint32(_input.length + metaData.bytesProcessed())\n        );\n        // If the proposal is being finalized, set the timestamp to the current block timestamp. This begins the\n        // challenge period, which must be waited out before the proposal can be finalized.\n        if (_finalize) {\n            metaData = metaData.setTimestamp(uint64(block.timestamp));\n\n            // If the number of bytes processed is not equal to the claimed size, the proposal cannot be finalized.\n            if (metaData.bytesProcessed() != metaData.claimedSize()) revert InvalidInputSize();\n        }\n\n        // Perist the latest branch to storage.\n        proposalBranches[msg.sender][_uuid] = branch;\n        // Persist the block number that these leaves were added in. This assists off-chain observers in reconstructing\n        // the proposal merkle tree by querying block bodies.\n        proposalBlocks[msg.sender][_uuid].push(uint64(block.number));\n        // Persist the updated metadata to storage.\n        proposalMetadata[msg.sender][_uuid] = metaData;\n\n        // Clobber memory and `log0` all calldata. This is safe because there is no execution afterwards within\n        // this callframe.\n        assembly {\n            mstore(0x00, shl(96, caller()))\n            calldatacopy(0x14, 0x00, calldatasize())\n            log0(0x00, add(0x14, calldatasize()))\n        }\n    }\n\n    /// @notice Challenge a keccak256 block that was committed to in the merkle tree.\n    function challengeLPP(\n        address _claimant,\n        uint256 _uuid,\n        LibKeccak.StateMatrix memory _stateMatrix,\n        Leaf calldata _preState,\n        bytes32[] calldata _preStateProof,\n        Leaf calldata _postState,\n        bytes32[] calldata _postStateProof\n    )\n    external\n    {\n        // Verify that both leaves are present in the merkle tree.\n        bytes32 root = getTreeRootLPP(_claimant, _uuid);\n        if (\n            !(\n            _verify(_preStateProof, root, _preState.index, _hashLeaf(_preState))\n            && _verify(_postStateProof, root, _postState.index, _hashLeaf(_postState))\n        )\n        ) revert InvalidProof();\n\n        // Verify that the prestate passed matches the intermediate state claimed in the leaf.\n        if (keccak256(abi.encode(_stateMatrix)) != _preState.stateCommitment) revert InvalidPreimage();\n\n        // Verify that the pre/post state are contiguous.\n        if (_preState.index + 1 != _postState.index) revert StatesNotContiguous();\n\n        // Absorb and permute the input bytes.\n        LibKeccak.absorb(_stateMatrix, _postState.input);\n        LibKeccak.permutation(_stateMatrix);\n\n        // Verify that the post state hash doesn't match the expected hash.\n        if (keccak256(abi.encode(_stateMatrix)) == _postState.stateCommitment) revert PostStateMatches();\n\n        // Mark the keccak claim as countered.\n        proposalMetadata[_claimant][_uuid] = proposalMetadata[_claimant][_uuid].setCountered(true);\n\n        // Pay out the bond to the challenger.\n        _payoutBond(_claimant, _uuid, msg.sender);\n    }\n\n    /// @notice Challenge the first keccak256 block that was absorbed.\n    function challengeFirstLPP(\n        address _claimant,\n        uint256 _uuid,\n        Leaf calldata _postState,\n        bytes32[] calldata _postStateProof\n    )\n    external\n    {\n        // Verify that the leaf is present in the merkle tree.\n        bytes32 root = getTreeRootLPP(_claimant, _uuid);\n        if (!_verify(_postStateProof, root, _postState.index, _hashLeaf(_postState))) revert InvalidProof();\n\n        // The poststate index must be 0 in order to challenge it with this function.\n        if (_postState.index != 0) revert StatesNotContiguous();\n\n        // Absorb and permute the input bytes into a fresh state matrix.\n        LibKeccak.StateMatrix memory stateMatrix;\n        LibKeccak.absorb(stateMatrix, _postState.input);\n        LibKeccak.permutation(stateMatrix);\n\n        // Verify that the post state hash doesn't match the expected hash.\n        if (keccak256(abi.encode(stateMatrix)) == _postState.stateCommitment) revert PostStateMatches();\n\n        // Mark the keccak claim as countered.\n        proposalMetadata[_claimant][_uuid] = proposalMetadata[_claimant][_uuid].setCountered(true);\n\n        // Pay out the bond to the challenger.\n        _payoutBond(_claimant, _uuid, msg.sender);\n    }\n\n    /// @notice Finalize a large preimage proposal after the challenge period has passed.\n    function squeezeLPP(\n        address _claimant,\n        uint256 _uuid,\n        LibKeccak.StateMatrix memory _stateMatrix,\n        Leaf calldata _preState,\n        bytes32[] calldata _preStateProof,\n        Leaf calldata _postState,\n        bytes32[] calldata _postStateProof\n    )\n    external\n    {\n        LPPMetaData metaData = proposalMetadata[_claimant][_uuid];\n\n        // Check if the proposal was countered.\n        if (metaData.countered()) revert BadProposal();\n\n        // Check if the proposal has been finalized at all.\n        if (metaData.timestamp() == 0) revert ActiveProposal();\n\n        // Check if the challenge period has passed since the proposal was finalized.\n        if (block.timestamp - metaData.timestamp() <= CHALLENGE_PERIOD) revert ActiveProposal();\n\n        // Verify that both leaves are present in the merkle tree.\n        bytes32 root = getTreeRootLPP(_claimant, _uuid);\n        if (\n            !(\n            _verify(_preStateProof, root, _preState.index, _hashLeaf(_preState))\n            && _verify(_postStateProof, root, _postState.index, _hashLeaf(_postState))\n        )\n        ) revert InvalidProof();\n\n        // Verify that the prestate passed matches the intermediate state claimed in the leaf.\n        if (keccak256(abi.encode(_stateMatrix)) != _preState.stateCommitment) revert InvalidPreimage();\n\n        // Verify that the pre/post state are contiguous.\n        if (_preState.index + 1 != _postState.index || _postState.index != metaData.blocksProcessed() - 1) {\n            revert StatesNotContiguous();\n        }\n\n        // Absorb and permute the input bytes. We perform no final verification on the state matrix here, since the\n        // proposal has passed the challenge period and is considered valid.\n        LibKeccak.absorb(_stateMatrix, _postState.input);\n        LibKeccak.permutation(_stateMatrix);\n        bytes32 finalDigest = LibKeccak.squeeze(_stateMatrix);\n        assembly {\n            finalDigest := or(and(finalDigest, not(shl(248, 0xFF))), shl(248, 0x02))\n        }\n\n        // Write the preimage part to the authorized preimage parts mapping.\n        uint256 partOffset = metaData.partOffset();\n        preimagePartOk[finalDigest][partOffset] = true;\n        preimageParts[finalDigest][partOffset] = proposalParts[_claimant][_uuid];\n        preimageLengths[finalDigest] = metaData.claimedSize();\n\n        // Pay out the bond to the claimant.\n        _payoutBond(_claimant, _uuid, _claimant);\n    }\n\n    /// @notice Gets the current merkle root of the large preimage proposal tree.\n    function getTreeRootLPP(address _owner, uint256 _uuid) public view returns (bytes32 treeRoot_) {\n        uint256 size = proposalMetadata[_owner][_uuid].blocksProcessed();\n        for (uint256 height = 0; height < KECCAK_TREE_DEPTH; height++) {\n            if ((size & 1) == 1) {\n                treeRoot_ = keccak256(abi.encode(proposalBranches[_owner][_uuid][height], treeRoot_));\n            } else {\n                treeRoot_ = keccak256(abi.encode(treeRoot_, zeroHashes[height]));\n            }\n            size >>= 1;\n        }\n    }\n\n    /// @notice Attempts to persist the preimage part to the caller's large preimage proposal storage, if the preimage\n    ///         part is present in the input data being posted.\n    /// @param _input The portion of the preimage being posted.\n    /// @param _uuid The UUID of the large preimage proposal.\n    /// @param _finalize Whether or not the proposal is being finalized in the current call.\n    /// @param _metaData The metadata of the large preimage proposal.\n    function _extractPreimagePart(\n        bytes calldata _input,\n        uint256 _uuid,\n        bool _finalize,\n        LPPMetaData _metaData\n    )\n    internal\n    {\n        uint256 offset = _metaData.partOffset();\n        uint256 claimedSize = _metaData.claimedSize();\n        uint256 currentSize = _metaData.bytesProcessed();\n\n        // Check if the part offset is present in the input data being posted. If it is, assign the part to the mapping.\n        if (offset < 8 && currentSize == 0) {\n            bytes32 preimagePart;\n            assembly {\n                mstore(0x00, shl(192, claimedSize))\n                mstore(0x08, calldataload(_input.offset))\n                preimagePart := mload(offset)\n            }\n            proposalParts[msg.sender][_uuid] = preimagePart;\n        } else if (offset >= 8 && (offset = offset - 8) >= currentSize && offset < currentSize + _input.length) {\n            uint256 relativeOffset = offset - currentSize;\n\n            // Revert if the full preimage part is not available in the data we're absorbing. The submitter must\n            // supply data that contains the full preimage part so that no partial preimage parts are stored in the\n            // oracle. Partial parts are *only* allowed at the tail end of the preimage, where no more data is available\n            // to be absorbed.\n            if (relativeOffset + 32 >= _input.length && !_finalize) revert PartOffsetOOB();\n\n            // If the preimage part is in the data we're about to absorb, persist the part to the caller's large\n            // preimaage metadata.\n            bytes32 preimagePart;\n            assembly {\n                preimagePart := calldataload(add(_input.offset, relativeOffset))\n            }\n            proposalParts[msg.sender][_uuid] = preimagePart;\n        }\n    }\n\n    /// @notice Check if leaf` at `index` verifies against the Merkle `root` and `branch`.\n    /// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#is_valid_merkle_branch\n    function _verify(\n        bytes32[] calldata _proof,\n        bytes32 _root,\n        uint256 _index,\n        bytes32 _leaf\n    )\n    internal\n    pure\n    returns (bool isValid_)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            function hashTwo(a, b) -> hash {\n                mstore(0x00, a)\n                mstore(0x20, b)\n                hash := keccak256(0x00, 0x40)\n            }\n\n            let value := _leaf\n            for {let i := 0x00} lt(i, KECCAK_TREE_DEPTH) {i := add(i, 0x01)} {\n                let branchValue := calldataload(add(_proof.offset, shl(0x05, i)))\n\n                switch and(shr(i, _index), 0x01)\n                case 1 {value := hashTwo(branchValue, value)}\n                default {value := hashTwo(value, branchValue)}\n            }\n\n            isValid_ := eq(value, _root)\n        }\n    }\n\n    /// @notice Pay out a proposal's bond. Reverts if the transfer fails.\n    function _payoutBond(address _claimant, uint256 _uuid, address _to) internal {\n        // Pay out the bond to the claimant.\n        uint256 bond = proposalBonds[_claimant][_uuid];\n        proposalBonds[_claimant][_uuid] = 0;\n        (bool success,) = _to.call{value: bond}(\"\");\n        if (!success) revert BondTransferFailed();\n    }\n\n    /// @notice Hashes leaf data for the preimage proposals tree\n    function _hashLeaf(Leaf memory _leaf) internal pure returns (bytes32 leaf_) {\n        leaf_ = keccak256(abi.encodePacked(_leaf.input, _leaf.index, _leaf.stateCommitment));\n    }\n}\n"
    },
    "contracts/L1/config/MetisConfig.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {Storage} from \"../../libraries/Storage.sol\";\nimport {ISemver} from \"../../universal/ISemver.sol\";\nimport {Initializable} from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n/// @custom:audit none This contracts is not yet audited.\n/// @title MetisConfig\n/// @notice The MetisConfig contract is used to manage configuration of global metis values.\ncontract MetisConfig is Initializable, ISemver {\n    /// @notice Enum representing different types of updates.\n    /// @custom:value GUARDIAN            Represents an update to the guardian.\n    enum UpdateType {\n        GUARDIAN\n    }\n\n    /// @notice Whether or not the Superchain is paused.\n    bytes32 public constant PAUSED_SLOT = bytes32(uint256(keccak256(\"metisConfig.paused\")) - 1);\n\n    /// @notice The address of the guardian, which can pause withdrawals from the System.\n    ///         It can only be modified by an upgrade.\n    bytes32 public constant GUARDIAN_SLOT = bytes32(uint256(keccak256(\"metisConfig.guardian\")) - 1);\n\n    /// @notice Emitted when the pause is triggered.\n    /// @param identifier A string helping to identify provenance of the pause transaction.\n    event Paused(string identifier);\n\n    /// @notice Emitted when the pause is lifted.\n    event Unpaused();\n\n    /// @notice Emitted when configuration is updated.\n    /// @param updateType Type of update.\n    /// @param data       Encoded update data.\n    event ConfigUpdate(UpdateType indexed updateType, bytes data);\n\n    /// @notice Semantic version.\n    /// @custom:semver 1.1.0\n    string public constant version = \"1.1.0\";\n\n    /// @notice Constructs the SuperchainConfig contract.\n    constructor() {\n        initialize({_guardian: address(0), _paused: false});\n    }\n\n    /// @notice Initializer.\n    /// @param _guardian    Address of the guardian, can pause the OptimismPortal.\n    /// @param _paused      Initial paused status.\n    function initialize(address _guardian, bool _paused) public initializer {\n        _setGuardian(_guardian);\n        if (_paused) {\n            _pause(\"Initializer paused\");\n        }\n    }\n\n    /// @notice Getter for the guardian address.\n    function guardian() public view returns (address guardian_) {\n        guardian_ = Storage.getAddress(GUARDIAN_SLOT);\n    }\n\n    /// @notice Getter for the current paused status.\n    function paused() public view returns (bool paused_) {\n        paused_ = Storage.getBool(PAUSED_SLOT);\n    }\n\n    /// @notice Pauses withdrawals.\n    /// @param _identifier (Optional) A string to identify provenance of the pause transaction.\n    function pause(string memory _identifier) external {\n        require(msg.sender == guardian(), \"MetisConfig: only guardian can pause\");\n        _pause(_identifier);\n    }\n\n    /// @notice Pauses withdrawals.\n    /// @param _identifier (Optional) A string to identify provenance of the pause transaction.\n    function _pause(string memory _identifier) internal {\n        Storage.setBool(PAUSED_SLOT, true);\n        emit Paused(_identifier);\n    }\n\n    /// @notice Unpauses withdrawals.\n    function unpause() external {\n        require(msg.sender == guardian(), \"MetisConfig: only guardian can unpause\");\n        Storage.setBool(PAUSED_SLOT, false);\n        emit Unpaused();\n    }\n\n    /// @notice Sets the guardian address. This is only callable during initialization, so an upgrade\n    ///         will be required to change the guardian.\n    /// @param _guardian The new guardian address.\n    function _setGuardian(address _guardian) internal {\n        Storage.setAddress(GUARDIAN_SLOT, _guardian);\n        emit ConfigUpdate(UpdateType.GUARDIAN, abi.encode(_guardian));\n    }\n}\n"
    },
    "contracts/L1/dispute/DisputeGameFactory.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {ISemver} from \"../../universal/ISemver.sol\";\nimport {IDisputeGame} from \"./interfaces/IDisputeGame.sol\";\nimport {IDisputeGameFactory} from \"./interfaces/IDisputeGameFactory.sol\";\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {LibClone} from \"solady/src/utils/LibClone.sol\";\nimport \"contracts/L1/dispute/lib/Types.sol\";\nimport \"contracts/L1/dispute/lib/Errors.sol\";\n\n/// @title DisputeGameFactory\n/// @notice A factory contract for creating `IDisputeGame` contracts. All created dispute games are stored in both a\n///         mapping and an append only array. The timestamp of the creation time of the dispute game is packed tightly\n///         into the storage slot with the address of the dispute game to make offchain discoverability of playable\n///         dispute games easier.\ncontract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver {\n    /// @dev Allows for the creation of clone proxies with immutable arguments.\n    using LibClone for address;\n\n    struct DisputeInfo {\n        GameType gameType;\n        address sender;\n        uint256 bond;\n        bytes32 l1Head;\n    }\n\n    /// @notice Semantic version.\n    /// @custom:semver 1.0.0\n    string public constant version = \"1.0.0\";\n\n    /// @inheritdoc IDisputeGameFactory\n    mapping(GameType => IDisputeGame) public gameImpls;\n\n    /// @inheritdoc IDisputeGameFactory\n    mapping(GameType => uint256) public initBonds;\n\n    /// @notice Mapping of a hash of `gameType || rootClaim || extraData` to the deployed `IDisputeGame` clone (where\n    //          `||` denotes concatenation).\n    mapping(Hash => GameId) internal _disputeGames;\n\n    /// @notice An append-only array of disputeGames that have been created. Used by offchain game solvers to\n    ///         efficiently track dispute games.\n    GameId[] internal _disputeGameList;\n\n    /// @notice An array of dispute games that have been requested.\n    mapping(bytes32 => DisputeInfo) public disputeGameCreationRequests;\n\n    /// @notice Constructs a new DisputeGameFactory contract.\n    constructor() OwnableUpgradeable() {\n        initialize(address(0));\n    }\n\n    /// @notice Initializes the contract.\n    /// @param _owner The owner of the contract.\n    function initialize(address _owner) public initializer {\n        __Ownable_init();\n        _transferOwnership(_owner);\n    }\n\n    /// @inheritdoc IDisputeGameFactory\n    function gameCount() external view returns (uint256 gameCount_) {\n        gameCount_ = _disputeGameList.length;\n    }\n\n    /// @inheritdoc IDisputeGameFactory\n    function games(\n        GameType _gameType,\n        Claim _rootClaim,\n        bytes calldata _extraData\n    )\n    external\n    view\n    returns (IDisputeGame proxy_, Timestamp timestamp_)\n    {\n        Hash uuid = getGameUUID(_gameType, _rootClaim, _extraData);\n        (, Timestamp timestamp, address proxy) = _disputeGames[uuid].unpack();\n        (proxy_, timestamp_) = (IDisputeGame(proxy), timestamp);\n    }\n\n    /// @inheritdoc IDisputeGameFactory\n    function gameAtIndex(uint256 _index)\n    external\n    view\n    returns (GameType gameType_, Timestamp timestamp_, IDisputeGame proxy_)\n    {\n        (GameType gameType, Timestamp timestamp, address proxy) = _disputeGameList[_index].unpack();\n        (gameType_, timestamp_, proxy_) = (gameType, timestamp, IDisputeGame(proxy));\n    }\n\n    /// @inheritdoc IDisputeGameFactory\n    function dispute(GameType _gameType, bytes calldata _extraData) external payable {\n        // Grab the implementation contract for the given `GameType`.\n        IDisputeGame impl = gameImpls[_gameType];\n\n        // If there is no implementation to clone for the given `GameType`, revert.\n        if (address(impl) == address(0)) revert NoImplementation(_gameType);\n\n        // If the required initialization bond is not met, revert.\n        if (msg.value != initBonds[_gameType]) revert IncorrectBondAmount();\n\n        // Get the hash of the parent block.\n        bytes32 parentHash = blockhash(block.number - 1);\n\n        // Save the dispute game creation request.\n        DisputeInfo memory info = DisputeInfo({\n            gameType: _gameType,\n            sender: msg.sender,\n            bond: msg.value,\n            l1Head: parentHash\n        });\n        disputeGameCreationRequests[keccak256(abi.encodePacked(_gameType, _extraData))] = info;\n\n        emit DisputeGameRequested(msg.sender, _gameType, msg.value, _extraData);\n    }\n\n    /// @inheritdoc IDisputeGameFactory\n    function create(\n        GameType _gameType,\n        Claim _rootClaim,\n        bytes calldata _extraData\n    )\n    external\n    onlyOwner\n    returns (IDisputeGame proxy_)\n    {\n        // Grab the implementation contract for the given `GameType`.\n        IDisputeGame impl = gameImpls[_gameType];\n\n        // If there is no implementation to clone for the given `GameType`, revert.\n        if (address(impl) == address(0)) revert NoImplementation(_gameType);\n\n        // find the given request\n        bytes32 requestUuid = keccak256(abi.encodePacked(_gameType, _extraData));\n        DisputeInfo memory info = disputeGameCreationRequests[requestUuid];\n\n        if (info.l1Head == bytes32(0)) revert NoDisputeGameRequests();\n\n        // If the required initialization bond is not met, revert.\n        if (info.bond != initBonds[_gameType]) revert IncorrectBondAmount();\n\n        // Clone the implementation contract and initialize it with the given parameters.\n        //\n        // CWIA Calldata Layout:\n        // ┌──────────────┬────────────────────────────────────┐\n        // │    Bytes     │            Description             │\n        // ├──────────────┼────────────────────────────────────┤\n        // │ [0, 20)      │ Game creator address               │\n        // │ [20, 52)     │ Root claim                         │\n        // │ [52, 84)     │ Parent block hash at creation time │\n        // │ [84, 84 + n) │ Extra data (opaque)                │\n        // └──────────────┴────────────────────────────────────┘\n        proxy_ = IDisputeGame(address(impl).clone(abi.encodePacked(msg.sender, _rootClaim, info.l1Head, _extraData)));\n        proxy_.initialize{value: info.bond}();\n\n        // Compute the unique identifier for the dispute game.\n        Hash uuid = getGameUUID(_gameType, _rootClaim, _extraData);\n\n        // If a dispute game with the same UUID already exists, revert.\n        if (GameId.unwrap(_disputeGames[uuid]) != bytes32(0)) revert GameAlreadyExists(uuid);\n\n        // Pack the game ID.\n        GameId id = LibGameId.pack(_gameType, Timestamp.wrap(uint64(block.timestamp)), address(proxy_));\n\n        // Store the dispute game id in the mapping & emit the `DisputeGameCreated` event.\n        _disputeGames[uuid] = id;\n        _disputeGameList.push(id);\n        delete disputeGameCreationRequests[requestUuid];\n        emit DisputeGameCreated(address(proxy_), _gameType, _rootClaim);\n    }\n\n    /// @inheritdoc IDisputeGameFactory\n    function getGameUUID(\n        GameType _gameType,\n        Claim _rootClaim,\n        bytes calldata _extraData\n    )\n    public\n    pure\n    returns (Hash uuid_)\n    {\n        uuid_ = Hash.wrap(keccak256(abi.encode(_gameType, _rootClaim, _extraData)));\n    }\n\n    /// @inheritdoc IDisputeGameFactory\n    function findLatestGames(\n        GameType _gameType,\n        uint256 _start,\n        uint256 _n\n    )\n    external\n    view\n    returns (GameSearchResult[] memory games_)\n    {\n        // If the `_start` index is greater than or equal to the game array length or `_n == 0`, return an empty array.\n        if (_start >= _disputeGameList.length || _n == 0) return games_;\n\n        // Allocate enough memory for the full array, but start the array's length at `0`. We may not use all of the\n        // memory allocated, but we don't know ahead of time the final size of the array.\n        assembly {\n            games_ := mload(0x40)\n            mstore(0x40, add(games_, add(0x20, shl(0x05, _n))))\n        }\n\n        // Perform a reverse linear search for the `_n` most recent games of type `_gameType`.\n        for (uint256 i = _start; i >= 0 && i <= _start;) {\n            GameId id = _disputeGameList[i];\n            (GameType gameType, Timestamp timestamp, address proxy) = id.unpack();\n\n            if (gameType.raw() == _gameType.raw()) {\n                // Increase the size of the `games_` array by 1.\n                // SAFETY: We can safely lazily allocate memory here because we pre-allocated enough memory for the max\n                //         possible size of the array.\n                assembly {\n                    mstore(games_, add(mload(games_), 0x01))\n                }\n\n                bytes memory extraData = IDisputeGame(proxy).extraData();\n                Claim rootClaim = IDisputeGame(proxy).rootClaim();\n                games_[games_.length - 1] = GameSearchResult({\n                    index: i,\n                    metadata: id,\n                    timestamp: timestamp,\n                    rootClaim: rootClaim,\n                    extraData: extraData\n                });\n                if (games_.length >= _n) break;\n            }\n\n            unchecked {\n                i--;\n            }\n        }\n    }\n\n    /// @inheritdoc IDisputeGameFactory\n    function setImplementation(GameType _gameType, IDisputeGame _impl) external onlyOwner {\n        gameImpls[_gameType] = _impl;\n        emit ImplementationSet(address(_impl), _gameType);\n    }\n\n    /// @inheritdoc IDisputeGameFactory\n    function setInitBond(GameType _gameType, uint256 _initBond) external onlyOwner {\n        initBonds[_gameType] = _initBond;\n        emit InitBondUpdated(_gameType, _initBond);\n    }\n}\n"
    },
    "contracts/L1/dispute/FaultDisputeGame.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport \"./interfaces/ILockingPool.sol\";\nimport \"contracts/L1/dispute/lib/Errors.sol\";\nimport \"contracts/L1/dispute/lib/Types.sol\";\nimport {Clone} from \"solady/src/utils/Clone.sol\";\nimport {FixedPointMathLib} from \"solady/src/utils/FixedPointMathLib.sol\";\nimport {Hashing} from \"../../libraries/Hashing.sol\";\nimport {IBigStepper} from \"./interfaces/IBigStepper.sol\";\nimport {IDelayedWETH} from \"./interfaces/IDelayedWETH.sol\";\nimport {IDisputeGame} from \"./interfaces/IDisputeGame.sol\";\nimport {IFaultDisputeGame} from \"./interfaces/IFaultDisputeGame.sol\";\nimport {IInitializable} from \"contracts/L1/dispute/interfaces/IInitializable.sol\";\nimport {IMVMStateCommitmentChain} from \"../rollup/IMVMStateCommitmentChain.sol\";\nimport {IPreimageOracle} from \"../cannon/interfaces/IPreimageOracle.sol\";\nimport {ISemver} from \"../../universal/ISemver.sol\";\nimport {Lib_AddressManager} from \"../../libraries/resolver/Lib_AddressManager.sol\";\n\nimport {Lib_OVMCodec} from \"../../libraries/codec/Lib_OVMCodec.sol\";\nimport {Lib_RLPReader} from \"../../libraries/rlp/Lib_RLPReader.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {OutputRoot, LocalPreimageKey, VMStatuses} from \"./lib/Types.sol\";\nimport {StateCommitmentChain} from \"../rollup/StateCommitmentChain.sol\";\nimport {Types} from \"../../libraries/Types.sol\";\n\n/// @title FaultDisputeGame\n/// @notice An implementation of the `IFaultDisputeGame` interface.\ncontract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver {\n    ////////////////////////////////////////////////////////////////\n    //                         State Vars                         //\n    ////////////////////////////////////////////////////////////////\n\n    /// @notice The absolute prestate of the instruction trace. This is a constant that is defined\n    ///         by the program that is being used to execute the trace.\n    Claim internal immutable ABSOLUTE_PRESTATE;\n\n    /// @notice The max depth of the game.\n    uint256 internal immutable MAX_GAME_DEPTH;\n\n    /// @notice The max depth of the output bisection portion of the position tree. Immediately beneath\n    ///         this depth, execution trace bisection begins.\n    uint256 internal immutable SPLIT_DEPTH;\n\n    /// @notice The maximum duration that may accumulate on a team's chess clock before they may no longer respond.\n    Duration internal immutable MAX_CLOCK_DURATION;\n\n    /// @notice An onchain VM that performs single instruction steps on a fault proof program trace.\n    IBigStepper internal immutable VM;\n\n    /// @notice The game type ID.\n    GameType internal immutable GAME_TYPE;\n\n    /// @notice WETH contract for holding ETH.\n    IDelayedWETH internal immutable WETH;\n\n    /// @notice The address manager contract.\n    Lib_AddressManager internal immutable ADDRESS_MANAGER;\n\n    /// @notice The chain ID of the L2 network this contract argues about.\n    uint256 internal immutable L2_CHAIN_ID;\n\n    /// @notice The duration of the clock extension. Will be doubled if the grandchild is the root claim of an execution\n    ///         trace bisection subgame.\n    Duration internal immutable CLOCK_EXTENSION;\n\n    /// @notice The global root claim's position is always at gindex 1.\n    Position internal constant ROOT_POSITION = Position.wrap(1);\n\n    /// @notice The index of the block number in the RLP-encoded block header.\n    /// @dev Consensus encoding reference:\n    /// https://github.com/paradigmxyz/reth/blob/5f82993c23164ce8ccdc7bf3ae5085205383a5c8/crates/primitives/src/header.rs#L368\n    uint256 internal constant HEADER_BLOCK_NUMBER_INDEX = 8;\n\n    /// @notice Semantic version.\n    /// @custom:semver 1.3.0-rc.1\n    string public constant version = \"1.3.0-rc.1\";\n\n    /// @notice The starting timestamp of the game\n    Timestamp public createdAt;\n\n    /// @notice The timestamp of the game's global resolution.\n    Timestamp public resolvedAt;\n\n    /// @inheritdoc IDisputeGame\n    GameStatus public status;\n\n    /// @notice Flag for the `initialize` function to prevent re-initialization.\n    bool internal initialized;\n\n    /// @notice Flag for whether or not the L2 block number claim has been invalidated via `challengeRootL2Block`.\n    bool public l2BlockNumberChallenged;\n\n    /// @notice The challenger of the L2 block number claim. Should always be `address(0)` if `l2BlockNumberChallenged`\n    ///         is `false`. Should be the address of the challenger if `l2BlockNumberChallenged` is `true`.\n    address public l2BlockNumberChallenger;\n\n    /// @notice An append-only array of all claims made during the dispute game.\n    ClaimData[] public claimData;\n\n    /// @notice Credited balances for winning participants.\n    mapping(address => uint256) public credit;\n\n    /// @notice A mapping to allow for constant-time lookups of existing claims.\n    mapping(Hash => bool) public claims;\n\n    /// @notice A mapping of subgames rooted at a claim index to other claim indices in the subgame.\n    mapping(uint256 => uint256[]) public subgames;\n\n    /// @notice A mapping of resolved subgames rooted at a claim index.\n    mapping(uint256 => bool) public resolvedSubgames;\n\n    /// @notice A mapping of claim indices to resolution checkpoints.\n    mapping(uint256 => ResolutionCheckpoint) public resolutionCheckpoints;\n\n    /// @notice The latest finalized output root, serving as the anchor for output bisection.\n    OutputRoot public startingOutputRoot;\n\n    /// @notice The name of the SCC contract.\n    string internal constant SCC_NAME = \"StateCommitmentChain\";\n\n    /// @notice The name of the locking pool contract.\n    string internal constant LOCKING_POOL_NAME = \"FaultProofLockingPool\";\n\n    /// @param _gameType The type ID of the game.\n    /// @param _absolutePrestate The absolute prestate of the instruction trace.\n    /// @param _maxGameDepth The maximum depth of bisection.\n    /// @param _splitDepth The final depth of the output bisection portion of the game.\n    /// @param _clockExtension The clock extension to perform when the remaining duration is less than the extension.\n    /// @param _maxClockDuration The maximum amount of time that may accumulate on a team's chess clock.\n    /// @param _vm An onchain VM that performs single instruction steps on an FPP trace.\n    /// @param _weth WETH contract for holding ETH.\n    /// @param _addressManager The contract that stores the names and addresses of metis contracts.\n    /// @param _l2ChainId Chain ID of the L2 network this contract argues about.\n    constructor(\n        GameType _gameType,\n        Claim _absolutePrestate,\n        uint256 _maxGameDepth,\n        uint256 _splitDepth,\n        Duration _clockExtension,\n        Duration _maxClockDuration,\n        IBigStepper _vm,\n        IDelayedWETH _weth,\n        Lib_AddressManager _addressManager,\n        uint256 _l2ChainId\n    ) {\n        // The max game depth may not be greater than `LibPosition.MAX_POSITION_BITLEN - 1`.\n        if (_maxGameDepth > LibPosition.MAX_POSITION_BITLEN - 1) revert MaxDepthTooLarge();\n\n        // The split depth plus one cannot be greater than or equal to the max game depth. We add\n        // an additional depth to the split depth to avoid a bug in trace ancestor lookup. We know\n        // that the case where the split depth is the max value for uint256 is equivalent to the\n        // second check though we do need to check it explicitly to avoid an overflow.\n        if (_splitDepth == type(uint256).max || _splitDepth + 1 >= _maxGameDepth) revert InvalidSplitDepth();\n\n        // The split depth cannot be 0 or 1 to stay in bounds of clock extension arithmetic.\n        if (_splitDepth < 2) revert InvalidSplitDepth();\n\n        // The PreimageOracle challenge period must fit into uint64 so we can safely use it here.\n        // Runtime check was added instead of changing the ABI since the contract is already\n        // deployed in production. We perform the same check within the PreimageOracle for the\n        // benefit of developers but also perform this check here defensively.\n        if (_vm.oracle().challengePeriod() > type(uint64).max) revert InvalidChallengePeriod();\n\n        // Determine the maximum clock extension which is either the split depth extension or the\n        // maximum game depth extension depending on the configuration of these contracts.\n        uint256 splitDepthExtension = uint256(_clockExtension.raw()) * 2;\n        uint256 maxGameDepthExtension = uint256(_clockExtension.raw()) + uint256(_vm.oracle().challengePeriod());\n        uint256 maxClockExtension = Math.max(splitDepthExtension, maxGameDepthExtension);\n\n        // The maximum clock extension must fit into a uint64.\n        if (maxClockExtension > type(uint64).max) revert InvalidClockExtension();\n\n        // The maximum clock extension may not be greater than the maximum clock duration.\n        if (uint64(maxClockExtension) > _maxClockDuration.raw()) revert InvalidClockExtension();\n\n        // Set up initial game state.\n        GAME_TYPE = _gameType;\n        ABSOLUTE_PRESTATE = _absolutePrestate;\n        MAX_GAME_DEPTH = _maxGameDepth;\n        SPLIT_DEPTH = _splitDepth;\n        CLOCK_EXTENSION = _clockExtension;\n        MAX_CLOCK_DURATION = _maxClockDuration;\n        VM = _vm;\n        WETH = _weth;\n        ADDRESS_MANAGER = _addressManager;\n        L2_CHAIN_ID = _l2ChainId;\n    }\n\n    /// @inheritdoc IInitializable\n    function initialize() public payable virtual {\n        // SAFETY: Any revert in this function will bubble up to the DisputeGameFactory and\n        // prevent the game from being created.\n        //\n        // Implicit assumptions:\n        // - The `gameStatus` state variable defaults to 0, which is `GameStatus.IN_PROGRESS`\n        // - The dispute game factory will enforce the required bond to initialize the game.\n        //\n        // Explicit checks:\n        // - The game must not have already been initialized.\n        // - An output root cannot be proposed at or before the starting block number.\n\n        // INVARIANT: The game must not have already been initialized.\n        if (initialized) revert AlreadyInitialized();\n\n        // Grab the latest anchor root.\n        IMVMStateCommitmentChain stateCommitmentChain = IMVMStateCommitmentChain(ADDRESS_MANAGER.getAddress(SCC_NAME));\n        (bytes32 scRoot, uint256 rootBlockNumber) = stateCommitmentChain.findEarliestDisputableBatch(L2_CHAIN_ID);\n\n        Hash root = Hash.wrap(scRoot);\n\n        // Should only happen if this is a new game type that hasn't been set up yet.\n        if (root.raw() == bytes32(0)) revert AnchorRootNotFound();\n\n        // we do not allow to dispute an already disputed batch\n        if (stateCommitmentChain.isDisputedBatch(scRoot)) revert ClaimAlreadyResolved();\n\n        // Set the starting output root.\n        startingOutputRoot = OutputRoot({l2BlockNumber: rootBlockNumber, root: root});\n\n        // Revert if the calldata size is not the expected length.\n        //\n        // This is to prevent adding extra or omitting bytes from to `extraData` that result in a different game UUID\n        // in the factory, but are not used by the game, which would allow for multiple dispute games for the same\n        // output proposal to be created.\n        //\n        // Expected length: 0x7A\n        // - 0x04 selector\n        // - 0x14 creator address\n        // - 0x20 root claim\n        // - 0x20 l1 head\n        // - 0x20 extraData\n        // - 0x02 CWIA bytes\n        assembly {\n            if iszero(eq(calldatasize(), 0x7A)) {\n            // Store the selector for `BadExtraData()` & revert\n                mstore(0x00, 0x9824bdab)\n                revert(0x1C, 0x04)\n            }\n        }\n\n        // Do not allow the game to be initialized if the root claim corresponds to a block at or before the\n        // configured starting block number.\n        if (l2BlockNumber() <= rootBlockNumber) revert UnexpectedRootClaim(rootClaim());\n\n        // Set the root claim\n        claimData.push(\n            ClaimData({\n                parentIndex: type(uint32).max,\n                counteredBy: address(0),\n                claimant: gameCreator(),\n                bond: uint128(msg.value),\n                claim: rootClaim(),\n                position: ROOT_POSITION,\n                clock: LibClock.wrap(Duration.wrap(0), Timestamp.wrap(uint64(block.timestamp)))\n            })\n        );\n\n        // Set the game as initialized.\n        initialized = true;\n\n        // Deposit the bond.\n        WETH.deposit{value: msg.value}();\n\n        // Set the game's starting timestamp\n        createdAt = Timestamp.wrap(uint64(block.timestamp));\n    }\n\n    ////////////////////////////////////////////////////////////////\n    //                  `IFaultDisputeGame` impl                  //\n    ////////////////////////////////////////////////////////////////\n\n    /// @inheritdoc IFaultDisputeGame\n    function step(\n        uint256 _claimIndex,\n        bool _isAttack,\n        bytes calldata _stateData,\n        bytes calldata _proof\n    )\n    public\n    virtual\n    {\n        // INVARIANT: Steps cannot be made unless the game is currently in progress.\n        if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress();\n\n        // Get the parent. If it does not exist, the call will revert with OOB.\n        ClaimData storage parent = claimData[_claimIndex];\n\n        // Pull the parent position out of storage.\n        Position parentPos = parent.position;\n        // Determine the position of the step.\n        Position stepPos = parentPos.move(_isAttack);\n\n        // INVARIANT: A step cannot be made unless the move position is 1 below the `MAX_GAME_DEPTH`\n        if (stepPos.depth() != MAX_GAME_DEPTH + 1) revert InvalidParent();\n\n        // Determine the expected pre & post states of the step.\n        Claim preStateClaim;\n        ClaimData storage postState;\n        if (_isAttack) {\n            // If the step position's index at depth is 0, the prestate is the absolute\n            // prestate.\n            // If the step is an attack at a trace index > 0, the prestate exists elsewhere in\n            // the game state.\n            // NOTE: We localize the `indexAtDepth` for the current execution trace subgame by finding\n            //       the remainder of the index at depth divided by 2 ** (MAX_GAME_DEPTH - SPLIT_DEPTH),\n            //       which is the number of leaves in each execution trace subgame. This is so that we can\n            //       determine whether or not the step position is represents the `ABSOLUTE_PRESTATE`.\n            preStateClaim = (stepPos.indexAtDepth() % (1 << (MAX_GAME_DEPTH - SPLIT_DEPTH))) == 0\n                ? ABSOLUTE_PRESTATE\n                : _findTraceAncestor(Position.wrap(parentPos.raw() - 1), parent.parentIndex, false).claim;\n            // For all attacks, the poststate is the parent claim.\n            postState = parent;\n        } else {\n            // If the step is a defense, the poststate exists elsewhere in the game state,\n            // and the parent claim is the expected pre-state.\n            preStateClaim = parent.claim;\n            postState = _findTraceAncestor(Position.wrap(parentPos.raw() + 1), parent.parentIndex, false);\n        }\n\n        // INVARIANT: The prestate is always invalid if the passed `_stateData` is not the\n        //            preimage of the prestate claim hash.\n        //            We ignore the highest order byte of the digest because it is used to\n        //            indicate the VM Status and is added after the digest is computed.\n        if (keccak256(_stateData) << 8 != preStateClaim.raw() << 8) revert InvalidPrestate();\n\n        // Compute the local preimage context for the step.\n        Hash uuid = _findLocalContext(_claimIndex);\n\n        // INVARIANT: If a step is an attack, the poststate is valid if the step produces\n        //            the same poststate hash as the parent claim's value.\n        //            If a step is a defense:\n        //              1. If the parent claim and the found post state agree with each other\n        //                 (depth diff % 2 == 0), the step is valid if it produces the same\n        //                 state hash as the post state's claim.\n        //              2. If the parent claim and the found post state disagree with each other\n        //                 (depth diff % 2 != 0), the parent cannot be countered unless the step\n        //                 produces the same state hash as `postState.claim`.\n        // SAFETY:    While the `attack` path does not need an extra check for the post\n        //            state's depth in relation to the parent, we don't need another\n        //            branch because (n - n) % 2 == 0.\n        bool validStep = VM.step(_stateData, _proof, uuid.raw()) == postState.claim.raw();\n        bool parentPostAgree = (parentPos.depth() - postState.position.depth()) % 2 == 0;\n        if (parentPostAgree == validStep) revert ValidStep();\n\n        // INVARIANT: A step cannot be made against a claim for a second time.\n        if (parent.counteredBy != address(0)) revert DuplicateStep();\n\n        // Set the parent claim as countered. We do not need to append a new claim to the game;\n        // instead, we can just set the existing parent as countered.\n        parent.counteredBy = msg.sender;\n    }\n\n    /// @notice Generic move function, used for both `attack` and `defend` moves.\n    /// @param _disputed The disputed `Claim`.\n    /// @param _challengeIndex The index of the claim being moved against.\n    /// @param _claim The claim at the next logical position in the game.\n    /// @param _isAttack Whether or not the move is an attack or defense.\n    function move(Claim _disputed, uint256 _challengeIndex, Claim _claim, bool _isAttack) public payable virtual {\n        // INVARIANT: Moves cannot be made unless the game is currently in progress.\n        if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress();\n\n        // Get the parent. If it does not exist, the call will revert with OOB.\n        ClaimData memory parent = claimData[_challengeIndex];\n\n        // INVARIANT: The claim at the _challengeIndex must be the disputed claim.\n        if (Claim.unwrap(parent.claim) != Claim.unwrap(_disputed)) revert InvalidDisputedClaimIndex();\n\n        // Compute the position that the claim commits to. Because the parent's position is already\n        // known, we can compute the next position by moving left or right depending on whether\n        // or not the move is an attack or defense.\n        Position parentPos = parent.position;\n        Position nextPosition = parentPos.move(_isAttack);\n        uint256 nextPositionDepth = nextPosition.depth();\n\n        // INVARIANT: A defense can never be made against the root claim of either the output root game or any\n        //            of the execution trace bisection subgames. This is because the root claim commits to the\n        //            entire state. Therefore, the only valid defense is to do nothing if it is agreed with.\n        if ((_challengeIndex == 0 || nextPositionDepth == SPLIT_DEPTH + 2) && !_isAttack) {\n            revert CannotDefendRootClaim();\n        }\n\n        // INVARIANT: No moves against the root claim can be made after it has been challenged with\n        //            `challengeRootL2Block`.`\n        if (l2BlockNumberChallenged && _challengeIndex == 0) revert L2BlockNumberChallenged();\n\n        // INVARIANT: A move can never surpass the `MAX_GAME_DEPTH`. The only option to counter a\n        //            claim at this depth is to perform a single instruction step on-chain via\n        //            the `step` function to prove that the state transition produces an unexpected\n        //            post-state.\n        if (nextPositionDepth > MAX_GAME_DEPTH) revert GameDepthExceeded();\n\n        // When the next position surpasses the split depth (i.e., it is the root claim of an execution\n        // trace bisection sub-game), we need to perform some extra verification steps.\n        if (nextPositionDepth == SPLIT_DEPTH + 1) {\n            _verifyExecBisectionRoot(_claim, _challengeIndex, parentPos, _isAttack);\n        }\n\n        // INVARIANT: The `msg.value` must exactly equal the required bond.\n        //            The root game creator does not need to pay for the bond, since the reward will be slashed from the pool.\n        if (claimData[0].claimant != msg.sender && getRequiredBond(nextPosition) != msg.value) revert IncorrectBondAmount();\n\n        // Compute the duration of the next clock. This is done by adding the duration of the\n        // grandparent claim to the difference between the current block timestamp and the\n        // parent's clock timestamp.\n        Duration nextDuration = getChallengerDuration(_challengeIndex);\n\n        // INVARIANT: A move can never be made once its clock has exceeded `MAX_CLOCK_DURATION`\n        //            seconds of time.\n        if (nextDuration.raw() == MAX_CLOCK_DURATION.raw()) revert ClockTimeExceeded();\n\n        // Clock extension is a mechanism that automatically extends the clock for a potential\n        // grandchild claim when there would be less than the clock extension time left if a player\n        // is forced to inherit another team's clock when countering a freeloader claim. Exact\n        // amount of clock extension time depends exactly where we are within the game.\n        uint64 actualExtension;\n        if (nextPositionDepth == MAX_GAME_DEPTH - 1) {\n            // If the next position is `MAX_GAME_DEPTH - 1` then we're about to execute a step. Our\n            // clock extension must therefore account for the LPP challenge period in addition to\n            // the standard clock extension.\n            actualExtension = CLOCK_EXTENSION.raw() + uint64(VM.oracle().challengePeriod());\n        } else if (nextPositionDepth == SPLIT_DEPTH - 1) {\n            // If the next position is `SPLIT_DEPTH - 1` then we're about to begin an execution\n            // trace bisection and we need to give extra time for the off-chain challenge agent to\n            // be able to generate the initial instruction trace on the native FPVM.\n            actualExtension = CLOCK_EXTENSION.raw() * 2;\n        } else {\n            // Otherwise, we just use the standard clock extension.\n            actualExtension = CLOCK_EXTENSION.raw();\n        }\n\n        // Check if we need to apply the clock extension.\n        if (nextDuration.raw() > MAX_CLOCK_DURATION.raw() - actualExtension) {\n            nextDuration = Duration.wrap(MAX_CLOCK_DURATION.raw() - actualExtension);\n        }\n\n        // Construct the next clock with the new duration and the current block timestamp.\n        Clock nextClock = LibClock.wrap(nextDuration, Timestamp.wrap(uint64(block.timestamp)));\n\n        // INVARIANT: There cannot be multiple identical claims with identical moves on the same challengeIndex. Multiple\n        //            claims at the same position may dispute the same challengeIndex. However, they must have different\n        //            values.\n        Hash claimHash = _claim.hashClaimPos(nextPosition, _challengeIndex);\n        if (claims[claimHash]) revert ClaimAlreadyExists();\n        claims[claimHash] = true;\n\n        // Create the new claim.\n        claimData.push(\n            ClaimData({\n                parentIndex: uint32(_challengeIndex),\n            // This is updated during subgame resolution\n                counteredBy: address(0),\n                claimant: msg.sender,\n                bond: uint128(msg.value),\n                claim: _claim,\n                position: nextPosition,\n                clock: nextClock\n            })\n        );\n\n        // Update the subgame rooted at the parent claim.\n        subgames[_challengeIndex].push(claimData.length - 1);\n\n        // Deposit the bond.\n        WETH.deposit{value: msg.value}();\n\n        // Emit the appropriate event for the attack or defense.\n        emit Move(_challengeIndex, _claim, msg.sender);\n    }\n\n    /// @inheritdoc IFaultDisputeGame\n    function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable {\n        move(_disputed, _parentIndex, _claim, true);\n    }\n\n    /// @inheritdoc IFaultDisputeGame\n    function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable {\n        move(_disputed, _parentIndex, _claim, false);\n    }\n\n    /// @inheritdoc IFaultDisputeGame\n    function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external {\n        // INVARIANT: Local data can only be added if the game is currently in progress.\n        if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress();\n\n        (Claim starting, Position startingPos, Claim disputed, Position disputedPos) =\n                        _findStartingAndDisputedOutputs(_execLeafIdx);\n        Hash uuid = _computeLocalContext(starting, startingPos, disputed, disputedPos);\n\n        IPreimageOracle oracle = VM.oracle();\n        if (_ident == LocalPreimageKey.L1_HEAD_HASH) {\n            // Load the L1 head hash\n            oracle.loadLocalData(_ident, uuid.raw(), l1Head().raw(), 32, _partOffset);\n        } else if (_ident == LocalPreimageKey.STARTING_OUTPUT_ROOT) {\n            // Load the starting proposal's output root.\n            oracle.loadLocalData(_ident, uuid.raw(), starting.raw(), 32, _partOffset);\n        } else if (_ident == LocalPreimageKey.DISPUTED_OUTPUT_ROOT) {\n            // Load the disputed proposal's output root\n            oracle.loadLocalData(_ident, uuid.raw(), disputed.raw(), 32, _partOffset);\n        } else if (_ident == LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER) {\n            // Load the disputed proposal's L2 block number as a big-endian uint64 in the\n            // high order 8 bytes of the word.\n\n            // We add the index at depth + 1 to the starting block number to get the disputed L2\n            // block number.\n            uint256 l2Number = startingOutputRoot.l2BlockNumber + disputedPos.traceIndex(SPLIT_DEPTH) + 1;\n\n            // Choose the minimum between the `l2BlockNumber` claim and the bisected-to L2 block number.\n            l2Number = l2Number < l2BlockNumber() ? l2Number : l2BlockNumber();\n\n            oracle.loadLocalData(_ident, uuid.raw(), bytes32(l2Number << 0xC0), 8, _partOffset);\n        } else if (_ident == LocalPreimageKey.CHAIN_ID) {\n            // Load the chain ID as a big-endian uint64 in the high order 8 bytes of the word.\n            oracle.loadLocalData(_ident, uuid.raw(), bytes32(L2_CHAIN_ID << 0xC0), 8, _partOffset);\n        } else {\n            revert InvalidLocalIdent();\n        }\n    }\n\n    /// @inheritdoc IFaultDisputeGame\n    function getNumToResolve(uint256 _claimIndex) public view returns (uint256 numRemainingChildren_) {\n        ResolutionCheckpoint storage checkpoint = resolutionCheckpoints[_claimIndex];\n        uint256[] storage challengeIndices = subgames[_claimIndex];\n        uint256 challengeIndicesLen = challengeIndices.length;\n\n        numRemainingChildren_ = challengeIndicesLen - checkpoint.subgameIndex;\n    }\n\n    /// @inheritdoc IFaultDisputeGame\n    function l2BlockNumber() public pure returns (uint256 l2BlockNumber_) {\n        l2BlockNumber_ = _getArgUint256(0x54);\n    }\n\n    /// @inheritdoc IFaultDisputeGame\n    function startingBlockNumber() external view returns (uint256 startingBlockNumber_) {\n        startingBlockNumber_ = startingOutputRoot.l2BlockNumber;\n    }\n\n    /// @inheritdoc IFaultDisputeGame\n    function startingRootHash() external view returns (Hash startingRootHash_) {\n        startingRootHash_ = startingOutputRoot.root;\n    }\n\n    /// @notice Challenges the root L2 block number by providing the preimage of the output root and the L2 block header\n    ///         and showing that the committed L2 block number is incorrect relative to the claimed L2 block number.\n    /// @param _outputRootProof The output root proof.\n    /// @param _headerRLP The RLP-encoded L2 block header.\n    function challengeRootL2Block(\n        Lib_OVMCodec.ChainBatchHeader calldata _outputRootProof,\n        bytes calldata _headerRLP\n    )\n    external\n    {\n        // INVARIANT: Moves cannot be made unless the game is currently in progress.\n        if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress();\n\n        // The root L2 block claim can only be challenged once.\n        if (l2BlockNumberChallenged) revert L2BlockNumberChallenged();\n\n        // Verify the output root preimage.\n        if (Lib_OVMCodec.hashBatchHeader(_outputRootProof) != rootClaim().raw()) revert InvalidOutputRootProof();\n\n        // Verify the block hash preimage.\n//        (, , bytes32 latestBlockhash, ) = abi.decode(_outputRootProof.extraData, (uint256, address, bytes32, uint256));\n//        if (keccak256(_headerRLP) != latestBlockhash) revert InvalidHeaderRLP();\n\n        // Decode the header RLP to find the number of the block. In the consensus encoding, the timestamp\n        // is the 9th element in the list that represents the block header.\n        Lib_RLPReader.RLPItem[] memory headerContents = Lib_RLPReader.readList(Lib_RLPReader.toRLPItem(_headerRLP));\n        bytes memory rawBlockNumber = Lib_RLPReader.readBytes(headerContents[HEADER_BLOCK_NUMBER_INDEX]);\n\n        // Sanity check the block number string length.\n        if (rawBlockNumber.length > 32) revert InvalidHeaderRLP();\n\n        // Convert the raw, left-aligned block number to a uint256 by aligning it as a big-endian\n        // number in the low-order bytes of a 32-byte word.\n        //\n        // SAFETY: The length of `rawBlockNumber` is checked above to ensure it is at most 32 bytes.\n        uint256 blockNumber;\n        assembly {\n            blockNumber := shr(shl(0x03, sub(0x20, mload(rawBlockNumber))), mload(add(rawBlockNumber, 0x20)))\n        }\n\n        // Ensure the block number does not match the block number claimed in the dispute game.\n        if (blockNumber == l2BlockNumber()) revert BlockNumberMatches();\n\n        // check block number is in batch range\n        if (blockNumber < _outputRootProof.prevTotalElements + 1 || blockNumber > _outputRootProof.prevTotalElements + _outputRootProof.batchSize) {\n            revert InvalidHeaderRLP();\n        }\n\n        // Issue a special counter to the root claim. This counter will always win the root claim subgame, and receive\n        // the bond from the root claimant.\n        l2BlockNumberChallenger = msg.sender;\n        l2BlockNumberChallenged = true;\n    }\n\n    ////////////////////////////////////////////////////////////////\n    //                    `IDisputeGame` impl                     //\n    ////////////////////////////////////////////////////////////////\n\n    /// @inheritdoc IDisputeGame\n    function resolve() external returns (GameStatus status_) {\n        // INVARIANT: Resolution cannot occur unless the game is currently in progress.\n        if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress();\n\n        // INVARIANT: Resolution cannot occur unless the absolute root subgame has been resolved.\n        if (!resolvedSubgames[0]) revert OutOfOrderResolution();\n\n        // Update the global game status; The dispute has concluded.\n        status_ = claimData[0].counteredBy == address(0) ? GameStatus.DEFENDER_WINS : GameStatus.CHALLENGER_WINS;\n        resolvedAt = Timestamp.wrap(uint64(block.timestamp));\n\n        // Handle locking pool slashing if challenger wins\n        if (status_ == GameStatus.CHALLENGER_WINS) {\n            address lockingPool = ADDRESS_MANAGER.getAddress(LOCKING_POOL_NAME);\n            if (lockingPool != address(0)) {\n                // Get the winning claimant (the one who successfully countered the root claim)\n                address winner = claimData[0].counteredBy;\n                \n                // Call slash on the locking pool\n                try ILockingPool(lockingPool).slash(winner) {\n                    // Slashing succeeded\n                } catch {\n                    // Slashing failed - we don't want to revert the whole resolution\n                    // but we should emit an event for monitoring\n                    emit SlashingFailed(winner);\n                }\n            }\n\n            // Mark batch as disputed\n            IMVMStateCommitmentChain(ADDRESS_MANAGER.getAddress(SCC_NAME)).saveDisputedBatch(claimData[0].claim.raw());\n        }\n\n        // Update the status and emit the resolved event, note that we're performing an assignment here.\n        emit Resolved(status = status_);\n    }\n\n    /// @inheritdoc IFaultDisputeGame\n    function resolveClaim(uint256 _claimIndex, uint256 _numToResolve) external {\n        // INVARIANT: Resolution cannot occur unless the game is currently in progress.\n        if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress();\n\n        ClaimData storage subgameRootClaim = claimData[_claimIndex];\n        Duration challengeClockDuration = getChallengerDuration(_claimIndex);\n\n        // INVARIANT: Cannot resolve a subgame unless the clock of its would-be counter has expired\n        // INVARIANT: Assuming ordered subgame resolution, challengeClockDuration is always >= MAX_CLOCK_DURATION if all\n        // descendant subgames are resolved\n        if (challengeClockDuration.raw() < MAX_CLOCK_DURATION.raw()) revert ClockNotExpired();\n\n        // INVARIANT: Cannot resolve a subgame twice.\n        if (resolvedSubgames[_claimIndex]) revert ClaimAlreadyResolved();\n\n        uint256[] storage challengeIndices = subgames[_claimIndex];\n        uint256 challengeIndicesLen = challengeIndices.length;\n\n        // Uncontested claims are resolved implicitly unless they are the root claim. Pay out the bond to the claimant\n        // and return early.\n        if (challengeIndicesLen == 0 && _claimIndex != 0) {\n            // In the event that the parent claim is at the max depth, there will always be 0 subgames. If the\n            // `counteredBy` field is set and there are no subgames, this implies that the parent claim was successfully\n            // stepped against. In this case, we pay out the bond to the party that stepped against the parent claim.\n            // Otherwise, the parent claim is uncontested, and the bond is returned to the claimant.\n            address counteredBy = subgameRootClaim.counteredBy;\n            address recipient = counteredBy == address(0) ? subgameRootClaim.claimant : counteredBy;\n            _distributeBond(recipient, subgameRootClaim);\n            resolvedSubgames[_claimIndex] = true;\n            return;\n        }\n\n        // Fetch the resolution checkpoint from storage.\n        ResolutionCheckpoint memory checkpoint = resolutionCheckpoints[_claimIndex];\n\n        // If the checkpoint does not currently exist, initialize the current left most position as max u128.\n        if (!checkpoint.initialCheckpointComplete) {\n            checkpoint.leftmostPosition = Position.wrap(type(uint128).max);\n            checkpoint.initialCheckpointComplete = true;\n\n            // If `_numToResolve == 0`, assume that we can check all child subgames in this one callframe.\n            if (_numToResolve == 0) _numToResolve = challengeIndicesLen;\n        }\n\n        // Assume parent is honest until proven otherwise\n        uint256 lastToResolve = checkpoint.subgameIndex + _numToResolve;\n        uint256 finalCursor = lastToResolve > challengeIndicesLen ? challengeIndicesLen : lastToResolve;\n        for (uint256 i = checkpoint.subgameIndex; i < finalCursor; i++) {\n            uint256 challengeIndex = challengeIndices[i];\n\n            // INVARIANT: Cannot resolve a subgame containing an unresolved claim\n            if (!resolvedSubgames[challengeIndex]) revert OutOfOrderResolution();\n\n            ClaimData storage claim = claimData[challengeIndex];\n\n            // If the child subgame is uncountered and further left than the current left-most counter,\n            // update the parent subgame's `countered` address and the current `leftmostCounter`.\n            // The left-most correct counter is preferred in bond payouts in order to discourage attackers\n            // from countering invalid subgame roots via an invalid defense position. As such positions\n            // cannot be correctly countered.\n            // Note that correctly positioned defense, but invalid claimes can still be successfully countered.\n            if (claim.counteredBy == address(0) && checkpoint.leftmostPosition.raw() > claim.position.raw()) {\n                checkpoint.counteredBy = claim.claimant;\n                checkpoint.leftmostPosition = claim.position;\n            }\n        }\n\n        // Increase the checkpoint's cursor position by the number of children that were checked.\n        checkpoint.subgameIndex = uint32(finalCursor);\n\n        // Persist the checkpoint and allow for continuing in a separate transaction, if resolution is not already\n        // complete.\n        resolutionCheckpoints[_claimIndex] = checkpoint;\n\n        // If all children have been traversed in the above loop, the subgame may be resolved. Otherwise, persist the\n        // checkpoint and allow for continuation in a separate transaction.\n        if (checkpoint.subgameIndex == challengeIndicesLen) {\n            address countered = checkpoint.counteredBy;\n\n            // Mark the subgame as resolved.\n            resolvedSubgames[_claimIndex] = true;\n\n            // Distribute the bond to the appropriate party.\n            if (_claimIndex == 0 && l2BlockNumberChallenged) {\n                // Special case: If the root claim has been challenged with the `challengeRootL2Block` function,\n                // the bond is always paid out to the issuer of that challenge.\n                address challenger = l2BlockNumberChallenger;\n                _distributeBond(challenger, subgameRootClaim);\n                subgameRootClaim.counteredBy = challenger;\n            } else {\n                // If the parent was not successfully countered, pay out the parent's bond to the claimant.\n                // If the parent was successfully countered, pay out the parent's bond to the challenger.\n                _distributeBond(countered == address(0) ? subgameRootClaim.claimant : countered, subgameRootClaim);\n\n                // Once a subgame is resolved, we percolate the result up the DAG so subsequent calls to\n                // resolveClaim will not need to traverse this subgame.\n                subgameRootClaim.counteredBy = countered;\n            }\n        }\n    }\n\n    /// @inheritdoc IDisputeGame\n    function gameType() public view override returns (GameType gameType_) {\n        gameType_ = GAME_TYPE;\n    }\n\n    /// @inheritdoc IDisputeGame\n    function gameCreator() public pure returns (address creator_) {\n        creator_ = _getArgAddress(0x00);\n    }\n\n    /// @inheritdoc IDisputeGame\n    function rootClaim() public pure returns (Claim rootClaim_) {\n        rootClaim_ = Claim.wrap(_getArgBytes32(0x14));\n    }\n\n    /// @inheritdoc IDisputeGame\n    function l1Head() public pure returns (Hash l1Head_) {\n        l1Head_ = Hash.wrap(_getArgBytes32(0x34));\n    }\n\n    /// @inheritdoc IDisputeGame\n    function extraData() public pure returns (bytes memory extraData_) {\n        // The extra data starts at the second word within the cwia calldata and\n        // is 32 bytes long.\n        extraData_ = _getArgBytes(0x54, 0x20);\n    }\n\n    /// @inheritdoc IDisputeGame\n    function gameData() external view returns (GameType gameType_, Claim rootClaim_, bytes memory extraData_) {\n        gameType_ = gameType();\n        rootClaim_ = rootClaim();\n        extraData_ = extraData();\n    }\n\n    ////////////////////////////////////////////////////////////////\n    //                       MISC EXTERNAL                        //\n    ////////////////////////////////////////////////////////////////\n\n    /// @notice Returns the required bond for a given move kind.\n    /// @param _position The position of the bonded interaction.\n    /// @return requiredBond_ The required ETH bond for the given move, in wei.\n    function getRequiredBond(Position _position) public view returns (uint256 requiredBond_) {\n        uint256 depth = uint256(_position.depth());\n        if (depth > MAX_GAME_DEPTH) revert GameDepthExceeded();\n\n        // Values taken from Big Bonds v1.5 (TM) spec.\n        uint256 assumedBaseFee = 200 gwei;\n        uint256 baseGasCharged = 400_000;\n        uint256 highGasCharged = 300_000_000;\n\n        // Goal here is to compute the fixed multiplier that will be applied to the base gas\n        // charged to get the required gas amount for the given depth. We apply this multiplier\n        // some `n` times where `n` is the depth of the position. We are looking for some number\n        // that, when multiplied by itself `MAX_GAME_DEPTH` times and then multiplied by the base\n        // gas charged, will give us the maximum gas that we want to charge.\n        // We want to solve for (highGasCharged/baseGasCharged) ** (1/MAX_GAME_DEPTH).\n        // We know that a ** (b/c) is equal to e ** (ln(a) * (b/c)).\n        // We can compute e ** (ln(a) * (b/c)) quite easily with FixedPointMathLib.\n\n        // Set up a, b, and c.\n        uint256 a = highGasCharged / baseGasCharged;\n        uint256 b = FixedPointMathLib.WAD;\n        uint256 c = MAX_GAME_DEPTH * FixedPointMathLib.WAD;\n\n        // Compute ln(a).\n        // slither-disable-next-line divide-before-multiply\n        uint256 lnA = uint256(FixedPointMathLib.lnWad(int256(a * FixedPointMathLib.WAD)));\n\n        // Computes (b / c) with full precision using WAD = 1e18.\n        uint256 bOverC = FixedPointMathLib.divWad(b, c);\n\n        // Compute e ** (ln(a) * (b/c))\n        // sMulWad can be used here since WAD = 1e18 maintains the same precision.\n        uint256 numerator = FixedPointMathLib.mulWad(lnA, bOverC);\n        int256 base = FixedPointMathLib.expWad(int256(numerator));\n\n        // Compute the required gas amount.\n        int256 rawGas = FixedPointMathLib.powWad(base, int256(depth * FixedPointMathLib.WAD));\n        uint256 requiredGas = FixedPointMathLib.mulWad(baseGasCharged, uint256(rawGas));\n\n        // Compute the required bond.\n        requiredBond_ = assumedBaseFee * requiredGas;\n    }\n\n    /// @notice Claim the credit belonging to the recipient address.\n    /// @param _recipient The owner and recipient of the credit.\n    function claimCredit(address _recipient) external {\n        // Remove the credit from the recipient prior to performing the external call.\n        uint256 recipientCredit = credit[_recipient];\n        credit[_recipient] = 0;\n\n        // Revert if the recipient has no credit to claim.\n        if (recipientCredit == 0) revert NoCreditToClaim();\n\n        // Try to withdraw the WETH amount so it can be used here.\n        WETH.withdraw(_recipient, recipientCredit);\n\n        // Transfer the credit to the recipient.\n        (bool success,) = _recipient.call{value : recipientCredit}(hex\"\");\n        if (!success) revert BondTransferFailed();\n    }\n\n    /// @notice Returns the amount of time elapsed on the potential challenger to `_claimIndex`'s chess clock. Maxes\n    ///         out at `MAX_CLOCK_DURATION`.\n    /// @param _claimIndex The index of the subgame root claim.\n    /// @return duration_ The time elapsed on the potential challenger to `_claimIndex`'s chess clock.\n    function getChallengerDuration(uint256 _claimIndex) public view returns (Duration duration_) {\n        // INVARIANT: The game must be in progress to query the remaining time to respond to a given claim.\n        if (status != GameStatus.IN_PROGRESS) {\n            revert GameNotInProgress();\n        }\n\n        // Fetch the subgame root claim.\n        ClaimData storage subgameRootClaim = claimData[_claimIndex];\n\n        // Fetch the parent of the subgame root's clock, if it exists.\n        Clock parentClock;\n        if (subgameRootClaim.parentIndex != type(uint32).max) {\n            parentClock = claimData[subgameRootClaim.parentIndex].clock;\n        }\n\n        // Compute the duration elapsed of the potential challenger's clock.\n        uint64 challengeDuration =\n                            uint64(parentClock.duration().raw() + (block.timestamp - subgameRootClaim.clock.timestamp().raw()));\n        duration_ = challengeDuration > MAX_CLOCK_DURATION.raw() ? MAX_CLOCK_DURATION : Duration.wrap(challengeDuration);\n    }\n\n    /// @notice Returns the length of the `claimData` array.\n    function claimDataLen() external view returns (uint256 len_) {\n        len_ = claimData.length;\n    }\n\n    ////////////////////////////////////////////////////////////////\n    //                     IMMUTABLE GETTERS                      //\n    ////////////////////////////////////////////////////////////////\n\n    /// @notice Returns the absolute prestate of the instruction trace.\n    function absolutePrestate() external view returns (Claim absolutePrestate_) {\n        absolutePrestate_ = ABSOLUTE_PRESTATE;\n    }\n\n    /// @notice Returns the max game depth.\n    function maxGameDepth() external view returns (uint256 maxGameDepth_) {\n        maxGameDepth_ = MAX_GAME_DEPTH;\n    }\n\n    /// @notice Returns the split depth.\n    function splitDepth() external view returns (uint256 splitDepth_) {\n        splitDepth_ = SPLIT_DEPTH;\n    }\n\n    /// @notice Returns the max clock duration.\n    function maxClockDuration() external view returns (Duration maxClockDuration_) {\n        maxClockDuration_ = MAX_CLOCK_DURATION;\n    }\n\n    /// @notice Returns the clock extension constant.\n    function clockExtension() external view returns (Duration clockExtension_) {\n        clockExtension_ = CLOCK_EXTENSION;\n    }\n\n    /// @notice Returns the address of the VM.\n    function vm() external view returns (IBigStepper vm_) {\n        vm_ = VM;\n    }\n\n    /// @notice Returns the WETH contract for holding ETH.\n    function weth() external view returns (IDelayedWETH weth_) {\n        weth_ = WETH;\n    }\n\n    /// @notice Returns the anchor state registry contract.\n    function scc() external view returns (IMVMStateCommitmentChain scc_) {\n        scc_ = IMVMStateCommitmentChain(ADDRESS_MANAGER.getAddress(SCC_NAME));\n    }\n\n    /// @notice Returns the chain ID of the L2 network this contract argues about.\n    function l2ChainId() external view returns (uint256 l2ChainId_) {\n        l2ChainId_ = L2_CHAIN_ID;\n    }\n\n    ////////////////////////////////////////////////////////////////\n    //                          HELPERS                           //\n    ////////////////////////////////////////////////////////////////\n\n    /// @notice Pays out the bond of a claim to a given recipient.\n    /// @param _recipient The recipient of the bond.\n    /// @param _bonded The claim to pay out the bond of.\n    function _distributeBond(address _recipient, ClaimData storage _bonded) internal {\n        // Set all bits in the bond value to indicate that the bond has been paid out.\n        uint256 bond = _bonded.bond;\n\n        // Increase the recipient's credit.\n        credit[_recipient] += bond;\n\n        // Unlock the bond.\n        WETH.unlock(_recipient, bond);\n    }\n\n    /// @notice Verifies the integrity of an execution bisection subgame's root claim. Reverts if the claim\n    ///         is invalid.\n    /// @param _rootClaim The root claim of the execution bisection subgame.\n    function _verifyExecBisectionRoot(\n        Claim _rootClaim,\n        uint256 _parentIdx,\n        Position _parentPos,\n        bool _isAttack\n    )\n    internal\n    view\n    {\n        // The root claim of an execution trace bisection sub-game must:\n        // 1. Signal that the VM panicked or resulted in an invalid transition if the disputed output root\n        //    was made by the opposing party.\n        // 2. Signal that the VM resulted in a valid transition if the disputed output root was made by the same party.\n\n        // If the move is a defense, the disputed output could have been made by either party. In this case, we\n        // need to search for the parent output to determine what the expected status byte should be.\n        Position disputedLeafPos = Position.wrap(_parentPos.raw() + 1);\n        ClaimData storage disputed = _findTraceAncestor({_pos: disputedLeafPos, _start: _parentIdx, _global: true});\n        uint8 vmStatus = uint8(_rootClaim.raw()[0]);\n\n        if (_isAttack || disputed.position.depth() % 2 == SPLIT_DEPTH % 2) {\n            // If the move is an attack, the parent output is always deemed to be disputed. In this case, we only need\n            // to check that the root claim signals that the VM panicked or resulted in an invalid transition.\n            // If the move is a defense, and the disputed output and creator of the execution trace subgame disagree,\n            // the root claim should also signal that the VM panicked or resulted in an invalid transition.\n            if (!(vmStatus == VMStatuses.INVALID.raw() || vmStatus == VMStatuses.PANIC.raw())) {\n                revert UnexpectedRootClaim(_rootClaim);\n            }\n        } else if (vmStatus != VMStatuses.VALID.raw()) {\n            // The disputed output and the creator of the execution trace subgame agree. The status byte should\n            // have signaled that the VM succeeded.\n            revert UnexpectedRootClaim(_rootClaim);\n        }\n    }\n\n    /// @notice Finds the trace ancestor of a given position within the DAG.\n    /// @param _pos The position to find the trace ancestor claim of.\n    /// @param _start The index to start searching from.\n    /// @param _global Whether or not to search the entire dag or just within an execution trace subgame. If set to\n    ///                `true`, and `_pos` is at or above the split depth, this function will revert.\n    /// @return ancestor_ The ancestor claim that commits to the same trace index as `_pos`.\n    function _findTraceAncestor(\n        Position _pos,\n        uint256 _start,\n        bool _global\n    )\n    internal\n    view\n    returns (ClaimData storage ancestor_)\n    {\n        // Grab the trace ancestor's expected position.\n        Position traceAncestorPos = _global ? _pos.traceAncestor() : _pos.traceAncestorBounded(SPLIT_DEPTH);\n\n        // Walk up the DAG to find a claim that commits to the same trace index as `_pos`. It is\n        // guaranteed that such a claim exists.\n        ancestor_ = claimData[_start];\n        while (ancestor_.position.raw() != traceAncestorPos.raw()) {\n            ancestor_ = claimData[ancestor_.parentIndex];\n        }\n    }\n\n    /// @notice Finds the starting and disputed output root for a given `ClaimData` within the DAG. This\n    ///         `ClaimData` must be below the `SPLIT_DEPTH`.\n    /// @param _start The index within `claimData` of the claim to start searching from.\n    /// @return startingClaim_ The starting output root claim.\n    /// @return startingPos_ The starting output root position.\n    /// @return disputedClaim_ The disputed output root claim.\n    /// @return disputedPos_ The disputed output root position.\n    function _findStartingAndDisputedOutputs(uint256 _start)\n    internal\n    view\n    returns (Claim startingClaim_, Position startingPos_, Claim disputedClaim_, Position disputedPos_)\n    {\n        // Fatch the starting claim.\n        uint256 claimIdx = _start;\n        ClaimData storage claim = claimData[claimIdx];\n\n        // If the starting claim's depth is less than or equal to the split depth, we revert as this is UB.\n        if (claim.position.depth() <= SPLIT_DEPTH) revert ClaimAboveSplit();\n\n        // We want to:\n        // 1. Find the first claim at the split depth.\n        // 2. Determine whether it was the starting or disputed output for the exec game.\n        // 3. Find the complimentary claim depending on the info from #2 (pre or post).\n\n        // Walk up the DAG until the ancestor's depth is equal to the split depth.\n        uint256 currentDepth;\n        ClaimData storage execRootClaim = claim;\n        while ((currentDepth = claim.position.depth()) > SPLIT_DEPTH) {\n            uint256 parentIndex = claim.parentIndex;\n\n            // If we're currently at the split depth + 1, we're at the root of the execution sub-game.\n            // We need to keep track of the root claim here to determine whether the execution sub-game was\n            // started with an attack or defense against the output leaf claim.\n            if (currentDepth == SPLIT_DEPTH + 1) execRootClaim = claim;\n\n            claim = claimData[parentIndex];\n            claimIdx = parentIndex;\n        }\n\n        // Determine whether the start of the execution sub-game was an attack or defense to the output root\n        // above. This is important because it determines which claim is the starting output root and which\n        // is the disputed output root.\n        (Position execRootPos, Position outputPos) = (execRootClaim.position, claim.position);\n        bool wasAttack = execRootPos.parent().raw() == outputPos.raw();\n\n        // Determine the starting and disputed output root indices.\n        // 1. If it was an attack, the disputed output root is `claim`, and the starting output root is\n        //    elsewhere in the DAG (it must commit to the block # index at depth of `outputPos - 1`).\n        // 2. If it was a defense, the starting output root is `claim`, and the disputed output root is\n        //    elsewhere in the DAG (it must commit to the block # index at depth of `outputPos + 1`).\n        if (wasAttack) {\n            // If this is an attack on the first output root (the block directly after the starting\n            // block number), the starting claim nor position exists in the tree. We leave these as\n            // 0, which can be easily identified due to 0 being an invalid Gindex.\n            if (outputPos.indexAtDepth() > 0) {\n                ClaimData storage starting = _findTraceAncestor(Position.wrap(outputPos.raw() - 1), claimIdx, true);\n                (startingClaim_, startingPos_) = (starting.claim, starting.position);\n            } else {\n                startingClaim_ = Claim.wrap(startingOutputRoot.root.raw());\n            }\n            (disputedClaim_, disputedPos_) = (claim.claim, claim.position);\n        } else {\n            ClaimData storage disputed = _findTraceAncestor(Position.wrap(outputPos.raw() + 1), claimIdx, true);\n            (startingClaim_, startingPos_) = (claim.claim, claim.position);\n            (disputedClaim_, disputedPos_) = (disputed.claim, disputed.position);\n        }\n    }\n\n    /// @notice Finds the local context hash for a given claim index that is present in an execution trace subgame.\n    /// @param _claimIndex The index of the claim to find the local context hash for.\n    /// @return uuid_ The local context hash.\n    function _findLocalContext(uint256 _claimIndex) internal view returns (Hash uuid_) {\n        (Claim starting, Position startingPos, Claim disputed, Position disputedPos) =\n                        _findStartingAndDisputedOutputs(_claimIndex);\n        uuid_ = _computeLocalContext(starting, startingPos, disputed, disputedPos);\n    }\n\n    /// @notice Computes the local context hash for a set of starting/disputed claim values and positions.\n    /// @param _starting The starting claim.\n    /// @param _startingPos The starting claim's position.\n    /// @param _disputed The disputed claim.\n    /// @param _disputedPos The disputed claim's position.\n    /// @return uuid_ The local context hash.\n    function _computeLocalContext(\n        Claim _starting,\n        Position _startingPos,\n        Claim _disputed,\n        Position _disputedPos\n    )\n    internal\n    pure\n    returns (Hash uuid_)\n    {\n        // A position of 0 indicates that the starting claim is the absolute prestate. In this special case,\n        // we do not include the starting claim within the local context hash.\n        uuid_ = _startingPos.raw() == 0\n            ? Hash.wrap(keccak256(abi.encode(_disputed, _disputedPos)))\n            : Hash.wrap(keccak256(abi.encode(_starting, _startingPos, _disputed, _disputedPos)));\n    }\n\n    /// @notice Emitted when slashing fails\n    event SlashingFailed(address indexed intendedRecipient);\n}\n"
    },
    "contracts/L1/dispute/interfaces/IAnchorStateRegistry.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IDisputeGameFactory} from \"./IDisputeGameFactory.sol\";\nimport {IFaultDisputeGame} from \"./IFaultDisputeGame.sol\";\n\nimport \"contracts/L1/dispute/lib/Types.sol\";\n\n/// @title IAnchorStateRegistry\n/// @notice Describes a contract that stores the anchor state for each game type.\ninterface IAnchorStateRegistry {\n    /// @notice Returns the anchor state for the given game type.\n    /// @param _gameType The game type to get the anchor state for.\n    /// @return The anchor state for the given game type.\n    function anchors(GameType _gameType) external view returns (Hash, uint256);\n\n    /// @notice Returns the DisputeGameFactory address.\n    /// @return DisputeGameFactory address.\n    function disputeGameFactory() external view returns (IDisputeGameFactory);\n\n    /// @notice Callable by FaultDisputeGame contracts to update the anchor state. Pulls the anchor state directly from\n    ///         the FaultDisputeGame contract and stores it in the registry if the new anchor state is valid and the\n    ///         state is newer than the current anchor state.\n    function tryUpdateAnchorState() external;\n\n    /// @notice Sets the anchor state given the game.\n    /// @param _game The game to set the anchor state for.\n    function setAnchorState(IFaultDisputeGame _game) external;\n}\n"
    },
    "contracts/L1/dispute/interfaces/IBigStepper.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IPreimageOracle} from \"../../cannon/interfaces/IPreimageOracle.sol\";\n\n/// @title IBigStepper\n/// @notice Describes a state machine that can perform a single instruction step, provided a prestate and an optional\n///         proof.\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⠶⢅⠒⢄⢔⣶⡦⣤⡤⠄⣀⠀⠀⠀⠀⠀⠀⠀\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠨⡏⠀⠀⠈⠢⣙⢯⣄⠀⢨⠯⡺⡘⢄⠀⠀⠀⠀⠀\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣶⡆⠀⠀⠀⠀⠈⠓⠬⡒⠡⣀⢙⡜⡀⠓⠄⠀⠀⠀\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡷⠿⣧⣀⡀⠀⠀⠀⠀⠀⠀⠉⠣⣞⠩⠥⠀⠼⢄⠀⠀\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⠀⠉⢹⣶⠒⠒⠂⠈⠉⠁⠘⡆⠀⣿⣿⠫⡄⠀\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⢶⣤⣀⡀⠀⠀⢸⡿⠀⠀⠀⠀⠀⢀⠞⠀⠀⢡⢨⢀⡄⠀\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡒⣿⢿⡤⠝⡣⠉⠁⠚⠛⠀⠤⠤⣄⡰⠁⠀⠀⠀⠉⠙⢸⠀⠀\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡤⢯⡌⡿⡇⠘⡷⠀⠁⠀⠀⢀⣰⠢⠲⠛⣈⣸⠦⠤⠶⠴⢬⣐⣊⡂⠀\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⡪⡗⢫⠞⠀⠆⣀⠻⠤⠴⠐⠚⣉⢀⠦⠂⠋⠁⠀⠁⠀⠀⠀⠀⢋⠉⠇⠀\n/// ⠀⠀⠀⠀⣀⡤⠐⠒⠘⡹⠉⢸⠇⠸⠀⠀⠀⠀⣀⣤⠴⠚⠉⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⠀⣾⠀\n/// ⠀⠀⠀⡰⠀⠉⠉⠀⠁⠀⠀⠈⢇⠈⠒⠒⠘⠈⢀⢡⡂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠀⢸⡄\n/// ⠀⠀⠸⣿⣆⠤⢀⡀⠀⠀⠀⠀⢘⡌⠀⠀⣀⣀⣀⡈⣤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⢸⡇\n/// ⠀⠀⢸⣀⠀⠉⠒⠐⠛⠋⠭⠭⠍⠉⠛⠒⠒⠒⠀⠒⠚⠛⠛⠛⠩⠭⠭⠭⠭⠤⠤⠤⠤⠤⠭⠭⠉⠓⡆\n/// ⠀⠀⠘⠿⣷⣶⣤⣤⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇\n/// ⠀⠀⠀⠀⠀⠉⠙⠛⠛⠻⠿⢿⣿⣿⣷⣶⣶⣶⣤⣤⣀⣁⣛⣃⣒⠿⠿⠿⠤⠠⠄⠤⠤⢤⣛⣓⣂⣻⡇\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠙⠛⠻⠿⠿⠿⢿⣿⣿⣿⣷⣶⣶⣾⣿⣿⣿⣿⠿⠟⠁\n/// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀\ninterface IBigStepper {\n    /// @notice Performs the state transition from a given prestate and returns the hash of the post state witness.\n    /// @param _stateData The raw opaque prestate data.\n    /// @param _proof Opaque proof data, can be used to prove things about the prestate in relation to the state of the\n    ///               interface's implementation.\n    /// @param _localContext The local key context for the preimage oracle. Optional, can be set as a constant if the\n    ///                      implementation only requires one set of local keys.\n    /// @return postState_ The hash of the post state witness after the state transition.\n    function step(\n        bytes calldata _stateData,\n        bytes calldata _proof,\n        bytes32 _localContext\n    )\n    external\n    returns (bytes32 postState_);\n\n    /// @notice Returns the preimage oracle used by the state machine.\n    function oracle() external view returns (IPreimageOracle oracle_);\n}\n"
    },
    "contracts/L1/dispute/interfaces/IDelayedWETH.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IWETH} from \"./IWETH.sol\";\n\n/// @title IDelayedWETH\n/// @notice Interface for the DelayedWETH contract.\ninterface IDelayedWETH is IWETH {\n    /// @notice Represents a withdrawal request.\n    struct WithdrawalRequest {\n        uint256 amount;\n        uint256 timestamp;\n    }\n\n    /// @notice Emitted when an unwrap is started.\n    /// @param src The address that started the unwrap.\n    /// @param wad The amount of WETH that was unwrapped.\n    event Unwrap(address indexed src, uint256 wad);\n\n    /// @notice Returns the withdrawal delay in seconds.\n    /// @return The withdrawal delay in seconds.\n    function delay() external view returns (uint256);\n\n    /// @notice Returns a withdrawal request for the given address.\n    /// @param _owner The address to query the withdrawal request of.\n    /// @param _guy Sub-account to query the withdrawal request of.\n    /// @return The withdrawal request for the given address-subaccount pair.\n    function withdrawals(address _owner, address _guy) external view returns (uint256, uint256);\n\n    /// @notice Unlocks withdrawals for the sender's account, after a time delay.\n    /// @param _guy Sub-account to unlock.\n    /// @param _wad The amount of WETH to unlock.\n    function unlock(address _guy, uint256 _wad) external;\n\n    /// @notice Extension to withdrawal, must provide a sub-account to withdraw from.\n    /// @param _guy Sub-account to withdraw from.\n    /// @param _wad The amount of WETH to withdraw.\n    function withdraw(address _guy, uint256 _wad) external;\n\n    /// @notice Allows the owner to recover from error cases by pulling ETH out of the contract.\n    /// @param _wad The amount of WETH to recover.\n    function recover(uint256 _wad) external;\n\n    /// @notice Allows the owner to recover from error cases by pulling ETH from a specific owner.\n    /// @param _guy The address to recover the WETH from.\n    /// @param _wad The amount of WETH to recover.\n    function hold(address _guy, uint256 _wad) external;\n}\n"
    },
    "contracts/L1/dispute/interfaces/IDisputeGame.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IInitializable} from \"./IInitializable.sol\";\n\nimport \"contracts/L1/dispute/lib/Types.sol\";\n\n/// @title IDisputeGame\n/// @notice The generic interface for a DisputeGame contract.\ninterface IDisputeGame is IInitializable {\n    /// @notice Emitted when the game is resolved.\n    /// @param status The status of the game after resolution.\n    event Resolved(GameStatus indexed status);\n\n    /// @notice Returns the timestamp that the DisputeGame contract was created at.\n    /// @return createdAt_ The timestamp that the DisputeGame contract was created at.\n    function createdAt() external view returns (Timestamp createdAt_);\n\n    /// @notice Returns the timestamp that the DisputeGame contract was resolved at.\n    /// @return resolvedAt_ The timestamp that the DisputeGame contract was resolved at.\n    function resolvedAt() external view returns (Timestamp resolvedAt_);\n\n    /// @notice Returns the current status of the game.\n    /// @return status_ The current status of the game.\n    function status() external view returns (GameStatus status_);\n\n    /// @notice Getter for the game type.\n    /// @dev The reference impl should be entirely different depending on the type (fault, validity)\n    ///      i.e. The game type should indicate the security model.\n    /// @return gameType_ The type of proof system being used.\n    function gameType() external view returns (GameType gameType_);\n\n    /// @notice Getter for the creator of the dispute game.\n    /// @dev `clones-with-immutable-args` argument #1\n    /// @return creator_ The creator of the dispute game.\n    function gameCreator() external pure returns (address creator_);\n\n    /// @notice Getter for the root claim.\n    /// @dev `clones-with-immutable-args` argument #2\n    /// @return rootClaim_ The root claim of the DisputeGame.\n    function rootClaim() external pure returns (Claim rootClaim_);\n\n    /// @notice Getter for the parent hash of the L1 block when the dispute game was created.\n    /// @dev `clones-with-immutable-args` argument #3\n    /// @return l1Head_ The parent hash of the L1 block when the dispute game was created.\n    function l1Head() external pure returns (Hash l1Head_);\n\n    /// @notice Getter for the extra data.\n    /// @dev `clones-with-immutable-args` argument #4\n    /// @return extraData_ Any extra data supplied to the dispute game contract by the creator.\n    function extraData() external pure returns (bytes memory extraData_);\n\n    /// @notice If all necessary information has been gathered, this function should mark the game\n    ///         status as either `CHALLENGER_WINS` or `DEFENDER_WINS` and return the status of\n    ///         the resolved game. It is at this stage that the bonds should be awarded to the\n    ///         necessary parties.\n    /// @dev May only be called if the `status` is `IN_PROGRESS`.\n    /// @return status_ The status of the game after resolution.\n    function resolve() external returns (GameStatus status_);\n\n    /// @notice A compliant implementation of this interface should return the components of the\n    ///         game UUID's preimage provided in the cwia payload. The preimage of the UUID is\n    ///         constructed as `keccak256(gameType . rootClaim . extraData)` where `.` denotes\n    ///         concatenation.\n    /// @return gameType_ The type of proof system being used.\n    /// @return rootClaim_ The root claim of the DisputeGame.\n    /// @return extraData_ Any extra data supplied to the dispute game contract by the creator.\n    function gameData() external view returns (GameType gameType_, Claim rootClaim_, bytes memory extraData_);\n}\n"
    },
    "contracts/L1/dispute/interfaces/IDisputeGameFactory.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IDisputeGame} from \"./IDisputeGame.sol\";\n\nimport \"contracts/L1/dispute/lib/Types.sol\";\n\n/// @title IDisputeGameFactory\n/// @notice The interface for a DisputeGameFactory contract.\ninterface IDisputeGameFactory {\n    /// @notice Emitted when a new dispute game is requested\n    /// @param requestor The address of the requestor\n    /// @param gameType The type of the dispute game\n    /// @param bond The bond (in wei) for initializing the game type\n    //. @param extraData Any extra data that should be provided to the created dispute game.\n    event DisputeGameRequested(address indexed requestor, GameType indexed gameType, uint256 bond, bytes extraData);\n\n    /// @notice Emitted when a new dispute game is created\n    /// @param disputeProxy The address of the dispute game proxy\n    /// @param gameType The type of the dispute game proxy's implementation\n    /// @param rootClaim The root claim of the dispute game\n    event DisputeGameCreated(address indexed disputeProxy, GameType indexed gameType, Claim indexed rootClaim);\n\n    /// @notice Emitted when a new game implementation added to the factory\n    /// @param impl The implementation contract for the given `GameType`.\n    /// @param gameType The type of the DisputeGame.\n    event ImplementationSet(address indexed impl, GameType indexed gameType);\n\n    /// @notice Emitted when a game type's initialization bond is updated\n    /// @param gameType The type of the DisputeGame.\n    /// @param newBond The new bond (in wei) for initializing the game type.\n    event InitBondUpdated(GameType indexed gameType, uint256 indexed newBond);\n\n    /// @notice Information about a dispute game found in a `findLatestGames` search.\n    struct GameSearchResult {\n        uint256 index;\n        GameId metadata;\n        Timestamp timestamp;\n        Claim rootClaim;\n        bytes extraData;\n    }\n\n    /// @notice The total number of dispute games created by this factory.\n    /// @return gameCount_ The total number of dispute games created by this factory.\n    function gameCount() external view returns (uint256 gameCount_);\n\n    /// @notice `games` queries an internal mapping that maps the hash of\n    ///         `gameType ++ rootClaim ++ extraData` to the deployed `DisputeGame` clone.\n    /// @dev `++` equates to concatenation.\n    /// @param _gameType The type of the DisputeGame - used to decide the proxy implementation\n    /// @param _rootClaim The root claim of the DisputeGame.\n    /// @param _extraData Any extra data that should be provided to the created dispute game.\n    /// @return proxy_ The clone of the `DisputeGame` created with the given parameters.\n    ///         Returns `address(0)` if nonexistent.\n    /// @return timestamp_ The timestamp of the creation of the dispute game.\n    function games(\n        GameType _gameType,\n        Claim _rootClaim,\n        bytes calldata _extraData\n    )\n    external\n    view\n    returns (IDisputeGame proxy_, Timestamp timestamp_);\n\n    /// @notice `gameAtIndex` returns the dispute game contract address and its creation timestamp\n    ///          at the given index. Each created dispute game increments the underlying index.\n    /// @param _index The index of the dispute game.\n    /// @return gameType_ The type of the DisputeGame - used to decide the proxy implementation.\n    /// @return timestamp_ The timestamp of the creation of the dispute game.\n    /// @return proxy_ The clone of the `DisputeGame` created with the given parameters.\n    ///         Returns `address(0)` if nonexistent.\n    function gameAtIndex(uint256 _index)\n    external\n    view\n    returns (GameType gameType_, Timestamp timestamp_, IDisputeGame proxy_);\n\n    /// @notice `gameImpls` is a mapping that maps `GameType`s to their respective\n    ///         `IDisputeGame` implementations.\n    /// @param _gameType The type of the dispute game.\n    /// @return impl_ The address of the implementation of the game type.\n    ///         Will be cloned on creation of a new dispute game with the given `gameType`.\n    function gameImpls(GameType _gameType) external view returns (IDisputeGame impl_);\n\n    /// @notice Returns the required bonds for initializing a dispute game of the given type.\n    /// @param _gameType The type of the dispute game.\n    /// @return bond_ The required bond for initializing a dispute game of the given type.\n    function initBonds(GameType _gameType) external view returns (uint256 bond_);\n\n    /// @notice Requests a new dispute game of the given type.\n    /// @dev Emits a `DisputeGameRequested` event.\n    /// @param _gameType The type of the dispute game.\n    /// @param _extraData Any extra data that should be provided to the created dispute game.\n    function dispute(GameType _gameType, bytes calldata _extraData) external payable;\n\n    /// @notice Creates a new DisputeGame proxy contract.\n    /// @param _gameType The type of the DisputeGame - used to decide the proxy implementation.\n    /// @param _rootClaim The root claim of the DisputeGame.\n    /// @param _extraData Any extra data that should be provided to the created dispute game.\n    /// @return proxy_ The address of the created DisputeGame proxy.\n    function create(\n        GameType _gameType,\n        Claim _rootClaim,\n        bytes calldata _extraData\n    )\n    external\n    returns (IDisputeGame proxy_);\n\n    /// @notice Sets the implementation contract for a specific `GameType`.\n    /// @dev May only be called by the `owner`.\n    /// @param _gameType The type of the DisputeGame.\n    /// @param _impl The implementation contract for the given `GameType`.\n    function setImplementation(GameType _gameType, IDisputeGame _impl) external;\n\n    /// @notice Sets the bond (in wei) for initializing a game type.\n    /// @dev May only be called by the `owner`.\n    /// @param _gameType The type of the DisputeGame.\n    /// @param _initBond The bond (in wei) for initializing a game type.\n    function setInitBond(GameType _gameType, uint256 _initBond) external;\n\n    /// @notice Returns a unique identifier for the given dispute game parameters.\n    /// @dev Hashes the concatenation of `gameType . rootClaim . extraData`\n    ///      without expanding memory.\n    /// @param _gameType The type of the DisputeGame.\n    /// @param _rootClaim The root claim of the DisputeGame.\n    /// @param _extraData Any extra data that should be provided to the created dispute game.\n    /// @return uuid_ The unique identifier for the given dispute game parameters.\n    function getGameUUID(\n        GameType _gameType,\n        Claim _rootClaim,\n        bytes memory _extraData\n    )\n    external\n    pure\n    returns (Hash uuid_);\n\n    /// @notice Finds the `_n` most recent `GameId`'s of type `_gameType` starting at `_start`. If there are less than\n    ///         `_n` games of type `_gameType` starting at `_start`, then the returned array will be shorter than `_n`.\n    /// @param _gameType The type of game to find.\n    /// @param _start The index to start the reverse search from.\n    /// @param _n The number of games to find.\n    function findLatestGames(\n        GameType _gameType,\n        uint256 _start,\n        uint256 _n\n    )\n    external\n    view\n    returns (GameSearchResult[] memory games_);\n}\n"
    },
    "contracts/L1/dispute/interfaces/IFaultDisputeGame.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IDisputeGame} from \"./IDisputeGame.sol\";\n\nimport \"contracts/L1/dispute/lib/Types.sol\";\n\n/// @title IFaultDisputeGame\n/// @notice The interface for a fault proof backed dispute game.\ninterface IFaultDisputeGame is IDisputeGame {\n    /// @notice The `ClaimData` struct represents the data associated with a Claim.\n    struct ClaimData {\n        uint32 parentIndex;\n        address counteredBy;\n        address claimant;\n        uint128 bond;\n        Claim claim;\n        Position position;\n        Clock clock;\n    }\n\n    /// @notice The `ResolutionCheckpoint` struct represents the data associated with an in-progress claim resolution.\n    struct ResolutionCheckpoint {\n        bool initialCheckpointComplete;\n        uint32 subgameIndex;\n        Position leftmostPosition;\n        address counteredBy;\n    }\n\n    /// @notice Emitted when a new claim is added to the DAG by `claimant`\n    /// @param parentIndex The index within the `claimData` array of the parent claim\n    /// @param claim The claim being added\n    /// @param claimant The address of the claimant\n    event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant);\n\n    /// @notice Attack a disagreed upon `Claim`.\n    /// @param _disputed The `Claim` being attacked.\n    /// @param _parentIndex Index of the `Claim` to attack in the `claimData` array. This must match the `_disputed`\n    /// claim.\n    /// @param _claim The `Claim` at the relative attack position.\n    function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable;\n\n    /// @notice Defend an agreed upon `Claim`.\n    /// @notice _disputed The `Claim` being defended.\n    /// @param _parentIndex Index of the claim to defend in the `claimData` array. This must match the `_disputed`\n    /// claim.\n    /// @param _claim The `Claim` at the relative defense position.\n    function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable;\n\n    /// @notice Perform an instruction step via an on-chain fault proof processor.\n    /// @dev This function should point to a fault proof processor in order to execute\n    ///      a step in the fault proof program on-chain. The interface of the fault proof\n    ///      processor contract should adhere to the `IBigStepper` interface.\n    /// @param _claimIndex The index of the challenged claim within `claimData`.\n    /// @param _isAttack Whether or not the step is an attack or a defense.\n    /// @param _stateData The stateData of the step is the preimage of the claim at the given\n    ///        prestate, which is at `_stateIndex` if the move is an attack and `_claimIndex` if\n    ///        the move is a defense. If the step is an attack on the first instruction, it is\n    ///        the absolute prestate of the fault proof VM.\n    /// @param _proof Proof to access memory nodes in the VM's merkle state tree.\n    function step(uint256 _claimIndex, bool _isAttack, bytes calldata _stateData, bytes calldata _proof) external;\n\n    /// @notice Posts the requested local data to the VM's `PreimageOralce`.\n    /// @param _ident The local identifier of the data to post.\n    /// @param _execLeafIdx The index of the leaf claim in an execution subgame that requires the local data for a step.\n    /// @param _partOffset The offset of the data to post.\n    function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external;\n\n    /// @notice Resolves the subgame rooted at the given claim index. `_numToResolve` specifies how many children of\n    ///         the subgame will be checked in this call. If `_numToResolve` is less than the number of children, an\n    ///         internal cursor will be updated and this function may be called again to complete resolution of the\n    ///         subgame.\n    /// @dev This function must be called bottom-up in the DAG\n    ///      A subgame is a tree of claims that has a maximum depth of 1.\n    ///      A subgame root claims is valid if, and only if, all of its child claims are invalid.\n    ///      At the deepest level in the DAG, a claim is invalid if there's a successful step against it.\n    /// @param _claimIndex The index of the subgame root claim to resolve.\n    /// @param _numToResolve The number of subgames to resolve in this call. If the input is `0`, and this is the first\n    ///                      page, this function will attempt to check all of the subgame's children at once.\n    function resolveClaim(uint256 _claimIndex, uint256 _numToResolve) external;\n\n    /// @notice Returns the number of children that still need to be resolved in order to fully resolve a subgame rooted\n    ///         at `_claimIndex`.\n    /// @param _claimIndex The subgame root claim's index within `claimData`.\n    /// @return numRemainingChildren_ The number of children that still need to be checked to resolve the subgame.\n    function getNumToResolve(uint256 _claimIndex) external view returns (uint256 numRemainingChildren_);\n\n    /// @notice The l2BlockNumber of the disputed output root in the `L2OutputOracle`.\n    function l2BlockNumber() external view returns (uint256 l2BlockNumber_);\n\n    /// @notice Starting output root and block number of the game.\n    function startingOutputRoot() external view returns (Hash startingRoot_, uint256 l2BlockNumber_);\n\n    /// @notice Only the starting block number of the game.\n    function startingBlockNumber() external view returns (uint256 startingBlockNumber_);\n\n    /// @notice Only the starting output root of the game.\n    function startingRootHash() external view returns (Hash startingRootHash_);\n}\n"
    },
    "contracts/L1/dispute/interfaces/IInitializable.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title IInitializable\n/// @notice An interface for initializable contracts.\ninterface IInitializable {\n    /// @notice Initializes the contract.\n    /// @dev This function may only be called once.\n    function initialize() external payable;\n}\n"
    },
    "contracts/L1/dispute/interfaces/ILockingPool.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title ILockingPool\n/// @notice Interface for the LockingPool contract\ninterface ILockingPool {\n    /// @notice Slashes a percentage of tokens from the pool\n    /// @param _recipient Address to receive the slashed tokens\n    function slash(address _recipient) external;\n} "
    },
    "contracts/L1/dispute/interfaces/IWETH.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title IWETH\n/// @notice Interface for WETH9.\ninterface IWETH {\n    /// @notice Emitted when an approval is made.\n    /// @param src The address that approved the transfer.\n    /// @param guy The address that was approved to transfer.\n    /// @param wad The amount that was approved to transfer.\n    event Approval(address indexed src, address indexed guy, uint256 wad);\n\n    /// @notice Emitted when a transfer is made.\n    /// @param src The address that transferred the WETH.\n    /// @param dst The address that received the WETH.\n    /// @param wad The amount of WETH that was transferred.\n    event Transfer(address indexed src, address indexed dst, uint256 wad);\n\n    /// @notice Emitted when a deposit is made.\n    /// @param dst The address that deposited the WETH.\n    /// @param wad The amount of WETH that was deposited.\n    event Deposit(address indexed dst, uint256 wad);\n\n    /// @notice Emitted when a withdrawal is made.\n    /// @param src The address that withdrew the WETH.\n    /// @param wad The amount of WETH that was withdrawn.\n    event Withdrawal(address indexed src, uint256 wad);\n\n    /// @notice Returns the name of the token.\n    /// @return The name of the token.\n    function name() external view returns (string memory);\n\n    /// @notice Returns the symbol of the token.\n    /// @return The symbol of the token.\n    function symbol() external view returns (string memory);\n\n    /// @notice Returns the number of decimals the token uses.\n    /// @return The number of decimals the token uses.\n    function decimals() external pure returns (uint8);\n\n    /// @notice Returns the balance of the given address.\n    /// @param owner The address to query the balance of.\n    /// @return The balance of the given address.\n    function balanceOf(address owner) external view returns (uint256);\n\n    /// @notice Returns the amount of WETH that the spender can transfer on behalf of the owner.\n    /// @param owner The address that owns the WETH.\n    /// @param spender The address that is approved to transfer the WETH.\n    /// @return The amount of WETH that the spender can transfer on behalf of the owner.\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /// @notice Allows WETH to be deposited by sending ether to the contract.\n    function deposit() external payable;\n\n    /// @notice Withdraws an amount of ETH.\n    /// @param wad The amount of ETH to withdraw.\n    function withdraw(uint256 wad) external;\n\n    /// @notice Returns the total supply of WETH.\n    /// @return The total supply of WETH.\n    function totalSupply() external view returns (uint256);\n\n    /// @notice Approves the given address to transfer the WETH on behalf of the caller.\n    /// @param guy The address that is approved to transfer the WETH.\n    /// @param wad The amount that is approved to transfer.\n    /// @return True if the approval was successful.\n    function approve(address guy, uint256 wad) external returns (bool);\n\n    /// @notice Transfers the given amount of WETH to the given address.\n    /// @param dst The address to transfer the WETH to.\n    /// @param wad The amount of WETH to transfer.\n    /// @return True if the transfer was successful.\n    function transfer(address dst, uint256 wad) external returns (bool);\n\n    /// @notice Transfers the given amount of WETH from the given address to the given address.\n    /// @param src The address to transfer the WETH from.\n    /// @param dst The address to transfer the WETH to.\n    /// @param wad The amount of WETH to transfer.\n    /// @return True if the transfer was successful.\n    function transferFrom(address src, address dst, uint256 wad) external returns (bool);\n}\n"
    },
    "contracts/L1/dispute/lib/Errors.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport \"./LibUDT.sol\";\n\n////////////////////////////////////////////////////////////////\n//                `DisputeGameFactory` Errors                 //\n////////////////////////////////////////////////////////////////\n\n/// @notice Thrown when a dispute game is attempted to be created with an unsupported game type.\n/// @param gameType The unsupported game type.\n    error NoImplementation(GameType gameType);\n\n/// @notice Thrown when a dispute game that already exists is attempted to be created.\n/// @param uuid The UUID of the dispute game that already exists.\n    error GameAlreadyExists(Hash uuid);\n\n/// @notice Thrown when the root claim has an unexpected VM status.\n///         Some games can only start with a root-claim with a specific status.\n/// @param rootClaim is the claim that was unexpected.\n    error UnexpectedRootClaim(Claim rootClaim);\n\n/// @notice Thrown when no dispute game requested.\n    error NoDisputeGameRequests();\n\n////////////////////////////////////////////////////////////////\n//                 `FaultDisputeGame` Errors                  //\n////////////////////////////////////////////////////////////////\n\n/// @notice Thrown when a dispute game has already been initialized.\n    error AlreadyInitialized();\n\n/// @notice Thrown when a supplied bond is not equal to the required bond amount to cover the cost of the interaction.\n    error IncorrectBondAmount();\n\n/// @notice Thrown when a credit claim is attempted for a value of 0.\n    error NoCreditToClaim();\n\n/// @notice Thrown when the transfer of credit to a recipient account reverts.\n    error BondTransferFailed();\n\n/// @notice Thrown when the `extraData` passed to the CWIA proxy is of improper length, or contains invalid information.\n    error BadExtraData();\n\n/// @notice Thrown when a defense against the root claim is attempted.\n    error CannotDefendRootClaim();\n\n/// @notice Thrown when a claim is attempting to be made that already exists.\n    error ClaimAlreadyExists();\n\n/// @notice Thrown when a disputed claim does not match its index in the game.\n    error InvalidDisputedClaimIndex();\n\n/// @notice Thrown when an action that requires the game to be `IN_PROGRESS` is invoked when\n///         the game is not in progress.\n    error GameNotInProgress();\n\n/// @notice Thrown when a move is attempted to be made after the clock has timed out.\n    error ClockTimeExceeded();\n\n/// @notice Thrown when the game is attempted to be resolved too early.\n    error ClockNotExpired();\n\n/// @notice Thrown when a move is attempted to be made at or greater than the max depth of the game.\n    error GameDepthExceeded();\n\n/// @notice Thrown when a step is attempted above the maximum game depth.\n    error InvalidParent();\n\n/// @notice Thrown when an invalid prestate is supplied to `step`.\n    error InvalidPrestate();\n\n/// @notice Thrown when a step is made that computes the expected post state correctly.\n    error ValidStep();\n\n/// @notice Thrown when a game is attempted to be initialized with an L1 head that does\n///         not contain the disputed output root.\n    error L1HeadTooOld();\n\n/// @notice Thrown when an invalid local identifier is passed to the `addLocalData` function.\n    error InvalidLocalIdent();\n\n/// @notice Thrown when resolving claims out of order.\n    error OutOfOrderResolution();\n\n/// @notice Thrown when resolving a claim that has already been resolved.\n    error ClaimAlreadyResolved();\n\n/// @notice Thrown when a parent output root is attempted to be found on a claim that is in\n///         the output root portion of the tree.\n    error ClaimAboveSplit();\n\n/// @notice Thrown on deployment if the split depth is greater than or equal to the max\n///         depth of the game.\n    error InvalidSplitDepth();\n\n/// @notice Thrown on deployment if the max clock duration is less than or equal to the clock extension.\n    error InvalidClockExtension();\n\n/// @notice Thrown on deployment if the PreimageOracle challenge period is too high.\n    error InvalidChallengePeriod();\n\n/// @notice Thrown on deployment if the max depth is greater than `LibPosition.`\n    error MaxDepthTooLarge();\n\n/// @notice Thrown when trying to step against a claim for a second time, after it has already been countered with\n///         an instruction step.\n    error DuplicateStep();\n\n/// @notice Thrown when an anchor root is not found for a given game type.\n    error AnchorRootNotFound();\n\n/// @notice Thrown when an output root proof is invalid.\n    error InvalidOutputRootProof();\n\n/// @notice Thrown when header RLP is invalid with respect to the block hash in an output root proof.\n    error InvalidHeaderRLP();\n\n/// @notice Thrown when there is a match between the block number in the output root proof and the block number\n///         claimed in the dispute game.\n    error BlockNumberMatches();\n\n/// @notice Thrown when the L2 block number claim has already been challenged.\n    error L2BlockNumberChallenged();\n\n////////////////////////////////////////////////////////////////\n//              `PermissionedDisputeGame` Errors              //\n////////////////////////////////////////////////////////////////\n\n/// @notice Thrown when an unauthorized address attempts to interact with the game.\n    error BadAuth();\n\n////////////////////////////////////////////////////////////////\n//              `AnchorStateRegistry` Errors                  //\n////////////////////////////////////////////////////////////////\n\n/// @notice Thrown when attempting to set an anchor state using an unregistered game.\n    error UnregisteredGame();\n\n/// @notice Thrown when attempting to set an anchor state using an invalid game result.\n    error InvalidGameStatus();\n"
    },
    "contracts/L1/dispute/lib/LibPosition.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\n    using LibPosition for Position global;\n\n/// @notice A `Position` represents a position of a claim within the game tree.\n/// @dev This is represented as a \"generalized index\" where the high-order bit\n/// is the level in the tree and the remaining bits is a unique bit pattern, allowing\n/// a unique identifier for each node in the tree. Mathematically, it is calculated\n/// as 2^{depth} + indexAtDepth.\n    type Position is uint128;\n\n/// @title LibPosition\n/// @notice This library contains helper functions for working with the `Position` type.\nlibrary LibPosition {\n    /// @notice the `MAX_POSITION_BITLEN` is the number of bits that the `Position` type, and the implementation of\n    ///         its behavior within this library, can safely support.\n    uint8 internal constant MAX_POSITION_BITLEN = 126;\n\n    /// @notice Computes a generalized index (2^{depth} + indexAtDepth).\n    /// @param _depth The depth of the position.\n    /// @param _indexAtDepth The index at the depth of the position.\n    /// @return position_ The computed generalized index.\n    function wrap(uint8 _depth, uint128 _indexAtDepth) internal pure returns (Position position_) {\n        assembly {\n        // gindex = 2^{_depth} + _indexAtDepth\n            position_ := add(shl(_depth, 1), _indexAtDepth)\n        }\n    }\n\n    /// @notice Pulls the `depth` out of a `Position` type.\n    /// @param _position The generalized index to get the `depth` of.\n    /// @return depth_ The `depth` of the `position` gindex.\n    /// @custom:attribution Solady <https://github.com/Vectorized/Solady>\n    function depth(Position _position) internal pure returns (uint8 depth_) {\n        // Return the most significant bit offset, which signifies the depth of the gindex.\n        assembly {\n            depth_ := or(depth_, shl(6, lt(0xffffffffffffffff, shr(depth_, _position))))\n            depth_ := or(depth_, shl(5, lt(0xffffffff, shr(depth_, _position))))\n\n        // For the remaining 32 bits, use a De Bruijn lookup.\n            _position := shr(depth_, _position)\n            _position := or(_position, shr(1, _position))\n            _position := or(_position, shr(2, _position))\n            _position := or(_position, shr(4, _position))\n            _position := or(_position, shr(8, _position))\n            _position := or(_position, shr(16, _position))\n\n            depth_ :=\n            or(\n                depth_,\n                byte(\n                    shr(251, mul(_position, shl(224, 0x07c4acdd))),\n                    0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f\n                )\n            )\n        }\n    }\n\n    /// @notice Pulls the `indexAtDepth` out of a `Position` type.\n    ///         The `indexAtDepth` is the left/right index of a position at a specific depth within\n    ///         the binary tree, starting from index 0. For example, at gindex 2, the `depth` = 1\n    ///         and the `indexAtDepth` = 0.\n    /// @param _position The generalized index to get the `indexAtDepth` of.\n    /// @return indexAtDepth_ The `indexAtDepth` of the `position` gindex.\n    function indexAtDepth(Position _position) internal pure returns (uint128 indexAtDepth_) {\n        // Return bits p_{msb-1}...p_{0}. This effectively pulls the 2^{depth} out of the gindex,\n        // leaving only the `indexAtDepth`.\n        uint256 msb = depth(_position);\n        assembly {\n            indexAtDepth_ := sub(_position, shl(msb, 1))\n        }\n    }\n\n    /// @notice Get the left child of `_position`.\n    /// @param _position The position to get the left position of.\n    /// @return left_ The position to the left of `position`.\n    function left(Position _position) internal pure returns (Position left_) {\n        assembly {\n            left_ := shl(1, _position)\n        }\n    }\n\n    /// @notice Get the right child of `_position`\n    /// @param _position The position to get the right position of.\n    /// @return right_ The position to the right of `position`.\n    function right(Position _position) internal pure returns (Position right_) {\n        assembly {\n            right_ := or(1, shl(1, _position))\n        }\n    }\n\n    /// @notice Get the parent position of `_position`.\n    /// @param _position The position to get the parent position of.\n    /// @return parent_ The parent position of `position`.\n    function parent(Position _position) internal pure returns (Position parent_) {\n        assembly {\n            parent_ := shr(1, _position)\n        }\n    }\n\n    /// @notice Get the deepest, right most gindex relative to the `position`. This is equivalent to\n    ///         calling `right` on a position until the maximum depth is reached.\n    /// @param _position The position to get the relative deepest, right most gindex of.\n    /// @param _maxDepth The maximum depth of the game.\n    /// @return rightIndex_ The deepest, right most gindex relative to the `position`.\n    function rightIndex(Position _position, uint256 _maxDepth) internal pure returns (Position rightIndex_) {\n        uint256 msb = depth(_position);\n        assembly {\n            let remaining := sub(_maxDepth, msb)\n            rightIndex_ := or(shl(remaining, _position), sub(shl(remaining, 1), 1))\n        }\n    }\n\n    /// @notice Get the deepest, right most trace index relative to the `position`. This is\n    ///         equivalent to calling `right` on a position until the maximum depth is reached and\n    ///         then finding its index at depth.\n    /// @param _position The position to get the relative trace index of.\n    /// @param _maxDepth The maximum depth of the game.\n    /// @return traceIndex_ The trace index relative to the `position`.\n    function traceIndex(Position _position, uint256 _maxDepth) internal pure returns (uint256 traceIndex_) {\n        uint256 msb = depth(_position);\n        assembly {\n            let remaining := sub(_maxDepth, msb)\n            traceIndex_ := sub(or(shl(remaining, _position), sub(shl(remaining, 1), 1)), shl(_maxDepth, 1))\n        }\n    }\n\n    /// @notice Gets the position of the highest ancestor of `_position` that commits to the same\n    ///         trace index.\n    /// @param _position The position to get the highest ancestor of.\n    /// @return ancestor_ The highest ancestor of `position` that commits to the same trace index.\n    function traceAncestor(Position _position) internal pure returns (Position ancestor_) {\n        // Create a field with only the lowest unset bit of `_position` set.\n        Position lsb;\n        assembly {\n            lsb := and(not(_position), add(_position, 1))\n        }\n        // Find the index of the lowest unset bit within the field.\n        uint256 msb = depth(lsb);\n        // The highest ancestor that commits to the same trace index is the original position\n        // shifted right by the index of the lowest unset bit.\n        assembly {\n            let a := shr(msb, _position)\n        // Bound the ancestor to the minimum gindex, 1.\n            ancestor_ := or(a, iszero(a))\n        }\n    }\n\n    /// @notice Gets the position of the highest ancestor of `_position` that commits to the same\n    ///         trace index, while still being below `_upperBoundExclusive`.\n    /// @param _position The position to get the highest ancestor of.\n    /// @param _upperBoundExclusive The exclusive upper depth bound, used to inform where to stop in order\n    ///                             to not escape a sub-tree.\n    /// @return ancestor_ The highest ancestor of `position` that commits to the same trace index.\n    function traceAncestorBounded(\n        Position _position,\n        uint256 _upperBoundExclusive\n    )\n    internal\n    pure\n    returns (Position ancestor_)\n    {\n        // This function only works for positions that are below the upper bound.\n        if (_position.depth() <= _upperBoundExclusive) {\n            assembly {\n            // Revert with `ClaimAboveSplit()`\n                mstore(0x00, 0xb34b5c22)\n                revert(0x1C, 0x04)\n            }\n        }\n\n        // Grab the global trace ancestor.\n        ancestor_ = traceAncestor(_position);\n\n        // If the ancestor is above or at the upper bound, shift it to be below the upper bound.\n        // This should be a special case that only covers positions that commit to the final leaf\n        // in a sub-tree.\n        if (ancestor_.depth() <= _upperBoundExclusive) {\n            ancestor_ = ancestor_.rightIndex(_upperBoundExclusive + 1);\n        }\n    }\n\n    /// @notice Get the move position of `_position`, which is the left child of:\n    ///         1. `_position` if `_isAttack` is true.\n    ///         2. `_position | 1` if `_isAttack` is false.\n    /// @param _position The position to get the relative attack/defense position of.\n    /// @param _isAttack Whether or not the move is an attack move.\n    /// @return move_ The move position relative to `position`.\n    function move(Position _position, bool _isAttack) internal pure returns (Position move_) {\n        assembly {\n            move_ := shl(1, or(iszero(_isAttack), _position))\n        }\n    }\n\n    /// @notice Get the value of a `Position` type in the form of the underlying uint128.\n    /// @param _position The position to get the value of.\n    /// @return raw_ The value of the `position` as a uint128 type.\n    function raw(Position _position) internal pure returns (uint128 raw_) {\n        assembly {\n            raw_ := _position\n        }\n    }\n}\n"
    },
    "contracts/L1/dispute/lib/LibUDT.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport \"./LibPosition.sol\";\n\nusing LibClaim for Claim global;\nusing LibHash for Hash global;\nusing LibDuration for Duration global;\nusing LibClock for Clock global;\nusing LibGameId for GameId global;\nusing LibTimestamp for Timestamp global;\nusing LibVMStatus for VMStatus global;\nusing LibGameType for GameType global;\n\n/// @notice A `Clock` represents a packed `Duration` and `Timestamp`\n/// @dev The packed layout of this type is as follows:\n/// ┌────────────┬────────────────┐\n/// │    Bits    │     Value      │\n/// ├────────────┼────────────────┤\n/// │ [0, 64)    │ Duration       │\n/// │ [64, 128)  │ Timestamp      │\n/// └────────────┴────────────────┘\n    type Clock is uint128;\n\n/// @title LibClock\n/// @notice This library contains helper functions for working with the `Clock` type.\nlibrary LibClock {\n    /// @notice Packs a `Duration` and `Timestamp` into a `Clock` type.\n    /// @param _duration The `Duration` to pack into the `Clock` type.\n    /// @param _timestamp The `Timestamp` to pack into the `Clock` type.\n    /// @return clock_ The `Clock` containing the `_duration` and `_timestamp`.\n    function wrap(Duration _duration, Timestamp _timestamp) internal pure returns (Clock clock_) {\n        assembly {\n            clock_ := or(shl(0x40, _duration), _timestamp)\n        }\n    }\n\n    /// @notice Pull the `Duration` out of a `Clock` type.\n    /// @param _clock The `Clock` type to pull the `Duration` out of.\n    /// @return duration_ The `Duration` pulled out of `_clock`.\n    function duration(Clock _clock) internal pure returns (Duration duration_) {\n        // Shift the high-order 64 bits into the low-order 64 bits, leaving only the `duration`.\n        assembly {\n            duration_ := shr(0x40, _clock)\n        }\n    }\n\n    /// @notice Pull the `Timestamp` out of a `Clock` type.\n    /// @param _clock The `Clock` type to pull the `Timestamp` out of.\n    /// @return timestamp_ The `Timestamp` pulled out of `_clock`.\n    function timestamp(Clock _clock) internal pure returns (Timestamp timestamp_) {\n        // Clean the high-order 192 bits by shifting the clock left and then right again, leaving\n        // only the `timestamp`.\n        assembly {\n            timestamp_ := shr(0xC0, shl(0xC0, _clock))\n        }\n    }\n\n    /// @notice Get the value of a `Clock` type in the form of the underlying uint128.\n    /// @param _clock The `Clock` type to get the value of.\n    /// @return clock_ The value of the `Clock` type as a uint128 type.\n    function raw(Clock _clock) internal pure returns (uint128 clock_) {\n        assembly {\n            clock_ := _clock\n        }\n    }\n}\n\n/// @notice A `GameId` represents a packed 4 byte game ID, a 8 byte timestamp, and a 20 byte address.\n/// @dev The packed layout of this type is as follows:\n/// ┌───────────┬───────────┐\n/// │   Bits    │   Value   │\n/// ├───────────┼───────────┤\n/// │ [0, 32)   │ Game Type │\n/// │ [32, 96)  │ Timestamp │\n/// │ [96, 256) │ Address   │\n/// └───────────┴───────────┘\n    type GameId is bytes32;\n\n/// @title LibGameId\n/// @notice Utility functions for packing and unpacking GameIds.\nlibrary LibGameId {\n    /// @notice Packs values into a 32 byte GameId type.\n    /// @param _gameType The game type.\n    /// @param _timestamp The timestamp of the game's creation.\n    /// @param _gameProxy The game proxy address.\n    /// @return gameId_ The packed GameId.\n    function pack(\n        GameType _gameType,\n        Timestamp _timestamp,\n        address _gameProxy\n    )\n    internal\n    pure\n    returns (GameId gameId_)\n    {\n        assembly {\n            gameId_ := or(or(shl(224, _gameType), shl(160, _timestamp)), _gameProxy)\n        }\n    }\n\n    /// @notice Unpacks values from a 32 byte GameId type.\n    /// @param _gameId The packed GameId.\n    /// @return gameType_ The game type.\n    /// @return timestamp_ The timestamp of the game's creation.\n    /// @return gameProxy_ The game proxy address.\n    function unpack(GameId _gameId)\n    internal\n    pure\n    returns (GameType gameType_, Timestamp timestamp_, address gameProxy_)\n    {\n        assembly {\n            gameType_ := shr(224, _gameId)\n            timestamp_ := and(shr(160, _gameId), 0xFFFFFFFFFFFFFFFF)\n            gameProxy_ := and(_gameId, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\n        }\n    }\n}\n\n/// @notice A claim represents an MPT root representing the state of the fault proof program.\n    type Claim is bytes32;\n\n/// @title LibClaim\n/// @notice This library contains helper functions for working with the `Claim` type.\nlibrary LibClaim {\n    /// @notice Get the value of a `Claim` type in the form of the underlying bytes32.\n    /// @param _claim The `Claim` type to get the value of.\n    /// @return claim_ The value of the `Claim` type as a bytes32 type.\n    function raw(Claim _claim) internal pure returns (bytes32 claim_) {\n        assembly {\n            claim_ := _claim\n        }\n    }\n\n    /// @notice Hashes a claim and a position together.\n    /// @param _claim A Claim type.\n    /// @param _position The position of `claim`.\n    /// @param _challengeIndex The index of the claim being moved against.\n    /// @return claimHash_ A hash of abi.encodePacked(claim, position|challengeIndex);\n    function hashClaimPos(\n        Claim _claim,\n        Position _position,\n        uint256 _challengeIndex\n    )\n    internal\n    pure\n    returns (Hash claimHash_)\n    {\n        assembly {\n            mstore(0x00, _claim)\n            mstore(0x20, or(shl(128, _position), and(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, _challengeIndex)))\n            claimHash_ := keccak256(0x00, 0x40)\n        }\n    }\n}\n\n/// @notice A dedicated duration type.\n/// @dev Unit: seconds\n    type Duration is uint64;\n\n/// @title LibDuration\n/// @notice This library contains helper functions for working with the `Duration` type.\nlibrary LibDuration {\n    /// @notice Get the value of a `Duration` type in the form of the underlying uint64.\n    /// @param _duration The `Duration` type to get the value of.\n    /// @return duration_ The value of the `Duration` type as a uint64 type.\n    function raw(Duration _duration) internal pure returns (uint64 duration_) {\n        assembly {\n            duration_ := _duration\n        }\n    }\n}\n\n/// @notice A custom type for a generic hash.\n    type Hash is bytes32;\n\n/// @title LibHash\n/// @notice This library contains helper functions for working with the `Hash` type.\nlibrary LibHash {\n    /// @notice Get the value of a `Hash` type in the form of the underlying bytes32.\n    /// @param _hash The `Hash` type to get the value of.\n    /// @return hash_ The value of the `Hash` type as a bytes32 type.\n    function raw(Hash _hash) internal pure returns (bytes32 hash_) {\n        assembly {\n            hash_ := _hash\n        }\n    }\n}\n\n/// @notice A dedicated timestamp type.\n    type Timestamp is uint64;\n\n/// @title LibTimestamp\n/// @notice This library contains helper functions for working with the `Timestamp` type.\nlibrary LibTimestamp {\n    /// @notice Get the value of a `Timestamp` type in the form of the underlying uint64.\n    /// @param _timestamp The `Timestamp` type to get the value of.\n    /// @return timestamp_ The value of the `Timestamp` type as a uint64 type.\n    function raw(Timestamp _timestamp) internal pure returns (uint64 timestamp_) {\n        assembly {\n            timestamp_ := _timestamp\n        }\n    }\n}\n\n/// @notice A `VMStatus` represents the status of a VM execution.\n    type VMStatus is uint8;\n\n/// @title LibVMStatus\n/// @notice This library contains helper functions for working with the `VMStatus` type.\nlibrary LibVMStatus {\n    /// @notice Get the value of a `VMStatus` type in the form of the underlying uint8.\n    /// @param _vmstatus The `VMStatus` type to get the value of.\n    /// @return vmstatus_ The value of the `VMStatus` type as a uint8 type.\n    function raw(VMStatus _vmstatus) internal pure returns (uint8 vmstatus_) {\n        assembly {\n            vmstatus_ := _vmstatus\n        }\n    }\n}\n\n/// @notice A `GameType` represents the type of game being played.\n    type GameType is uint32;\n\n/// @title LibGameType\n/// @notice This library contains helper functions for working with the `GameType` type.\nlibrary LibGameType {\n    /// @notice Get the value of a `GameType` type in the form of the underlying uint32.\n    /// @param _gametype The `GameType` type to get the value of.\n    /// @return gametype_ The value of the `GameType` type as a uint32 type.\n    function raw(GameType _gametype) internal pure returns (uint32 gametype_) {\n        assembly {\n            gametype_ := _gametype\n        }\n    }\n}\n"
    },
    "contracts/L1/dispute/lib/Types.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport \"./LibUDT.sol\";\n\n/// @notice The current status of the dispute game.\n    enum GameStatus {\n        // The game is currently in progress, and has not been resolved.\n        IN_PROGRESS,\n        // The game has concluded, and the `rootClaim` was challenged successfully.\n        CHALLENGER_WINS,\n        // The game has concluded, and the `rootClaim` could not be contested.\n        DEFENDER_WINS\n    }\n\n/// @notice Represents an L2 output root and the L2 block number at which it was generated.\n/// @custom:field root The output root.\n/// @custom:field l2BlockNumber The L2 block number at which the output root was generated.\n    struct OutputRoot {\n        Hash root;\n        uint256 l2BlockNumber;\n    }\n\n/// @title GameTypes\n/// @notice A library that defines the IDs of games that can be played.\nlibrary GameTypes {\n    /// @dev A dispute game type the uses the cannon vm.\n    GameType internal constant CANNON = GameType.wrap(0);\n\n    /// @dev A permissioned dispute game type the uses the cannon vm.\n    GameType internal constant PERMISSIONED_CANNON = GameType.wrap(1);\n\n    /// @notice A dispute game type the uses the asterisc VM\n    GameType internal constant ASTERISC = GameType.wrap(2);\n\n    /// @notice A dispute game type with short game duration for testing withdrawals.\n    ///         Not intended for production use.\n    GameType internal constant FAST = GameType.wrap(254);\n\n    /// @notice A dispute game type that uses an alphabet vm.\n    ///         Not intended for production use.\n    GameType internal constant ALPHABET = GameType.wrap(255);\n}\n\n/// @title VMStatuses\n/// @notice Named type aliases for the various valid VM status bytes.\nlibrary VMStatuses {\n    /// @notice The VM has executed successfully and the outcome is valid.\n    VMStatus internal constant VALID = VMStatus.wrap(0);\n\n    /// @notice The VM has executed successfully and the outcome is invalid.\n    VMStatus internal constant INVALID = VMStatus.wrap(1);\n\n    /// @notice The VM has paniced.\n    VMStatus internal constant PANIC = VMStatus.wrap(2);\n\n    /// @notice The VM execution is still in progress.\n    VMStatus internal constant UNFINISHED = VMStatus.wrap(3);\n}\n\n/// @title LocalPreimageKey\n/// @notice Named type aliases for local `PreimageOracle` key identifiers.\nlibrary LocalPreimageKey {\n    /// @notice The identifier for the L1 head hash.\n    uint256 internal constant L1_HEAD_HASH = 0x01;\n\n    /// @notice The identifier for the starting output root.\n    uint256 internal constant STARTING_OUTPUT_ROOT = 0x02;\n\n    /// @notice The identifier for the disputed output root.\n    uint256 internal constant DISPUTED_OUTPUT_ROOT = 0x03;\n\n    /// @notice The identifier for the disputed L2 block number.\n    uint256 internal constant DISPUTED_L2_BLOCK_NUMBER = 0x04;\n\n    /// @notice The identifier for the chain ID.\n    uint256 internal constant CHAIN_ID = 0x05;\n}\n"
    },
    "contracts/L1/dispute/LockingPool.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {MetisConfig} from \"../config/MetisConfig.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {IDisputeGameFactory} from \"../dispute/interfaces/IDisputeGameFactory.sol\";\nimport {IFaultDisputeGame} from \"../dispute/interfaces/IFaultDisputeGame.sol\";\nimport {IDisputeGame} from \"../dispute/interfaces/IDisputeGame.sol\";\nimport \"contracts/L1/dispute/lib/Types.sol\";\nimport \"contracts/L1/dispute/lib/Errors.sol\";\nimport {ILockingPool} from \"./interfaces/ILockingPool.sol\";\n\n/// @title LockingPool\n/// @notice A locking pool contract that allows users to lock tokens with a delayed withdrawal mechanism\n/// @dev Based on DelayedWETH's delayed withdrawal mechanism\ncontract LockingPool is OwnableUpgradeable, ILockingPool {\n    using SafeERC20 for IERC20;\n\n    /// @notice Struct representing a withdrawal request\n    struct WithdrawalRequest {\n        uint256 amount;\n        uint256 timestamp;\n    }\n\n    /// @notice The token being locked in the pool\n    IERC20 public token;\n\n    /// @notice The withdrawal delay period in seconds\n    uint256 public lockPeriod;\n\n    /// @notice The slash ratio (base 10000, i.e., 100.00%)\n    uint256 public slashRatio;\n\n    /// @notice The MetisConfig contract\n    MetisConfig public config;\n\n    /// @notice The DisputeGameFactory contract\n    IDisputeGameFactory public disputeGameFactory;\n\n    /// @notice Mapping of user withdrawal requests\n    mapping(address => WithdrawalRequest) public withdrawals;\n\n    /// @notice Mapping of user balances\n    mapping(address => uint256) public balanceOf;\n\n    /// @notice Total amount of tokens locked\n    uint256 public totalLocked;\n\n    /// @notice Array of sequencer addresses\n    address[] public depositedSequencers;\n\n    /// @notice Emitted when tokens are deposited\n    event Deposit(address indexed user, uint256 amount);\n\n    /// @notice Emitted when a withdrawal is requested\n    event Unlock(address indexed user, uint256 amount);\n\n    /// @notice Emitted when tokens are withdrawn\n    event Withdraw(address indexed user, uint256 amount);\n\n    /// @notice Emitted when tokens are slashed\n    event Slashed(address indexed recipient, uint256 amount);\n\n    /// @notice Emitted when slash ratio is updated\n    event SlashRatioUpdated(uint256 oldRatio, uint256 newRatio);\n\n    /// @notice Emitted when lock period is updated\n    event LockPeriodUpdated(uint256 oldPeriod, uint256 newPeriod);\n\n    /// @param _token The ERC20 token contract address\n    /// @param _lockPeriod Initial lock period in seconds\n    /// @param _slashRatio Initial slash ratio (base 10000)\n    /// @param _disputeGameFactory The DisputeGameFactory contract address\n    constructor(\n        address _token,\n        uint256 _lockPeriod,\n        uint256 _slashRatio,\n        IDisputeGameFactory _disputeGameFactory\n    ) {\n        require(_token != address(0), \"LockingPool: invalid token\");\n        require(address(_disputeGameFactory) != address(0), \"LockingPool: invalid factory\");\n        token = IERC20(_token);\n        lockPeriod = _lockPeriod;\n        slashRatio = _slashRatio;\n        disputeGameFactory = _disputeGameFactory;\n        initialize(address(0), MetisConfig(address(0)));\n    }\n\n    /// @notice Initializes the contract\n    /// @param _owner The owner address\n    /// @param _config The MetisConfig contract address\n    function initialize(address _owner, MetisConfig _config) public initializer {\n        __Ownable_init();\n        _transferOwnership(_owner);\n        config = _config;\n    }\n\n    /// @notice Deposits tokens into the pool\n    /// @param _amount Amount of tokens to deposit\n    function deposit(uint256 _amount) external {\n        require(_amount > 0, \"LockingPool: zero deposit\");\n        \n        token.safeTransferFrom(msg.sender, address(this), _amount);\n        balanceOf[msg.sender] += _amount;\n        totalLocked += _amount;\n\n        bool depositedBefore = false;\n        for (uint256 i = 0; i < depositedSequencers.length; i++) {\n            if (depositedSequencers[i] == msg.sender) {\n                depositedBefore = true;\n                break;\n            }\n        }\n\n        if (!depositedBefore) {\n            depositedSequencers.push(msg.sender);\n        }\n        \n        emit Deposit(msg.sender, _amount);\n    }\n\n    /// @notice Requests to unlock tokens\n    /// @param _amount Amount of tokens to unlock\n    function unlock(uint256 _amount) external {\n        require(balanceOf[msg.sender] >= _amount, \"LockingPool: insufficient balance\");\n        \n        WithdrawalRequest storage wd = withdrawals[msg.sender];\n        wd.timestamp = block.timestamp;\n        wd.amount += _amount;\n        \n        emit Unlock(msg.sender, _amount);\n    }\n\n    /// @notice Withdraws unlocked tokens\n    /// @param _amount Amount of tokens to withdraw\n    function withdraw(uint256 _amount) external {\n        require(!config.paused(), \"LockingPool: contract is paused\");\n        \n        WithdrawalRequest storage wd = withdrawals[msg.sender];\n        require(wd.amount >= _amount, \"LockingPool: insufficient unlocked withdrawal\");\n        require(wd.timestamp > 0, \"LockingPool: withdrawal not unlocked\");\n        require(\n            wd.timestamp + lockPeriod <= block.timestamp,\n            \"LockingPool: withdrawal delay not met\"\n        );\n        \n        wd.amount -= _amount;\n        balanceOf[msg.sender] -= _amount;\n        totalLocked -= _amount;\n\n        // remove sender from deposited sequencers if balance is zero\n        if (balanceOf[msg.sender] == 0) {\n            for (uint256 i = 0; i < depositedSequencers.length; i++) {\n                if (depositedSequencers[i] == msg.sender) {\n                    depositedSequencers[i] = depositedSequencers[depositedSequencers.length - 1];\n                    depositedSequencers.pop();\n                    break;\n                }\n            }\n        }\n        \n        token.safeTransfer(msg.sender, _amount);\n        emit Withdraw(msg.sender, _amount);\n    }\n\n    /// @notice Slashes a percentage of tokens from the pool\n    /// @param _recipient Address to receive the slashed tokens\n    function slash(address _recipient) external {\n        require(_recipient != address(0), \"LockingPool: invalid recipient\");\n        require(totalLocked > 0, \"LockingPool: no tokens to slash\");\n\n        // Verify the caller is a valid dispute game\n        IFaultDisputeGame game = IFaultDisputeGame(msg.sender);\n        (GameType gameType, Claim rootClaim, bytes memory extraData) = game.gameData();\n\n        // Get the verified address of the game based on the game data\n        (IDisputeGame factoryRegisteredGame,) = disputeGameFactory.games({\n            _gameType: gameType,\n            _rootClaim: rootClaim,\n            _extraData: extraData\n        });\n\n        // Must be a valid game\n        if (address(factoryRegisteredGame) != address(game)) revert UnregisteredGame();\n\n        // Must be a game that resolved in favor of the challenger\n        if (game.status() != GameStatus.CHALLENGER_WINS) {\n            revert InvalidGameStatus();\n        }\n\n        // Track actual slashed amount\n        uint256 actualSlashedAmount;\n        \n        // Cache users array to avoid multiple storage reads\n        address[] memory users = depositedSequencers;\n        uint256 usersLength = users.length;\n        \n        // First pass: calculate actual slashed amount\n        for (uint256 i; i < usersLength;) {\n            address user = users[i];\n            uint256 userBalance = balanceOf[user];\n            if (userBalance > 0) {\n                // Calculate user's slash amount\n                uint256 userSlashAmount = (userBalance * slashRatio) / 10000;\n                if (userSlashAmount > 0) {\n                    actualSlashedAmount += userSlashAmount;\n                    // Update user balance\n                    balanceOf[user] = userBalance - userSlashAmount;\n                }\n            }\n            // Gas optimization for loops\n            unchecked { ++i; }\n        }\n\n        // Require some tokens were actually slashed\n        require(actualSlashedAmount > 0, \"LockingPool: slash amount too small\");\n\n        // Update total locked amount\n        totalLocked -= actualSlashedAmount;\n\n        // Transfer the actual slashed amount\n        token.safeTransfer(_recipient, actualSlashedAmount);\n        emit Slashed(_recipient, actualSlashedAmount);\n    }\n\n    /// @notice Updates the slash ratio\n    /// @param _newRatio New slash ratio (base 10000)\n    function setSlashRatio(uint256 _newRatio) external onlyOwner {\n        uint256 oldRatio = slashRatio;\n        slashRatio = _newRatio;\n        emit SlashRatioUpdated(oldRatio, _newRatio);\n    }\n\n    /// @notice Updates the lock period\n    /// @param _newPeriod New lock period in seconds\n    function setLockPeriod(uint256 _newPeriod) external onlyOwner {\n        uint256 oldPeriod = lockPeriod;\n        lockPeriod = _newPeriod;\n        emit LockPeriodUpdated(oldPeriod, _newPeriod);\n    }\n\n    /// @notice Gets the withdrawal request details for a user\n    /// @param _user User address\n    /// @return amount Amount requested for withdrawal\n    /// @return timestamp Timestamp of the withdrawal request\n    function getWithdrawalRequest(address _user) \n        external \n        view \n        returns (uint256 amount, uint256 timestamp) \n    {\n        WithdrawalRequest memory wd = withdrawals[_user];\n        return (wd.amount, wd.timestamp);\n    }\n} "
    },
    "contracts/L1/dispute/PermissionedDisputeGame.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { IDelayedWETH } from \"contracts/L1/dispute/interfaces/IDelayedWETH.sol\";\nimport { IAnchorStateRegistry } from \"contracts/L1/dispute/interfaces/IAnchorStateRegistry.sol\";\nimport { FaultDisputeGame, IFaultDisputeGame, IBigStepper, IInitializable } from \"contracts/L1/dispute/FaultDisputeGame.sol\";\nimport { Lib_AddressManager } from \"../../libraries/resolver/Lib_AddressManager.sol\";\nimport \"contracts/L1/dispute/lib/Types.sol\";\nimport \"contracts/L1/dispute/lib/Errors.sol\";\n\n/// @title PermissionedDisputeGame\n/// @notice PermissionedDisputeGame is a contract that inherits from `FaultDisputeGame`, and contains two roles:\n///         - The `challenger` role, which is allowed to challenge a dispute.\n///         - The `proposer` role, which is allowed to create proposals and participate in their game.\n///         This contract exists as a way for networks to support the fault proof iteration of the OptimismPortal\n///         contract without needing to support a fully permissionless system. Permissionless systems can introduce\n///         costs that certain networks may not wish to support. This contract can also be used as a fallback mechanism\n///         in case of a failure in the permissionless fault proof system in the stage one release.\ncontract PermissionedDisputeGame is FaultDisputeGame {\n    /// @notice The proposer role is allowed to create proposals and participate in the dispute game.\n    address internal immutable PROPOSER;\n\n    /// @notice The challenger role is allowed to participate in the dispute game.\n    address internal immutable CHALLENGER;\n\n    /// @notice Modifier that gates access to the `challenger` and `proposer` roles.\n    modifier onlyAuthorized() {\n        if (!(msg.sender == PROPOSER || msg.sender == CHALLENGER)) {\n            revert BadAuth();\n        }\n        _;\n    }\n\n    /// @param _gameType The type ID of the game.\n    /// @param _absolutePrestate The absolute prestate of the instruction trace.\n    /// @param _maxGameDepth The maximum depth of bisection.\n    /// @param _splitDepth The final depth of the output bisection portion of the game.\n    /// @param _clockExtension The clock extension to perform when the remaining duration is less than the extension.\n    /// @param _maxClockDuration The maximum amount of time that may accumulate on a team's chess clock.\n    /// @param _vm An onchain VM that performs single instruction steps on an FPP trace.\n    /// @param _weth WETH contract for holding ETH.\n    /// @param _addressManager Address manager contract.\n    /// @param _l2ChainId Chain ID of the L2 network this contract argues about.\n    /// @param _proposer Address that is allowed to create instances of this contract.\n    /// @param _challenger Address that is allowed to challenge instances of this contract.\n    constructor(\n        GameType _gameType,\n        Claim _absolutePrestate,\n        uint256 _maxGameDepth,\n        uint256 _splitDepth,\n        Duration _clockExtension,\n        Duration _maxClockDuration,\n        IBigStepper _vm,\n        IDelayedWETH _weth,\n        Lib_AddressManager _addressManager,\n        uint256 _l2ChainId,\n        address _proposer,\n        address _challenger\n    )\n    FaultDisputeGame(\n    _gameType,\n    _absolutePrestate,\n    _maxGameDepth,\n    _splitDepth,\n    _clockExtension,\n    _maxClockDuration,\n    _vm,\n    _weth,\n    _addressManager,\n    _l2ChainId\n    )\n    {\n        PROPOSER = _proposer;\n        CHALLENGER = _challenger;\n    }\n\n    /// @inheritdoc IFaultDisputeGame\n    function step(\n        uint256 _claimIndex,\n        bool _isAttack,\n        bytes calldata _stateData,\n        bytes calldata _proof\n    )\n    public\n    override\n    onlyAuthorized\n    {\n        super.step(_claimIndex, _isAttack, _stateData, _proof);\n    }\n\n    /// @notice Generic move function, used for both `attack` and `defend` moves.\n    /// @notice _disputed The disputed `Claim`.\n    /// @param _challengeIndex The index of the claim being moved against. This must match the `_disputed` claim.\n    /// @param _claim The claim at the next logical position in the game.\n    /// @param _isAttack Whether or not the move is an attack or defense.\n    function move(\n        Claim _disputed,\n        uint256 _challengeIndex,\n        Claim _claim,\n        bool _isAttack\n    )\n    public\n    payable\n    override\n    onlyAuthorized\n    {\n        super.move(_disputed, _challengeIndex, _claim, _isAttack);\n    }\n\n    /// @inheritdoc IInitializable\n    function initialize() public payable override {\n        // The creator of the dispute game must be the proposer EOA.\n        if (tx.origin != PROPOSER) revert BadAuth();\n\n        // Fallthrough initialization.\n        super.initialize();\n    }\n\n    ////////////////////////////////////////////////////////////////\n    //                     IMMUTABLE GETTERS                      //\n    ////////////////////////////////////////////////////////////////\n\n    /// @notice Returns the proposer address.\n    function proposer() external view returns (address proposer_) {\n        proposer_ = PROPOSER;\n    }\n\n    /// @notice Returns the challenger address.\n    function challenger() external view returns (address challenger_) {\n        challenger_ = CHALLENGER;\n    }\n}\n"
    },
    "contracts/L1/dispute/weth/DelayedWETH.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {MetisConfig} from \"../../config/MetisConfig.sol\";\nimport {ISemver} from \"../../../universal/ISemver.sol\";\nimport {IDelayedWETH} from \"../interfaces/IDelayedWETH.sol\";\nimport {IWETH} from \"../interfaces/IWETH.sol\";\nimport {WETH98} from \"./WETH98.sol\";\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {Initializable} from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n/// @title DelayedWETH\n/// @notice DelayedWETH is an extension to WETH9 that allows for delayed withdrawals. Accounts must trigger an unlock\n///         function before they can withdraw WETH. Accounts must trigger unlock by specifying a sub-account and an\n///         amount of WETH to unlock. Accounts can trigger the unlock function at any time, but must wait a delay\n///         period before they can withdraw after the unlock function is triggered. DelayedWETH is designed to be used\n///         by the DisputeGame contracts where unlock will only be triggered after a dispute is resolved. DelayedWETH\n///         is meant to sit behind a proxy contract and has an owner address that can pull WETH from any account and\n///         can recover ETH from the contract itself. Variable and function naming vaguely follows the vibe of WETH9.\n///         Not the prettiest contract in the world, but it gets the job done.\ncontract DelayedWETH is OwnableUpgradeable, WETH98, IDelayedWETH, ISemver {\n    /// @notice Semantic version.\n    /// @custom:semver 1.1.0-rc.1\n    string public constant version = \"1.1.0-rc.1\";\n\n    /// @inheritdoc IDelayedWETH\n    mapping(address => mapping(address => WithdrawalRequest)) public withdrawals;\n\n    /// @notice Withdrawal delay in seconds.\n    uint256 internal immutable DELAY_SECONDS;\n\n    /// @notice Address of the MetisConfig contract.\n    MetisConfig public config;\n\n    /// @param _delay The delay for withdrawals in seconds.\n    constructor(uint256 _delay) {\n        DELAY_SECONDS = _delay;\n        initialize({_owner: address(0), _config: MetisConfig(address(0))});\n    }\n\n    /// @notice Initializes the contract.\n    /// @param _owner The address of the owner.\n    /// @param _config Address of the SuperchainConfig contract.\n    function initialize(address _owner, MetisConfig _config) public initializer {\n        __Ownable_init();\n        _transferOwnership(_owner);\n        config = _config;\n    }\n\n    /// @inheritdoc IDelayedWETH\n    function delay() external view returns (uint256) {\n        return DELAY_SECONDS;\n    }\n\n    /// @inheritdoc IDelayedWETH\n    function unlock(address _guy, uint256 _wad) external {\n        // Note that the unlock function can be called by any address, but the actual unlocking capability still only\n        // gives the msg.sender the ability to withdraw from the account. As long as the unlock and withdraw functions\n        // are called with the proper recipient addresses, this will be safe. Could be made safer by having external\n        // accounts execute withdrawals themselves but that would have added extra complexity and made DelayedWETH a\n        // leaky abstraction, so we chose this instead.\n        WithdrawalRequest storage wd = withdrawals[msg.sender][_guy];\n        wd.timestamp = block.timestamp;\n        wd.amount += _wad;\n    }\n\n    /// @inheritdoc IWETH\n    function withdraw(uint256 _wad) public override(WETH98, IWETH) {\n        withdraw(msg.sender, _wad);\n    }\n\n    /// @inheritdoc IDelayedWETH\n    function withdraw(address _guy, uint256 _wad) public {\n        require(!config.paused(), \"DelayedWETH: contract is paused\");\n        WithdrawalRequest storage wd = withdrawals[msg.sender][_guy];\n        require(wd.amount >= _wad, \"DelayedWETH: insufficient unlocked withdrawal\");\n        require(wd.timestamp > 0, \"DelayedWETH: withdrawal not unlocked\");\n        require(wd.timestamp + DELAY_SECONDS <= block.timestamp, \"DelayedWETH: withdrawal delay not met\");\n        wd.amount -= _wad;\n        super.withdraw(_wad);\n    }\n\n    /// @inheritdoc IDelayedWETH\n    function recover(uint256 _wad) external {\n        require(msg.sender == owner(), \"DelayedWETH: not owner\");\n        uint256 amount = _wad < address(this).balance ? _wad : address(this).balance;\n        (bool success,) = payable(msg.sender).call{value : amount}(hex\"\");\n        require(success, \"DelayedWETH: recover failed\");\n    }\n\n    /// @inheritdoc IDelayedWETH\n    function hold(address _guy, uint256 _wad) external {\n        require(msg.sender == owner(), \"DelayedWETH: not owner\");\n        allowance[_guy][msg.sender] = _wad;\n        emit Approval(_guy, msg.sender, _wad);\n    }\n}\n"
    },
    "contracts/L1/dispute/weth/WETH98.sol": {
      "content": "// SPDX-License-Identifier: GPL-3.0\n// Copyright (C) 2015, 2016, 2017 Dapphub\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\n// Based on WETH9 by Dapphub.\n// Modified by OP Labs.\n\npragma solidity 0.8.15;\n\nimport {IWETH} from \"../interfaces/IWETH.sol\";\n\n/// @title WETH98\n/// @notice WETH98 is a version of WETH9 upgraded for Solidity 0.8.x.\ncontract WETH98 is IWETH {\n    uint8 public constant decimals = 18;\n\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    /// @notice Pipes to deposit.\n    receive() external payable {\n        deposit();\n    }\n\n    /// @notice Pipes to deposit.\n    fallback() external payable {\n        deposit();\n    }\n\n    /// @inheritdoc IWETH\n    function name() external view virtual override returns (string memory) {\n        return \"Wrapped Ether\";\n    }\n\n    /// @inheritdoc IWETH\n    function symbol() external view virtual override returns (string memory) {\n        return \"WETH\";\n    }\n\n    /// @inheritdoc IWETH\n    function deposit() public payable virtual {\n        balanceOf[msg.sender] += msg.value;\n        emit Deposit(msg.sender, msg.value);\n    }\n\n    /// @inheritdoc IWETH\n    function withdraw(uint256 wad) public virtual {\n        require(balanceOf[msg.sender] >= wad);\n        balanceOf[msg.sender] -= wad;\n        payable(msg.sender).transfer(wad);\n        emit Withdrawal(msg.sender, wad);\n    }\n\n    /// @inheritdoc IWETH\n    function totalSupply() external view returns (uint256) {\n        return address(this).balance;\n    }\n\n    /// @inheritdoc IWETH\n    function approve(address guy, uint256 wad) external returns (bool) {\n        allowance[msg.sender][guy] = wad;\n        emit Approval(msg.sender, guy, wad);\n        return true;\n    }\n\n    /// @inheritdoc IWETH\n    function transfer(address dst, uint256 wad) external returns (bool) {\n        return transferFrom(msg.sender, dst, wad);\n    }\n\n    /// @inheritdoc IWETH\n    function transferFrom(address src, address dst, uint256 wad) public returns (bool) {\n        require(balanceOf[src] >= wad);\n\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\n            require(allowance[src][msg.sender] >= wad);\n            allowance[src][msg.sender] -= wad;\n        }\n\n        balanceOf[src] -= wad;\n        balanceOf[dst] += wad;\n\n        emit Transfer(src, dst, wad);\n\n        return true;\n    }\n}\n"
    },
    "contracts/L1/messaging/IL1CrossDomainMessenger.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\n\n/* Interface Imports */\nimport { ICrossDomainMessenger } from \"../../libraries/bridge/ICrossDomainMessenger.sol\";\n\n/**\n * @title IL1CrossDomainMessenger\n */\ninterface IL1CrossDomainMessenger is ICrossDomainMessenger {\n    /*******************\n     * Data Structures *\n     *******************/\n\n    struct L2MessageInclusionProof {\n        bytes32 stateRoot;\n        Lib_OVMCodec.ChainBatchHeader stateRootBatchHeader;\n        Lib_OVMCodec.ChainInclusionProof stateRootProof;\n        bytes stateTrieWitness;\n        bytes storageTrieWitness;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Relays a cross domain message to a contract.\n     * @param _target Target contract address.\n     * @param _sender Message sender address.\n     * @param _message Message to send to the target.\n     * @param _messageNonce Nonce for the provided message.\n     * @param _proof Inclusion proof for the given message.\n     */\n    function relayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce,\n        L2MessageInclusionProof memory _proof\n    ) external;\n\n    /**\n     * Replays a cross domain message to the target messenger.\n     * @param _target Target contract address.\n     * @param _sender Original sender address.\n     * @param _message Message to send to the target.\n     * @param _queueIndex CTC Queue index for the message to replay.\n     * @param _oldGasLimit Original gas limit used to send the message.\n     * @param _newGasLimit New gas limit to be used for this message.\n     */\n    function replayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _queueIndex,\n        uint32 _oldGasLimit,\n        uint32 _newGasLimit\n    ) external;\n\n    /**\n     * Relays a cross domain message to a contract with L2 chain id.\n     * @param _chainId L2 chain id.\n     * @param _target Target contract address.\n     * @param _sender Message sender address.\n     * @param _message Message to send to the target.\n     * @param _messageNonce Nonce for the provided message.\n     * @param _proof Inclusion proof for the given message.\n     */\n    function relayMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce,\n        L2MessageInclusionProof memory _proof\n    ) external;\n\n    /**\n     * Replays a cross domain message to the target messenger with L2 chain id.\n     * @param _chainId L2 chain id.\n     * @param _target Target contract address.\n     * @param _sender Original sender address.\n     * @param _message Message to send to the target.\n     * @param _oldGasLimit Original gas limit used to send the message.\n     * @param _newGasLimit New gas limit to be used for this message.\n     */\n    function replayMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _queueIndex,\n        uint32 _oldGasLimit,\n        uint32 _newGasLimit\n    ) external;\n}\n"
    },
    "contracts/L1/messaging/IL1ERC20Bridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title IL1ERC20Bridge\n */\ninterface IL1ERC20Bridge {\n    /**********\n     * Events *\n     **********/\n\n    event ERC20DepositInitiated(\n        address indexed _l1Token,\n        address indexed _l2Token,\n        address indexed _from,\n        address _to,\n        uint256 _amount,\n        bytes _data\n    );\n\n    event ERC20WithdrawalFinalized(\n        address indexed _l1Token,\n        address indexed _l2Token,\n        address indexed _from,\n        address _to,\n        uint256 _amount,\n        bytes _data\n    );\n\n    event ERC20ChainID(uint256 _chainid);\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @dev get the address of the corresponding L2 bridge contract.\n     * @return Address of the corresponding L2 bridge contract.\n     */\n    function l2TokenBridge() external returns (address);\n\n    /**\n     * @dev deposit an amount of the ERC20 to the caller's balance on L2.\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _amount Amount of the ERC20 to deposit\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositERC20(\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external;\n\n    /**\n     * @dev deposit an amount of ERC20 to a recipient's balance on L2.\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _to L2 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositERC20To(\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external;\n\n    /**\n     * @dev deposit an amount of the ERC20 to the caller's balance on L2.\n     * @param _chainid chainid\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _amount Amount of the ERC20 to deposit\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositERC20ByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable;\n\n    /**\n     * @dev deposit an amount of ERC20 to a recipient's balance on L2.\n     * @param _chainid chainid\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _to L2 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositERC20ToByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable;\n\n    /*************************\n     * Cross-chain Functions *\n     *************************/\n\n    /**\n     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n     * L1 ERC20 token.\n     * This call will fail if the initialized withdrawal from L2 has not been finalized.\n     *\n     * @param _l1Token Address of L1 token to finalizeWithdrawal for.\n     * @param _l2Token Address of L2 token where withdrawal was initiated.\n     * @param _from L2 address initiating the transfer.\n     * @param _to L1 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _data Data provided by the sender on L2. This data is provided\n     *   solely as a convenience for external contracts. Aside from enforcing a maximum\n     *   length, these contracts provide no guarantees about its content.\n     */\n    function finalizeERC20Withdrawal(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n\n    /**\n     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n     * L1 ERC20 token.\n     * This call will fail if the initialized withdrawal from L2 has not been finalized.\n     *\n     * @param _chainid chainid\n     * @param _l1Token Address of L1 token to finalizeWithdrawal for.\n     * @param _l2Token Address of L2 token where withdrawal was initiated.\n     * @param _from L2 address initiating the transfer.\n     * @param _to L1 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _data Data provided by the sender on L2. This data is provided\n     *   solely as a convenience for external contracts. Aside from enforcing a maximum\n     *   length, these contracts provide no guarantees about its content.\n     */\n    function finalizeERC20WithdrawalByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n\n    /**\n     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n     * L1 ERC20 token.\n     * This call will fail if the initialized withdrawal from L2 has not been finalized.\n     *\n     * @param _chainid chainid\n     * @param _from L2 address initiating the transfer.\n     * @param _to L1 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _data Data provided by the sender on L2. This data is provided\n     *   solely as a convenience for external contracts. Aside from enforcing a maximum\n     *   length, these contracts provide no guarantees about its content.\n     */\n    function finalizeMetisWithdrawalByChainId(\n        uint256 _chainid,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n}\n"
    },
    "contracts/L1/messaging/IL1StandardBridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\nimport \"./IL1ERC20Bridge.sol\";\n\n/**\n * @title IL1StandardBridge\n */\ninterface IL1StandardBridge is IL1ERC20Bridge {\n    /**********\n     * Events *\n     **********/\n    event ETHDepositInitiated(\n        address indexed _from,\n        address indexed _to,\n        uint256 _amount,\n        bytes _data,\n        uint256 chainId\n    );\n\n    event ETHWithdrawalFinalized(\n        address indexed _from,\n        address indexed _to,\n        uint256 _amount,\n        bytes _data,\n        uint256 chainId\n    );\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @dev Deposit an amount of the ETH to the caller's balance on L2.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositETH(uint32 _l2Gas, bytes calldata _data) external payable;\n\n    /**\n     * @dev Deposit an amount of ETH to a recipient's balance on L2.\n     * @param _to L2 address to credit the withdrawal to.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function depositETHTo(\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable;\n\n    function depositETHByChainId(\n        uint256 _chainId,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable;\n\n    function depositETHToByChainId(\n        uint256 _chainId,\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable;\n\n    /*************************\n     * Cross-chain Functions *\n     *************************/\n\n    /**\n     * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n     * L1 ETH token. Since only the xDomainMessenger can call this function, it will never be called\n     * before the withdrawal is finalized.\n     * @param _from L2 address initiating the transfer.\n     * @param _to L1 address to credit the withdrawal to.\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function finalizeETHWithdrawal(\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n\n    function finalizeETHWithdrawalByChainId(\n        uint256 _chainId,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n}\n"
    },
    "contracts/L1/messaging/L1CrossDomainMessenger.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { AddressAliasHelper } from \"../../standards/AddressAliasHelper.sol\";\nimport { Lib_AddressResolver } from \"../../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\nimport { Lib_AddressManager } from \"../../libraries/resolver/Lib_AddressManager.sol\";\nimport { Lib_SecureMerkleTrie } from \"../../libraries/trie/Lib_SecureMerkleTrie.sol\";\nimport { Lib_DefaultValues } from \"../../libraries/constants/Lib_DefaultValues.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\nimport { Lib_CrossDomainUtils } from \"../../libraries/bridge/Lib_CrossDomainUtils.sol\";\n\n/* Interface Imports */\nimport { IL1CrossDomainMessenger } from \"./IL1CrossDomainMessenger.sol\";\nimport { ICanonicalTransactionChain } from \"../rollup/ICanonicalTransactionChain.sol\";\nimport { IStateCommitmentChain } from \"../rollup/IStateCommitmentChain.sol\";\nimport { iMVM_DiscountOracle } from \"../../MVM/iMVM_DiscountOracle.sol\";\n\n/* External Imports */\nimport {\n    OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {\n    PausableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {\n    ReentrancyGuardUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\n\n/**\n * @title L1CrossDomainMessenger\n * @dev The L1 Cross Domain Messenger contract sends messages from L1 to L2, and relays messages\n * from L2 onto L1. In the event that a message sent from L1 to L2 is rejected for exceeding the L2\n * epoch gas limit, it can be resubmitted via this contract's replay function.\n *\n * Runtime target: EVM\n */\ncontract L1CrossDomainMessenger is\n    IL1CrossDomainMessenger,\n    Lib_AddressResolver,\n    OwnableUpgradeable,\n    PausableUpgradeable,\n    ReentrancyGuardUpgradeable\n{\n    /**********\n     * Events *\n     **********/\n\n    event MessageBlocked(bytes32 indexed _xDomainCalldataHash);\n\n    event MessageAllowed(bytes32 indexed _xDomainCalldataHash);\n\n    /**********************\n     * Contract Variables *\n     **********************/\n\n    mapping(bytes32 => bool) public blockedMessages;\n    mapping(bytes32 => bool) public relayedMessages;\n    mapping(bytes32 => bool) public successfulMessages;\n\n    address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;\n    uint256 internal constant DEFAULT_CHAINID = 1088;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * This contract is intended to be behind a delegate proxy.\n     * We pass the zero address to the address resolver just to satisfy the constructor.\n     * We still need to set this value in initialize().\n     */\n    constructor() Lib_AddressResolver(address(0)) {}\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @param _libAddressManager Address of the Address Manager.\n     */\n    function initialize(address _libAddressManager) public initializer {\n        require(\n            address(libAddressManager) == address(0),\n            \"L1CrossDomainMessenger already intialized.\"\n        );\n        libAddressManager = Lib_AddressManager(_libAddressManager);\n        xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;\n\n        // Initialize upgradable OZ contracts\n        __Context_init_unchained(); // Context is a dependency for both Ownable and Pausable\n        __Ownable_init_unchained();\n        __Pausable_init_unchained();\n        __ReentrancyGuard_init_unchained();\n    }\n\n    /**\n     * Pause relaying.\n     */\n    function pause() external onlyOwner {\n        _pause();\n    }\n\n    /**\n     * Unpause relaying.\n     */\n    function unpause() external onlyOwner {\n        _unpause();\n    }\n\n    /**\n     * Block a message.\n     * @param _xDomainCalldataHash Hash of the message to block.\n     */\n    function blockMessage(bytes32 _xDomainCalldataHash) external onlyOwner {\n        blockedMessages[_xDomainCalldataHash] = true;\n        emit MessageBlocked(_xDomainCalldataHash);\n    }\n\n    /**\n     * Allow a message.\n     * @param _xDomainCalldataHash Hash of the message to block.\n     */\n    function allowMessage(bytes32 _xDomainCalldataHash) external onlyOwner {\n        blockedMessages[_xDomainCalldataHash] = false;\n        emit MessageAllowed(_xDomainCalldataHash);\n    }\n\n    function xDomainMessageSender() external view returns (address) {\n        require(\n            xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER,\n            \"xDomainMessageSender is not set\"\n        );\n        return xDomainMsgSender;\n    }\n\n    /**\n     * Sends a cross domain message to the target messenger.\n     * only accounts checked by MVM_DiscountOracle.isXDomainSenderAllowed can send message from L1 to L2\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 memory _message,\n        uint32 _gasLimit\n    ) external payable {\n        sendMessageViaChainId(DEFAULT_CHAINID, _target, _message, _gasLimit);\n\n        // iMVM_DiscountOracle oracle = iMVM_DiscountOracle(resolve('MVM_DiscountOracle'));\n        // // this function will check against the whitelist and take the fee\n        // oracle.processL2SeqGas{value:msg.value}(msg.sender, DEFAULT_CHAINID);\n\n        // address ovmCanonicalTransactionChain = resolve(\"CanonicalTransactionChain\");\n        // // Use the CTC queue length as nonce\n        // uint40 nonce = ICanonicalTransactionChain(ovmCanonicalTransactionChain).getQueueLength();\n\n        // bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n        //     _target,\n        //     msg.sender,\n        //     _message,\n        //     nonce\n        // );\n\n        // _sendXDomainMessage(ovmCanonicalTransactionChain, xDomainCalldata, _gasLimit);\n\n        // emit SentMessage(_target, msg.sender, _message, nonce, _gasLimit, DEFAULT_CHAINID);\n    }\n\n    /**\n     * Sends a cross domain message to the target messenger.\n     * only accounts checked by MVM_DiscountOracle.isXDomainSenderAllowed can send message from L1 to L2\n     * @param _chainId L2 chain id.\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 sendMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        bytes memory _message,\n        uint32 _gasLimit\n    ) public payable override {\n        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(resolve(\"MVM_DiscountOracle\"));\n\n        // this function will check against the whitelist and take the fee\n        oracle.processL2SeqGas{ value: msg.value }(msg.sender, _chainId);\n\n        address ovmCanonicalTransactionChain = resolve(\"CanonicalTransactionChain\");\n\n        // Use the CTC queue length as nonce\n        uint40 nonce = ICanonicalTransactionChain(ovmCanonicalTransactionChain)\n            .getQueueLengthByChainId(_chainId);\n\n        bytes memory xDomainCalldataRaw = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            msg.sender,\n            _message,\n            nonce\n        );\n\n        _sendXDomainMessageViaChainId(\n            _chainId,\n            ovmCanonicalTransactionChain,\n            xDomainCalldataRaw,\n            _gasLimit\n        );\n        emit SentMessage(_target, msg.sender, _message, nonce, _gasLimit, _chainId);\n    }\n\n    /**\n     * Relays a cross domain message to a contract.\n     * @inheritdoc IL1CrossDomainMessenger\n     */\n    function relayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce,\n        L2MessageInclusionProof memory _proof\n    ) external whenNotPaused {\n        relayMessageViaChainId(DEFAULT_CHAINID, _target, _sender, _message, _messageNonce, _proof);\n    }\n\n    /**\n     * Replays a cross domain message to the target messenger.\n     * @inheritdoc IL1CrossDomainMessenger\n     */\n    function replayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _queueIndex,\n        uint32 _oldGasLimit,\n        uint32 _newGasLimit\n    ) external {\n        replayMessageViaChainId(\n            DEFAULT_CHAINID,\n            _target,\n            _sender,\n            _message,\n            _queueIndex,\n            _oldGasLimit,\n            _newGasLimit\n        );\n    }\n\n    function relayMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce,\n        L2MessageInclusionProof memory _proof\n    ) public override nonReentrant whenNotPaused {\n        bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            _sender,\n            _message,\n            _messageNonce\n        );\n        require(\n            _verifyXDomainMessageByChainId(_chainId, xDomainCalldata, _proof) == true,\n            \"Provided message could not be verified.\"\n        );\n\n        bytes32 xDomainCalldataHash = keccak256(xDomainCalldata);\n\n        require(\n            successfulMessages[xDomainCalldataHash] == false,\n            \"Provided message has already been received.\"\n        );\n\n        require(\n            blockedMessages[xDomainCalldataHash] == false,\n            \"Provided message has been blocked.\"\n        );\n\n        require(\n            _target != resolve(\"CanonicalTransactionChain\"),\n            \"Cannot send L2->L1 messages to L1 system contracts.\"\n        );\n\n        xDomainMsgSender = _sender;\n        (bool success, ) = _target.call(_message);\n        xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;\n\n        // Mark the message as received if the call was successful. Ensures that a message can be\n        // relayed multiple times in the case that the call reverted.\n        if (success) {\n            successfulMessages[xDomainCalldataHash] = true;\n            emit RelayedMessage(xDomainCalldataHash);\n        } else {\n            emit FailedRelayedMessage(xDomainCalldataHash);\n        }\n\n        // Store an identifier that can be used to prove that the given message was relayed by some\n        // user. Gives us an easy way to pay relayers for their work.\n        bytes32 relayId = keccak256(abi.encodePacked(xDomainCalldata, msg.sender, block.number));\n        relayedMessages[relayId] = true;\n    }\n\n    /**\n     * Replays a cross domain message to the target messenger.\n     *\n     */\n    function replayMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _queueIndex,\n        uint32 _oldGasLimit,\n        uint32 _newGasLimit\n    ) public override {\n        // Verify that the message is in the queue:\n        address canonicalTransactionChain = resolve(\"CanonicalTransactionChain\");\n        Lib_OVMCodec.QueueElement memory element = ICanonicalTransactionChain(\n            canonicalTransactionChain\n        ).getQueueElementByChainId(_chainId, _queueIndex);\n\n        //Compute the calldata that was originally used to send the message.\n        bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            _sender,\n            _message,\n            _queueIndex\n        );\n\n        // Compute the transactionHash\n        bytes32 transactionHash = keccak256(\n            abi.encode(\n                AddressAliasHelper.applyL1ToL2Alias(address(this)),\n                Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,\n                _oldGasLimit,\n                xDomainCalldata\n            )\n        );\n\n        require(\n            transactionHash == element.transactionHash,\n            \"Provided message has not been enqueued.\"\n        );\n\n        _sendXDomainMessageViaChainId(\n            _chainId,\n            canonicalTransactionChain,\n            xDomainCalldata,\n            _newGasLimit\n        );\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Verifies that the given message is valid.\n     * @param _xDomainCalldata Calldata to verify.\n     * @param _proof Inclusion proof for the message.\n     * @return Whether or not the provided message is valid.\n     */\n    function _verifyXDomainMessage(\n        bytes memory _xDomainCalldata,\n        L2MessageInclusionProof memory _proof\n    ) internal view returns (bool) {\n        return (_verifyStateRootProof(_proof) && _verifyStorageProof(_xDomainCalldata, _proof));\n    }\n\n    /**\n     * Verifies that the state root within an inclusion proof is valid.\n     * @param _proof Message inclusion proof.\n     * @return Whether or not the provided proof is valid.\n     */\n    function _verifyStateRootProof(L2MessageInclusionProof memory _proof)\n        internal\n        view\n        returns (bool)\n    {\n        IStateCommitmentChain ovmStateCommitmentChain = IStateCommitmentChain(\n            resolve(\"StateCommitmentChain\")\n        );\n\n        return (!ovmStateCommitmentChain.insideFraudProofWindow(_proof.stateRootBatchHeader) &&\n            ovmStateCommitmentChain.verifyStateCommitment(\n                _proof.stateRoot,\n                _proof.stateRootBatchHeader,\n                _proof.stateRootProof\n            ));\n    }\n\n    /**\n     * Verifies that the storage proof within an inclusion proof is valid.\n     * @param _xDomainCalldata Encoded message calldata.\n     * @param _proof Message inclusion proof.\n     * @return Whether or not the provided proof is valid.\n     */\n    function _verifyStorageProof(\n        bytes memory _xDomainCalldata,\n        L2MessageInclusionProof memory _proof\n    ) internal pure returns (bool) {\n        bytes32 storageKey = keccak256(\n            abi.encodePacked(\n                keccak256(\n                    abi.encodePacked(\n                        _xDomainCalldata,\n                        Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER\n                    )\n                ),\n                uint256(0)\n            )\n        );\n\n        (bool exists, bytes memory encodedMessagePassingAccount) = Lib_SecureMerkleTrie.get(\n            abi.encodePacked(Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER),\n            _proof.stateTrieWitness,\n            _proof.stateRoot\n        );\n\n        require(\n            exists,\n            \"Message passing predeploy has not been initialized or invalid proof provided.\"\n        );\n\n        Lib_OVMCodec.EVMAccount memory account = Lib_OVMCodec.decodeEVMAccount(\n            encodedMessagePassingAccount\n        );\n\n        return\n            Lib_SecureMerkleTrie.verifyInclusionProof(\n                abi.encodePacked(storageKey),\n                abi.encodePacked(uint8(1)),\n                _proof.storageTrieWitness,\n                account.storageRoot\n            );\n    }\n\n    /**\n     * Sends a cross domain message.\n     * @param _canonicalTransactionChain Address of the CanonicalTransactionChain instance.\n     * @param _message Message to send.\n     * @param _gasLimit OVM gas limit for the message.\n     */\n    function _sendXDomainMessage(\n        address _canonicalTransactionChain,\n        bytes memory _message,\n        uint256 _gasLimit\n    ) internal {\n        ICanonicalTransactionChain(_canonicalTransactionChain).enqueue(\n            Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,\n            _gasLimit,\n            _message\n        );\n    }\n\n    /**\n     * Verifies that the given message is valid.\n     * @param _xDomainCalldata Calldata to verify.\n     * @param _proof Inclusion proof for the message.\n     * @return Whether or not the provided message is valid.\n     */\n    function _verifyXDomainMessageByChainId(\n        uint256 _chainId,\n        bytes memory _xDomainCalldata,\n        L2MessageInclusionProof memory _proof\n    ) internal view returns (bool) {\n        return (_verifyStateRootProofByChainId(_chainId, _proof) &&\n            _verifyStorageProof(_xDomainCalldata, _proof));\n    }\n\n    /**\n     * Verifies that the state root within an inclusion proof is valid.\n     * @param _proof Message inclusion proof.\n     * @return Whether or not the provided proof is valid.\n     */\n    function _verifyStateRootProofByChainId(uint256 _chainId, L2MessageInclusionProof memory _proof)\n        internal\n        view\n        returns (bool)\n    {\n        IStateCommitmentChain ovmStateCommitmentChain = IStateCommitmentChain(\n            resolve(\"StateCommitmentChain\")\n        );\n\n        return (!ovmStateCommitmentChain.insideFraudProofWindow(_proof.stateRootBatchHeader) &&\n            ovmStateCommitmentChain.verifyStateCommitmentByChainId(\n                _chainId,\n                _proof.stateRoot,\n                _proof.stateRootBatchHeader,\n                _proof.stateRootProof\n            ));\n    }\n\n    /**\n     * Sends a cross domain message via chain id.\n     * @param _chainId L2 chain id.\n     * @param _message Message to send.\n     * @param _gasLimit OVM gas limit for the message.\n     */\n    function _sendXDomainMessageViaChainId(\n        uint256 _chainId,\n        address _canonicalTransactionChain,\n        bytes memory _message,\n        uint256 _gasLimit\n    ) internal {\n        ICanonicalTransactionChain(_canonicalTransactionChain).enqueueByChainId(\n            _chainId,\n            Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,\n            _gasLimit,\n            _message\n        );\n    }\n}\n"
    },
    "contracts/L1/messaging/L1StandardBridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { IL1StandardBridge } from \"./IL1StandardBridge.sol\";\nimport { IL1ERC20Bridge } from \"./IL1ERC20Bridge.sol\";\nimport { IL2ERC20Bridge } from \"../../L2/messaging/IL2ERC20Bridge.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/* Library Imports */\nimport { CrossDomainEnabled } from \"../../libraries/bridge/CrossDomainEnabled.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { iMVM_DiscountOracle } from \"../../MVM/iMVM_DiscountOracle.sol\";\nimport { Lib_AddressManager } from \"../../libraries/resolver/Lib_AddressManager.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/**\n * @title L1StandardBridge\n * @dev The L1 ETH and ERC20 Bridge is a contract which stores deposited L1 funds and standard\n * tokens that are in use on L2. It synchronizes a corresponding L2 Bridge, informing it of deposits\n * and listening to it for newly finalized withdrawals.\n *\n * Runtime target: EVM\n */\ncontract L1StandardBridge is IL1StandardBridge, CrossDomainEnabled {\n    using SafeERC20 for IERC20;\n\n    /********************************\n     * External Contract References *\n     ********************************/\n\n    address public l2TokenBridge;\n    address public metis;\n    address public addressmgr;\n\n    // Maps L1 token to chainid to L2 token to balance of the L1 token deposited\n    mapping(address => mapping(uint256 => mapping(address => uint256))) public deposits;\n\n    uint256 public constant DEFAULT_CHAINID = 1088;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    // This contract lives behind a proxy, so the constructor parameters will go unused.\n    constructor() CrossDomainEnabled(address(0)) {}\n\n    /******************\n     * Initialization *\n     ******************/\n\n    /**\n     * @param _l1messenger L1 Messenger address being used for cross-chain communications.\n     * @param _l2TokenBridge L2 standard bridge address.\n     */\n    function initialize(\n        address _l1messenger,\n        address _l2TokenBridge,\n        address _metis,\n        address _addressmgr\n    ) public {\n        require(messenger == address(0), \"Contract has already been initialized.\");\n        messenger = _l1messenger;\n        l2TokenBridge = _l2TokenBridge;\n        metis = _metis;\n        addressmgr = _addressmgr;\n    }\n\n    /**************\n     * Depositing *\n     **************/\n\n    /** @dev 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     */\n    modifier onlyEOA() {\n        // Used to stop deposits from contracts (avoid accidentally lost tokens)\n        require(!Address.isContract(msg.sender), \"Account not EOA\");\n        _;\n    }\n\n    /**\n     * @dev do not accept no data call\n     */\n    //receive() external payable onlyEOA {\n    //    _initiateETHDeposit(msg.sender, msg.sender, 200_000, bytes(\"\"));\n    //}\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function depositETH(uint32 _l2Gas, bytes calldata _data) external payable onlyEOA {\n        _initiateETHDeposit(msg.sender, msg.sender, _l2Gas, _data);\n    }\n\n    function depositETHByChainId(\n        uint256 _chainId,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable override onlyEOA {\n        _initiateETHDepositByChainId(_chainId, msg.sender, msg.sender, _l2Gas, _data);\n    }\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function depositETHTo(\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable {\n        _initiateETHDeposit(msg.sender, _to, _l2Gas, _data);\n    }\n\n    function depositETHToByChainId(\n        uint256 _chainId,\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable override {\n        _initiateETHDepositByChainId(_chainId, msg.sender, _to, _l2Gas, _data);\n    }\n\n    /**\n     * @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of\n     * the deposit.\n     * @param _from Account to pull the deposit from on L1.\n     * @param _to Account to give the deposit to on L2.\n     * @param _l2Gas Gas limit required to complete the deposit on L2,\n     *        it should equal to or large than oracle.getMinL2Gas(),\n     *        user should send at least _l2Gas * oracle.getDiscount().\n     *        Bridging tokens and coins require paying fees, and there is the defined minimal L2 Gas limit,\n     *        which may make the defined by user Gas value increase.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateETHDeposit(\n        address _from,\n        address _to,\n        uint32 _l2Gas,\n        bytes memory _data\n    ) internal {\n        _initiateETHDepositByChainId(DEFAULT_CHAINID, _from, _to, _l2Gas, _data);\n    }\n\n    /**\n     * @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of\n     * the deposit.\n     * @param _chainId L2 chain id.\n     * @param _from Account to pull the deposit from on L1.\n     * @param _to Account to give the deposit to on L2.\n     * @param _l2Gas Gas limit required to complete the deposit on L2,\n     *        it should equal to or large than oracle.getMinL2Gas(),\n     *        user should send at least _l2Gas * oracle.getDiscount().\n     *        Bridging tokens and coins require paying fees, and there is the defined minimal L2 Gas limit,\n     *        which may make the defined by user Gas value increase.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateETHDepositByChainId(\n        uint256 _chainId,\n        address _from,\n        address _to,\n        uint32 _l2Gas,\n        bytes memory _data\n    ) internal {\n        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(\n            Lib_AddressManager(addressmgr).getAddress(\"MVM_DiscountOracle\")\n        );\n        uint32 mingas = uint32(oracle.getMinL2Gas());\n        if (_l2Gas < mingas) {\n            _l2Gas = mingas;\n        }\n        uint256 fee = _l2Gas * oracle.getDiscount();\n\n        require(\n            fee < msg.value,\n            string(\n                abi.encodePacked(\n                    \"insufficient fee supplied. send at least \",\n                    Lib_Uint.uint2str(fee)\n                )\n            )\n        );\n        // Construct calldata for finalizeDeposit call\n        bytes memory message = abi.encodeWithSelector(\n            IL2ERC20Bridge.finalizeDeposit.selector,\n            address(0),\n            Lib_PredeployAddresses.OVM_ETH,\n            _from,\n            _to,\n            msg.value - fee,\n            _data\n        );\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            l2TokenBridge,\n            _l2Gas,\n            message,\n            fee // only send the supplied fees over (obviously)\n        );\n\n        emit ETHDepositInitiated(_from, _to, msg.value - fee, _data, _chainId);\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function depositERC20(\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external virtual onlyEOA {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            msg.sender,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function depositERC20To(\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external virtual {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    function depositERC20ByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable virtual override onlyEOA {\n        _initiateERC20DepositByChainId(\n            _chainid,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            msg.sender,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    function depositERC20ToByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable virtual override {\n        _initiateERC20DepositByChainId(\n            _chainid,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    /**\n     * @dev Performs the logic for deposits by informing the L2 Deposited Token\n     * contract of the deposit and calling a handler to lock the L1 funds. (e.g. transferFrom)\n     *\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _from Account to pull the deposit from on L1\n     * @param _to Account to give the deposit to on L2\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _l2Gas Gas limit required to complete the deposit on L2,\n     *        it should equal to or large than oracle.getMinL2Gas(),\n     *        user should send at least _l2Gas * oracle.getDiscount().\n     *        Bridging tokens and coins require paying fees, and there is the defined minimal L2 Gas limit,\n     *        which may make the defined by user Gas value increase.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateERC20Deposit(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) internal {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            _from,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    /**\n     * @dev Performs the logic for deposits by informing the L2 Deposited Token\n     * contract of the deposit and calling a handler to lock the L1 funds. (e.g. transferFrom)\n     *\n     * @param _chainId L2 chain id\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _from Account to pull the deposit from on L1\n     * @param _to Account to give the deposit to on L2\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _l2Gas Gas limit required to complete the deposit on L2,\n     *        it should equal to or large than oracle.getMinL2Gas(),\n     *        user should send at least _l2Gas * oracle.getDiscount().\n     *        Bridging tokens and coins require paying fees, and there is the defined minimal L2 Gas limit,\n     *        which may make the defined by user Gas value increase.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateERC20DepositByChainId(\n        uint256 _chainId,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) internal {\n        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(\n            Lib_AddressManager(addressmgr).getAddress(\"MVM_DiscountOracle\")\n        );\n\n        // stack too deep. so no more local variables\n        if (_l2Gas < uint32(oracle.getMinL2Gas())) {\n            _l2Gas = uint32(oracle.getMinL2Gas());\n        }\n\n        require(\n            _l2Gas * oracle.getDiscount() <= msg.value,\n            string(\n                abi.encodePacked(\n                    \"insufficient fee supplied. send at least \",\n                    Lib_Uint.uint2str(_l2Gas * oracle.getDiscount())\n                )\n            )\n        );\n\n        // When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future\n        // withdrawals. safeTransferFrom also checks if the contract has code, so this will fail if\n        // _from is an EOA or address(0).\n        IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);\n\n        bytes memory message;\n        if (_l1Token == metis) {\n            // Construct calldata for finalizeDeposit call\n            _l2Token = Lib_PredeployAddresses.MVM_COINBASE;\n            message = abi.encodeWithSelector(\n                IL2ERC20Bridge.finalizeDeposit.selector,\n                address(0),\n                Lib_PredeployAddresses.MVM_COINBASE,\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        } else {\n            // Construct calldata for finalizeDeposit call\n            message = abi.encodeWithSelector(\n                IL2ERC20Bridge.finalizeDeposit.selector,\n                _l1Token,\n                _l2Token,\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        }\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            l2TokenBridge,\n            _l2Gas,\n            message,\n            msg.value //send all values as fees to cover l2 tx cost\n        );\n\n        deposits[_l1Token][_chainId][_l2Token] = deposits[_l1Token][_chainId][_l2Token] + (_amount);\n\n        emit ERC20ChainID(_chainId);\n        emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    /*************************\n     * Cross-chain Functions *\n     *************************/\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function finalizeETHWithdrawal(\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external onlyFromCrossDomainAccount(l2TokenBridge) {\n        (bool success, ) = _to.call{ value: _amount }(new bytes(0));\n        require(success, \"TransferHelper::safeTransferETH: ETH transfer failed\");\n\n        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, DEFAULT_CHAINID);\n    }\n\n    function finalizeETHWithdrawalByChainId(\n        uint256 _chainid,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        (bool success, ) = _to.call{ value: _amount }(new bytes(0));\n        require(success, \"TransferHelper::safeTransferETH: ETH transfer failed\");\n\n        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, _chainid);\n    }\n\n    function finalizeMetisWithdrawalByChainId(\n        uint256 _chainid,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        _finalizeERC20WithdrawalByChainId(\n            _chainid,\n            metis,\n            Lib_PredeployAddresses.MVM_COINBASE,\n            _from,\n            _to,\n            _amount,\n            _data\n        );\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function finalizeERC20Withdrawal(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external onlyFromCrossDomainAccount(l2TokenBridge) {\n        _finalizeERC20WithdrawalByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            _from,\n            _to,\n            _amount,\n            _data\n        );\n    }\n\n    function finalizeERC20WithdrawalByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        _finalizeERC20WithdrawalByChainId(_chainid, _l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    function _finalizeERC20WithdrawalByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) internal {\n        deposits[_l1Token][_chainid][_l2Token] = deposits[_l1Token][_chainid][_l2Token] - _amount;\n\n        // When a withdrawal is finalized on L1, the L1 Bridge transfers the funds to the withdrawer\n        IERC20(_l1Token).safeTransfer(_to, _amount);\n\n        emit ERC20ChainID(_chainid);\n        emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    /*****************************\n     * Temporary - Migrating ETH *\n     *****************************/\n\n    /**\n     * @dev Adds ETH balance to the account. This is meant to allow for ETH\n     * to be migrated from an old gateway to a new gateway.\n     * NOTE: This is left for one upgrade only so we are able to receive the migrated ETH from the\n     * old contract\n     */\n    function donateETH() external payable {}\n}\n"
    },
    "contracts/L1/messaging/L1StandardBridgeLocal.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { IL1StandardBridge } from \"./IL1StandardBridge.sol\";\nimport { IL1ERC20Bridge } from \"./IL1ERC20Bridge.sol\";\nimport { IL2ERC20Bridge } from \"../../L2/messaging/IL2ERC20Bridge.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/* Library Imports */\nimport { CrossDomainEnabled } from \"../../libraries/bridge/CrossDomainEnabled.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { iMVM_DiscountOracle } from \"../../MVM/iMVM_DiscountOracle.sol\";\nimport { Lib_AddressManager } from \"../../libraries/resolver/Lib_AddressManager.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/**\n * @title L1StandardBridgeLocal\n * @dev The L1 ETH and ERC20 Bridge is a contract which stores deposited L1 funds and standard\n * tokens that are in use on L2. It synchronizes a corresponding L2 Bridge, informing it of deposits\n * and listening to it for newly finalized withdrawals.\n *\n * Runtime target: EVM\n */\ncontract L1StandardBridgeLocal is IL1StandardBridge, CrossDomainEnabled {\n    using SafeERC20 for IERC20;\n\n    /********************************\n     * External Contract References *\n     ********************************/\n\n    address public l2TokenBridge;\n    address public metis;\n    address public addressmgr;\n\n    // Maps L1 token to chainid to L2 token to balance of the L1 token deposited\n    mapping(address => mapping(uint256 => mapping(address => uint256))) public deposits;\n\n    uint256 public constant DEFAULT_CHAINID = 1088;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    // This contract lives behind a proxy, so the constructor parameters will go unused.\n    constructor() CrossDomainEnabled(address(0)) {}\n\n    /******************\n     * Initialization *\n     ******************/\n\n    /**\n     * @param _l1messenger L1 Messenger address being used for cross-chain communications.\n     * @param _l2TokenBridge L2 standard bridge address.\n     */\n    function initialize(\n        address _l1messenger,\n        address _l2TokenBridge,\n        address _metis,\n        address _addressmgr\n    ) public {\n        require(messenger == address(0), \"Contract has already been initialized.\");\n        messenger = _l1messenger;\n        l2TokenBridge = _l2TokenBridge;\n        metis = _metis;\n        addressmgr = _addressmgr;\n    }\n\n    /**************\n     * Depositing *\n     **************/\n\n    /** @dev 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     */\n    modifier onlyEOA() {\n        // Used to stop deposits from contracts (avoid accidentally lost tokens)\n        require(!Address.isContract(msg.sender), \"Account not EOA\");\n        _;\n    }\n\n    /**\n     * @dev do not accept no data call\n     */\n    receive() external payable onlyEOA {\n        require(false, \"do not send eth directly\");\n    }\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function depositETH(uint32 _l2Gas, bytes calldata _data) external payable onlyEOA {\n        _initiateETHDeposit(msg.sender, msg.sender, _l2Gas, _data);\n    }\n\n    function depositETHByChainId(\n        uint256 _chainId,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable override onlyEOA {\n        _initiateETHDepositByChainId(_chainId, msg.sender, msg.sender, _l2Gas, _data);\n    }\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function depositETHTo(\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable {\n        _initiateETHDeposit(msg.sender, _to, _l2Gas, _data);\n    }\n\n    function depositETHToByChainId(\n        uint256 _chainId,\n        address _to,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable override {\n        _initiateETHDepositByChainId(_chainId, msg.sender, _to, _l2Gas, _data);\n    }\n\n    /**\n     * @dev Performs the logic for deposits by storing the ETH and informing the L2 ETH Gateway of\n     * the deposit.\n     * @param _from Account to pull the deposit from on L1.\n     * @param _to Account to give the deposit to on L2.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateETHDeposit(\n        address _from,\n        address _to,\n        uint32 _l2Gas,\n        bytes memory _data\n    ) internal {\n        _initiateETHDepositByChainId(DEFAULT_CHAINID, _from, _to, _l2Gas, _data);\n    }\n\n    function _initiateETHDepositByChainId(\n        uint256 _chainId,\n        address _from,\n        address _to,\n        uint32 _l2Gas,\n        bytes memory _data\n    ) internal {\n        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(\n            Lib_AddressManager(addressmgr).getAddress(\"MVM_DiscountOracle\")\n        );\n        uint32 mingas = uint32(oracle.getMinL2Gas());\n        if (_l2Gas < mingas) {\n            _l2Gas = mingas;\n        }\n        uint256 fee = _l2Gas * oracle.getDiscount();\n\n        require(\n            fee <= msg.value,\n            string(\n                abi.encodePacked(\n                    \"insufficient fee supplied. send at least \",\n                    Lib_Uint.uint2str(fee)\n                )\n            )\n        );\n        // Construct calldata for finalizeDeposit call\n        bytes memory message = abi.encodeWithSelector(\n            IL2ERC20Bridge.finalizeDeposit.selector,\n            address(0),\n            Lib_PredeployAddresses.MVM_COINBASE, //MVM: only for local dev environment for easier funding\n            _from,\n            _to,\n            msg.value - fee,\n            _data\n        );\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            l2TokenBridge,\n            _l2Gas,\n            message,\n            fee // only send the supplied fees over (obviously)\n        );\n\n        emit ETHDepositInitiated(_from, _to, msg.value, _data, _chainId);\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function depositERC20(\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external virtual onlyEOA {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            msg.sender,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function depositERC20To(\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external virtual {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    function depositERC20ByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable virtual override onlyEOA {\n        _initiateERC20DepositByChainId(\n            _chainid,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            msg.sender,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    function depositERC20ToByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) external payable virtual override {\n        _initiateERC20DepositByChainId(\n            _chainid,\n            _l1Token,\n            _l2Token,\n            msg.sender,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    /**\n     * @dev Performs the logic for deposits by informing the L2 Deposited Token\n     * contract of the deposit and calling a handler to lock the L1 funds. (e.g. transferFrom)\n     *\n     * @param _l1Token Address of the L1 ERC20 we are depositing\n     * @param _l2Token Address of the L1 respective L2 ERC20\n     * @param _from Account to pull the deposit from on L1\n     * @param _to Account to give the deposit to on L2\n     * @param _amount Amount of the ERC20 to deposit.\n     * @param _l2Gas Gas limit required to complete the deposit on L2.\n     * @param _data Optional data to forward to L2. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateERC20Deposit(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) internal {\n        _initiateERC20DepositByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            _from,\n            _to,\n            _amount,\n            _l2Gas,\n            _data\n        );\n    }\n\n    function _initiateERC20DepositByChainId(\n        uint256 _chainId,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        uint32 _l2Gas,\n        bytes calldata _data\n    ) internal {\n        iMVM_DiscountOracle oracle = iMVM_DiscountOracle(\n            Lib_AddressManager(addressmgr).getAddress(\"MVM_DiscountOracle\")\n        );\n\n        // stack too deep. so no more local variables\n        if (_l2Gas < uint32(oracle.getMinL2Gas())) {\n            _l2Gas = uint32(oracle.getMinL2Gas());\n        }\n\n        require(\n            _l2Gas * oracle.getDiscount() <= msg.value,\n            string(\n                abi.encodePacked(\n                    \"insufficient fee supplied. send at least \",\n                    Lib_Uint.uint2str(_l2Gas * oracle.getDiscount())\n                )\n            )\n        );\n\n        // When a deposit is initiated on L1, the L1 Bridge transfers the funds to itself for future\n        // withdrawals. safeTransferFrom also checks if the contract has code, so this will fail if\n        // _from is an EOA or address(0).\n        IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);\n\n        bytes memory message;\n        if (_l1Token == metis) {\n            // Construct calldata for finalizeDeposit call\n            _l2Token = Lib_PredeployAddresses.MVM_COINBASE;\n            message = abi.encodeWithSelector(\n                IL2ERC20Bridge.finalizeDeposit.selector,\n                address(0),\n                Lib_PredeployAddresses.MVM_COINBASE,\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        } else {\n            // Construct calldata for finalizeDeposit call\n            message = abi.encodeWithSelector(\n                IL2ERC20Bridge.finalizeDeposit.selector,\n                _l1Token,\n                _l2Token,\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        }\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            l2TokenBridge,\n            _l2Gas,\n            message,\n            msg.value //send all values as fees to cover l2 tx cost\n        );\n\n        deposits[_l1Token][_chainId][_l2Token] = deposits[_l1Token][_chainId][_l2Token] + (_amount);\n\n        emit ERC20ChainID(_chainId);\n        emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    /*************************\n     * Cross-chain Functions *\n     *************************/\n\n    /**\n     * @inheritdoc IL1StandardBridge\n     */\n    function finalizeETHWithdrawal(\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external onlyFromCrossDomainAccount(l2TokenBridge) {\n        (bool success, ) = _to.call{ value: _amount }(new bytes(0));\n        require(success, \"TransferHelper::safeTransferETH: ETH transfer failed\");\n\n        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, DEFAULT_CHAINID);\n    }\n\n    function finalizeETHWithdrawalByChainId(\n        uint256 _chainid,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        (bool success, ) = _to.call{ value: _amount }(new bytes(0));\n        require(success, \"TransferHelper::safeTransferETH: ETH transfer failed\");\n\n        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, _chainid);\n    }\n\n    function finalizeMetisWithdrawalByChainId(\n        uint256 _chainid,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        // _finalizeERC20WithdrawalByChainId(\n        //     _chainid,\n        //     metis,\n        //     Lib_PredeployAddresses.MVM_COINBASE,\n        //     _from,\n        //     _to,\n        //     _amount,\n        //     _data\n        // );\n\n        //MVM: only for local dev environment for easier funding\n        (bool success, ) = _to.call{ value: _amount }(new bytes(0));\n        require(success, \"TransferHelper::safeTransferETH: ETH transfer failed\");\n\n        emit ETHWithdrawalFinalized(_from, _to, _amount, _data, _chainid);\n    }\n\n    /**\n     * @inheritdoc IL1ERC20Bridge\n     */\n    function finalizeERC20Withdrawal(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external onlyFromCrossDomainAccount(l2TokenBridge) {\n        _finalizeERC20WithdrawalByChainId(\n            DEFAULT_CHAINID,\n            _l1Token,\n            _l2Token,\n            _from,\n            _to,\n            _amount,\n            _data\n        );\n    }\n\n    function finalizeERC20WithdrawalByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external override onlyFromCrossDomainAccount(l2TokenBridge) {\n        _finalizeERC20WithdrawalByChainId(_chainid, _l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    function _finalizeERC20WithdrawalByChainId(\n        uint256 _chainid,\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) internal {\n        deposits[_l1Token][_chainid][_l2Token] = deposits[_l1Token][_chainid][_l2Token] - _amount;\n\n        // When a withdrawal is finalized on L1, the L1 Bridge transfers the funds to the withdrawer\n        IERC20(_l1Token).safeTransfer(_to, _amount);\n\n        emit ERC20ChainID(_chainid);\n        emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);\n    }\n\n    /*****************************\n     * Temporary - Migrating ETH *\n     *****************************/\n\n    /**\n     * @dev Adds ETH balance to the account. This is meant to allow for ETH\n     * to be migrated from an old gateway to a new gateway.\n     * NOTE: This is left for one upgrade only so we are able to receive the migrated ETH from the\n     * old contract\n     */\n    function donateETH() external payable {}\n}\n"
    },
    "contracts/L1/rollup/CanonicalTransactionChain.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { AddressAliasHelper } from \"../../standards/AddressAliasHelper.sol\";\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\nimport { Lib_AddressResolver } from \"../../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/* Interface Imports */\nimport { ICanonicalTransactionChain } from \"./ICanonicalTransactionChain.sol\";\nimport { IChainStorageContainer } from \"./IChainStorageContainer.sol\";\n\n/**\n * @title CanonicalTransactionChain\n * @dev The Canonical Transaction Chain (CTC) contract is an append-only log of transactions\n * which must be applied to the rollup state. It defines the ordering of rollup transactions by\n * writing them to the 'CTC:batches' instance of the Chain Storage Container.\n * The CTC only allows Proxy__OVM_L1CrossDomainMessenger address to 'enqueue' an L2 transaction, which will require that the\n * Sequencer will eventually append it to the rollup state.\n * The manager can add, delete and update the transactions data, update queue data,\n * when a fraud proof accepted in challege.\n *\n * Runtime target: EVM\n */\ncontract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressResolver {\n    /*************\n     * Constants *\n     *************/\n\n    // L2 tx gas-related\n    uint256 public constant MIN_ROLLUP_TX_GAS = 100000;\n    uint256 public constant MAX_ROLLUP_TX_SIZE = 50000;\n\n    // The approximate cost of calling the enqueue function\n    uint256 public enqueueGasCost;\n    // The ratio of the cost of L1 gas to the cost of L2 gas\n    uint256 public l2GasDiscountDivisor;\n    // The amount of L2 gas which can be forwarded to L2 without spam prevention via 'gas burn'.\n    // Calculated as the product of l2GasDiscountDivisor * enqueueGasCost.\n    // See comments in enqueue() for further detail.\n    uint256 public enqueueL2GasPrepaid;\n    //default l2 chain id\n    uint256 public constant DEFAULT_CHAINID = 1088;\n\n    // Encoding-related (all in bytes)\n    uint256 internal constant BATCH_CONTEXT_SIZE = 16;\n    // uint256 internal constant BATCH_CONTEXT_LENGTH_POS = 12;\n    uint256 internal constant BATCH_CONTEXT_START_POS = 15;\n    // uint256 internal constant TX_DATA_HEADER_SIZE = 3;\n    // uint256 internal constant BYTES_TILL_TX_DATA = 65;\n\n    /*************\n     * Variables *\n     *************/\n\n    uint256 public maxTransactionGasLimit;\n\n    /***************\n     * Queue State *\n     ***************/\n\n    mapping(uint256 => uint40) private _nextQueueIndex; // index of the first queue element not yet included\n    mapping(uint256 => Lib_OVMCodec.QueueElement[]) private queueElements;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor(\n        address _libAddressManager,\n        uint256 _maxTransactionGasLimit,\n        uint256 _l2GasDiscountDivisor,\n        uint256 _enqueueGasCost\n    ) Lib_AddressResolver(_libAddressManager) {\n        maxTransactionGasLimit = _maxTransactionGasLimit;\n        l2GasDiscountDivisor = _l2GasDiscountDivisor;\n        enqueueGasCost = _enqueueGasCost;\n        enqueueL2GasPrepaid = _l2GasDiscountDivisor * _enqueueGasCost;\n    }\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    /**\n     * Modifier to enforce that, if configured, only the Burn Admin may\n     * successfully call a method.\n     */\n    modifier onlyBurnAdmin() {\n        require(msg.sender == libAddressManager.owner(), \"Only callable by the Burn Admin.\");\n        _;\n    }\n\n    /*******************************\n     * Authorized Setter Functions *\n     *******************************/\n\n    /**\n     * Allows the Burn Admin to update the parameters which determine the amount of gas to burn.\n     * The value of enqueueL2GasPrepaid is immediately updated as well.\n     */\n    function setGasParams(uint256 _l2GasDiscountDivisor, uint256 _enqueueGasCost)\n        external\n        onlyBurnAdmin\n    {\n        enqueueGasCost = _enqueueGasCost;\n        l2GasDiscountDivisor = _l2GasDiscountDivisor;\n        // See the comment in enqueue() for the rationale behind this formula.\n        enqueueL2GasPrepaid = _l2GasDiscountDivisor * _enqueueGasCost;\n\n        emit L2GasParamsUpdated(l2GasDiscountDivisor, enqueueGasCost, enqueueL2GasPrepaid);\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Accesses the batch storage container.\n     * @return Reference to the batch storage container.\n     */\n    function batches() public view returns (IChainStorageContainer) {\n        return IChainStorageContainer(resolve(\"ChainStorageContainer-CTC-batches\"));\n    }\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElements() public view returns (uint256 _totalElements) {\n        (uint40 totalElements, , , ) = _getBatchExtraData();\n        return uint256(totalElements);\n    }\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatches() external view returns (uint256 _totalBatches) {\n        return batches().length();\n    }\n\n    /**\n     * Returns the index of the next element to be enqueued.\n     * @return Index for the next queue element.\n     */\n    function getNextQueueIndex() external view returns (uint40) {\n        return _nextQueueIndex[DEFAULT_CHAINID];\n    }\n\n    /**\n     * Returns the timestamp of the last transaction.\n     * @return Timestamp for the last transaction.\n     */\n    function getLastTimestamp() external view returns (uint40) {\n        (, , uint40 lastTimestamp, ) = _getBatchExtraData();\n        return lastTimestamp;\n    }\n\n    /**\n     * Returns the blocknumber of the last transaction.\n     * @return Blocknumber for the last transaction.\n     */\n    function getLastBlockNumber() external view returns (uint40) {\n        (, , , uint40 lastBlockNumber) = _getBatchExtraData();\n        return lastBlockNumber;\n    }\n\n    /**\n     * Gets the queue element at a particular index.\n     * @param _index Index of the queue element to access.\n     * @return _element Queue element at the given index.\n     */\n    function getQueueElement(uint256 _index)\n        external\n        view\n        returns (Lib_OVMCodec.QueueElement memory _element)\n    {\n        return queueElements[DEFAULT_CHAINID][_index];\n    }\n\n    /**\n     * Get the number of queue elements which have not yet been included.\n     * @return Number of pending queue elements.\n     */\n    function getNumPendingQueueElements() external view returns (uint40) {\n        return uint40(queueElements[DEFAULT_CHAINID].length) - _nextQueueIndex[DEFAULT_CHAINID];\n    }\n\n    /**\n     * Retrieves the length of the queue, including\n     * both pending and canonical transactions.\n     * @return Length of the queue.\n     */\n    function getQueueLength() external view returns (uint40) {\n        return uint40(queueElements[DEFAULT_CHAINID].length);\n    }\n\n    /**\n     * Adds a transaction to the queue.\n     * @param _target Target L2 contract to send the transaction to.\n     * @param _gasLimit Gas limit for the enqueued L2 transaction.\n     * @param _data Transaction data.\n     */\n    function enqueue(\n        address _target,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) external {\n        enqueueByChainId(DEFAULT_CHAINID, _target, _gasLimit, _data);\n    }\n\n    /**\n     * Allows the sequencer to append a batch of transactions.\n     * @dev This function uses a custom encoding scheme for efficiency reasons.\n     * .param _shouldStartAtElement Specific batch we expect to start appending to.\n     * .param _totalElementsToAppend Total number of batch elements we expect to append.\n     * .param _contexts Array of batch contexts.\n     * .param _transactionDataFields Array of raw transaction data.\n     */\n    function appendSequencerBatch() external {\n        uint40 shouldStartAtElement;\n        uint24 totalElementsToAppend;\n        uint24 numContexts;\n        assembly {\n            shouldStartAtElement := shr(216, calldataload(4))\n            totalElementsToAppend := shr(232, calldataload(9))\n            numContexts := shr(232, calldataload(12))\n        }\n\n        require(\n            shouldStartAtElement == getTotalElements(),\n            \"Actual batch start index does not match expected start index.\"\n        );\n\n        require(\n            msg.sender == resolve(\"MVM_Sequencer\"),\n            \"Function can only be called by the Sequencer.\"\n        );\n\n        uint40 nextTransactionPtr = uint40(\n            BATCH_CONTEXT_START_POS + BATCH_CONTEXT_SIZE * numContexts\n        );\n\n        require(msg.data.length >= nextTransactionPtr, \"Not enough BatchContexts provided.\");\n\n        // Counter for number of sequencer transactions appended so far.\n        uint32 numSequencerTransactions = 0;\n\n        // Cache the _nextQueueIndex storage variable to a temporary stack variable.\n        // This is safe as long as nothing reads or writes to the storage variable\n        // until it is updated by the temp variable.\n        uint40 nextQueueIndex = _nextQueueIndex[DEFAULT_CHAINID];\n\n        BatchContext memory curContext;\n        for (uint32 i = 0; i < numContexts; i++) {\n            BatchContext memory nextContext = _getBatchContext(i);\n\n            // Now we can update our current context.\n            curContext = nextContext;\n\n            // Process sequencer transactions first.\n            numSequencerTransactions += uint32(curContext.numSequencedTransactions);\n\n            // Now process any subsequent queue transactions.\n            nextQueueIndex += uint40(curContext.numSubsequentQueueTransactions);\n        }\n\n        require(\n            nextQueueIndex <= queueElements[DEFAULT_CHAINID].length,\n            \"Attempted to append more elements than are available in the queue.\"\n        );\n\n        // Generate the required metadata that we need to append this batch\n        uint40 numQueuedTransactions = totalElementsToAppend - numSequencerTransactions;\n        uint40 blockTimestamp;\n        uint40 blockNumber;\n        if (curContext.numSubsequentQueueTransactions == 0) {\n            // The last element is a sequencer tx, therefore pull timestamp and block number from\n            // the last context.\n            blockTimestamp = uint40(curContext.timestamp);\n            blockNumber = uint40(curContext.blockNumber);\n        } else {\n            // The last element is a queue tx, therefore pull timestamp and block number from the\n            // queue element.\n            // curContext.numSubsequentQueueTransactions > 0 which means that we've processed at\n            // least one queue element. We increment nextQueueIndex after processing each queue\n            // element, so the index of the last element we processed is nextQueueIndex - 1.\n            Lib_OVMCodec.QueueElement memory lastElement = queueElements[DEFAULT_CHAINID][\n                nextQueueIndex - 1\n            ];\n\n            blockTimestamp = lastElement.timestamp;\n            blockNumber = lastElement.blockNumber;\n        }\n\n        // Cache the previous blockhash to ensure all transaction data can be retrieved efficiently.\n        _appendBatch(\n            blockhash(block.number - 1),\n            totalElementsToAppend,\n            numQueuedTransactions,\n            blockTimestamp,\n            blockNumber\n        );\n\n        emit SequencerBatchAppended(\n            DEFAULT_CHAINID,\n            nextQueueIndex - numQueuedTransactions,\n            numQueuedTransactions,\n            getTotalElements()\n        );\n\n        // Update the _nextQueueIndex storage variable.\n        _nextQueueIndex[DEFAULT_CHAINID] = nextQueueIndex;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Returns the BatchContext located at a particular index.\n     * @param _index The index of the BatchContext\n     * @return The BatchContext at the specified index.\n     */\n    function _getBatchContext(uint256 _index) internal pure returns (BatchContext memory) {\n        uint256 contextPtr = 15 + _index * BATCH_CONTEXT_SIZE;\n        uint256 numSequencedTransactions;\n        uint256 numSubsequentQueueTransactions;\n        uint256 ctxTimestamp;\n        uint256 ctxBlockNumber;\n\n        assembly {\n            numSequencedTransactions := shr(232, calldataload(contextPtr))\n            numSubsequentQueueTransactions := shr(232, calldataload(add(contextPtr, 3)))\n            ctxTimestamp := shr(216, calldataload(add(contextPtr, 6)))\n            ctxBlockNumber := shr(216, calldataload(add(contextPtr, 11)))\n        }\n\n        return\n            BatchContext({\n                numSequencedTransactions: numSequencedTransactions,\n                numSubsequentQueueTransactions: numSubsequentQueueTransactions,\n                timestamp: ctxTimestamp,\n                blockNumber: ctxBlockNumber\n            });\n    }\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Index of the next queue element.\n     */\n    function _getBatchExtraData()\n        internal\n        view\n        returns (\n            uint40,\n            uint40,\n            uint40,\n            uint40\n        )\n    {\n        bytes27 extraData = batches().getGlobalMetadata();\n\n        uint40 totalElements;\n        uint40 nextQueueIndex;\n        uint40 lastTimestamp;\n        uint40 lastBlockNumber;\n\n        // solhint-disable max-line-length\n        assembly {\n            extraData := shr(40, extraData)\n            totalElements := and(\n                extraData,\n                0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n            )\n            nextQueueIndex := shr(\n                40,\n                and(extraData, 0x00000000000000000000000000000000000000000000FFFFFFFFFF0000000000)\n            )\n            lastTimestamp := shr(\n                80,\n                and(extraData, 0x0000000000000000000000000000000000FFFFFFFFFF00000000000000000000)\n            )\n            lastBlockNumber := shr(\n                120,\n                and(extraData, 0x000000000000000000000000FFFFFFFFFF000000000000000000000000000000)\n            )\n        }\n        // solhint-enable max-line-length\n\n        return (totalElements, nextQueueIndex, lastTimestamp, lastBlockNumber);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _nextQueueIdx Index of the next queue element.\n     * @param _timestamp Timestamp for the last batch.\n     * @param _blockNumber Block number of the last batch.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraData(\n        uint40 _totalElements,\n        uint40 _nextQueueIdx,\n        uint40 _timestamp,\n        uint40 _blockNumber\n    ) internal pure returns (bytes27) {\n        // bytes27 extraData;\n        // assembly {\n        //     extraData := _totalElements\n        //     extraData := or(extraData, shl(40, _nextQueueIdx))\n        //     extraData := or(extraData, shl(80, _timestamp))\n        //     extraData := or(extraData, shl(120, _blockNumber))\n        //     extraData := shl(40, extraData)\n        // }\n\n        // return extraData;\n        return\n            _makeBatchExtraDataByChainId(_totalElements, _nextQueueIdx, _timestamp, _blockNumber);\n    }\n\n    /**\n     * Inserts a batch into the chain of batches.\n     * @param _transactionRoot Root of the transaction tree for this batch.\n     * @param _batchSize Number of elements in the batch.\n     * @param _numQueuedTransactions Number of queue transactions in the batch.\n     * @param _timestamp The latest batch timestamp.\n     * @param _blockNumber The latest batch blockNumber.\n     */\n    function _appendBatch(\n        bytes32 _transactionRoot,\n        uint256 _batchSize,\n        uint256 _numQueuedTransactions,\n        uint40 _timestamp,\n        uint40 _blockNumber\n    ) internal {\n        IChainStorageContainer batchesRef = batches();\n        (uint40 totalElements, uint40 nextQueueIndex, , ) = _getBatchExtraData();\n\n        Lib_OVMCodec.ChainBatchHeader memory header = Lib_OVMCodec.ChainBatchHeader({\n            batchIndex: batchesRef.length(),\n            batchRoot: _transactionRoot,\n            batchSize: _batchSize,\n            prevTotalElements: totalElements,\n            extraData: hex\"\"\n        });\n\n        emit TransactionBatchAppended(\n            DEFAULT_CHAINID,\n            header.batchIndex,\n            header.batchRoot,\n            header.batchSize,\n            header.prevTotalElements,\n            header.extraData\n        );\n\n        bytes32 batchHeaderHash = Lib_OVMCodec.hashBatchHeader(header);\n        bytes27 latestBatchContext = _makeBatchExtraData(\n            totalElements + uint40(header.batchSize),\n            nextQueueIndex + uint40(_numQueuedTransactions),\n            _timestamp,\n            _blockNumber\n        );\n\n        batchesRef.push(batchHeaderHash, latestBatchContext);\n    }\n\n    //added chain id for public function\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElementsByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _totalElements)\n    {\n        (uint40 totalElements, , , ) = _getBatchExtraDataByChainId(_chainId);\n        return uint256(totalElements);\n    }\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatchesByChainId(uint256 _chainId)\n        external\n        view\n        override\n        returns (uint256 _totalBatches)\n    {\n        return batches().lengthByChainId(_chainId);\n    }\n\n    /**\n     * Returns the index of the next element to be enqueued.\n     * @return Index for the next queue element.\n     */\n    function getNextQueueIndexByChainId(uint256 _chainId) external view override returns (uint40) {\n        (, uint40 nextQueueIndex, , ) = _getBatchExtraDataByChainId(_chainId);\n        return nextQueueIndex;\n    }\n\n    /**\n     * Returns the timestamp of the last transaction.\n     * @return Timestamp for the last transaction.\n     */\n    function getLastTimestampByChainId(uint256 _chainId) external view override returns (uint40) {\n        (, , uint40 lastTimestamp, ) = _getBatchExtraDataByChainId(_chainId);\n        return lastTimestamp;\n    }\n\n    /**\n     * Returns the blocknumber of the last transaction.\n     * @return Blocknumber for the last transaction.\n     */\n    function getLastBlockNumberByChainId(uint256 _chainId) external view override returns (uint40) {\n        (, , , uint40 lastBlockNumber) = _getBatchExtraDataByChainId(_chainId);\n        return lastBlockNumber;\n    }\n\n    /**\n     * Gets the queue element at a particular index.\n     * @param _index Index of the queue element to access.\n     * @return _element Queue element at the given index.\n     */\n    function getQueueElementByChainId(uint256 _chainId, uint256 _index)\n        external\n        view\n        override\n        returns (Lib_OVMCodec.QueueElement memory _element)\n    {\n        return queueElements[_chainId][_index];\n    }\n\n    /**\n     * Get the number of queue elements which have not yet been included.\n     * @return Number of pending queue elements.\n     */\n    function getNumPendingQueueElementsByChainId(uint256 _chainId)\n        external\n        view\n        override\n        returns (uint40)\n    {\n        return uint40(queueElements[_chainId].length) - _nextQueueIndex[_chainId];\n    }\n\n    /**\n     * Retrieves the length of the queue, including\n     * both pending and canonical transactions.\n     * @return Length of the queue.\n     */\n    function getQueueLengthByChainId(uint256 _chainId) external view override returns (uint40) {\n        return uint40(queueElements[_chainId].length);\n    }\n\n    /**\n     * Adds a transaction to the queue.\n     * @param _target Target L2 contract to send the transaction to.\n     * @param _gasLimit Gas limit for the enqueued L2 transaction.\n     * @param _data Transaction data.\n     */\n    function enqueueByChainId(\n        uint256 _chainId,\n        address _target,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) public override {\n        require(\n            msg.sender == resolve(\"Proxy__OVM_L1CrossDomainMessenger\"),\n            \"only the cross domain messenger can enqueue\"\n        );\n\n        require(\n            _data.length <= MAX_ROLLUP_TX_SIZE,\n            \"Transaction data size exceeds maximum for rollup transaction.\"\n        );\n\n        require(\n            _gasLimit <= maxTransactionGasLimit,\n            \"Transaction gas limit exceeds maximum for rollup transaction.\"\n        );\n\n        require(_gasLimit >= MIN_ROLLUP_TX_GAS, \"Transaction gas limit too low to enqueue.\");\n\n        // Transactions submitted to the queue lack a method for paying gas fees to the Sequencer.\n        // So we need to prevent spam attacks by ensuring that the cost of enqueueing a transaction\n        // from L1 to L2 is not underpriced. For transaction with a high L2 gas limit, we do this by\n        // burning some extra gas on L1. Of course there is also some intrinsic cost to enqueueing a\n        // transaction, so we want to make sure not to over-charge (by burning too much L1 gas).\n        // Therefore, we define 'enqueueL2GasPrepaid' as the L2 gas limit above which we must burn\n        // additional gas on L1. This threshold is the product of two inputs:\n        // 1. enqueueGasCost: the base cost of calling this function.\n        // 2. l2GasDiscountDivisor: the ratio between the cost of gas on L1 and L2. This is a\n        //    positive integer, meaning we assume L2 gas is always less costly.\n        // The calculation below for gasToConsume can be seen as converting the difference (between\n        // the specified L2 gas limit and the prepaid L2 gas limit) to an L1 gas amount.\n        if (_gasLimit > enqueueL2GasPrepaid) {\n            uint256 gasToConsume = (_gasLimit - enqueueL2GasPrepaid) / l2GasDiscountDivisor;\n            uint256 startingGas = gasleft();\n\n            // Although this check is not necessary (burn below will run out of gas if not true), it\n            // gives the user an explicit reason as to why the enqueue attempt failed.\n            require(startingGas > gasToConsume, \"Insufficient gas for L2 rate limiting burn.\");\n\n            uint256 i;\n            while (startingGas - gasleft() < gasToConsume) {\n                i++;\n            }\n        }\n\n        // Apply an aliasing unless msg.sender == tx.origin. This prevents an attack in which a\n        // contract on L1 has the same address as a contract on L2 but doesn't have the same code.\n        // We can safely ignore this for EOAs because they're guaranteed to have the same \"code\"\n        // (i.e. no code at all). This also makes it possible for users to interact with contracts\n        // on L2 even when the Sequencer is down.\n        address sender;\n        if (msg.sender == tx.origin) {\n            sender = msg.sender;\n        } else {\n            sender = AddressAliasHelper.applyL1ToL2Alias(msg.sender);\n        }\n\n        bytes32 transactionHash = keccak256(abi.encode(sender, _target, _gasLimit, _data));\n\n        queueElements[_chainId].push(\n            Lib_OVMCodec.QueueElement({\n                transactionHash: transactionHash,\n                timestamp: uint40(block.timestamp),\n                blockNumber: uint40(block.number)\n            })\n        );\n\n        uint256 queueIndex = queueElements[_chainId].length - 1;\n        emit TransactionEnqueued(\n            _chainId,\n            sender,\n            _target,\n            _gasLimit,\n            _data,\n            queueIndex,\n            block.timestamp\n        );\n    }\n\n    /**\n     * Allows the sequencer to append a batch of transactions.\n     * @dev This function uses a custom encoding scheme for efficiency reasons.\n     * .param _shouldStartAtElement Specific batch we expect to start appending to.\n     * .param _totalElementsToAppend Total number of batch elements we expect to append.\n     * .param _contexts Array of batch contexts.\n     * .param _transactionDataFields Array of raw transaction data.\n     */\n    function appendSequencerBatchByChainId() external override {\n        uint256 _chainId;\n        uint40 shouldStartAtElement;\n        uint24 totalElementsToAppend;\n        uint24 numContexts;\n        assembly {\n            _chainId := calldataload(4)\n            shouldStartAtElement := shr(216, calldataload(36))\n            totalElementsToAppend := shr(232, calldataload(41))\n            numContexts := shr(232, calldataload(44))\n        }\n\n        require(\n            shouldStartAtElement == getTotalElementsByChainId(_chainId),\n            \"Actual batch start index does not match expected start index.\"\n        );\n\n        require(\n            msg.sender ==\n                resolve(string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Sequencer\"))),\n            \"Function can only be called by the Sequencer.\"\n        );\n\n        require(numContexts > 0, \"Must provide at least one batch context.\");\n\n        require(totalElementsToAppend > 0, \"Must append at least one element.\");\n\n        uint40 nextTransactionPtr = uint40(\n            BATCH_CONTEXT_START_POS + BATCH_CONTEXT_SIZE * numContexts\n        );\n\n        require(msg.data.length >= nextTransactionPtr, \"Not enough BatchContexts provided.\");\n\n        // Cache the _nextQueueIndex storage variable to a temporary stack variable.\n        // This is safe as long as nothing reads or writes to the storage variable\n        // until it is updated by the temp variable.\n        uint40 nextQueueIndex = _nextQueueIndex[_chainId];\n\n        // Counter for number of sequencer transactions appended so far.\n        uint32 numSequencerTransactions = 0;\n\n        BatchContext memory curContext;\n        for (uint32 i = 0; i < numContexts; i++) {\n            BatchContext memory nextContext = _getBatchContextByChainId(0, i);\n\n            // Now we can update our current context.\n            curContext = nextContext;\n            // Process sequencer transactions first.\n            numSequencerTransactions += uint32(curContext.numSequencedTransactions);\n\n            // Now process any subsequent queue transactions.\n            nextQueueIndex += uint40(curContext.numSubsequentQueueTransactions);\n        }\n\n        require(\n            nextQueueIndex <= queueElements[_chainId].length,\n            \"Attempted to append more elements than are available in the queue.\"\n        );\n\n        // Generate the required metadata that we need to append this batch\n        uint40 numQueuedTransactions = totalElementsToAppend - numSequencerTransactions;\n        uint40 blockTimestamp;\n        uint40 blockNumber;\n        if (curContext.numSubsequentQueueTransactions == 0) {\n            // The last element is a sequencer tx, therefore pull timestamp and block number from\n            // the last context.\n            blockTimestamp = uint40(curContext.timestamp);\n            blockNumber = uint40(curContext.blockNumber);\n        } else {\n            // The last element is a queue tx, therefore pull timestamp and block number from the\n            // queue element.\n            // curContext.numSubsequentQueueTransactions > 0 which means that we've processed at\n            // least one queue element. We increment nextQueueIndex after processing each queue\n            // element, so the index of the last element we processed is nextQueueIndex - 1.\n            Lib_OVMCodec.QueueElement memory lastElement = queueElements[_chainId][\n                nextQueueIndex - 1\n            ];\n\n            blockTimestamp = lastElement.timestamp;\n            blockNumber = lastElement.blockNumber;\n        }\n\n        // Cache the previous blockhash to ensure all transaction data can be retrieved efficiently.\n        _appendBatchByChainId(\n            _chainId,\n            blockhash(block.number - 1),\n            totalElementsToAppend,\n            numQueuedTransactions,\n            blockTimestamp,\n            blockNumber\n        );\n\n        emit SequencerBatchAppended(\n            _chainId,\n            nextQueueIndex - numQueuedTransactions,\n            numQueuedTransactions,\n            getTotalElementsByChainId(_chainId)\n        );\n\n        // Update the _nextQueueIndex storage variable.\n        _nextQueueIndex[_chainId] = nextQueueIndex;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Returns the BatchContext located at a particular index.\n     * @param _index The index of the BatchContext\n     * @return The BatchContext at the specified index.\n     */\n    function _getBatchContextByChainId(uint256 _ptrStart, uint256 _index)\n        internal\n        pure\n        returns (BatchContext memory)\n    {\n        uint256 contextPtr = _ptrStart + 32 + 15 + _index * BATCH_CONTEXT_SIZE;\n        uint256 numSequencedTransactions;\n        uint256 numSubsequentQueueTransactions;\n        uint256 ctxTimestamp;\n        uint256 ctxBlockNumber;\n\n        assembly {\n            numSequencedTransactions := shr(232, calldataload(contextPtr))\n            numSubsequentQueueTransactions := shr(232, calldataload(add(contextPtr, 3)))\n            ctxTimestamp := shr(216, calldataload(add(contextPtr, 6)))\n            ctxBlockNumber := shr(216, calldataload(add(contextPtr, 11)))\n        }\n\n        return\n            BatchContext({\n                numSequencedTransactions: numSequencedTransactions,\n                numSubsequentQueueTransactions: numSubsequentQueueTransactions,\n                timestamp: ctxTimestamp,\n                blockNumber: ctxBlockNumber\n            });\n    }\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Index of the next queue element.\n     */\n    function _getBatchExtraDataByChainId(uint256 _chainId)\n        internal\n        view\n        returns (\n            uint40,\n            uint40,\n            uint40,\n            uint40\n        )\n    {\n        bytes27 extraData = batches().getGlobalMetadataByChainId(_chainId);\n\n        uint40 totalElements;\n        uint40 nextQueueIndex;\n        uint40 lastTimestamp;\n        uint40 lastBlockNumber;\n        assembly {\n            extraData := shr(40, extraData)\n            totalElements := and(\n                extraData,\n                0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n            )\n            nextQueueIndex := shr(\n                40,\n                and(extraData, 0x00000000000000000000000000000000000000000000FFFFFFFFFF0000000000)\n            )\n            lastTimestamp := shr(\n                80,\n                and(extraData, 0x0000000000000000000000000000000000FFFFFFFFFF00000000000000000000)\n            )\n            lastBlockNumber := shr(\n                120,\n                and(extraData, 0x000000000000000000000000FFFFFFFFFF000000000000000000000000000000)\n            )\n        }\n\n        return (totalElements, nextQueueIndex, lastTimestamp, lastBlockNumber);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _nextQueueIdx Index of the next queue element.\n     * @param _timestamp Timestamp for the last batch.\n     * @param _blockNumber Block number of the last batch.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraDataByChainId(\n        uint40 _totalElements,\n        uint40 _nextQueueIdx,\n        uint40 _timestamp,\n        uint40 _blockNumber\n    ) internal pure returns (bytes27) {\n        bytes27 extraData;\n        assembly {\n            extraData := _totalElements\n            extraData := or(extraData, shl(40, _nextQueueIdx))\n            extraData := or(extraData, shl(80, _timestamp))\n            extraData := or(extraData, shl(120, _blockNumber))\n            extraData := shl(40, extraData)\n        }\n\n        return extraData;\n    }\n\n    /**\n     * Inserts a batch into the chain of batches.\n     * @param _transactionRoot Root of the transaction tree for this batch.\n     * @param _batchSize Number of elements in the batch.\n     * @param _numQueuedTransactions Number of queue transactions in the batch.\n     * @param _timestamp The latest batch timestamp.\n     * @param _blockNumber The latest batch blockNumber.\n     */\n    function _appendBatchByChainId(\n        uint256 _chainId,\n        bytes32 _transactionRoot,\n        uint256 _batchSize,\n        uint256 _numQueuedTransactions,\n        uint40 _timestamp,\n        uint40 _blockNumber\n    ) internal {\n        IChainStorageContainer batchesRef = batches();\n        (uint40 totalElements, uint40 nextQueueIndex, , ) = _getBatchExtraDataByChainId(_chainId);\n\n        Lib_OVMCodec.ChainBatchHeader memory header = Lib_OVMCodec.ChainBatchHeader({\n            batchIndex: batchesRef.lengthByChainId(_chainId),\n            batchRoot: _transactionRoot,\n            batchSize: _batchSize,\n            prevTotalElements: totalElements,\n            extraData: hex\"\"\n        });\n\n        emit TransactionBatchAppended(\n            _chainId,\n            header.batchIndex,\n            header.batchRoot,\n            header.batchSize,\n            header.prevTotalElements,\n            header.extraData\n        );\n\n        bytes32 batchHeaderHash = Lib_OVMCodec.hashBatchHeader(header);\n        bytes27 latestBatchContext = _makeBatchExtraDataByChainId(\n            totalElements + uint40(header.batchSize),\n            nextQueueIndex + uint40(_numQueuedTransactions),\n            _timestamp,\n            _blockNumber\n        );\n\n        batchesRef.pushByChainId(_chainId, batchHeaderHash, latestBatchContext);\n    }\n\n    modifier onlyManager() {\n        require(\n            msg.sender == resolve(\"MVM_SuperManager\"),\n            \"ChainStorageContainer: Function can only be called by the owner.\"\n        );\n        _;\n    }\n\n    function pushQueueByChainId(uint256 _chainId, Lib_OVMCodec.QueueElement calldata _object)\n        external\n        override\n        onlyManager\n    {\n        queueElements[_chainId].push(_object);\n        emit QueuePushed(msg.sender, _chainId, _object);\n    }\n\n    function setQueueByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        Lib_OVMCodec.QueueElement calldata _object\n    ) external override onlyManager {\n        queueElements[_chainId][_index] = _object;\n        emit QueueSetted(msg.sender, _chainId, _index, _object);\n    }\n\n    function setBatchGlobalMetadataByChainId(uint256 _chainId, bytes27 _globalMetadata)\n        external\n        override\n        onlyManager\n    {\n        batches().setGlobalMetadataByChainId(_chainId, _globalMetadata);\n        emit BatchesGlobalMetadataSet(msg.sender, _chainId, _globalMetadata);\n    }\n\n    function getBatchGlobalMetadataByChainId(uint256 _chainId)\n        external\n        view\n        override\n        returns (bytes27)\n    {\n        return batches().getGlobalMetadataByChainId(_chainId);\n    }\n\n    function lengthBatchByChainId(uint256 _chainId) external view override returns (uint256) {\n        return batches().lengthByChainId(_chainId);\n    }\n\n    function pushBatchByChainId(\n        uint256 _chainId,\n        bytes32 _object,\n        bytes27 _globalMetadata\n    ) external override onlyManager {\n        batches().pushByChainId(_chainId, _object, _globalMetadata);\n        emit BatchPushed(msg.sender, _chainId, _object, _globalMetadata);\n    }\n\n    function setBatchByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes32 _object\n    ) external override onlyManager {\n        batches().setByChainId(_chainId, _index, _object);\n        emit BatchSetted(msg.sender, _chainId, _index, _object);\n    }\n\n    function getBatchByChainId(uint256 _chainId, uint256 _index)\n        external\n        view\n        override\n        returns (bytes32)\n    {\n        return batches().getByChainId(_chainId, _index);\n    }\n\n    function deleteBatchElementsAfterInclusiveByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    ) external override onlyManager {\n        batches().deleteElementsAfterInclusiveByChainId(_chainId, _index, _globalMetadata);\n        emit BatchElementDeleted(msg.sender, _chainId, _index, _globalMetadata);\n    }\n}\n"
    },
    "contracts/L1/rollup/ChainStorageContainer.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_Buffer } from \"../../libraries/utils/Lib_Buffer.sol\";\nimport { Lib_AddressResolver } from \"../../libraries/resolver/Lib_AddressResolver.sol\";\n\n/* Interface Imports */\nimport { IChainStorageContainer } from \"./IChainStorageContainer.sol\";\n\n/**\n * @title ChainStorageContainer\n * @dev The Chain Storage Container provides its owner contract with read, write and delete\n * functionality. This provides gas efficiency gains by enabling it to overwrite storage slots which\n * can no longer be used in a fraud proof due to the fraud window having passed, and the associated\n * chain state or transactions being finalized.\n * Two distinct Chain Storage Containers will be deployed on Layer 1:\n * 1. Stores transaction batches for the Canonical Transaction Chain\n * 2. Stores chain state batches for the State Commitment Chain\n *\n * Runtime target: EVM\n */\ncontract ChainStorageContainer is IChainStorageContainer, Lib_AddressResolver {\n    /*************\n     * Libraries *\n     *************/\n\n    using Lib_Buffer for Lib_Buffer.Buffer;\n\n    /**************\n     *  constant  *\n     **************/\n    uint256 public constant DEFAULT_CHAINID = 1088;\n\n    /*************\n     * Variables *\n     *************/\n\n    string public owner;\n    mapping(uint256 => Lib_Buffer.Buffer) internal buffers;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _libAddressManager Address of the Address Manager.\n     * @param _owner Name of the contract that owns this container (will be resolved later).\n     */\n    constructor(address _libAddressManager, string memory _owner)\n        Lib_AddressResolver(_libAddressManager)\n    {\n        owner = _owner;\n    }\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    modifier onlyOwner() {\n        require(\n            msg.sender == resolve(owner),\n            \"ChainStorageContainer: Function can only be called by the owner.\"\n        );\n        _;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function setGlobalMetadata(bytes27 _globalMetadata) public onlyOwner {\n        return setGlobalMetadataByChainId(DEFAULT_CHAINID, _globalMetadata);\n    }\n\n    function setByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes32 _object\n    ) public override onlyOwner {\n        buffers[_chainId].set(_index, _object);\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function setGlobalMetadataByChainId(uint256 _chainId, bytes27 _globalMetadata)\n        public\n        override\n        onlyOwner\n    {\n        return buffers[_chainId].setExtraData(_globalMetadata);\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function getGlobalMetadata() public view returns (bytes27) {\n        return getGlobalMetadataByChainId(DEFAULT_CHAINID);\n    }\n\n    function getGlobalMetadataByChainId(uint256 _chainId) public view override returns (bytes27) {\n        return buffers[_chainId].getExtraData();\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function length() public view returns (uint256) {\n        return lengthByChainId(DEFAULT_CHAINID);\n    }\n\n    function lengthByChainId(uint256 _chainId) public view override returns (uint256) {\n        return uint256(buffers[_chainId].getLength());\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function push(bytes32 _object) public onlyOwner {\n        pushByChainId(DEFAULT_CHAINID, _object);\n    }\n\n    function pushByChainId(uint256 _chainId, bytes32 _object) public override onlyOwner {\n        buffers[_chainId].push(_object);\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function push(bytes32 _object, bytes27 _globalMetadata) public onlyOwner {\n        pushByChainId(DEFAULT_CHAINID, _object, _globalMetadata);\n    }\n\n    function pushByChainId(\n        uint256 _chainId,\n        bytes32 _object,\n        bytes27 _globalMetadata\n    ) public override onlyOwner {\n        buffers[_chainId].push(_object, _globalMetadata);\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function get(uint256 _index) public view returns (bytes32) {\n        return getByChainId(DEFAULT_CHAINID, _index);\n    }\n\n    function getByChainId(uint256 _chainId, uint256 _index) public view override returns (bytes32) {\n        return buffers[_chainId].get(uint40(_index));\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function deleteElementsAfterInclusive(uint256 _index) public onlyOwner {\n        deleteElementsAfterInclusiveByChainId(DEFAULT_CHAINID, _index);\n    }\n\n    function deleteElementsAfterInclusiveByChainId(uint256 _chainId, uint256 _index)\n        public\n        override\n        onlyOwner\n    {\n        buffers[_chainId].deleteElementsAfterInclusive(uint40(_index));\n    }\n\n    /**\n     * @inheritdoc IChainStorageContainer\n     */\n    function deleteElementsAfterInclusive(uint256 _index, bytes27 _globalMetadata)\n        public\n        onlyOwner\n    {\n        deleteElementsAfterInclusiveByChainId(DEFAULT_CHAINID, _index, _globalMetadata);\n    }\n\n    function deleteElementsAfterInclusiveByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    ) public override onlyOwner {\n        buffers[_chainId].deleteElementsAfterInclusive(uint40(_index), _globalMetadata);\n    }\n}\n"
    },
    "contracts/L1/rollup/ICanonicalTransactionChain.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\n\n/* Interface Imports */\nimport { IChainStorageContainer } from \"./IChainStorageContainer.sol\";\n\n/**\n * @title ICanonicalTransactionChain\n */\ninterface ICanonicalTransactionChain {\n    /**********\n     * Events *\n     **********/\n    event QueueGlobalMetadataSet(address _sender, uint256 _chainId, bytes27 _globalMetadata);\n\n    event QueuePushed(address _sender, uint256 _chainId, Lib_OVMCodec.QueueElement _object);\n\n    event QueueSetted(\n        address _sender,\n        uint256 _chainId,\n        uint256 _index,\n        Lib_OVMCodec.QueueElement _object\n    );\n\n    event QueueElementDeleted(\n        address _sender,\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    );\n\n    event BatchesGlobalMetadataSet(address _sender, uint256 _chainId, bytes27 _globalMetadata);\n\n    event BatchPushed(address _sender, uint256 _chainId, bytes32 _object, bytes27 _globalMetadata);\n\n    event BatchSetted(address _sender, uint256 _chainId, uint256 _index, bytes32 _object);\n\n    event BatchElementDeleted(\n        address _sender,\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    );\n\n    event L2GasParamsUpdated(\n        uint256 l2GasDiscountDivisor,\n        uint256 enqueueGasCost,\n        uint256 enqueueL2GasPrepaid\n    );\n\n    event TransactionEnqueued(\n        uint256 _chainId,\n        address indexed _l1TxOrigin,\n        address indexed _target,\n        uint256 _gasLimit,\n        bytes _data,\n        uint256 indexed _queueIndex,\n        uint256 _timestamp\n    );\n\n    event QueueBatchAppended(\n        uint256 _chainId,\n        uint256 _startingQueueIndex,\n        uint256 _numQueueElements,\n        uint256 _totalElements\n    );\n\n    event SequencerBatchAppended(\n        uint256 _chainId,\n        uint256 _startingQueueIndex,\n        uint256 _numQueueElements,\n        uint256 _totalElements\n    );\n\n    event TransactionBatchAppended(\n        uint256 _chainId,\n        uint256 indexed _batchIndex,\n        bytes32 _batchRoot,\n        uint256 _batchSize,\n        uint256 _prevTotalElements,\n        bytes _extraData\n    );\n\n    /***********\n     * Structs *\n     ***********/\n\n    struct BatchContext {\n        uint256 numSequencedTransactions;\n        uint256 numSubsequentQueueTransactions;\n        uint256 timestamp;\n        uint256 blockNumber;\n    }\n\n    /*******************************\n     * Authorized Setter Functions *\n     *******************************/\n\n    /**\n     * Allows the Burn Admin to update the parameters which determine the amount of gas to burn.\n     * The value of enqueueL2GasPrepaid is immediately updated as well.\n     */\n    function setGasParams(uint256 _l2GasDiscountDivisor, uint256 _enqueueGasCost) external;\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Accesses the batch storage container.\n     * @return Reference to the batch storage container.\n     */\n    function batches() external view returns (IChainStorageContainer);\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElements() external view returns (uint256 _totalElements);\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatches() external view returns (uint256 _totalBatches);\n\n    /**\n     * Returns the index of the next element to be enqueued.\n     * @return Index for the next queue element.\n     */\n    function getNextQueueIndex() external view returns (uint40);\n\n    /**\n     * Gets the queue element at a particular index.\n     * @param _index Index of the queue element to access.\n     * @return _element Queue element at the given index.\n     */\n    function getQueueElement(uint256 _index)\n        external\n        view\n        returns (Lib_OVMCodec.QueueElement memory _element);\n\n    /**\n     * Returns the timestamp of the last transaction.\n     * @return Timestamp for the last transaction.\n     */\n    function getLastTimestamp() external view returns (uint40);\n\n    /**\n     * Returns the blocknumber of the last transaction.\n     * @return Blocknumber for the last transaction.\n     */\n    function getLastBlockNumber() external view returns (uint40);\n\n    /**\n     * Get the number of queue elements which have not yet been included.\n     * @return Number of pending queue elements.\n     */\n    function getNumPendingQueueElements() external view returns (uint40);\n\n    /**\n     * Retrieves the length of the queue, including\n     * both pending and canonical transactions.\n     * @return Length of the queue.\n     */\n    function getQueueLength() external view returns (uint40);\n\n    /**\n     * Adds a transaction to the queue.\n     * @param _target Target contract to send the transaction to.\n     * @param _gasLimit Gas limit for the given transaction.\n     * @param _data Transaction data.\n     */\n    function enqueue(\n        address _target,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) external;\n\n    /**\n     * Allows the sequencer to append a batch of transactions.\n     * @dev This function uses a custom encoding scheme for efficiency reasons.\n     * .param _shouldStartAtElement Specific batch we expect to start appending to.\n     * .param _totalElementsToAppend Total number of batch elements we expect to append.\n     * .param _contexts Array of batch contexts.\n     * .param _transactionDataFields Array of raw transaction data.\n     */\n    function appendSequencerBatch(\n        // uint40 _shouldStartAtElement,\n        // uint24 _totalElementsToAppend,\n        // BatchContext[] _contexts,\n        // bytes[] _transactionDataFields\n    ) external;\n\n    //added chain id function\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @param _chainId identity for the l2 chain.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElementsByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _totalElements);\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @param _chainId identity for the l2 chain.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatchesByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _totalBatches);\n\n    /**\n     * Returns the index of the next element to be enqueued.\n     * @param _chainId identity for the l2 chain.\n     * @return Index for the next queue element.\n     */\n    function getNextQueueIndexByChainId(uint256 _chainId) external view returns (uint40);\n\n    /**\n     * Gets the queue element at a particular index.\n     * @param _chainId identity for the l2 chain.\n     * @param _index Index of the queue element to access.\n     * @return _element Queue element at the given index.\n     */\n    function getQueueElementByChainId(uint256 _chainId, uint256 _index)\n        external\n        view\n        returns (Lib_OVMCodec.QueueElement memory _element);\n\n    /**\n     * Returns the timestamp of the last transaction.\n     * @param _chainId identity for the l2 chain.\n     * @return Timestamp for the last transaction.\n     */\n    function getLastTimestampByChainId(uint256 _chainId) external view returns (uint40);\n\n    /**\n     * Returns the blocknumber of the last transaction.\n     * @param _chainId identity for the l2 chain.\n     * @return Blocknumber for the last transaction.\n     */\n    function getLastBlockNumberByChainId(uint256 _chainId) external view returns (uint40);\n\n    /**\n     * Get the number of queue elements which have not yet been included.\n     * @param _chainId identity for the l2 chain.\n     * @return Number of pending queue elements.\n     */\n    function getNumPendingQueueElementsByChainId(uint256 _chainId) external view returns (uint40);\n\n    /**\n     * Retrieves the length of the queue, including\n     * both pending and canonical transactions.\n     * @param _chainId identity for the l2 chain.\n     * @return Length of the queue.\n     */\n    function getQueueLengthByChainId(uint256 _chainId) external view returns (uint40);\n\n    /**\n     * Adds a transaction to the queue.\n     * @param _chainId identity for the l2 chain.\n     * @param _target Target contract to send the transaction to.\n     * @param _gasLimit Gas limit for the given transaction.\n     * @param _data Transaction data.\n     */\n    function enqueueByChainId(\n        uint256 _chainId,\n        address _target,\n        uint256 _gasLimit,\n        bytes memory _data\n    ) external;\n\n    /**\n     * Allows the sequencer to append a batch of transactions.\n     * @dev This function uses a custom encoding scheme for efficiency reasons.\n     * .param _chainId identity for the l2 chain.\n     * .param _shouldStartAtElement Specific batch we expect to start appending to.\n     * .param _totalElementsToAppend Total number of batch elements we expect to append.\n     * .param _contexts Array of batch contexts.\n     * .param _transactionDataFields Array of raw transaction data.\n     */\n    function appendSequencerBatchByChainId(\n        // uint256 _chainId,\n        // uint40 _shouldStartAtElement,\n        // uint24 _totalElementsToAppend,\n        // BatchContext[] _contexts,\n        // bytes[] _transactionDataFields\n    ) external;\n\n    function pushQueueByChainId(uint256 _chainId, Lib_OVMCodec.QueueElement calldata _object)\n        external;\n\n    function setQueueByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        Lib_OVMCodec.QueueElement calldata _object\n    ) external;\n\n    function setBatchGlobalMetadataByChainId(uint256 _chainId, bytes27 _globalMetadata) external;\n\n    function getBatchGlobalMetadataByChainId(uint256 _chainId) external view returns (bytes27);\n\n    function lengthBatchByChainId(uint256 _chainId) external view returns (uint256);\n\n    function pushBatchByChainId(\n        uint256 _chainId,\n        bytes32 _object,\n        bytes27 _globalMetadata\n    ) external;\n\n    function setBatchByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes32 _object\n    ) external;\n\n    function getBatchByChainId(uint256 _chainId, uint256 _index) external view returns (bytes32);\n\n    function deleteBatchElementsAfterInclusiveByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    ) external;\n}\n"
    },
    "contracts/L1/rollup/IChainStorageContainer.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title IChainStorageContainer\n */\ninterface IChainStorageContainer {\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Sets the container's global metadata field. We're using `bytes27` here because we use five\n     * bytes to maintain the length of the underlying data structure, meaning we have an extra\n     * 27 bytes to store arbitrary data.\n     * @param _globalMetadata New global metadata to set.\n     */\n    function setGlobalMetadata(bytes27 _globalMetadata) external;\n\n    /**\n     * Retrieves the container's global metadata field.\n     * @return Container global metadata field.\n     */\n    function getGlobalMetadata() external view returns (bytes27);\n\n    /**\n     * Retrieves the number of objects stored in the container.\n     * @return Number of objects in the container.\n     */\n    function length() external view returns (uint256);\n\n    /**\n     * Pushes an object into the container.\n     * @param _object A 32 byte value to insert into the container.\n     */\n    function push(bytes32 _object) external;\n\n    /**\n     * Pushes an object into the container. Function allows setting the global metadata since\n     * we'll need to touch the \"length\" storage slot anyway, which also contains the global\n     * metadata (it's an optimization).\n     * @param _object A 32 byte value to insert into the container.\n     * @param _globalMetadata New global metadata for the container.\n     */\n    function push(bytes32 _object, bytes27 _globalMetadata) external;\n\n    /**\n     * Set an object into the container. Function allows setting the global metadata since\n     * we'll need to touch the \"length\" storage slot anyway, which also contains the global\n     * metadata (it's an optimization).\n     * @param _index position.\n     * @param _object A 32 byte value to insert into the container.\n     */\n    function setByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes32 _object\n    ) external;\n\n    /**\n     * Retrieves an object from the container.\n     * @param _index Index of the particular object to access.\n     * @return 32 byte object value.\n     */\n    function get(uint256 _index) external view returns (bytes32);\n\n    /**\n     * Removes all objects after and including a given index.\n     * @param _index Object index to delete from.\n     */\n    function deleteElementsAfterInclusive(uint256 _index) external;\n\n    /**\n     * Removes all objects after and including a given index. Also allows setting the global\n     * metadata field.\n     * @param _index Object index to delete from.\n     * @param _globalMetadata New global metadata for the container.\n     */\n    function deleteElementsAfterInclusive(uint256 _index, bytes27 _globalMetadata) external;\n\n    /**\n     * Sets the container's global metadata field. We're using `bytes27` here because we use five\n     * bytes to maintain the length of the underlying data structure, meaning we have an extra\n     * 27 bytes to store arbitrary data.\n     * @param _chainId identity for the l2 chain.\n     * @param _globalMetadata New global metadata to set.\n     */\n    function setGlobalMetadataByChainId(uint256 _chainId, bytes27 _globalMetadata) external;\n\n    /**\n     * Retrieves the container's global metadata field.\n     * @param _chainId identity for the l2 chain.\n     * @return Container global metadata field.\n     */\n    function getGlobalMetadataByChainId(uint256 _chainId) external view returns (bytes27);\n\n    /**\n     * Retrieves the number of objects stored in the container.\n     * @param _chainId identity for the l2 chain.\n     * @return Number of objects in the container.\n     */\n    function lengthByChainId(uint256 _chainId) external view returns (uint256);\n\n    /**\n     * Pushes an object into the container.\n     * @param _chainId identity for the l2 chain.\n     * @param _object A 32 byte value to insert into the container.\n     */\n    function pushByChainId(uint256 _chainId, bytes32 _object) external;\n\n    /**\n     * Pushes an object into the container. Function allows setting the global metadata since\n     * we'll need to touch the \"length\" storage slot anyway, which also contains the global\n     * metadata (it's an optimization).\n     * @param _chainId identity for the l2 chain.\n     * @param _object A 32 byte value to insert into the container.\n     * @param _globalMetadata New global metadata for the container.\n     */\n    function pushByChainId(\n        uint256 _chainId,\n        bytes32 _object,\n        bytes27 _globalMetadata\n    ) external;\n\n    /**\n     * Retrieves an object from the container.\n     * @param _chainId identity for the l2 chain.\n     * @param _index Index of the particular object to access.\n     * @return 32 byte object value.\n     */\n    function getByChainId(uint256 _chainId, uint256 _index) external view returns (bytes32);\n\n    /**\n     * Removes all objects after and including a given index.\n     * @param _chainId identity for the l2 chain.\n     * @param _index Object index to delete from.\n     */\n    function deleteElementsAfterInclusiveByChainId(uint256 _chainId, uint256 _index) external;\n\n    /**\n     * Removes all objects after and including a given index. Also allows setting the global\n     * metadata field.\n     * @param _chainId identity for the l2 chain.\n     * @param _index Object index to delete from.\n     * @param _globalMetadata New global metadata for the container.\n     */\n    function deleteElementsAfterInclusiveByChainId(\n        uint256 _chainId,\n        uint256 _index,\n        bytes27 _globalMetadata\n    ) external;\n}\n"
    },
    "contracts/L1/rollup/IMVMStateCommitmentChain.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\nimport { IChainStorageContainer } from \"./IChainStorageContainer.sol\";\n\n/**\n * @title IStateCommitmentChain\n */\ninterface IMVMStateCommitmentChain {\n    /**********\n     * Events *\n     **********/\n\n    event StateBatchAppended(\n        uint256 _chainId,\n        uint256 indexed _batchIndex,\n        bytes32 _batchRoot,\n        uint256 _batchSize,\n        uint256 _prevTotalElements,\n        bytes _extraData\n    );\n\n    event StateBatchDeleted(uint256 _chainId, uint256 indexed _batchIndex, bytes32 _batchRoot);\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Get the earliest disputable state root.\n     * @param _chainId chain id for the l2 chain.\n     * @return _earliestDisputableBatch Earliest disputable state root.\n     */\n    function findEarliestDisputableBatch(uint256 _chainId) external view returns (bytes32 _earliestDisputableBatch, uint256 blockNumber);\n\n    function batches() external view returns (IChainStorageContainer);\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElements() external view returns (uint256 _totalElements);\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatches() external view returns (uint256 _totalBatches);\n\n    /**\n     * Retrieves the timestamp of the last batch submitted by the sequencer.\n     * @return _lastSequencerTimestamp Last sequencer batch timestamp.\n     */\n    function getLastSequencerTimestamp() external view returns (uint256 _lastSequencerTimestamp);\n\n    /**\n     * Appends a batch of state roots to the chain.\n     * @param _batch Batch of state roots.\n     * @param _shouldStartAtElement Index of the element at which this batch should start.\n     * @param _lastBatchBlockHash Block hash of the last batch.\n     * @param _lastBatchBlockNumber Block number of the last batch.\n     */\n    function appendStateBatch(bytes32[] calldata _batch, uint256 _shouldStartAtElement, bytes32 _lastBatchBlockHash, uint256 _lastBatchBlockNumber) external;\n\n    /**\n     * Deletes all state roots after (and including) a given batch.\n     * @param _batchHeader Header of the batch to start deleting from.\n     */\n    function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external;\n\n    /**\n     * Verifies a batch inclusion proof.\n     * @param _element Hash of the element to verify a proof for.\n     * @param _batchHeader Header of the batch in which the element was included.\n     * @param _proof Merkle inclusion proof for the element.\n     */\n    function verifyStateCommitment(\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) external view returns (bool _verified);\n\n    /**\n     * Checks whether a given batch is still inside its fraud proof window.\n     * @param _batchHeader Header of the batch to check.\n     * @return _inside Whether or not the batch is inside the fraud proof window.\n     */\n    function insideFraudProofWindow(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)\n        external\n        view\n        returns (bool _inside);\n\n    /**\n     * Saves a batch as disputed.\n     * @param stateHeaderHash Hash of the disputed state header.\n     */\n    function saveDisputedBatch(bytes32 stateHeaderHash) external;\n\n    /**\n     * Checks if a batch is disputed.\n     * @param stateHeaderHash Hash of the disputed state header.\n     * @return _disputed Whether or not the batch is disputed.\n     */\n    function isDisputedBatch(bytes32 stateHeaderHash) external view returns (bool _disputed);\n\n    /********************\n     * chain id added func *\n     ********************/\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @param _chainId identity for the l2 chain.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElementsByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _totalElements);\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @param _chainId identity for the l2 chain.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatchesByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _totalBatches);\n\n    /**\n     * Retrieves the timestamp of the last batch submitted by the sequencer.\n     * @param _chainId identity for the l2 chain.\n     * @return _lastSequencerTimestamp Last sequencer batch timestamp.\n     */\n    function getLastSequencerTimestampByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _lastSequencerTimestamp);\n\n    /**\n     * Appends a batch of state roots to the chain.\n     * @param _chainId identity for the l2 chain.\n     * @param _batch Batch of state roots.\n     * @param _shouldStartAtElement Index of the element at which this batch should start.\n     * @param _proposer proposer of the batch\n     * @param _lastBatchBlockHash Block hash of the last batch.\n     * @param _lastBatchBlockNumber Block number of the last batch.\n     */\n    function appendStateBatchByChainId(\n        uint256 _chainId,\n        bytes32[] calldata _batch,\n        uint256 _shouldStartAtElement,\n        string calldata _proposer,\n        bytes32 _lastBatchBlockHash,\n        uint256 _lastBatchBlockNumber\n    ) external;\n\n    /**\n     * Deletes all state roots after (and including) a given batch.\n     * @param _chainId identity for the l2 chain.\n     * @param _batchHeader Header of the batch to start deleting from.\n     */\n    function deleteStateBatchByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) external;\n\n    /**\n     * Verifies a batch inclusion proof.\n     * @param _chainId identity for the l2 chain.\n     * @param _element Hash of the element to verify a proof for.\n     * @param _batchHeader Header of the batch in which the element was included.\n     * @param _proof Merkle inclusion proof for the element.\n     */\n    function verifyStateCommitmentByChainId(\n        uint256 _chainId,\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) external view returns (bool _verified);\n\n    /**\n     * Checks whether a given batch is still inside its fraud proof window.\n     * @param _chainId identity for the l2 chain.\n     * @param _batchHeader Header of the batch to check.\n     * @return _inside Whether or not the batch is inside the fraud proof window.\n     */\n    function insideFraudProofWindowByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) external view returns (bool _inside);\n}\n"
    },
    "contracts/L1/rollup/IStateCommitmentChain.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\nimport { IChainStorageContainer } from \"./IChainStorageContainer.sol\";\n\n/**\n * @title IStateCommitmentChain\n */\ninterface IStateCommitmentChain {\n    /**********\n     * Events *\n     **********/\n\n    event StateBatchAppended(\n        uint256 _chainId,\n        uint256 indexed _batchIndex,\n        bytes32 _batchRoot,\n        uint256 _batchSize,\n        uint256 _prevTotalElements,\n        bytes _extraData\n    );\n\n    event StateBatchDeleted(uint256 _chainId, uint256 indexed _batchIndex, bytes32 _batchRoot);\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function batches() external view returns (IChainStorageContainer);\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElements() external view returns (uint256 _totalElements);\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatches() external view returns (uint256 _totalBatches);\n\n    /**\n     * Retrieves the timestamp of the last batch submitted by the sequencer.\n     * @return _lastSequencerTimestamp Last sequencer batch timestamp.\n     */\n    function getLastSequencerTimestamp() external view returns (uint256 _lastSequencerTimestamp);\n\n    /**\n     * Appends a batch of state roots to the chain.\n     * @param _batch Batch of state roots.\n     * @param _shouldStartAtElement Index of the element at which this batch should start.\n     */\n    function appendStateBatch(bytes32[] calldata _batch, uint256 _shouldStartAtElement) external;\n\n    /**\n     * Deletes all state roots after (and including) a given batch.\n     * @param _batchHeader Header of the batch to start deleting from.\n     */\n    function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external;\n\n    /**\n     * Verifies a batch inclusion proof.\n     * @param _element Hash of the element to verify a proof for.\n     * @param _batchHeader Header of the batch in which the element was included.\n     * @param _proof Merkle inclusion proof for the element.\n     */\n    function verifyStateCommitment(\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) external view returns (bool _verified);\n\n    /**\n     * Checks whether a given batch is still inside its fraud proof window.\n     * @param _batchHeader Header of the batch to check.\n     * @return _inside Whether or not the batch is inside the fraud proof window.\n     */\n    function insideFraudProofWindow(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)\n        external\n        view\n        returns (bool _inside);\n\n    /********************\n     * chain id added func *\n     ********************/\n\n    /**\n     * Retrieves the total number of elements submitted.\n     * @param _chainId identity for the l2 chain.\n     * @return _totalElements Total submitted elements.\n     */\n    function getTotalElementsByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _totalElements);\n\n    /**\n     * Retrieves the total number of batches submitted.\n     * @param _chainId identity for the l2 chain.\n     * @return _totalBatches Total submitted batches.\n     */\n    function getTotalBatchesByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _totalBatches);\n\n    /**\n     * Retrieves the timestamp of the last batch submitted by the sequencer.\n     * @param _chainId identity for the l2 chain.\n     * @return _lastSequencerTimestamp Last sequencer batch timestamp.\n     */\n    function getLastSequencerTimestampByChainId(uint256 _chainId)\n        external\n        view\n        returns (uint256 _lastSequencerTimestamp);\n\n    /**\n     * Appends a batch of state roots to the chain.\n     * @param _chainId identity for the l2 chain.\n     * @param _batch Batch of state roots.\n     * @param _shouldStartAtElement Index of the element at which this batch should start.\n     */\n    function appendStateBatchByChainId(\n        uint256 _chainId,\n        bytes32[] calldata _batch,\n        uint256 _shouldStartAtElement,\n        string calldata proposer\n    ) external;\n\n    /**\n     * Deletes all state roots after (and including) a given batch.\n     * @param _chainId identity for the l2 chain.\n     * @param _batchHeader Header of the batch to start deleting from.\n     */\n    function deleteStateBatchByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) external;\n\n    /**\n     * Verifies a batch inclusion proof.\n     * @param _chainId identity for the l2 chain.\n     * @param _element Hash of the element to verify a proof for.\n     * @param _batchHeader Header of the batch in which the element was included.\n     * @param _proof Merkle inclusion proof for the element.\n     */\n    function verifyStateCommitmentByChainId(\n        uint256 _chainId,\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) external view returns (bool _verified);\n\n    /**\n     * Checks whether a given batch is still inside its fraud proof window.\n     * @param _chainId identity for the l2 chain.\n     * @param _batchHeader Header of the batch to check.\n     * @return _inside Whether or not the batch is inside the fraud proof window.\n     */\n    function insideFraudProofWindowByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) external view returns (bool _inside);\n}\n"
    },
    "contracts/L1/rollup/StateCommitmentChain.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\nimport { Lib_AddressResolver } from \"../../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_MerkleTree } from \"../../libraries/utils/Lib_MerkleTree.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/* Interface Imports */\nimport { IStateCommitmentChain } from \"./IStateCommitmentChain.sol\";\nimport { ICanonicalTransactionChain } from \"./ICanonicalTransactionChain.sol\";\nimport { IBondManager } from \"../verification/IBondManager.sol\";\nimport { IChainStorageContainer } from \"./IChainStorageContainer.sol\";\n\n/**\n * @title StateCommitmentChain\n * @dev The State Commitment Chain (SCC) contract contains a list of proposed state roots which\n * Proposers assert to be a result of each transaction in the Canonical Transaction Chain (CTC).\n * Elements here have a 1:1 correspondence with transactions in the CTC, and should be the unique\n * state root calculated off-chain by applying the canonical transactions one by one.\n *\n * Runtime target: EVM\n */\ncontract StateCommitmentChain is IStateCommitmentChain, Lib_AddressResolver {\n    /*************\n     * Constants *\n     *************/\n\n    uint256 public FRAUD_PROOF_WINDOW;\n    uint256 public SEQUENCER_PUBLISH_WINDOW;\n\n    uint256 public DEFAULT_CHAINID = 1088;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _libAddressManager Address of the Address Manager.\n     */\n    constructor(\n        address _libAddressManager,\n        uint256 _fraudProofWindow,\n        uint256 _sequencerPublishWindow\n    ) Lib_AddressResolver(_libAddressManager) {\n        FRAUD_PROOF_WINDOW = _fraudProofWindow;\n        SEQUENCER_PUBLISH_WINDOW = _sequencerPublishWindow;\n    }\n\n    function setFraudProofWindow(uint256 window) external {\n        require(msg.sender == resolve(\"METIS_MANAGER\"), \"now allowed\");\n        FRAUD_PROOF_WINDOW = window;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Accesses the batch storage container.\n     * @return Reference to the batch storage container.\n     */\n    function batches() public view returns (IChainStorageContainer) {\n        return IChainStorageContainer(resolve(\"ChainStorageContainer-SCC-batches\"));\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalElements() external view returns (uint256 _totalElements) {\n        return getTotalElementsByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalBatches() external view returns (uint256 _totalBatches) {\n        return getTotalBatchesByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getLastSequencerTimestamp() external view returns (uint256 _lastSequencerTimestamp) {\n        return getLastSequencerTimestampByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function appendStateBatch(bytes32[] memory _batch, uint256 _shouldStartAtElement) external {\n        //require (1==0, \"don't use\");\n        string memory proposer = string(\n            abi.encodePacked(Lib_Uint.uint2str(DEFAULT_CHAINID), \"_MVM_Proposer\")\n        );\n        appendStateBatchByChainId(DEFAULT_CHAINID, _batch, _shouldStartAtElement, proposer);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external {\n        deleteStateBatchByChainId(DEFAULT_CHAINID, _batchHeader);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function verifyStateCommitment(\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) external view returns (bool) {\n        return verifyStateCommitmentByChainId(DEFAULT_CHAINID, _element, _batchHeader, _proof);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function insideFraudProofWindow(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)\n        public\n        view\n        returns (bool _inside)\n    {\n        (uint256 timestamp, ) = abi.decode(_batchHeader.extraData, (uint256, address));\n\n        require(timestamp != 0, \"Batch header timestamp cannot be zero\");\n        return (timestamp + FRAUD_PROOF_WINDOW) > block.timestamp;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Timestamp of the last batch submitted by the sequencer.\n     */\n    function _getBatchExtraData() internal view returns (uint40, uint40) {\n        // bytes27 extraData = batches().getGlobalMetadata();\n\n        // // solhint-disable max-line-length\n        // uint40 totalElements;\n        // uint40 lastSequencerTimestamp;\n        // assembly {\n        //     extraData := shr(40, extraData)\n        //     totalElements := and(\n        //         extraData,\n        //         0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n        //     )\n        //     lastSequencerTimestamp := shr(\n        //         40,\n        //         and(extraData, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)\n        //     )\n        // }\n        // // solhint-enable max-line-length\n\n        // return (totalElements, lastSequencerTimestamp);\n\n        return _getBatchExtraDataByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _lastSequencerTimestamp Timestamp of the last batch submitted by the sequencer.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraData(uint40 _totalElements, uint40 _lastSequencerTimestamp)\n        internal\n        pure\n        returns (bytes27)\n    {\n        bytes27 extraData;\n        assembly {\n            extraData := _totalElements\n            extraData := or(extraData, shl(40, _lastSequencerTimestamp))\n            extraData := shl(40, extraData)\n        }\n\n        return extraData;\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalElementsByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _totalElements)\n    {\n        (uint40 totalElements, ) = _getBatchExtraDataByChainId(_chainId);\n        return uint256(totalElements);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getTotalBatchesByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _totalBatches)\n    {\n        return batches().lengthByChainId(_chainId);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function getLastSequencerTimestampByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _lastSequencerTimestamp)\n    {\n        (, uint40 lastSequencerTimestamp) = _getBatchExtraDataByChainId(_chainId);\n        return uint256(lastSequencerTimestamp);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function appendStateBatchByChainId(\n        uint256 _chainId,\n        bytes32[] memory _batch,\n        uint256 _shouldStartAtElement,\n        string memory proposer\n    ) public override {\n        // Fail fast in to make sure our batch roots aren't accidentally made fraudulent by the\n        // publication of batches by some other user.\n        require(\n            _shouldStartAtElement == getTotalElementsByChainId(_chainId),\n            \"Actual batch start index does not match expected start index.\"\n        );\n\n        address proposerAddr = resolve(proposer);\n\n        // Proposers must have previously staked at the BondManager\n        require(\n            IBondManager(resolve(\"BondManager\")).isCollateralizedByChainId(\n                _chainId,\n                msg.sender,\n                proposerAddr\n            ),\n            \"Proposer does not have enough collateral posted\"\n        );\n\n        require(_batch.length > 0, \"Cannot submit an empty state batch.\");\n\n        require(\n            getTotalElementsByChainId(_chainId) + _batch.length <=\n                ICanonicalTransactionChain(resolve(\"CanonicalTransactionChain\"))\n                    .getTotalElementsByChainId(_chainId),\n            \"Number of state roots cannot exceed the number of canonical transactions.\"\n        );\n\n        // Pass the block's timestamp and the publisher of the data\n        // to be used in the fraud proofs\n        _appendBatchByChainId(\n            _chainId,\n            _batch,\n            abi.encode(block.timestamp, msg.sender),\n            proposerAddr\n        );\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function deleteStateBatchByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) public override {\n        require(\n            msg.sender ==\n                resolve(\n                    string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_FraudVerifier\"))\n                ),\n            \"State batches can only be deleted by the MVM_FraudVerifier.\"\n        );\n\n        require(\n            insideFraudProofWindow(_batchHeader),\n            \"State batches can only be deleted within the fraud proof window.\"\n        );\n\n        _deleteBatchByChainId(_chainId, _batchHeader);\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function verifyStateCommitmentByChainId(\n        uint256 _chainId,\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) public view override returns (bool) {\n        require(_isValidBatchHeaderByChainId(_chainId, _batchHeader), \"Invalid batch header.\");\n\n        require(\n            Lib_MerkleTree.verify(\n                _batchHeader.batchRoot,\n                _element,\n                _proof.index,\n                _proof.siblings,\n                _batchHeader.batchSize\n            ),\n            \"Invalid inclusion proof.\"\n        );\n\n        return true;\n    }\n\n    /**\n     * @inheritdoc IStateCommitmentChain\n     */\n    function insideFraudProofWindowByChainId(\n        uint256,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) public view override returns (bool _inside) {\n        (uint256 timestamp, ) = abi.decode(_batchHeader.extraData, (uint256, address));\n\n        require(timestamp != 0, \"Batch header timestamp cannot be zero\");\n        return timestamp + FRAUD_PROOF_WINDOW > block.timestamp;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Timestamp of the last batch submitted by the sequencer.\n     */\n    function _getBatchExtraDataByChainId(uint256 _chainId) internal view returns (uint40, uint40) {\n        bytes27 extraData = batches().getGlobalMetadataByChainId(_chainId);\n\n        uint40 totalElements;\n        uint40 lastSequencerTimestamp;\n        assembly {\n            extraData := shr(40, extraData)\n            totalElements := and(\n                extraData,\n                0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n            )\n            lastSequencerTimestamp := shr(\n                40,\n                and(extraData, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)\n            )\n        }\n\n        return (totalElements, lastSequencerTimestamp);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _lastSequencerTimestamp Timestamp of the last batch submitted by the sequencer.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraDataByChainId(uint40 _totalElements, uint40 _lastSequencerTimestamp)\n        internal\n        pure\n        returns (bytes27)\n    {\n        bytes27 extraData;\n        assembly {\n            extraData := _totalElements\n            extraData := or(extraData, shl(40, _lastSequencerTimestamp))\n            extraData := shl(40, extraData)\n        }\n\n        return extraData;\n    }\n\n    /**\n     * Appends a batch to the chain.\n     * @param _batch Elements within the batch.\n     * @param _extraData Any extra data to append to the batch.\n     */\n    function _appendBatchByChainId(\n        uint256 _chainId,\n        bytes32[] memory _batch,\n        bytes memory _extraData,\n        address\n    ) internal {\n        (uint40 totalElements, uint40 lastSequencerTimestamp) = _getBatchExtraDataByChainId(\n            _chainId\n        );\n\n        lastSequencerTimestamp = uint40(block.timestamp);\n\n        // if (msg.sender == proposer) {\n        //     lastSequencerTimestamp = uint40(block.timestamp);\n        // } else {\n        //     // We keep track of the last batch submitted by the sequencer so there's a window in\n        //     // which only the sequencer can publish state roots. A window like this just reduces\n        //     // the chance of \"system breaking\" state roots being published while we're still in\n        //     // testing mode. This window should be removed or significantly reduced in the future.\n        //     require(\n        //         lastSequencerTimestamp + SEQUENCER_PUBLISH_WINDOW < block.timestamp,\n        //         \"Cannot publish state roots within the sequencer publication window.\"\n        //     );\n        // }\n\n        // For efficiency reasons getMerkleRoot modifies the `_batch` argument in place\n        // while calculating the root hash therefore any arguments passed to it must not\n        // be used again afterwards\n        Lib_OVMCodec.ChainBatchHeader memory batchHeader = Lib_OVMCodec.ChainBatchHeader({\n            batchIndex: getTotalBatchesByChainId(_chainId),\n            batchRoot: Lib_MerkleTree.getMerkleRoot(_batch),\n            batchSize: _batch.length,\n            prevTotalElements: totalElements,\n            extraData: _extraData\n        });\n\n        emit StateBatchAppended(\n            _chainId,\n            batchHeader.batchIndex,\n            batchHeader.batchRoot,\n            batchHeader.batchSize,\n            batchHeader.prevTotalElements,\n            batchHeader.extraData\n        );\n\n        batches().pushByChainId(\n            _chainId,\n            Lib_OVMCodec.hashBatchHeader(batchHeader),\n            _makeBatchExtraDataByChainId(\n                uint40(batchHeader.prevTotalElements + batchHeader.batchSize),\n                lastSequencerTimestamp\n            )\n        );\n    }\n\n    /**\n     * Removes a batch and all subsequent batches from the chain.\n     * @param _batchHeader Header of the batch to remove.\n     */\n    function _deleteBatchByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) internal {\n        require(\n            _batchHeader.batchIndex < batches().lengthByChainId(_chainId),\n            \"Invalid batch index.\"\n        );\n\n        require(_isValidBatchHeaderByChainId(_chainId, _batchHeader), \"Invalid batch header.\");\n\n        batches().deleteElementsAfterInclusiveByChainId(\n            _chainId,\n            _batchHeader.batchIndex,\n            _makeBatchExtraDataByChainId(uint40(_batchHeader.prevTotalElements), 0)\n        );\n\n        emit StateBatchDeleted(_chainId, _batchHeader.batchIndex, _batchHeader.batchRoot);\n    }\n\n    /**\n     * Checks that a batch header matches the stored hash for the given index.\n     * @param _batchHeader Batch header to validate.\n     * @return Whether or not the header matches the stored one.\n     */\n    function _isValidBatchHeaderByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) internal view returns (bool) {\n        return\n            Lib_OVMCodec.hashBatchHeader(_batchHeader) ==\n            batches().getByChainId(_chainId, _batchHeader.batchIndex);\n    }\n}\n"
    },
    "contracts/L1/verification/BondManager.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { IBondManager } from \"./IBondManager.sol\";\n\n/* Contract Imports */\nimport { Lib_AddressResolver } from \"../../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/**\n * @title BondManager\n * @dev This contract is, for now, a stub of the \"real\" BondManager that does nothing but\n * allow the \"OVM_Proposer\" to submit state root batches.\n *\n * Runtime target: EVM\n */\ncontract BondManager is IBondManager, Lib_AddressResolver {\n    /**\n     * @param _libAddressManager Address of the Address Manager.\n     */\n    constructor(address _libAddressManager) Lib_AddressResolver(_libAddressManager) {}\n\n    /**\n     * Checks whether a given address is properly collateralized and can perform actions within\n     * the system.\n     * @param _who Address to check.\n     * @return true if the address is properly collateralized, false otherwise.\n     */\n    function isCollateralized(address _who) public view returns (bool) {\n        // Only authenticate sequencer to submit state root batches.\n        return _who == resolve(\"OVM_Proposer\");\n    }\n\n    function isCollateralizedByChainId(\n        uint256 _chainId,\n        address _who,\n        address _prop\n    ) public view override returns (bool) {\n        require(_who == _prop, \"sender must the proposer!\");\n        require(\n            _prop ==\n                resolve(string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Proposer\"))),\n            \"Proposer does not match this chain.\"\n        );\n        return true;\n        //return bonds[_who].state == State.COLLATERALIZED;\n    }\n\n    // function registerSequencerByChainId(\n    //    uint256 _chainId,\n    //    address _sequencer,\n    //    address _proposer\n    //) public {\n    //}\n}\n"
    },
    "contracts/L1/verification/IBondManager.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title IBondManager\n */\ninterface IBondManager {\n    /********************\n     * Public Functions *\n     ********************/\n\n    function isCollateralized(address _who) external view returns (bool);\n\n    function isCollateralizedByChainId(\n        uint256 _chainId,\n        address _who,\n        address _prop\n    ) external view returns (bool);\n}\n"
    },
    "contracts/L2/messaging/IL2CrossDomainMessenger.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { ICrossDomainMessenger } from \"../../libraries/bridge/ICrossDomainMessenger.sol\";\n\n/**\n * @title IL2CrossDomainMessenger\n */\ninterface IL2CrossDomainMessenger is ICrossDomainMessenger {\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Relays a cross domain message to a contract.\n     * @param _target Target contract address.\n     * @param _sender Message sender address.\n     * @param _message Message to send to the target.\n     * @param _messageNonce Nonce for the provided message.\n     */\n    function relayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce\n    ) external;\n}\n"
    },
    "contracts/L2/messaging/IL2ERC20Bridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title IL2ERC20Bridge\n */\ninterface IL2ERC20Bridge {\n    /**********\n     * Events *\n     **********/\n\n    event WithdrawalInitiated(\n        address indexed _l1Token,\n        address indexed _l2Token,\n        address indexed _from,\n        address _to,\n        uint256 _amount,\n        bytes _data\n    );\n\n    event DepositFinalized(\n        address indexed _l1Token,\n        address indexed _l2Token,\n        address indexed _from,\n        address _to,\n        uint256 _amount,\n        bytes _data\n    );\n\n    event DepositFailed(\n        address indexed _l1Token,\n        address indexed _l2Token,\n        address indexed _from,\n        address _to,\n        uint256 _amount,\n        bytes _data\n    );\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @dev get the address of the corresponding L1 bridge contract.\n     * @return Address of the corresponding L1 bridge contract.\n     */\n    function l1TokenBridge() external returns (address);\n\n    /**\n     * @dev initiate a withdraw of some tokens to the caller's account on L1\n     * @param _l2Token Address of L2 token where withdrawal was initiated.\n     * @param _amount Amount of the token to withdraw.\n     * param _l1Gas Unused, but included for potential forward compatibility considerations.\n     * @param _data Optional data to forward to L1. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function withdraw(\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable;\n\n    /**\n     * @dev initiate a withdraw of some token to a recipient's account on L1.\n     * @param _l2Token Address of L2 token where withdrawal is initiated.\n     * @param _to L1 adress to credit the withdrawal to.\n     * @param _amount Amount of the token to withdraw.\n     * param _l1Gas Unused, but included for potential forward compatibility considerations.\n     * @param _data Optional data to forward to L1. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function withdrawTo(\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable;\n\n    /*************************\n     * Cross-chain Functions *\n     *************************/\n\n    /**\n     * @dev Complete a deposit from L1 to L2, and credits funds to the recipient's balance of this\n     * L2 token. This call will fail if it did not originate from a corresponding deposit in\n     * L1StandardTokenBridge.\n     * @param _l1Token Address for the l1 token this is called with\n     * @param _l2Token Address for the l2 token this is called with\n     * @param _from Account to pull the deposit from on L2.\n     * @param _to Address to receive the withdrawal at\n     * @param _amount Amount of the token to withdraw\n     * @param _data Data provider by the sender on L1. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function finalizeDeposit(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external;\n}\n"
    },
    "contracts/L2/messaging/L2CrossDomainMessenger.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { AddressAliasHelper } from \"../../standards/AddressAliasHelper.sol\";\nimport { Lib_CrossDomainUtils } from \"../../libraries/bridge/Lib_CrossDomainUtils.sol\";\nimport { Lib_DefaultValues } from \"../../libraries/constants/Lib_DefaultValues.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/* Interface Imports */\nimport { IL2CrossDomainMessenger } from \"./IL2CrossDomainMessenger.sol\";\nimport { iOVM_L2ToL1MessagePasser } from \"../predeploys/iOVM_L2ToL1MessagePasser.sol\";\nimport { OVM_DeployerWhitelist } from \"../predeploys/OVM_DeployerWhitelist.sol\";\n\n/**\n * @title L2CrossDomainMessenger\n * @dev The L2 Cross Domain Messenger contract sends messages from L2 to L1, and is the entry point\n * for L2 messages sent via the L1 Cross Domain Messenger.\n *\n */\ncontract L2CrossDomainMessenger is IL2CrossDomainMessenger {\n    /*************\n     * Variables *\n     *************/\n\n    mapping(bytes32 => bool) public relayedMessages;\n    mapping(bytes32 => bool) public successfulMessages;\n    mapping(bytes32 => bool) public sentMessages;\n    uint256 public messageNonce;\n    address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;\n    address public l1CrossDomainMessenger;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor(address _l1CrossDomainMessenger) {\n        l1CrossDomainMessenger = _l1CrossDomainMessenger;\n    }\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    modifier onlyWhitelisted() {\n        require(\n            OVM_DeployerWhitelist(Lib_PredeployAddresses.DEPLOYER_WHITELIST).isXDomainSenderAllowed(\n                    msg.sender\n                ),\n            // solhint-disable-next-line max-line-length\n            \"L2 to L1 messages are restricted to whitelisted senders.\"\n        );\n        _;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function xDomainMessageSender() public view returns (address) {\n        require(\n            xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER,\n            \"xDomainMessageSender is not set\"\n        );\n        return xDomainMsgSender;\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 memory _message,\n        uint32 _gasLimit\n    ) public payable onlyWhitelisted {\n        bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            msg.sender,\n            _message,\n            messageNonce\n        );\n\n        sentMessages[keccak256(xDomainCalldata)] = true;\n\n        (bool sent, ) = Lib_PredeployAddresses.SEQUENCER_FEE_WALLET.call{ value: msg.value }(\"\");\n        require(sent, \"Failed to send bridge fee\");\n\n        // Actually send the message.\n        iOVM_L2ToL1MessagePasser(Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER).passMessageToL1(\n            xDomainCalldata\n        );\n\n        // Emit an event before we bump the nonce or the nonce will be off by one.\n        emit SentMessage(_target, msg.sender, _message, messageNonce, _gasLimit, 1); //sending to l1 so chainid set to 1\n        messageNonce += 1;\n    }\n\n    /**\n     * Relays a cross domain message to a contract.\n     * @inheritdoc IL2CrossDomainMessenger\n     */\n    function relayMessage(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce\n    ) public {\n        require(\n            AddressAliasHelper.undoL1ToL2Alias(msg.sender) == l1CrossDomainMessenger,\n            \"Provided message could not be verified.\"\n        );\n\n        bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(\n            _target,\n            _sender,\n            _message,\n            _messageNonce\n        );\n\n        bytes32 xDomainCalldataHash = keccak256(xDomainCalldata);\n\n        require(\n            successfulMessages[xDomainCalldataHash] == false,\n            \"Provided message has already been received.\"\n        );\n\n        // Prevent calls to OVM_L2ToL1MessagePasser, which would enable\n        // an attacker to maliciously craft the _message to spoof\n        // a call from any L2 account.\n        if (_target == Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER) {\n            // Write to the successfulMessages mapping and return immediately.\n            successfulMessages[xDomainCalldataHash] = true;\n            return;\n        }\n\n        xDomainMsgSender = _sender;\n        (bool success, ) = _target.call(_message);\n        xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER;\n\n        // Mark the message as received if the call was successful. Ensures that a message can be\n        // relayed multiple times in the case that the call reverted.\n        if (success == true) {\n            successfulMessages[xDomainCalldataHash] = true;\n            emit RelayedMessage(xDomainCalldataHash);\n        } else {\n            emit FailedRelayedMessage(xDomainCalldataHash);\n        }\n\n        // Store an identifier that can be used to prove that the given message was relayed by some\n        // user. Gives us an easy way to pay relayers for their work.\n        bytes32 relayId = keccak256(abi.encodePacked(xDomainCalldata, msg.sender, block.number));\n\n        relayedMessages[relayId] = true;\n    }\n\n    function sendMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        bytes calldata _message,\n        uint32 _gasLimit\n    ) public payable {}\n}\n"
    },
    "contracts/L2/messaging/L2StandardBridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { IL1StandardBridge } from \"../../L1/messaging/IL1StandardBridge.sol\";\nimport { IL1ERC20Bridge } from \"../../L1/messaging/IL1ERC20Bridge.sol\";\nimport { IL2ERC20Bridge } from \"./IL2ERC20Bridge.sol\";\n\n/* Library Imports */\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { CrossDomainEnabled } from \"../../libraries/bridge/CrossDomainEnabled.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\nimport { Lib_Uint } from \"../../libraries/utils/Lib_Uint.sol\";\n\n/* Contract Imports */\nimport { IL2StandardERC20 } from \"../../standards/IL2StandardERC20.sol\";\nimport { OVM_GasPriceOracle } from \"../predeploys/OVM_GasPriceOracle.sol\";\n\n/**\n * @title L2StandardBridge\n * @dev The L2 Standard bridge is a contract which works together with the L1 Standard bridge to\n * enable ETH and ERC20 transitions between L1 and L2.\n * This contract acts as a minter for new tokens when it hears about deposits into the L1 Standard\n * bridge.\n * This contract also acts as a burner of the tokens intended for withdrawal, informing the L1\n * bridge to release L1 funds.\n */\ncontract L2StandardBridge is IL2ERC20Bridge, CrossDomainEnabled {\n    /********************************\n     * External Contract References *\n     ********************************/\n\n    address public l1TokenBridge;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _l2CrossDomainMessenger Cross-domain messenger used by this contract.\n     * @param _l1TokenBridge Address of the L1 bridge deployed to the main chain.\n     */\n    constructor(address _l2CrossDomainMessenger, address _l1TokenBridge)\n        CrossDomainEnabled(_l2CrossDomainMessenger)\n    {\n        l1TokenBridge = _l1TokenBridge;\n    }\n\n    function getChainID() internal view returns (uint256) {\n        uint256 id;\n        assembly {\n            id := chainid()\n        }\n        return id;\n    }\n\n    /***************\n     * Withdrawing *\n     ***************/\n\n    /**\n     * @inheritdoc IL2ERC20Bridge\n     */\n    function withdraw(\n        address _l2Token,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable virtual {\n        _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _l1Gas, _data);\n    }\n\n    function withdrawMetis(\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable virtual {\n        _initiateWithdrawal(\n            Lib_PredeployAddresses.MVM_COINBASE,\n            msg.sender,\n            msg.sender,\n            _amount,\n            _l1Gas,\n            _data\n        );\n    }\n\n    /**\n     * @inheritdoc IL2ERC20Bridge\n     */\n    function withdrawTo(\n        address _l2Token,\n        address _to,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable virtual {\n        _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _l1Gas, _data);\n    }\n\n    function withdrawMetisTo(\n        address _to,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) external payable virtual {\n        _initiateWithdrawal(\n            Lib_PredeployAddresses.MVM_COINBASE,\n            msg.sender,\n            _to,\n            _amount,\n            _l1Gas,\n            _data\n        );\n    }\n\n    /**\n     * @dev Performs the logic for deposits by storing the token and informing the L2 token Gateway\n     * of the deposit.\n     * @param _l2Token Address of L2 token where withdrawal was initiated.\n     * @param _from Account to pull the deposit from on L2.\n     * @param _to Account to give the withdrawal to on L1.\n     * @param _amount Amount of the token to withdraw.\n     * param _l1Gas Unused, but included for potential forward compatibility considerations.\n     * @param _data Optional data to forward to L1. This data is provided\n     *        solely as a convenience for external contracts. Aside from enforcing a maximum\n     *        length, these contracts provide no guarantees about its content.\n     */\n    function _initiateWithdrawal(\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        uint32 _l1Gas,\n        bytes calldata _data\n    ) internal {\n        uint256 minL1Gas = OVM_GasPriceOracle(Lib_PredeployAddresses.OVM_GASPRICE_ORACLE)\n            .minErc20BridgeCost();\n\n        // require minimum gas unless, the metis manager is the sender\n        require(\n            msg.value >= minL1Gas || _from == Lib_PredeployAddresses.SEQUENCER_FEE_WALLET,\n            string(\n                abi.encodePacked(\n                    \"insufficient withdrawal fee supplied. need at least \",\n                    Lib_Uint.uint2str(minL1Gas)\n                )\n            )\n        );\n\n        // When a withdrawal is initiated, we burn the withdrawer's funds to prevent subsequent L2\n        // usage\n        IL2StandardERC20(_l2Token).burn(msg.sender, _amount);\n\n        // Construct calldata for l1TokenBridge.finalizeERC20Withdrawal(_to, _amount)\n        address l1Token = IL2StandardERC20(_l2Token).l1Token();\n        bytes memory message;\n\n        if (_l2Token == Lib_PredeployAddresses.OVM_ETH) {\n            message = abi.encodeWithSelector(\n                IL1StandardBridge.finalizeETHWithdrawalByChainId.selector,\n                getChainID(),\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        } else if (_l2Token == Lib_PredeployAddresses.MVM_COINBASE) {\n            message = abi.encodeWithSelector(\n                IL1ERC20Bridge.finalizeMetisWithdrawalByChainId.selector,\n                getChainID(),\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        } else {\n            message = abi.encodeWithSelector(\n                IL1ERC20Bridge.finalizeERC20WithdrawalByChainId.selector,\n                getChainID(),\n                l1Token,\n                _l2Token,\n                _from,\n                _to,\n                _amount,\n                _data\n            );\n        }\n\n        // Send message up to L1 bridge\n        sendCrossDomainMessage(\n            l1TokenBridge,\n            _l1Gas,\n            message,\n            msg.value // send all value as fees to cover relayer cost\n        );\n\n        emit WithdrawalInitiated(l1Token, _l2Token, msg.sender, _to, _amount, _data);\n    }\n\n    /************************************\n     * Cross-chain Function: Depositing *\n     ************************************/\n\n    /**\n     * @inheritdoc IL2ERC20Bridge\n     */\n    function finalizeDeposit(\n        address _l1Token,\n        address _l2Token,\n        address _from,\n        address _to,\n        uint256 _amount,\n        bytes calldata _data\n    ) external virtual onlyFromCrossDomainAccount(l1TokenBridge) {\n        // Check the target token is compliant and\n        // verify the deposited token on L1 matches the L2 deposited token representation here\n        if (\n            ERC165Checker.supportsInterface(_l2Token, 0x1d1d8b63) &&\n            _l1Token == IL2StandardERC20(_l2Token).l1Token()\n        ) {\n            // When a deposit is finalized, we credit the account on L2 with the same amount of\n            // tokens.\n            IL2StandardERC20(_l2Token).mint(_to, _amount);\n            emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _data);\n        } else {\n            // disable because the mechanism is incompatible with the new xdomain fee structure.\n\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 funds 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            //    iOVM_L1ERC20Bridge.finalizeERC20Withdrawal.selector,\n            //    _l1Token,\n            //    _l2Token,\n            //    _to,   // switched the _to and _from here to bounce back the deposit to the sender\n            //    _from,\n            //    _amount,\n            //    _data\n            //);\n\n            // Send message up to L1 bridge\n            //sendCrossDomainMessage(\n            //    l1TokenBridge,\n            //    0,\n            //    message,\n            //    0\n            //);\n            emit DepositFailed(_l1Token, _l2Token, _from, _to, _amount, _data);\n        }\n    }\n}\n"
    },
    "contracts/L2/messaging/L2StandardTokenFactory.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Contract Imports */\nimport { L2StandardERC20 } from \"../../standards/L2StandardERC20.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/**\n * @title L2StandardTokenFactory\n * @dev Factory contract for creating standard L2 token representations of L1 ERC20s\n * compatible with and working on the standard bridge.\n */\ncontract L2StandardTokenFactory {\n    event StandardL2TokenCreated(address indexed _l1Token, address indexed _l2Token);\n\n    /**\n     * @dev Creates an instance of the standard ERC20 token on L2.\n     * @param _l1Token Address of the corresponding L1 token.\n     * @param _name ERC20 name.\n     * @param _symbol ERC20 symbol.\n     */\n    function createStandardL2Token(\n        address _l1Token,\n        string memory _name,\n        string memory _symbol\n    ) external {\n        require(_l1Token != address(0), \"Must provide L1 token address\");\n\n        L2StandardERC20 l2Token = new L2StandardERC20(\n            Lib_PredeployAddresses.L2_STANDARD_BRIDGE,\n            _l1Token,\n            _name,\n            _symbol\n        );\n\n        emit StandardL2TokenCreated(_l1Token, address(l2Token));\n    }\n}\n"
    },
    "contracts/L2/predeploys/iOVM_L1BlockNumber.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title iOVM_L1BlockNumber\n */\ninterface iOVM_L1BlockNumber {\n    /********************\n     * Public Functions *\n     ********************/\n\n    function getL1BlockNumber() external view returns (uint256);\n}\n"
    },
    "contracts/L2/predeploys/iOVM_L2ToL1MessagePasser.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title iOVM_L2ToL1MessagePasser\n */\ninterface iOVM_L2ToL1MessagePasser {\n    /**********\n     * Events *\n     **********/\n\n    event L2ToL1Message(uint256 _nonce, address _sender, bytes _data);\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function passMessageToL1(bytes calldata _message) external;\n}\n"
    },
    "contracts/L2/predeploys/iOVM_SequencerFeeVault.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/* Contract Imports */\nimport { L2StandardBridge } from \"../messaging/L2StandardBridge.sol\";\nimport { CrossDomainEnabled } from \"../../libraries/bridge/CrossDomainEnabled.sol\";\n\n/**\n * @title OVM_SequencerFeeVault\n * @dev Simple holding contract for fees paid to the Sequencer. Likely to be replaced in the future\n * but \"good enough for now\".\n */\ninterface iOVM_SequencerFeeVault {\n    /*************\n     * Constants *\n     *************/\n\n    event ChainSwitch(address l1Wallet, address l2Manager);\n    event ConfigChange(bytes config);\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function withdraw(uint256 amount) external payable;\n\n    function finalizeChainSwitch(address _FeeWallet, address _L2Manager) external;\n\n    function finalizeChainConfig(bytes calldata config) external;\n\n    function send(address payable to, uint256 amount) external;\n\n    function sendBatch(address payable[] calldata tos, uint256[] calldata amounts) external;\n\n    function getL2Manager() external view returns (address);\n}\n"
    },
    "contracts/L2/predeploys/OVM_DeployerWhitelist.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { iOVM_SequencerFeeVault } from \"./iOVM_SequencerFeeVault.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/**\n * @title OVM_DeployerWhitelist\n * @dev The Deployer Whitelist is a temporary predeploy used to provide additional safety during the\n * initial phases of our mainnet roll out. It is owned by the Optimism team, and defines accounts\n * which are allowed to deploy contracts on Layer2. The Execution Manager will only allow an\n * ovmCREATE or ovmCREATE2 operation to proceed if the deployer's address whitelisted.\n */\ncontract OVM_DeployerWhitelist {\n    /**********\n     * Events *\n     **********/\n\n    event OwnerChanged(address oldOwner, address newOwner);\n    event WhitelistStatusChanged(address deployer, bool whitelisted);\n    event WhitelistDisabled(address oldOwner);\n    mapping(address => bool) public xDomainWL;\n\n    /**********************\n     * Contract Constants *\n     **********************/\n\n    // WARNING: When owner is set to address(0), the whitelist is disabled.\n    address public owner;\n    mapping(address => bool) public whitelist;\n    bool public allowArbitraryDeployment;\n    bool public allowAllXDomainSenders;\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    /**\n     * Blocks functions to anyone except the contract owner.\n     */\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"Function can only be called by the owner of this contract.\");\n        _;\n    }\n\n    modifier onlyManager() {\n        require(\n            msg.sender ==\n                iOVM_SequencerFeeVault(Lib_PredeployAddresses.SEQUENCER_FEE_WALLET).getL2Manager(),\n            \"Function can only be called by the l2manager.\"\n        );\n        _;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Adds or removes an address from the deployment whitelist.\n     * @param _deployer Address to update permissions for.\n     * @param _isWhitelisted Whether or not the address is whitelisted.\n     */\n    function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external onlyOwner {\n        whitelist[_deployer] = _isWhitelisted;\n        allowArbitraryDeployment = false;\n        emit WhitelistStatusChanged(_deployer, _isWhitelisted);\n    }\n\n    function setWhitelistedXDomainSender(address _sender, bool _isWhitelisted) external onlyOwner {\n        xDomainWL[_sender] = _isWhitelisted;\n        allowAllXDomainSenders = false;\n        emit WhitelistStatusChanged(_sender, _isWhitelisted);\n    }\n\n    /**\n     * Updates the owner of this contract.\n     * @param _owner Address of the new owner.\n     */\n    function setOwner(address _owner) public onlyOwner {\n        emit OwnerChanged(owner, _owner);\n        owner = _owner;\n    }\n\n    /**\n     * Permanently enables arbitrary contract deployment and deletes the owner.\n     */\n    function enableArbitraryContractDeployment() external onlyOwner {\n        emit WhitelistDisabled(owner);\n        allowArbitraryDeployment = true;\n    }\n\n    function enableAllXDomainSenders() external onlyOwner {\n        emit WhitelistDisabled(owner);\n        allowAllXDomainSenders = true;\n    }\n\n    /**\n     * Checks whether an address is allowed to deploy contracts.\n     * @param _deployer Address to check.\n     * @return _allowed Whether or not the address can deploy contracts.\n     */\n    function isDeployerAllowed(address _deployer) external view returns (bool) {\n        return (owner == address(0) || allowArbitraryDeployment || whitelist[_deployer]);\n    }\n\n    function isXDomainSenderAllowed(address _sender) external view returns (bool) {\n        return (owner == address(0) || allowAllXDomainSenders == true || xDomainWL[_sender]);\n    }\n}\n"
    },
    "contracts/L2/predeploys/OVM_ETH.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/* Contract Imports */\nimport { L2StandardERC20 } from \"../../standards/L2StandardERC20.sol\";\n\n/**\n * @title OVM_ETH\n * @dev The ETH predeploy provides an ERC20 interface for ETH deposited to Layer 2. Note that\n * unlike on Layer 1, Layer 2 accounts do not have a balance field.\n */\ncontract OVM_ETH is L2StandardERC20 {\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor()\n        L2StandardERC20(Lib_PredeployAddresses.L2_STANDARD_BRIDGE, address(0), \"Ether\", \"WETH\")\n    {}\n}\n"
    },
    "contracts/L2/predeploys/OVM_GasPriceOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* External Imports */\n\nimport { iOVM_SequencerFeeVault } from \"./iOVM_SequencerFeeVault.sol\";\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/**\n * @title OVM_GasPriceOracle\n * @dev This contract exposes the current l2 gas price, a measure of how congested the network\n * currently is. This measure is used by the Sequencer to determine what fee to charge for\n * transactions. When the system is more congested, the l2 gas price will increase and fees\n * will also increase as a result.\n *\n * All public variables are set while generating the initial L2 state. The\n * constructor doesn't run in practice as the L2 state generation script uses\n * the deployed bytecode instead of running the initcode.\n */\ncontract OVM_GasPriceOracle {\n    /*************\n     * Variables *\n     *************/\n    address public owner;\n    // Current L2 gas price\n    uint256 public gasPrice;\n    // Current L1 base fee\n    uint256 public l1BaseFee;\n    // Amortized cost of batch submission per transaction\n    uint256 public overhead;\n    // Value to scale the fee up by\n    uint256 public scalar;\n    // Number of decimals of the scalar\n    uint256 public decimals;\n\n    // minimum gas to bridge the asset back to l1\n    uint256 public minErc20BridgeCost;\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    /**\n     * Blocks functions to anyone except the contract owner.\n     */\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"Function can only be called by the owner of this contract.\");\n        _;\n    }\n\n    modifier onlyManager() {\n        require(\n            msg.sender ==\n                iOVM_SequencerFeeVault(Lib_PredeployAddresses.SEQUENCER_FEE_WALLET).getL2Manager(),\n            \"Function can only be called by the l2manager.\"\n        );\n        _;\n    }\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _owner Address that will initially own this contract.\n     */\n    constructor(address _owner) {\n        owner = _owner;\n    }\n\n    /**********\n     * Events *\n     **********/\n\n    event GasPriceUpdated(uint256);\n    event L1BaseFeeUpdated(uint256);\n    event OverheadUpdated(uint256);\n    event ScalarUpdated(uint256);\n    event DecimalsUpdated(uint256);\n    event MinErc20BridgeCostUpdated(uint256);\n    event OwnerChanged(address oldOwner, address newOwner);\n\n    /********************\n     * Public Functions *\n     ********************/\n    /**\n     * Updates the owner of this contract.\n     * @param _owner Address of the new owner.\n     */\n    function setOwner(address _owner) public onlyManager {\n        emit OwnerChanged(owner, _owner);\n        owner = _owner;\n    }\n\n    /**\n     * Allows the owner to modify the l2 gas price.\n     * @param _gasPrice New l2 gas price.\n     */\n    function setGasPrice(uint256 _gasPrice) public onlyOwner {\n        gasPrice = _gasPrice;\n        emit GasPriceUpdated(_gasPrice);\n    }\n\n    /**\n     * Allows the owner to modify the l1 bridge price.\n     * @param _minCost New l2 gas price.\n     */\n    function setMinErc20BridgeCost(uint256 _minCost) public onlyOwner {\n        minErc20BridgeCost = _minCost;\n        emit MinErc20BridgeCostUpdated(_minCost);\n    }\n\n    /**\n     * Allows the owner to modify the l1 base fee.\n     * @param _baseFee New l1 base fee\n     */\n    function setL1BaseFee(uint256 _baseFee) public onlyOwner {\n        if (l1BaseFee > 0) {\n            require(_baseFee < (l1BaseFee * 105) / 100, \"increase is capped at 5%\");\n        }\n        l1BaseFee = _baseFee;\n        emit L1BaseFeeUpdated(_baseFee);\n    }\n\n    /**\n     * Allows the owner to modify the overhead.\n     * @param _overhead New overhead\n     */\n    function setOverhead(uint256 _overhead) public onlyOwner {\n        if (overhead > 0) {\n            require(_overhead < (overhead * 105) / 100, \"increase is capped at 5%\");\n        }\n        overhead = _overhead;\n        emit OverheadUpdated(_overhead);\n    }\n\n    /**\n     * Allows the owner to modify the scalar.\n     * @param _scalar New scalar\n     */\n    function setScalar(uint256 _scalar) public onlyOwner {\n        if (scalar > 0) {\n            require(_scalar < (scalar * 105) / 100, \"increase is capped at 5%\");\n        }\n        scalar = _scalar;\n        emit ScalarUpdated(_scalar);\n    }\n\n    /**\n     * Allows the owner to modify the decimals.\n     * For maximum safety, this method should only be called when there is no active tx\n     * @param _decimals New decimals\n     */\n    function setDecimals(uint256 _decimals) public onlyOwner {\n        decimals = _decimals;\n        emit DecimalsUpdated(_decimals);\n    }\n\n    /**\n     * Computes the L1 portion of the fee\n     * based on the size of the RLP encoded tx\n     * and the current l1BaseFee\n     * @param _data Unsigned RLP encoded tx, 6 elements\n     * @return L1 fee that should be paid for the tx\n     */\n    function getL1Fee(bytes memory _data) public view returns (uint256) {\n        uint256 l1GasUsed = getL1GasUsed(_data);\n        uint256 l1Fee = l1GasUsed * l1BaseFee;\n        uint256 divisor = 10**decimals;\n        uint256 unscaled = l1Fee * scalar;\n        uint256 scaled = unscaled / divisor;\n        return scaled;\n    }\n\n    // solhint-disable max-line-length\n    /**\n     * Computes the amount of L1 gas used for a transaction\n     * The overhead represents the per batch gas overhead of\n     * posting both transaction and state roots to L1 given larger\n     * batch sizes.\n     * 4 gas for 0 byte\n     * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L33\n     * 16 gas for non zero byte\n     * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L87\n     * This will need to be updated if calldata gas prices change\n     * Account for the transaction being unsigned\n     * Padding is added to account for lack of signature on transaction\n     * 1 byte for RLP V prefix\n     * 1 byte for V\n     * 1 byte for RLP R prefix\n     * 32 bytes for R\n     * 1 byte for RLP S prefix\n     * 32 bytes for S\n     * Total: 68 bytes of padding\n     * @param _data Unsigned RLP encoded tx, 6 elements\n     * @return Amount of L1 gas used for a transaction\n     */\n    // solhint-enable max-line-length\n    function getL1GasUsed(bytes memory _data) public view returns (uint256) {\n        uint256 total = 0;\n        for (uint256 i = 0; i < _data.length; i++) {\n            if (_data[i] == 0) {\n                total += 4;\n            } else {\n                total += 16;\n            }\n        }\n        uint256 unsigned = total + overhead;\n        return unsigned + (68 * 16);\n    }\n}\n"
    },
    "contracts/L2/predeploys/OVM_L2ToL1MessagePasser.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Interface Imports */\nimport { iOVM_L2ToL1MessagePasser } from \"./iOVM_L2ToL1MessagePasser.sol\";\n\n/**\n * @title OVM_L2ToL1MessagePasser\n * @dev The L2 to L1 Message Passer is a utility contract which facilitate an L1 proof of the\n * of a message on L2. The L1 Cross Domain Messenger performs this proof in its\n * _verifyStorageProof function, which verifies the existence of the transaction hash in this\n * contract's `sentMessages` mapping.\n\n */\ncontract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser {\n    /**********************\n     * Contract Variables *\n     **********************/\n\n    mapping(bytes32 => bool) public sentMessages;\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Passes a message to L1.\n     * @param _message Message to pass to L1.\n     */\n    function passMessageToL1(bytes memory _message) public {\n        // Note: although this function is public, only messages sent from the\n        // L2CrossDomainMessenger will be relayed by the L1CrossDomainMessenger.\n        // This is enforced by a check in L1CrossDomainMessenger._verifyStorageProof().\n        sentMessages[keccak256(abi.encodePacked(_message, msg.sender))] = true;\n    }\n}\n"
    },
    "contracts/L2/predeploys/OVM_SequencerFeeVault.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_PredeployAddresses } from \"../../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/* Contract Imports */\nimport { L2StandardBridge } from \"../messaging/L2StandardBridge.sol\";\nimport { CrossDomainEnabled } from \"../../libraries/bridge/CrossDomainEnabled.sol\";\nimport { iOVM_SequencerFeeVault } from \"./iOVM_SequencerFeeVault.sol\";\nimport { iMVM_ChainConfig } from \"../../MVM/iMVM_ChainConfig.sol\";\n\n/**\n * @title OVM_SequencerFeeVault\n * @dev Simple holding contract for fees paid to the Sequencer. Likely to be replaced in the future\n * but \"good enough for now\".\n */\ncontract OVM_SequencerFeeVault is iOVM_SequencerFeeVault, CrossDomainEnabled {\n    /*************\n     * Variables *\n     *************/\n\n    // Address on L1 that will hold the fees once withdrawn. Dynamically initialized within l2geth.\n    address public l1FeeWallet;\n    address public l1Manager;\n    address public l2Manager;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _l1FeeWallet Initial address for the L1 wallet that will hold fees once withdrawn.\n     * Currently HAS NO EFFECT in production because l2geth will mutate this storage slot during\n     * the genesis block. This is ONLY for testing purposes.\n     */\n    constructor(\n        address _l2CrossDomainMessenger,\n        address _l1FeeWallet,\n        address _l1Manager\n    ) CrossDomainEnabled(_l2CrossDomainMessenger) {\n        l1FeeWallet = _l1FeeWallet;\n        l1Manager = _l1Manager;\n    }\n\n    modifier onlyManager() {\n        require(msg.sender == l2Manager, \"not allowed\");\n        _;\n    }\n\n    /************\n     * Fallback *\n     ************/\n\n    receive() external payable {}\n\n    // Fallback function is called when msg.data is not empty\n    fallback() external payable {}\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    function withdraw(uint256 amount) public payable onlyManager {\n        require(address(this).balance >= amount, \"not enough balance to withraw\");\n\n        if (amount == 0) {\n            amount = address(this).balance;\n        }\n\n        L2StandardBridge(Lib_PredeployAddresses.L2_STANDARD_BRIDGE).withdrawTo{ value: msg.value }(\n            Lib_PredeployAddresses.MVM_COINBASE,\n            l1FeeWallet,\n            amount,\n            0,\n            bytes(\"\")\n        );\n    }\n\n    function finalizeChainSwitch(address _FeeWallet, address _L2Manager)\n        external\n        virtual\n        onlyFromCrossDomainAccount(l1Manager)\n    {\n        l1FeeWallet = _FeeWallet;\n        l2Manager = _L2Manager;\n        emit ChainSwitch(l1FeeWallet, l2Manager);\n    }\n\n    function finalizeChainConfig(bytes calldata values)\n        external\n        virtual\n        onlyFromCrossDomainAccount(l1Manager)\n    {\n        iMVM_ChainConfig(Lib_PredeployAddresses.MVM_CHAIN_CONFIG).setConfig(values);\n        emit ConfigChange(values);\n    }\n\n    function send(address payable to, uint256 amount) public onlyManager {\n        (bool sent, ) = to.call{ value: amount }(\"\");\n        require(sent, \"Failed to send metis\");\n    }\n\n    function sendBatch(address payable[] calldata tos, uint256[] calldata amounts)\n        public\n        onlyManager\n    {\n        require(tos.length == amounts.length, \"lengths of the parameters do not match\");\n        for (uint256 i = 0; i < tos.length; i++) {\n            send(tos[i], amounts[i]);\n        }\n    }\n\n    function getL2Manager() public view returns (address) {\n        return l2Manager;\n    }\n}\n"
    },
    "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 * Runtime target: 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        uint256 fee\n    ) internal {\n        getCrossDomainMessenger().sendMessage{ value: fee }(\n            _crossDomainTarget,\n            _message,\n            _gasLimit\n        );\n    }\n\n    /**\n     * @notice Sends a message to an account on another domain\n     * @param _chainId L2 chain id.\n     * @param _crossDomainTarget The intended recipient on the destination domain\n     * @param _gasLimit The gasLimit for the receipt of the message on the target domain.\n     * @param _message The data to send to the target (usually calldata to a function with `onlyFromCrossDomainAccount()`)\n     */\n    function sendCrossDomainMessageViaChainId(\n        uint256 _chainId,\n        address _crossDomainTarget,\n        uint32 _gasLimit,\n        bytes memory _message,\n        uint256 fee\n    ) internal {\n        getCrossDomainMessenger().sendMessageViaChainId{ value: fee }(\n            _chainId,\n            _crossDomainTarget,\n            _message,\n            _gasLimit\n        );\n    }\n}\n"
    },
    "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        uint256 chainId\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 payable;\n\n    /**\n     * Sends a cross domain message to the target messenger.\n     * @param _chainId L2 chain id.\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 sendMessageViaChainId(\n        uint256 _chainId,\n        address _target,\n        bytes calldata _message,\n        uint32 _gasLimit\n    ) external payable;\n}\n"
    },
    "contracts/libraries/bridge/Lib_CrossDomainUtils.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_RLPReader } from \"../rlp/Lib_RLPReader.sol\";\n\n/**\n * @title Lib_CrossDomainUtils\n */\nlibrary Lib_CrossDomainUtils {\n    /**\n     * Generates the correct cross domain calldata for a message.\n     * @param _target Target contract address.\n     * @param _sender Message sender address.\n     * @param _message Message to send to the target.\n     * @param _messageNonce Nonce for the provided message.\n     * @return ABI encoded cross domain calldata.\n     */\n    function encodeXDomainCalldata(\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce\n    ) internal pure returns (bytes memory) {\n        return\n            abi.encodeWithSignature(\n                \"relayMessage(address,address,bytes,uint256)\",\n                _target,\n                _sender,\n                _message,\n                _messageNonce\n            );\n    }\n\n    /**\n     * Generates the correct cross domain calldata for a message.\n     * @param _chainId L2 chain id.\n     * @param _target Target contract address.\n     * @param _sender Message sender address.\n     * @param _message Message to send to the target.\n     * @param _messageNonce Nonce for the provided message.\n     * @return ABI encoded cross domain calldata.\n     */\n    function encodeXDomainCalldataViaChainId(\n        uint256 _chainId,\n        address _target,\n        address _sender,\n        bytes memory _message,\n        uint256 _messageNonce\n    ) internal pure returns (bytes memory) {\n        return\n            abi.encodeWithSignature(\n                \"relayMessageViaChainId(uint256,address,address,bytes,uint256)\",\n                _chainId,\n                _target,\n                _sender,\n                _message,\n                _messageNonce\n            );\n    }\n}\n"
    },
    "contracts/libraries/codec/Lib_OVMCodec.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_RLPReader } from \"../rlp/Lib_RLPReader.sol\";\n\n/**\n * @title Lib_OVMCodec\n */\nlibrary Lib_OVMCodec {\n    /*********\n     * Enums *\n     *********/\n\n    enum QueueOrigin {\n        SEQUENCER_QUEUE,\n        L1TOL2_QUEUE\n    }\n\n    /***********\n     * Structs *\n     ***********/\n\n    struct EVMAccount {\n        uint256 nonce;\n        uint256 balance;\n        bytes32 storageRoot;\n        bytes32 codeHash;\n    }\n\n    struct ChainBatchHeader {\n        uint256 batchIndex;\n        bytes32 batchRoot;\n        uint256 batchSize;\n        uint256 prevTotalElements;\n        bytes extraData;\n    }\n\n    struct ChainInclusionProof {\n        uint256 index;\n        bytes32[] siblings;\n    }\n\n    struct Transaction {\n        uint256 timestamp;\n        uint256 blockNumber;\n        QueueOrigin l1QueueOrigin;\n        address l1TxOrigin;\n        address entrypoint;\n        uint256 gasLimit;\n        bytes data;\n    }\n\n    struct TransactionChainElement {\n        bool isSequenced;\n        uint256 queueIndex; // QUEUED TX ONLY\n        uint256 timestamp; // SEQUENCER TX ONLY\n        uint256 blockNumber; // SEQUENCER TX ONLY\n        bytes txData; // SEQUENCER TX ONLY\n    }\n\n    struct QueueElement {\n        bytes32 transactionHash;\n        uint40 timestamp;\n        uint40 blockNumber;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Encodes a standard OVM transaction.\n     * @param _transaction OVM transaction to encode.\n     * @return Encoded transaction bytes.\n     */\n    function encodeTransaction(Transaction memory _transaction)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return\n            abi.encodePacked(\n                _transaction.timestamp,\n                _transaction.blockNumber,\n                _transaction.l1QueueOrigin,\n                _transaction.l1TxOrigin,\n                _transaction.entrypoint,\n                _transaction.gasLimit,\n                _transaction.data\n            );\n    }\n\n    /**\n     * Hashes a standard OVM transaction.\n     * @param _transaction OVM transaction to encode.\n     * @return Hashed transaction\n     */\n    function hashTransaction(Transaction memory _transaction) internal pure returns (bytes32) {\n        return keccak256(encodeTransaction(_transaction));\n    }\n\n    /**\n     * @notice Decodes an RLP-encoded account state into a useful struct.\n     * @param _encoded RLP-encoded account state.\n     * @return Account state struct.\n     */\n    function decodeEVMAccount(bytes memory _encoded) internal pure returns (EVMAccount memory) {\n        Lib_RLPReader.RLPItem[] memory accountState = Lib_RLPReader.readList(_encoded);\n\n        return\n            EVMAccount({\n                nonce: Lib_RLPReader.readUint256(accountState[0]),\n                balance: Lib_RLPReader.readUint256(accountState[1]),\n                storageRoot: Lib_RLPReader.readBytes32(accountState[2]),\n                codeHash: Lib_RLPReader.readBytes32(accountState[3])\n            });\n    }\n\n    /**\n     * Calculates a hash for a given batch header.\n     * @param _batchHeader Header to hash.\n     * @return Hash of the header.\n     */\n    function hashBatchHeader(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)\n        internal\n        pure\n        returns (bytes32)\n    {\n        return\n            keccak256(\n                abi.encode(\n                    _batchHeader.batchRoot,\n                    _batchHeader.batchSize,\n                    _batchHeader.prevTotalElements,\n                    _batchHeader.extraData\n                )\n            );\n    }\n}\n"
    },
    "contracts/libraries/constants/Lib_DefaultValues.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_DefaultValues\n */\nlibrary Lib_DefaultValues {\n    // The default x-domain message sender being set to a non-zero value makes\n    // deployment a bit more expensive, but in exchange the refund on every call to\n    // `relayMessage` by the L1 and L2 messengers will be higher.\n    address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;\n}\n"
    },
    "contracts/libraries/constants/Lib_PredeployAddresses.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_PredeployAddresses\n */\nlibrary Lib_PredeployAddresses {\n    address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n    address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n    address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n    address internal constant MVM_CHAIN_CONFIG = 0x4200000000000000000000000000000000000005;\n    address internal constant OVM_ETH = 0x420000000000000000000000000000000000000A;\n    address internal constant MVM_COINBASE = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;\n    address internal constant L2_CROSS_DOMAIN_MESSENGER =\n        0x4200000000000000000000000000000000000007;\n    address internal constant LIB_ADDRESS_MANAGER = 0x4200000000000000000000000000000000000008;\n    address internal constant PROXY_EOA = 0x4200000000000000000000000000000000000009;\n    address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n    address payable internal constant SEQUENCER_FEE_WALLET =\n        payable(0x4200000000000000000000000000000000000011);\n    address internal constant L2_STANDARD_TOKEN_FACTORY =\n        0x4200000000000000000000000000000000000012;\n    address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n    address internal constant OVM_GASPRICE_ORACLE = 0x420000000000000000000000000000000000000F;\n}\n"
    },
    "contracts/libraries/crypto/LibKeccak.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/// @title LibKeccak\n/// @notice An EVM implementation of the Keccak-f[1600] permutation.\n/// @author clabby <https://github.com/clabby>\n/// @custom:attribution geohot <https://github.com/geohot>\nlibrary LibKeccak {\n    /// @notice The block size of the Keccak-f[1600] permutation, 1088 bits (136 bytes).\n    uint256 internal constant BLOCK_SIZE_BYTES = 136;\n\n    /// @notice The round constants for the keccak256 hash function. Packed in memory for efficient reading during the\n    ///         permutation.\n    bytes internal constant ROUND_CONSTANTS = abi.encode(\n        0x00000000000000010000000000008082800000000000808a8000000080008000, // r1,r2,r3,r4\n        0x000000000000808b000000008000000180000000800080818000000000008009, // r5,r6,r7,r8\n        0x000000000000008a00000000000000880000000080008009000000008000000a, // r9,r10,r11,r12\n        0x000000008000808b800000000000008b80000000000080898000000000008003, // r13,r14,r15,r16\n        0x80000000000080028000000000000080000000000000800a800000008000000a, // r17,r18,r19,r20\n        0x8000000080008081800000000000808000000000800000018000000080008008 // r21,r22,r23,r24\n    );\n\n    /// @notice A mask for 64-bit values.\n    uint64 private constant U64_MASK = 0xFFFFFFFFFFFFFFFF;\n\n    /// @notice The 5x5 state matrix for the keccak-f[1600] permutation.\n    struct StateMatrix {\n        uint64[25] state;\n    }\n\n    /// @notice Performs the Keccak-f[1600] permutation on the given 5x5 state matrix.\n    function permutation(StateMatrix memory _stateMatrix) internal pure {\n        // Pull the round constants into memory to avoid reallocation in the unrolled permutation loop.\n        bytes memory roundConstants = ROUND_CONSTANTS;\n\n        assembly {\n        // Add 32 to the state matrix pointer to skip the data location field.\n            let stateMatrixPtr := add(_stateMatrix, 0x20)\n            let rcPtr := add(roundConstants, 0x20)\n\n        // set a state element in the passed `StateMatrix` struct memory ptr.\n            function setStateElem(ptr, idx, data) {\n                mstore(add(ptr, shl(0x05, idx)), and(data, U64_MASK))\n            }\n\n        // fetch a state element from the passed `StateMatrix` struct memory ptr.\n            function stateElem(ptr, idx) -> elem {\n                elem := mload(add(ptr, shl(0x05, idx)))\n            }\n\n        // 64 bit logical shift\n            function shl64(a, b) -> val {\n                val := and(shl(a, b), U64_MASK)\n            }\n\n        // Performs an indivudual rho + pi computation, to be used in the full `thetaRhoPi` chain.\n            function rhoPi(ptr, destIdx, srcIdx, fact, dt) {\n                let xs1 := xor(stateElem(ptr, srcIdx), dt)\n                let res := xor(shl(fact, xs1), shr(sub(64, fact), xs1))\n                setStateElem(ptr, destIdx, res)\n            }\n\n        // xor a column in the state matrix\n            function xorColumn(ptr, col) -> val {\n                val :=\n                xor(\n                    xor(xor(stateElem(ptr, col), stateElem(ptr, add(col, 5))), stateElem(ptr, add(col, 10))),\n                    xor(stateElem(ptr, add(col, 15)), stateElem(ptr, add(col, 20)))\n                )\n            }\n\n        // Performs the `theta`, `rho`, and `pi` steps of the Keccak-f[1600] permutation on\n        // the passed `StateMatrix` struct memory ptr.\n            function thetaRhoPi(ptr) {\n            // Theta\n                let C0 := xorColumn(ptr, 0)\n                let C1 := xorColumn(ptr, 1)\n                let C2 := xorColumn(ptr, 2)\n                let C3 := xorColumn(ptr, 3)\n                let C4 := xorColumn(ptr, 4)\n                let D0 := xor(xor(shl64(1, C1), shr(63, C1)), C4)\n                let D1 := xor(xor(shl64(1, C2), shr(63, C2)), C0)\n                let D2 := xor(xor(shl64(1, C3), shr(63, C3)), C1)\n                let D3 := xor(xor(shl64(1, C4), shr(63, C4)), C2)\n                let D4 := xor(xor(shl64(1, C0), shr(63, C0)), C3)\n\n                let xs1 := xor(stateElem(ptr, 1), D1)\n                let A1 := xor(shl(1, xs1), shr(63, xs1))\n\n                setStateElem(ptr, 0, xor(stateElem(ptr, 0), D0))\n                rhoPi(ptr, 1, 6, 44, D1)\n                rhoPi(ptr, 6, 9, 20, D4)\n                rhoPi(ptr, 9, 22, 61, D2)\n                rhoPi(ptr, 22, 14, 39, D4)\n                rhoPi(ptr, 14, 20, 18, D0)\n                rhoPi(ptr, 20, 2, 62, D2)\n                rhoPi(ptr, 2, 12, 43, D2)\n                rhoPi(ptr, 12, 13, 25, D3)\n                rhoPi(ptr, 13, 19, 8, D4)\n                rhoPi(ptr, 19, 23, 56, D3)\n                rhoPi(ptr, 23, 15, 41, D0)\n                rhoPi(ptr, 15, 4, 27, D4)\n                rhoPi(ptr, 4, 24, 14, D4)\n                rhoPi(ptr, 24, 21, 2, D1)\n                rhoPi(ptr, 21, 8, 55, D3)\n                rhoPi(ptr, 8, 16, 45, D1)\n                rhoPi(ptr, 16, 5, 36, D0)\n                rhoPi(ptr, 5, 3, 28, D3)\n                rhoPi(ptr, 3, 18, 21, D3)\n                rhoPi(ptr, 18, 17, 15, D2)\n                rhoPi(ptr, 17, 11, 10, D1)\n                rhoPi(ptr, 11, 7, 6, D2)\n                rhoPi(ptr, 7, 10, 3, D0)\n                setStateElem(ptr, 10, A1)\n            }\n\n        // Inner `chi` function, unrolled in `chi` for performance.\n            function innerChi(ptr, start) {\n                let A0 := stateElem(ptr, start)\n                let A1 := stateElem(ptr, add(start, 1))\n                let A2 := stateElem(ptr, add(start, 2))\n                let A3 := stateElem(ptr, add(start, 3))\n                let A4 := stateElem(ptr, add(start, 4))\n\n                setStateElem(ptr, start, xor(A0, and(not(A1), A2)))\n                setStateElem(ptr, add(start, 1), xor(A1, and(not(A2), A3)))\n                setStateElem(ptr, add(start, 2), xor(A2, and(not(A3), A4)))\n                setStateElem(ptr, add(start, 3), xor(A3, and(not(A4), A0)))\n                setStateElem(ptr, add(start, 4), xor(A4, and(not(A0), A1)))\n            }\n\n        // Performs the `chi` step of the Keccak-f[1600] permutation on the passed `StateMatrix` struct memory ptr\n            function chi(ptr) {\n                innerChi(ptr, 0)\n                innerChi(ptr, 5)\n                innerChi(ptr, 10)\n                innerChi(ptr, 15)\n                innerChi(ptr, 20)\n            }\n\n        // Perform the full Keccak-f[1600] permutation on a `StateMatrix` struct memory ptr for a given round.\n            function permute(ptr, roundsPtr, round) {\n            // Theta, Rho, Pi, Chi\n                thetaRhoPi(ptr)\n                chi(ptr)\n            // Iota\n                let roundConst := shr(192, mload(add(roundsPtr, shl(0x03, round))))\n                setStateElem(ptr, 0, xor(stateElem(ptr, 0), roundConst))\n            }\n\n        // Unroll the permutation loop.\n            permute(stateMatrixPtr, rcPtr, 0)\n            permute(stateMatrixPtr, rcPtr, 1)\n            permute(stateMatrixPtr, rcPtr, 2)\n            permute(stateMatrixPtr, rcPtr, 3)\n            permute(stateMatrixPtr, rcPtr, 4)\n            permute(stateMatrixPtr, rcPtr, 5)\n            permute(stateMatrixPtr, rcPtr, 6)\n            permute(stateMatrixPtr, rcPtr, 7)\n            permute(stateMatrixPtr, rcPtr, 8)\n            permute(stateMatrixPtr, rcPtr, 9)\n            permute(stateMatrixPtr, rcPtr, 10)\n            permute(stateMatrixPtr, rcPtr, 11)\n            permute(stateMatrixPtr, rcPtr, 12)\n            permute(stateMatrixPtr, rcPtr, 13)\n            permute(stateMatrixPtr, rcPtr, 14)\n            permute(stateMatrixPtr, rcPtr, 15)\n            permute(stateMatrixPtr, rcPtr, 16)\n            permute(stateMatrixPtr, rcPtr, 17)\n            permute(stateMatrixPtr, rcPtr, 18)\n            permute(stateMatrixPtr, rcPtr, 19)\n            permute(stateMatrixPtr, rcPtr, 20)\n            permute(stateMatrixPtr, rcPtr, 21)\n            permute(stateMatrixPtr, rcPtr, 22)\n            permute(stateMatrixPtr, rcPtr, 23)\n        }\n    }\n\n    /// @notice Absorb a fixed-sized block into the sponge.\n    function absorb(StateMatrix memory _stateMatrix, bytes memory _input) internal pure {\n        assembly {\n        // The input must be 1088 bits long.\n            if iszero(eq(mload(_input), 136)) {revert(0, 0)}\n\n            let dataPtr := add(_input, 0x20)\n            let statePtr := add(_stateMatrix, 0x20)\n\n        // set a state element in the passed `StateMatrix` struct memory ptr.\n            function setStateElem(ptr, idx, data) {\n                mstore(add(ptr, shl(0x05, idx)), and(data, U64_MASK))\n            }\n\n        // fetch a state element from the passed `StateMatrix` struct memory ptr.\n            function stateElem(ptr, idx) -> elem {\n                elem := mload(add(ptr, shl(0x05, idx)))\n            }\n\n        // Inner sha3 absorb XOR function\n            function absorbInner(stateMatrixPtr, inputPtr, idx) {\n                let boWord := mload(add(inputPtr, shl(3, idx)))\n\n                let res :=\n                or(\n                    or(\n                        or(shl(56, byte(7, boWord)), shl(48, byte(6, boWord))),\n                        or(shl(40, byte(5, boWord)), shl(32, byte(4, boWord)))\n                    ),\n                    or(\n                        or(shl(24, byte(3, boWord)), shl(16, byte(2, boWord))),\n                        or(shl(8, byte(1, boWord)), byte(0, boWord))\n                    )\n                )\n                setStateElem(stateMatrixPtr, idx, xor(stateElem(stateMatrixPtr, idx), res))\n            }\n\n        // Unroll the input XOR loop.\n            absorbInner(statePtr, dataPtr, 0)\n            absorbInner(statePtr, dataPtr, 1)\n            absorbInner(statePtr, dataPtr, 2)\n            absorbInner(statePtr, dataPtr, 3)\n            absorbInner(statePtr, dataPtr, 4)\n            absorbInner(statePtr, dataPtr, 5)\n            absorbInner(statePtr, dataPtr, 6)\n            absorbInner(statePtr, dataPtr, 7)\n            absorbInner(statePtr, dataPtr, 8)\n            absorbInner(statePtr, dataPtr, 9)\n            absorbInner(statePtr, dataPtr, 10)\n            absorbInner(statePtr, dataPtr, 11)\n            absorbInner(statePtr, dataPtr, 12)\n            absorbInner(statePtr, dataPtr, 13)\n            absorbInner(statePtr, dataPtr, 14)\n            absorbInner(statePtr, dataPtr, 15)\n            absorbInner(statePtr, dataPtr, 16)\n        }\n    }\n\n    /// @notice Squeezes the final keccak256 digest from the passed `StateMatrix`.\n    function squeeze(StateMatrix memory _stateMatrix) internal pure returns (bytes32 hash_) {\n        assembly {\n        // 64 bit logical shift\n            function shl64(a, b) -> val {\n                val := and(shl(a, b), U64_MASK)\n            }\n\n        // convert a big endian 64-bit value to a little endian 64-bit value.\n            function toLE(beVal) -> leVal {\n                beVal := or(and(shl64(8, beVal), 0xFF00FF00FF00FF00), and(shr(8, beVal), 0x00FF00FF00FF00FF))\n                beVal := or(and(shl64(16, beVal), 0xFFFF0000FFFF0000), and(shr(16, beVal), 0x0000FFFF0000FFFF))\n                leVal := or(shl64(32, beVal), shr(32, beVal))\n            }\n\n        // fetch a state element from the passed `StateMatrix` struct memory ptr.\n            function stateElem(ptr, idx) -> elem {\n                elem := mload(add(ptr, shl(0x05, idx)))\n            }\n\n            let stateMatrixPtr := add(_stateMatrix, 0x20)\n            hash_ :=\n            or(\n                or(shl(192, toLE(stateElem(stateMatrixPtr, 0))), shl(128, toLE(stateElem(stateMatrixPtr, 1)))),\n                or(shl(64, toLE(stateElem(stateMatrixPtr, 2))), toLE(stateElem(stateMatrixPtr, 3)))\n            )\n        }\n    }\n\n    /// @notice Pads input data to an even multiple of the Keccak-f[1600] permutation block size, 1088 bits (136 bytes).\n    function pad(bytes calldata _data) internal pure returns (bytes memory padded_) {\n        assembly {\n            padded_ := mload(0x40)\n\n        // Grab the original length of `_data`\n            let len := _data.length\n\n            let dataPtr := add(padded_, 0x20)\n            let endPtr := add(dataPtr, len)\n\n        // Copy the data into memory.\n            calldatacopy(dataPtr, _data.offset, len)\n\n            let modBlockSize := mod(len, BLOCK_SIZE_BYTES)\n            switch modBlockSize\n            case false {\n            // Clean the full padding block. It is possible that this memory is dirty, since solidity sometimes does\n            // not update the free memory pointer when allocating memory, for example with external calls. To do\n            // this, we read out-of-bounds from the calldata, which will always return 0 bytes.\n                calldatacopy(endPtr, calldatasize(), 0x88)\n\n            // If the input is a perfect multiple of the block size, then we add a full extra block of padding.\n                mstore8(endPtr, 0x01)\n                mstore8(sub(add(endPtr, BLOCK_SIZE_BYTES), 0x01), 0x80)\n\n            // Update the length of the data to include the padding.\n                mstore(padded_, add(len, BLOCK_SIZE_BYTES))\n            }\n            default {\n            // If the input is not a perfect multiple of the block size, then we add a partial block of padding.\n            // This should entail a set bit after the input, followed by as many zero bits as necessary to fill\n            // the block, followed by a single 1 bit in the lowest-order bit of the final block.\n\n                let remaining := sub(BLOCK_SIZE_BYTES, modBlockSize)\n                let newLen := add(len, remaining)\n                let paddedEndPtr := add(dataPtr, newLen)\n\n            // Clean the remainder to ensure that the intermediate data between the padding bits is 0. It is\n            // possible that this memory is dirty, since solidity sometimes does not update the free memory pointer\n            // when allocating memory, for example with external calls. To do this, we read out-of-bounds from the\n            // calldata, which will always return 0 bytes.\n                let partialRemainder := sub(paddedEndPtr, endPtr)\n                calldatacopy(endPtr, calldatasize(), partialRemainder)\n\n            // Store the padding bits.\n                mstore8(sub(paddedEndPtr, 0x01), 0x80)\n                mstore8(endPtr, or(byte(0x00, mload(endPtr)), 0x01))\n\n            // Update the length of the data to include the padding. The length should be a multiple of the\n            // block size after this.\n                mstore(padded_, newLen)\n            }\n\n        // Update the free memory pointer.\n            mstore(0x40, add(padded_, and(add(mload(padded_), 0x3F), not(0x1F))))\n        }\n    }\n\n    /// @notice Pads input data to an even multiple of the Keccak-f[1600] permutation block size, 1088 bits (136 bytes).\n    function padMemory(bytes memory _data) internal pure returns (bytes memory padded_) {\n        assembly {\n            padded_ := mload(0x40)\n\n        // Grab the original length of `_data`\n            let len := mload(_data)\n\n            let dataPtr := add(padded_, 0x20)\n            let endPtr := add(dataPtr, len)\n\n        // Copy the data.\n            let originalDataPtr := add(_data, 0x20)\n            for {let i := 0x00} lt(i, len) {i := add(i, 0x20)} {\n                mstore(add(dataPtr, i), mload(add(originalDataPtr, i)))\n            }\n\n            let modBlockSize := mod(len, BLOCK_SIZE_BYTES)\n            switch modBlockSize\n            case false {\n            // Clean the full padding block. It is possible that this memory is dirty, since solidity sometimes does\n            // not update the free memory pointer when allocating memory, for example with external calls. To do\n            // this, we read out-of-bounds from the calldata, which will always return 0 bytes.\n                calldatacopy(endPtr, calldatasize(), 0x88)\n\n            // If the input is a perfect multiple of the block size, then we add a full extra block of padding.\n                mstore8(sub(add(endPtr, BLOCK_SIZE_BYTES), 0x01), 0x80)\n                mstore8(endPtr, 0x01)\n\n            // Update the length of the data to include the padding.\n                mstore(padded_, add(len, BLOCK_SIZE_BYTES))\n            }\n            default {\n            // If the input is not a perfect multiple of the block size, then we add a partial block of padding.\n            // This should entail a set bit after the input, followed by as many zero bits as necessary to fill\n            // the block, followed by a single 1 bit in the lowest-order bit of the final block.\n\n                let remaining := sub(BLOCK_SIZE_BYTES, modBlockSize)\n                let newLen := add(len, remaining)\n                let paddedEndPtr := add(dataPtr, newLen)\n\n            // Clean the remainder to ensure that the intermediate data between the padding bits is 0. It is\n            // possible that this memory is dirty, since solidity sometimes does not update the free memory pointer\n            // when allocating memory, for example with external calls. To do this, we read out-of-bounds from the\n            // calldata, which will always return 0 bytes.\n                let partialRemainder := sub(paddedEndPtr, endPtr)\n                calldatacopy(endPtr, calldatasize(), partialRemainder)\n\n            // Store the padding bits.\n                mstore8(sub(paddedEndPtr, 0x01), 0x80)\n                mstore8(endPtr, or(byte(0x00, mload(endPtr)), 0x01))\n\n            // Update the length of the data to include the padding. The length should be a multiple of the\n            // block size after this.\n                mstore(padded_, newLen)\n            }\n\n        // Update the free memory pointer.\n            mstore(0x40, add(padded_, and(add(mload(padded_), 0x3F), not(0x1F))))\n        }\n    }\n}\n"
    },
    "contracts/libraries/Encoding.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {Hashing} from \"./Hashing.sol\";\nimport {Types} from \"./Types.sol\";\nimport {Lib_RLPWriter as RLPWriter} from \"./rlp/Lib_RLPWriter.sol\";\n\n/// @title Encoding\n/// @notice Encoding handles Optimism's various different encoding schemes.\nlibrary Encoding {\n    /// @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent\n    ///         to the L2 system. Useful for searching for a deposit in the L2 system. The\n    ///         transaction is prefixed with 0x7e to identify its EIP-2718 type.\n    /// @param _tx User deposit transaction to encode.\n    /// @return RLP encoded L2 deposit transaction.\n    function encodeDepositTransaction(Types.UserDepositTransaction memory _tx) internal pure returns (bytes memory) {\n        bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);\n        bytes[] memory raw = new bytes[](8);\n        raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));\n        raw[1] = RLPWriter.writeAddress(_tx.from);\n        raw[2] = _tx.isCreation ? RLPWriter.writeBytes(\"\") : RLPWriter.writeAddress(_tx.to);\n        raw[3] = RLPWriter.writeUint(_tx.mint);\n        raw[4] = RLPWriter.writeUint(_tx.value);\n        raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));\n        raw[6] = RLPWriter.writeBool(false);\n        raw[7] = RLPWriter.writeBytes(_tx.data);\n        return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));\n    }\n\n    /// @notice Encodes the cross domain message based on the version that is encoded into the\n    ///         message nonce.\n    /// @param _nonce    Message nonce with version encoded into the first two bytes.\n    /// @param _sender   Address of the sender of the message.\n    /// @param _target   Address of the target of the message.\n    /// @param _value    ETH value to send to the target.\n    /// @param _gasLimit Gas limit to use for the message.\n    /// @param _data     Data to send with the message.\n    /// @return Encoded cross domain message.\n    function encodeCrossDomainMessage(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    )\n    internal\n    pure\n    returns (bytes memory)\n    {\n        (, uint16 version) = decodeVersionedNonce(_nonce);\n        if (version == 0) {\n            return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);\n        } else if (version == 1) {\n            return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n        } else {\n            revert(\"Encoding: unknown cross domain message version\");\n        }\n    }\n\n    /// @notice Encodes a cross domain message based on the V0 (legacy) encoding.\n    /// @param _target Address of the target of the message.\n    /// @param _sender Address of the sender of the message.\n    /// @param _data   Data to send with the message.\n    /// @param _nonce  Message nonce.\n    /// @return Encoded cross domain message.\n    function encodeCrossDomainMessageV0(\n        address _target,\n        address _sender,\n        bytes memory _data,\n        uint256 _nonce\n    )\n    internal\n    pure\n    returns (bytes memory)\n    {\n        return abi.encodeWithSignature(\"relayMessage(address,address,bytes,uint256)\", _target, _sender, _data, _nonce);\n    }\n\n    /// @notice Encodes a cross domain message based on the V1 (current) encoding.\n    /// @param _nonce    Message nonce.\n    /// @param _sender   Address of the sender of the message.\n    /// @param _target   Address of the target of the message.\n    /// @param _value    ETH value to send to the target.\n    /// @param _gasLimit Gas limit to use for the message.\n    /// @param _data     Data to send with the message.\n    /// @return Encoded cross domain message.\n    function encodeCrossDomainMessageV1(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    )\n    internal\n    pure\n    returns (bytes memory)\n    {\n        return abi.encodeWithSignature(\n            \"relayMessage(uint256,address,address,uint256,uint256,bytes)\",\n            _nonce,\n            _sender,\n            _target,\n            _value,\n            _gasLimit,\n            _data\n        );\n    }\n\n    /// @notice Adds a version number into the first two bytes of a message nonce.\n    /// @param _nonce   Message nonce to encode into.\n    /// @param _version Version number to encode into the message nonce.\n    /// @return Message nonce with version encoded into the first two bytes.\n    function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {\n        uint256 nonce;\n        assembly {\n            nonce := or(shl(240, _version), _nonce)\n        }\n        return nonce;\n    }\n\n    /// @notice Pulls the version out of a version-encoded nonce.\n    /// @param _nonce Message nonce with version encoded into the first two bytes.\n    /// @return Nonce without encoded version.\n    /// @return Version of the message.\n    function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {\n        uint240 nonce;\n        uint16 version;\n        assembly {\n            nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\n            version := shr(240, _nonce)\n        }\n        return (nonce, version);\n    }\n\n    /// @notice Returns an appropriately encoded call to L1Block.setL1BlockValuesEcotone\n    /// @param baseFeeScalar       L1 base fee Scalar\n    /// @param blobBaseFeeScalar   L1 blob base fee Scalar\n    /// @param sequenceNumber      Number of L2 blocks since epoch start.\n    /// @param timestamp           L1 timestamp.\n    /// @param number              L1 blocknumber.\n    /// @param baseFee             L1 base fee.\n    /// @param blobBaseFee         L1 blob base fee.\n    /// @param hash                L1 blockhash.\n    /// @param batcherHash         Versioned hash to authenticate batcher by.\n    function encodeSetL1BlockValuesEcotone(\n        uint32 baseFeeScalar,\n        uint32 blobBaseFeeScalar,\n        uint64 sequenceNumber,\n        uint64 timestamp,\n        uint64 number,\n        uint256 baseFee,\n        uint256 blobBaseFee,\n        bytes32 hash,\n        bytes32 batcherHash\n    )\n    internal\n    pure\n    returns (bytes memory)\n    {\n        bytes4 functionSignature = bytes4(keccak256(\"setL1BlockValuesEcotone()\"));\n        return abi.encodePacked(\n            functionSignature,\n            baseFeeScalar,\n            blobBaseFeeScalar,\n            sequenceNumber,\n            timestamp,\n            number,\n            baseFee,\n            blobBaseFee,\n            hash,\n            batcherHash\n        );\n    }\n\n    /// @notice Returns an appropriately encoded call to L1Block.setL1BlockValuesInterop\n    /// @param _baseFeeScalar       L1 base fee Scalar\n    /// @param _blobBaseFeeScalar   L1 blob base fee Scalar\n    /// @param _sequenceNumber      Number of L2 blocks since epoch start.\n    /// @param _timestamp           L1 timestamp.\n    /// @param _number              L1 blocknumber.\n    /// @param _baseFee             L1 base fee.\n    /// @param _blobBaseFee         L1 blob base fee.\n    /// @param _hash                L1 blockhash.\n    /// @param _batcherHash         Versioned hash to authenticate batcher by.\n    /// @param _dependencySet       Array of the chain IDs in the interop dependency set.\n    function encodeSetL1BlockValuesInterop(\n        uint32 _baseFeeScalar,\n        uint32 _blobBaseFeeScalar,\n        uint64 _sequenceNumber,\n        uint64 _timestamp,\n        uint64 _number,\n        uint256 _baseFee,\n        uint256 _blobBaseFee,\n        bytes32 _hash,\n        bytes32 _batcherHash,\n        uint256[] memory _dependencySet\n    )\n    internal\n    pure\n    returns (bytes memory)\n    {\n        require(_dependencySet.length <= type(uint8).max, \"Encoding: dependency set length is too large\");\n        // Check that the batcher hash is just the address with 0 padding to the left for version 0.\n        require(uint160(uint256(_batcherHash)) == uint256(_batcherHash), \"Encoding: invalid batcher hash\");\n\n        bytes4 functionSignature = bytes4(keccak256(\"setL1BlockValuesInterop()\"));\n        return abi.encodePacked(\n            functionSignature,\n            _baseFeeScalar,\n            _blobBaseFeeScalar,\n            _sequenceNumber,\n            _timestamp,\n            _number,\n            _baseFee,\n            _blobBaseFee,\n            _hash,\n            _batcherHash,\n            uint8(_dependencySet.length),\n            _dependencySet\n        );\n    }\n}\n"
    },
    "contracts/libraries/errors/CommonErrors.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @notice Error for an unauthorized CALLER.\n    error Unauthorized();\n\n/// @notice Error for when a method is called that only works when using a custom gas token.\n    error OnlyCustomGasToken();\n\n/// @notice Error for when a method is called that only works when NOT using a custom gas token.\n    error NotCustomGasToken();\n\n/// @notice Error for when a transfer via call fails.\n    error TransferFailed();\n"
    },
    "contracts/libraries/Hashing.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {Encoding} from \"./Encoding.sol\";\nimport {Types} from \"./Types.sol\";\n\n/// @title Hashing\n/// @notice Hashing handles Optimism's various different hashing schemes.\nlibrary Hashing {\n    /// @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a\n    ///         given deposit is sent to the L2 system. Useful for searching for a deposit in the L2\n    ///         system.\n    /// @param _tx User deposit transaction to hash.\n    /// @return Hash of the RLP encoded L2 deposit transaction.\n    function hashDepositTransaction(Types.UserDepositTransaction memory _tx) internal pure returns (bytes32) {\n        return keccak256(Encoding.encodeDepositTransaction(_tx));\n    }\n\n    /// @notice Computes the deposit transaction's \"source hash\", a value that guarantees the hash\n    ///         of the L2 transaction that corresponds to a deposit is unique and is\n    ///         deterministically generated from L1 transaction data.\n    /// @param _l1BlockHash Hash of the L1 block where the deposit was included.\n    /// @param _logIndex    The index of the log that created the deposit transaction.\n    /// @return Hash of the deposit transaction's \"source hash\".\n    function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex) internal pure returns (bytes32) {\n        bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));\n        return keccak256(abi.encode(bytes32(0), depositId));\n    }\n\n    /// @notice Hashes the cross domain message based on the version that is encoded into the\n    ///         message nonce.\n    /// @param _nonce    Message nonce with version encoded into the first two bytes.\n    /// @param _sender   Address of the sender of the message.\n    /// @param _target   Address of the target of the message.\n    /// @param _value    ETH value to send to the target.\n    /// @param _gasLimit Gas limit to use for the message.\n    /// @param _data     Data to send with the message.\n    /// @return Hashed cross domain message.\n    function hashCrossDomainMessage(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    )\n    internal\n    pure\n    returns (bytes32)\n    {\n        (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n        if (version == 0) {\n            return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);\n        } else if (version == 1) {\n            return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);\n        } else {\n            revert(\"Hashing: unknown cross domain message version\");\n        }\n    }\n\n    /// @notice Hashes a cross domain message based on the V0 (legacy) encoding.\n    /// @param _target Address of the target of the message.\n    /// @param _sender Address of the sender of the message.\n    /// @param _data   Data to send with the message.\n    /// @param _nonce  Message nonce.\n    /// @return Hashed cross domain message.\n    function hashCrossDomainMessageV0(\n        address _target,\n        address _sender,\n        bytes memory _data,\n        uint256 _nonce\n    )\n    internal\n    pure\n    returns (bytes32)\n    {\n        return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));\n    }\n\n    /// @notice Hashes a cross domain message based on the V1 (current) encoding.\n    /// @param _nonce    Message nonce.\n    /// @param _sender   Address of the sender of the message.\n    /// @param _target   Address of the target of the message.\n    /// @param _value    ETH value to send to the target.\n    /// @param _gasLimit Gas limit to use for the message.\n    /// @param _data     Data to send with the message.\n    /// @return Hashed cross domain message.\n    function hashCrossDomainMessageV1(\n        uint256 _nonce,\n        address _sender,\n        address _target,\n        uint256 _value,\n        uint256 _gasLimit,\n        bytes memory _data\n    )\n    internal\n    pure\n    returns (bytes32)\n    {\n        return keccak256(Encoding.encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data));\n    }\n\n    /// @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract\n    /// @param _tx Withdrawal transaction to hash.\n    /// @return Hashed withdrawal transaction.\n    function hashWithdrawal(Types.WithdrawalTransaction memory _tx) internal pure returns (bytes32) {\n        return keccak256(abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data));\n    }\n\n    /// @notice Hashes the various elements of an output root proof into an output root hash which\n    ///         can be used to check if the proof is valid.\n    /// @param _outputRootProof Output root proof which should hash to an output root.\n    /// @return Hashed output root proof.\n    function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof) internal pure returns (bytes32) {\n        return keccak256(\n            abi.encode(\n                _outputRootProof.version,\n                _outputRootProof.stateRoot,\n                _outputRootProof.messagePasserStorageRoot,\n                _outputRootProof.latestBlockhash\n            )\n        );\n    }\n}\n"
    },
    "contracts/libraries/resolver/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"
    },
    "contracts/libraries/resolver/Lib_AddressResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_AddressManager } from \"./Lib_AddressManager.sol\";\n\n/**\n * @title Lib_AddressResolver\n */\nabstract contract Lib_AddressResolver {\n    /*************\n     * Variables *\n     *************/\n\n    Lib_AddressManager public libAddressManager;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _libAddressManager Address of the Lib_AddressManager.\n     */\n    constructor(address _libAddressManager) {\n        libAddressManager = Lib_AddressManager(_libAddressManager);\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * Resolves the address associated with a given name.\n     * @param _name Name to resolve an address for.\n     * @return Address associated with the given name.\n     */\n    function resolve(string memory _name) public view returns (address) {\n        return libAddressManager.getAddress(_name);\n    }\n}\n"
    },
    "contracts/libraries/resolver/Lib_ResolvedDelegateProxy.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_AddressManager } from \"./Lib_AddressManager.sol\";\n\n/**\n * @title Lib_ResolvedDelegateProxy\n */\ncontract Lib_ResolvedDelegateProxy {\n    /*************\n     * Variables *\n     *************/\n\n    // Using mappings to store fields to avoid overwriting storage slots in the\n    // implementation contract. For example, instead of storing these fields at\n    // storage slot `0` & `1`, they are stored at `keccak256(key + slot)`.\n    // See: https://solidity.readthedocs.io/en/v0.7.0/internals/layout_in_storage.html\n    // NOTE: Do not use this code in your own contract system.\n    //      There is a known flaw in this contract, and we will remove it from the repository\n    //      in the near future. Due to the very limited way that we are using it, this flaw is\n    //      not an issue in our system.\n    mapping(address => string) private implementationName;\n    mapping(address => Lib_AddressManager) private addressManager;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _libAddressManager Address of the Lib_AddressManager.\n     * @param _implementationName implementationName of the contract to proxy to.\n     */\n    constructor(address _libAddressManager, string memory _implementationName) {\n        addressManager[address(this)] = Lib_AddressManager(_libAddressManager);\n        implementationName[address(this)] = _implementationName;\n    }\n\n    /*********************\n     * Fallback Function *\n     *********************/\n\n    fallback() external payable {\n        address target = addressManager[address(this)].getAddress(\n            (implementationName[address(this)])\n        );\n\n        require(target != address(0), \"Target address must be initialized.\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(msg.data);\n\n        if (success == true) {\n            assembly {\n                return(add(returndata, 0x20), mload(returndata))\n            }\n        } else {\n            assembly {\n                revert(add(returndata, 0x20), mload(returndata))\n            }\n        }\n    }\n}\n"
    },
    "contracts/libraries/rlp/Lib_RLPReader.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_RLPReader\n * @dev Adapted from \"RLPReader\" by Hamdi Allam (hamdi.allam97@gmail.com).\n */\nlibrary Lib_RLPReader {\n    /*************\n     * Constants *\n     *************/\n\n    uint256 internal constant MAX_LIST_LENGTH = 32;\n\n    /*********\n     * Enums *\n     *********/\n\n    enum RLPItemType {\n        DATA_ITEM,\n        LIST_ITEM\n    }\n\n    /***********\n     * Structs *\n     ***********/\n\n    struct RLPItem {\n        uint256 length;\n        uint256 ptr;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Converts bytes to a reference to memory position and length.\n     * @param _in Input bytes to convert.\n     * @return Output memory reference.\n     */\n    function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {\n        uint256 ptr;\n        assembly {\n            ptr := add(_in, 32)\n        }\n\n        return RLPItem({ length: _in.length, ptr: ptr });\n    }\n\n    /**\n     * Reads an RLP list value into a list of RLP items.\n     * @param _in RLP list value.\n     * @return Decoded RLP list items.\n     */\n    function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {\n        (uint256 listOffset, , RLPItemType itemType) = _decodeLength(_in);\n\n        require(itemType == RLPItemType.LIST_ITEM, \"Invalid RLP list value.\");\n\n        // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by\n        // writing to the length. Since we can't know the number of RLP items without looping over\n        // the entire input, we'd have to loop twice to accurately size this array. It's easier to\n        // simply set a reasonable maximum list length and decrease the size before we finish.\n        RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH);\n\n        uint256 itemCount = 0;\n        uint256 offset = listOffset;\n        while (offset < _in.length) {\n            require(itemCount < MAX_LIST_LENGTH, \"Provided RLP list exceeds max list length.\");\n\n            (uint256 itemOffset, uint256 itemLength, ) = _decodeLength(\n                RLPItem({ length: _in.length - offset, ptr: _in.ptr + offset })\n            );\n\n            out[itemCount] = RLPItem({ length: itemLength + itemOffset, ptr: _in.ptr + offset });\n\n            itemCount += 1;\n            offset += itemOffset + itemLength;\n        }\n\n        // Decrease the array size to match the actual item count.\n        assembly {\n            mstore(out, itemCount)\n        }\n\n        return out;\n    }\n\n    /**\n     * Reads an RLP list value into a list of RLP items.\n     * @param _in RLP list value.\n     * @return Decoded RLP list items.\n     */\n    function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {\n        return readList(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP bytes value into bytes.\n     * @param _in RLP bytes value.\n     * @return Decoded bytes.\n     */\n    function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n        (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n        require(itemType == RLPItemType.DATA_ITEM, \"Invalid RLP bytes value.\");\n\n        return _copy(_in.ptr, itemOffset, itemLength);\n    }\n\n    /**\n     * Reads an RLP bytes value into bytes.\n     * @param _in RLP bytes value.\n     * @return Decoded bytes.\n     */\n    function readBytes(bytes memory _in) internal pure returns (bytes memory) {\n        return readBytes(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP string value into a string.\n     * @param _in RLP string value.\n     * @return Decoded string.\n     */\n    function readString(RLPItem memory _in) internal pure returns (string memory) {\n        return string(readBytes(_in));\n    }\n\n    /**\n     * Reads an RLP string value into a string.\n     * @param _in RLP string value.\n     * @return Decoded string.\n     */\n    function readString(bytes memory _in) internal pure returns (string memory) {\n        return readString(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP bytes32 value into a bytes32.\n     * @param _in RLP bytes32 value.\n     * @return Decoded bytes32.\n     */\n    function readBytes32(RLPItem memory _in) internal pure returns (bytes32) {\n        require(_in.length <= 33, \"Invalid RLP bytes32 value.\");\n\n        (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n        require(itemType == RLPItemType.DATA_ITEM, \"Invalid RLP bytes32 value.\");\n\n        uint256 ptr = _in.ptr + itemOffset;\n        bytes32 out;\n        assembly {\n            out := mload(ptr)\n\n            // Shift the bytes over to match the item size.\n            if lt(itemLength, 32) {\n                out := div(out, exp(256, sub(32, itemLength)))\n            }\n        }\n\n        return out;\n    }\n\n    /**\n     * Reads an RLP bytes32 value into a bytes32.\n     * @param _in RLP bytes32 value.\n     * @return Decoded bytes32.\n     */\n    function readBytes32(bytes memory _in) internal pure returns (bytes32) {\n        return readBytes32(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP uint256 value into a uint256.\n     * @param _in RLP uint256 value.\n     * @return Decoded uint256.\n     */\n    function readUint256(RLPItem memory _in) internal pure returns (uint256) {\n        return uint256(readBytes32(_in));\n    }\n\n    /**\n     * Reads an RLP uint256 value into a uint256.\n     * @param _in RLP uint256 value.\n     * @return Decoded uint256.\n     */\n    function readUint256(bytes memory _in) internal pure returns (uint256) {\n        return readUint256(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP bool value into a bool.\n     * @param _in RLP bool value.\n     * @return Decoded bool.\n     */\n    function readBool(RLPItem memory _in) internal pure returns (bool) {\n        require(_in.length == 1, \"Invalid RLP boolean value.\");\n\n        uint256 ptr = _in.ptr;\n        uint256 out;\n        assembly {\n            out := byte(0, mload(ptr))\n        }\n\n        require(out == 0 || out == 1, \"Lib_RLPReader: Invalid RLP boolean value, must be 0 or 1\");\n\n        return out != 0;\n    }\n\n    /**\n     * Reads an RLP bool value into a bool.\n     * @param _in RLP bool value.\n     * @return Decoded bool.\n     */\n    function readBool(bytes memory _in) internal pure returns (bool) {\n        return readBool(toRLPItem(_in));\n    }\n\n    /**\n     * Reads an RLP address value into a address.\n     * @param _in RLP address value.\n     * @return Decoded address.\n     */\n    function readAddress(RLPItem memory _in) internal pure returns (address) {\n        if (_in.length == 1) {\n            return address(0);\n        }\n\n        require(_in.length == 21, \"Invalid RLP address value.\");\n\n        return address(uint160(readUint256(_in)));\n    }\n\n    /**\n     * Reads an RLP address value into a address.\n     * @param _in RLP address value.\n     * @return Decoded address.\n     */\n    function readAddress(bytes memory _in) internal pure returns (address) {\n        return readAddress(toRLPItem(_in));\n    }\n\n    /**\n     * Reads the raw bytes of an RLP item.\n     * @param _in RLP item to read.\n     * @return Raw RLP bytes.\n     */\n    function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n        return _copy(_in);\n    }\n\n    /*********************\n     * Private Functions *\n     *********************/\n\n    /**\n     * Decodes the length of an RLP item.\n     * @param _in RLP item to decode.\n     * @return Offset of the encoded data.\n     * @return Length of the encoded data.\n     * @return RLP item type (LIST_ITEM or DATA_ITEM).\n     */\n    function _decodeLength(RLPItem memory _in)\n        private\n        pure\n        returns (\n            uint256,\n            uint256,\n            RLPItemType\n        )\n    {\n        require(_in.length > 0, \"RLP item cannot be null.\");\n\n        uint256 ptr = _in.ptr;\n        uint256 prefix;\n        assembly {\n            prefix := byte(0, mload(ptr))\n        }\n\n        if (prefix <= 0x7f) {\n            // Single byte.\n\n            return (0, 1, RLPItemType.DATA_ITEM);\n        } else if (prefix <= 0xb7) {\n            // Short string.\n\n            uint256 strLen = prefix - 0x80;\n\n            require(_in.length > strLen, \"Invalid RLP short string.\");\n\n            return (1, strLen, RLPItemType.DATA_ITEM);\n        } else if (prefix <= 0xbf) {\n            // Long string.\n            uint256 lenOfStrLen = prefix - 0xb7;\n\n            require(_in.length > lenOfStrLen, \"Invalid RLP long string length.\");\n\n            uint256 strLen;\n            assembly {\n                // Pick out the string length.\n                strLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfStrLen)))\n            }\n\n            require(_in.length > lenOfStrLen + strLen, \"Invalid RLP long string.\");\n\n            return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n        } else if (prefix <= 0xf7) {\n            // Short list.\n            uint256 listLen = prefix - 0xc0;\n\n            require(_in.length > listLen, \"Invalid RLP short list.\");\n\n            return (1, listLen, RLPItemType.LIST_ITEM);\n        } else {\n            // Long list.\n            uint256 lenOfListLen = prefix - 0xf7;\n\n            require(_in.length > lenOfListLen, \"Invalid RLP long list length.\");\n\n            uint256 listLen;\n            assembly {\n                // Pick out the list length.\n                listLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfListLen)))\n            }\n\n            require(_in.length > lenOfListLen + listLen, \"Invalid RLP long list.\");\n\n            return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n        }\n    }\n\n    /**\n     * Copies the bytes from a memory location.\n     * @param _src Pointer to the location to read from.\n     * @param _offset Offset to start reading from.\n     * @param _length Number of bytes to read.\n     * @return Copied bytes.\n     */\n    function _copy(\n        uint256 _src,\n        uint256 _offset,\n        uint256 _length\n    ) private pure returns (bytes memory) {\n        bytes memory out = new bytes(_length);\n        if (out.length == 0) {\n            return out;\n        }\n\n        uint256 src = _src + _offset;\n        uint256 dest;\n        assembly {\n            dest := add(out, 32)\n        }\n\n        // Copy over as many complete words as we can.\n        for (uint256 i = 0; i < _length / 32; i++) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n\n            src += 32;\n            dest += 32;\n        }\n\n        // Pick out the remaining bytes.\n        uint256 mask;\n        unchecked {\n            mask = 256**(32 - (_length % 32)) - 1;\n        }\n\n        assembly {\n            mstore(dest, or(and(mload(src), not(mask)), and(mload(dest), mask)))\n        }\n        return out;\n    }\n\n    /**\n     * Copies an RLP item into bytes.\n     * @param _in RLP item to copy.\n     * @return Copied bytes.\n     */\n    function _copy(RLPItem memory _in) private pure returns (bytes memory) {\n        return _copy(_in.ptr, 0, _in.length);\n    }\n}\n"
    },
    "contracts/libraries/rlp/Lib_RLPWriter.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_RLPWriter\n * @author Bakaoh (with modifications)\n */\nlibrary Lib_RLPWriter {\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * RLP encodes a byte string.\n     * @param _in The byte string to encode.\n     * @return The RLP encoded string in bytes.\n     */\n    function writeBytes(bytes memory _in) internal pure returns (bytes memory) {\n        bytes memory encoded;\n\n        if (_in.length == 1 && uint8(_in[0]) < 128) {\n            encoded = _in;\n        } else {\n            encoded = abi.encodePacked(_writeLength(_in.length, 128), _in);\n        }\n\n        return encoded;\n    }\n\n    /**\n     * RLP encodes a list of RLP encoded byte byte strings.\n     * @param _in The list of RLP encoded byte strings.\n     * @return The RLP encoded list of items in bytes.\n     */\n    function writeList(bytes[] memory _in) internal pure returns (bytes memory) {\n        bytes memory list = _flatten(_in);\n        return abi.encodePacked(_writeLength(list.length, 192), list);\n    }\n\n    /**\n     * RLP encodes a string.\n     * @param _in The string to encode.\n     * @return The RLP encoded string in bytes.\n     */\n    function writeString(string memory _in) internal pure returns (bytes memory) {\n        return writeBytes(bytes(_in));\n    }\n\n    /**\n     * RLP encodes an address.\n     * @param _in The address to encode.\n     * @return The RLP encoded address in bytes.\n     */\n    function writeAddress(address _in) internal pure returns (bytes memory) {\n        return writeBytes(abi.encodePacked(_in));\n    }\n\n    /**\n     * RLP encodes a uint.\n     * @param _in The uint256 to encode.\n     * @return The RLP encoded uint256 in bytes.\n     */\n    function writeUint(uint256 _in) internal pure returns (bytes memory) {\n        return writeBytes(_toBinary(_in));\n    }\n\n    /**\n     * RLP encodes a bool.\n     * @param _in The bool to encode.\n     * @return The RLP encoded bool in bytes.\n     */\n    function writeBool(bool _in) internal pure returns (bytes memory) {\n        bytes memory encoded = new bytes(1);\n        encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));\n        return encoded;\n    }\n\n    /*********************\n     * Private Functions *\n     *********************/\n\n    /**\n     * Encode the first byte, followed by the `len` in binary form if `length` is more than 55.\n     * @param _len The length of the string or the payload.\n     * @param _offset 128 if item is string, 192 if item is list.\n     * @return RLP encoded bytes.\n     */\n    function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {\n        bytes memory encoded;\n\n        if (_len < 56) {\n            encoded = new bytes(1);\n            encoded[0] = bytes1(uint8(_len) + uint8(_offset));\n        } else {\n            uint256 lenLen;\n            uint256 i = 1;\n            while (_len / i != 0) {\n                lenLen++;\n                i *= 256;\n            }\n\n            encoded = new bytes(lenLen + 1);\n            encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);\n            for (i = 1; i <= lenLen; i++) {\n                encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));\n            }\n        }\n\n        return encoded;\n    }\n\n    /**\n     * Encode integer in big endian binary form with no leading zeroes.\n     * @notice TODO: This should be optimized with assembly to save gas costs.\n     * @param _x The integer to encode.\n     * @return RLP encoded bytes.\n     */\n    function _toBinary(uint256 _x) private pure returns (bytes memory) {\n        bytes memory b = abi.encodePacked(_x);\n\n        uint256 i = 0;\n        for (; i < 32; i++) {\n            if (b[i] != 0) {\n                break;\n            }\n        }\n\n        bytes memory res = new bytes(32 - i);\n        for (uint256 j = 0; j < res.length; j++) {\n            res[j] = b[i++];\n        }\n\n        return res;\n    }\n\n    /**\n     * Copies a piece of memory to another location.\n     * @notice From: https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol.\n     * @param _dest Destination location.\n     * @param _src Source location.\n     * @param _len Length of memory to copy.\n     */\n    function _memcpy(\n        uint256 _dest,\n        uint256 _src,\n        uint256 _len\n    ) private pure {\n        uint256 dest = _dest;\n        uint256 src = _src;\n        uint256 len = _len;\n\n        for (; len >= 32; len -= 32) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n            dest += 32;\n            src += 32;\n        }\n\n        uint256 mask;\n        unchecked {\n            mask = 256**(32 - len) - 1;\n        }\n        assembly {\n            let srcpart := and(mload(src), not(mask))\n            let destpart := and(mload(dest), mask)\n            mstore(dest, or(destpart, srcpart))\n        }\n    }\n\n    /**\n     * Flattens a list of byte strings into one byte string.\n     * @notice From: https://github.com/sammayo/solidity-rlp-encoder/blob/master/RLPEncode.sol.\n     * @param _list List of byte strings to flatten.\n     * @return The flattened byte string.\n     */\n    function _flatten(bytes[] memory _list) private pure returns (bytes memory) {\n        if (_list.length == 0) {\n            return new bytes(0);\n        }\n\n        uint256 len;\n        uint256 i = 0;\n        for (; i < _list.length; i++) {\n            len += _list[i].length;\n        }\n\n        bytes memory flattened = new bytes(len);\n        uint256 flattenedPtr;\n        assembly {\n            flattenedPtr := add(flattened, 0x20)\n        }\n\n        for (i = 0; i < _list.length; i++) {\n            bytes memory item = _list[i];\n\n            uint256 listPtr;\n            assembly {\n                listPtr := add(item, 0x20)\n            }\n\n            _memcpy(flattenedPtr, listPtr, item.length);\n            flattenedPtr += _list[i].length;\n        }\n\n        return flattened;\n    }\n}\n"
    },
    "contracts/libraries/Storage.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Storage\n/// @notice Storage handles reading and writing to arbitary storage locations\nlibrary Storage {\n    /// @notice Returns an address stored in an arbitrary storage slot.\n    ///         These storage slots decouple the storage layout from\n    ///         solc's automation.\n    /// @param _slot The storage slot to retrieve the address from.\n    function getAddress(bytes32 _slot) internal view returns (address addr_) {\n        assembly {\n            addr_ := sload(_slot)\n        }\n    }\n\n    /// @notice Stores an address in an arbitrary storage slot, `_slot`.\n    /// @param _slot The storage slot to store the address in.\n    /// @param _address The protocol version to store\n    /// @dev WARNING! This function must be used cautiously, as it allows for overwriting addresses\n    ///      in arbitrary storage slots.\n    function setAddress(bytes32 _slot, address _address) internal {\n        assembly {\n            sstore(_slot, _address)\n        }\n    }\n\n    /// @notice Returns a uint256 stored in an arbitrary storage slot.\n    ///         These storage slots decouple the storage layout from\n    ///         solc's automation.\n    /// @param _slot The storage slot to retrieve the address from.\n    function getUint(bytes32 _slot) internal view returns (uint256 value_) {\n        assembly {\n            value_ := sload(_slot)\n        }\n    }\n\n    /// @notice Stores a value in an arbitrary storage slot, `_slot`.\n    /// @param _slot The storage slot to store the address in.\n    /// @param _value The protocol version to store\n    /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values\n    ///      in arbitrary storage slots.\n    function setUint(bytes32 _slot, uint256 _value) internal {\n        assembly {\n            sstore(_slot, _value)\n        }\n    }\n\n    /// @notice Returns a bytes32 stored in an arbitrary storage slot.\n    ///         These storage slots decouple the storage layout from\n    ///         solc's automation.\n    /// @param _slot The storage slot to retrieve the address from.\n    function getBytes32(bytes32 _slot) internal view returns (bytes32 value_) {\n        assembly {\n            value_ := sload(_slot)\n        }\n    }\n\n    /// @notice Stores a bytes32 value in an arbitrary storage slot, `_slot`.\n    /// @param _slot The storage slot to store the address in.\n    /// @param _value The bytes32 value to store.\n    /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values\n    ///      in arbitrary storage slots.\n    function setBytes32(bytes32 _slot, bytes32 _value) internal {\n        assembly {\n            sstore(_slot, _value)\n        }\n    }\n\n    /// @notice Stores a bool value in an arbitrary storage slot, `_slot`.\n    /// @param _slot The storage slot to store the bool in.\n    /// @param _value The bool value to store\n    /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values\n    ///      in arbitrary storage slots.\n    function setBool(bytes32 _slot, bool _value) internal {\n        assembly {\n            sstore(_slot, _value)\n        }\n    }\n\n    /// @notice Returns a bool stored in an arbitrary storage slot.\n    /// @param _slot The storage slot to retrieve the bool from.\n    function getBool(bytes32 _slot) internal view returns (bool value_) {\n        assembly {\n            value_ := sload(_slot)\n        }\n    }\n}\n"
    },
    "contracts/libraries/trie/Lib_MerkleTrie.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_BytesUtils } from \"../utils/Lib_BytesUtils.sol\";\nimport { Lib_RLPReader } from \"../rlp/Lib_RLPReader.sol\";\nimport { Lib_RLPWriter } from \"../rlp/Lib_RLPWriter.sol\";\n\n/**\n * @title Lib_MerkleTrie\n */\nlibrary Lib_MerkleTrie {\n    /*******************\n     * Data Structures *\n     *******************/\n\n    enum NodeType {\n        BranchNode,\n        ExtensionNode,\n        LeafNode\n    }\n\n    struct TrieNode {\n        bytes encoded;\n        Lib_RLPReader.RLPItem[] decoded;\n    }\n\n    /**********************\n     * Contract Constants *\n     **********************/\n\n    // TREE_RADIX determines the number of elements per branch node.\n    uint256 constant TREE_RADIX = 16;\n    // Branch nodes have TREE_RADIX elements plus an additional `value` slot.\n    uint256 constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n    // Leaf nodes and extension nodes always have two elements, a `path` and a `value`.\n    uint256 constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n    // Prefixes are prepended to the `path` within a leaf or extension node and\n    // allow us to differentiate between the two node types. `ODD` or `EVEN` is\n    // determined by the number of nibbles within the unprefixed `path`. If the\n    // number of nibbles if even, we need to insert an extra padding nibble so\n    // the resulting prefixed `path` has an even number of nibbles.\n    uint8 constant PREFIX_EXTENSION_EVEN = 0;\n    uint8 constant PREFIX_EXTENSION_ODD = 1;\n    uint8 constant PREFIX_LEAF_EVEN = 2;\n    uint8 constant PREFIX_LEAF_ODD = 3;\n\n    // Just a utility constant. RLP represents `NULL` as 0x80.\n    bytes1 constant RLP_NULL = bytes1(0x80);\n    bytes constant RLP_NULL_BYTES = hex\"80\";\n    bytes32 internal constant KECCAK256_RLP_NULL_BYTES = keccak256(RLP_NULL_BYTES);\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * @notice Verifies a proof that a given key/value pair is present in the\n     * Merkle trie.\n     * @param _key Key of the node to search for, as a hex string.\n     * @param _value Value of the node to search for, as a hex string.\n     * @param _proof Merkle trie inclusion proof for the desired node. Unlike\n     * traditional Merkle trees, this proof is executed top-down and consists\n     * of a list of RLP-encoded nodes that make a path down to the target node.\n     * @param _root Known root of the Merkle trie. Used to verify that the\n     * included proof is correctly constructed.\n     * @return _verified `true` if the k/v pair exists in the trie, `false` otherwise.\n     */\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool _verified) {\n        (bool exists, bytes memory value) = get(_key, _proof, _root);\n\n        return (exists && Lib_BytesUtils.equal(_value, value));\n    }\n\n    /**\n     * @notice Updates a Merkle trie and returns a new root hash.\n     * @param _key Key of the node to update, as a hex string.\n     * @param _value Value of the node to update, as a hex string.\n     * @param _proof Merkle trie inclusion proof for the node *nearest* the\n     * target node. If the key exists, we can simply update the value.\n     * Otherwise, we need to modify the trie to handle the new k/v pair.\n     * @param _root Known root of the Merkle trie. Used to verify that the\n     * included proof is correctly constructed.\n     * @return _updatedRoot Root hash of the newly constructed trie.\n     */\n    function update(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bytes32 _updatedRoot) {\n        // Special case when inserting the very first node.\n        if (_root == KECCAK256_RLP_NULL_BYTES) {\n            return getSingleNodeRootHash(_key, _value);\n        }\n\n        TrieNode[] memory proof = _parseProof(_proof);\n        (uint256 pathLength, bytes memory keyRemainder, ) = _walkNodePath(proof, _key, _root);\n        TrieNode[] memory newPath = _getNewPath(proof, pathLength, _key, keyRemainder, _value);\n\n        return _getUpdatedTrieRoot(newPath, _key);\n    }\n\n    /**\n     * @notice Retrieves the value associated with a given key.\n     * @param _key Key to search for, as hex bytes.\n     * @param _proof Merkle trie inclusion proof for the key.\n     * @param _root Known root of the Merkle trie.\n     * @return _exists Whether or not the key exists.\n     * @return _value Value of the key if it exists.\n     */\n    function get(\n        bytes memory _key,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool _exists, bytes memory _value) {\n        TrieNode[] memory proof = _parseProof(_proof);\n        (uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(\n            proof,\n            _key,\n            _root\n        );\n\n        bool exists = keyRemainder.length == 0;\n\n        require(exists || isFinalNode, \"Provided proof is invalid.\");\n\n        bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes(\"\");\n\n        return (exists, value);\n    }\n\n    /**\n     * Computes the root hash for a trie with a single node.\n     * @param _key Key for the single node.\n     * @param _value Value for the single node.\n     * @return _updatedRoot Hash of the trie.\n     */\n    function getSingleNodeRootHash(bytes memory _key, bytes memory _value)\n        internal\n        pure\n        returns (bytes32 _updatedRoot)\n    {\n        return keccak256(_makeLeafNode(Lib_BytesUtils.toNibbles(_key), _value).encoded);\n    }\n\n    /*********************\n     * Private Functions *\n     *********************/\n\n    /**\n     * @notice Walks through a proof using a provided key.\n     * @param _proof Inclusion proof to walk through.\n     * @param _key Key to use for the walk.\n     * @param _root Known root of the trie.\n     * @return _pathLength Length of the final path\n     * @return _keyRemainder Portion of the key remaining after the walk.\n     * @return _isFinalNode Whether or not we've hit a dead end.\n     */\n    function _walkNodePath(\n        TrieNode[] memory _proof,\n        bytes memory _key,\n        bytes32 _root\n    )\n        private\n        pure\n        returns (\n            uint256 _pathLength,\n            bytes memory _keyRemainder,\n            bool _isFinalNode\n        )\n    {\n        uint256 pathLength = 0;\n        bytes memory key = Lib_BytesUtils.toNibbles(_key);\n\n        bytes32 currentNodeID = _root;\n        uint256 currentKeyIndex = 0;\n        uint256 currentKeyIncrement = 0;\n        TrieNode memory currentNode;\n\n        // Proof is top-down, so we start at the first element (root).\n        for (uint256 i = 0; i < _proof.length; i++) {\n            currentNode = _proof[i];\n            currentKeyIndex += currentKeyIncrement;\n\n            // Keep track of the proof elements we actually need.\n            // It's expensive to resize arrays, so this simply reduces gas costs.\n            pathLength += 1;\n\n            if (currentKeyIndex == 0) {\n                // First proof element is always the root node.\n                require(keccak256(currentNode.encoded) == currentNodeID, \"Invalid root hash\");\n            } else if (currentNode.encoded.length >= 32) {\n                // Nodes 32 bytes or larger are hashed inside branch nodes.\n                require(\n                    keccak256(currentNode.encoded) == currentNodeID,\n                    \"Invalid large internal hash\"\n                );\n            } else {\n                // Nodes smaller than 31 bytes aren't hashed.\n                require(\n                    Lib_BytesUtils.toBytes32(currentNode.encoded) == currentNodeID,\n                    \"Invalid internal node hash\"\n                );\n            }\n\n            if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {\n                if (currentKeyIndex == key.length) {\n                    // We've hit the end of the key\n                    // meaning the value should be within this branch node.\n                    break;\n                } else {\n                    // We're not at the end of the key yet.\n                    // Figure out what the next node ID should be and continue.\n                    uint8 branchKey = uint8(key[currentKeyIndex]);\n                    Lib_RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];\n                    currentNodeID = _getNodeID(nextNode);\n                    currentKeyIncrement = 1;\n                    continue;\n                }\n            } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n                bytes memory path = _getNodePath(currentNode);\n                uint8 prefix = uint8(path[0]);\n                uint8 offset = 2 - (prefix % 2);\n                bytes memory pathRemainder = Lib_BytesUtils.slice(path, offset);\n                bytes memory keyRemainder = Lib_BytesUtils.slice(key, currentKeyIndex);\n                uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n                if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n                    if (\n                        pathRemainder.length == sharedNibbleLength &&\n                        keyRemainder.length == sharedNibbleLength\n                    ) {\n                        // The key within this leaf matches our key exactly.\n                        // Increment the key index to reflect that we have no remainder.\n                        currentKeyIndex += sharedNibbleLength;\n                    }\n\n                    // We've hit a leaf node, so our next node should be NULL.\n                    currentNodeID = bytes32(RLP_NULL);\n                    break;\n                } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n                    if (sharedNibbleLength != pathRemainder.length) {\n                        // Our extension node is not identical to the remainder.\n                        // We've hit the end of this path\n                        // updates will need to modify this extension.\n                        currentNodeID = bytes32(RLP_NULL);\n                        break;\n                    } else {\n                        // Our extension shares some nibbles.\n                        // Carry on to the next node.\n                        currentNodeID = _getNodeID(currentNode.decoded[1]);\n                        currentKeyIncrement = sharedNibbleLength;\n                        continue;\n                    }\n                } else {\n                    revert(\"Received a node with an unknown prefix\");\n                }\n            } else {\n                revert(\"Received an unparseable node.\");\n            }\n        }\n\n        // If our node ID is NULL, then we're at a dead end.\n        bool isFinalNode = currentNodeID == bytes32(RLP_NULL);\n        return (pathLength, Lib_BytesUtils.slice(key, currentKeyIndex), isFinalNode);\n    }\n\n    /**\n     * @notice Creates new nodes to support a k/v pair insertion into a given Merkle trie path.\n     * @param _path Path to the node nearest the k/v pair.\n     * @param _pathLength Length of the path. Necessary because the provided path may include\n     *  additional nodes (e.g., it comes directly from a proof) and we can't resize in-memory\n     *  arrays without costly duplication.\n     * @param _key Full original key.\n     * @param _keyRemainder Portion of the initial key that must be inserted into the trie.\n     * @param _value Value to insert at the given key.\n     * @return _newPath A new path with the inserted k/v pair and extra supporting nodes.\n     */\n    function _getNewPath(\n        TrieNode[] memory _path,\n        uint256 _pathLength,\n        bytes memory _key,\n        bytes memory _keyRemainder,\n        bytes memory _value\n    ) private pure returns (TrieNode[] memory _newPath) {\n        bytes memory keyRemainder = _keyRemainder;\n\n        // Most of our logic depends on the status of the last node in the path.\n        TrieNode memory lastNode = _path[_pathLength - 1];\n        NodeType lastNodeType = _getNodeType(lastNode);\n\n        // Create an array for newly created nodes.\n        // We need up to three new nodes, depending on the contents of the last node.\n        // Since array resizing is expensive, we'll keep track of the size manually.\n        // We're using an explicit `totalNewNodes += 1` after insertions for clarity.\n        TrieNode[] memory newNodes = new TrieNode[](3);\n        uint256 totalNewNodes = 0;\n\n        // solhint-disable-next-line max-line-length\n        // Reference: https://github.com/ethereumjs/merkle-patricia-tree/blob/c0a10395aab37d42c175a47114ebfcbd7efcf059/src/baseTrie.ts#L294-L313\n        bool matchLeaf = false;\n        if (lastNodeType == NodeType.LeafNode) {\n            uint256 l = 0;\n            if (_path.length > 0) {\n                for (uint256 i = 0; i < _path.length - 1; i++) {\n                    if (_getNodeType(_path[i]) == NodeType.BranchNode) {\n                        l++;\n                    } else {\n                        l += _getNodeKey(_path[i]).length;\n                    }\n                }\n            }\n\n            if (\n                _getSharedNibbleLength(\n                    _getNodeKey(lastNode),\n                    Lib_BytesUtils.slice(Lib_BytesUtils.toNibbles(_key), l)\n                ) ==\n                _getNodeKey(lastNode).length &&\n                keyRemainder.length == 0\n            ) {\n                matchLeaf = true;\n            }\n        }\n\n        if (matchLeaf) {\n            // We've found a leaf node with the given key.\n            // Simply need to update the value of the node to match.\n            newNodes[totalNewNodes] = _makeLeafNode(_getNodeKey(lastNode), _value);\n            totalNewNodes += 1;\n        } else if (lastNodeType == NodeType.BranchNode) {\n            if (keyRemainder.length == 0) {\n                // We've found a branch node with the given key.\n                // Simply need to update the value of the node to match.\n                newNodes[totalNewNodes] = _editBranchValue(lastNode, _value);\n                totalNewNodes += 1;\n            } else {\n                // We've found a branch node, but it doesn't contain our key.\n                // Reinsert the old branch for now.\n                newNodes[totalNewNodes] = lastNode;\n                totalNewNodes += 1;\n                // Create a new leaf node, slicing our remainder since the first byte points\n                // to our branch node.\n                newNodes[totalNewNodes] = _makeLeafNode(\n                    Lib_BytesUtils.slice(keyRemainder, 1),\n                    _value\n                );\n                totalNewNodes += 1;\n            }\n        } else {\n            // Our last node is either an extension node or a leaf node with a different key.\n            bytes memory lastNodeKey = _getNodeKey(lastNode);\n            uint256 sharedNibbleLength = _getSharedNibbleLength(lastNodeKey, keyRemainder);\n\n            if (sharedNibbleLength != 0) {\n                // We've got some shared nibbles between the last node and our key remainder.\n                // We'll need to insert an extension node that covers these shared nibbles.\n                bytes memory nextNodeKey = Lib_BytesUtils.slice(lastNodeKey, 0, sharedNibbleLength);\n                newNodes[totalNewNodes] = _makeExtensionNode(nextNodeKey, _getNodeHash(_value));\n                totalNewNodes += 1;\n\n                // Cut down the keys since we've just covered these shared nibbles.\n                lastNodeKey = Lib_BytesUtils.slice(lastNodeKey, sharedNibbleLength);\n                keyRemainder = Lib_BytesUtils.slice(keyRemainder, sharedNibbleLength);\n            }\n\n            // Create an empty branch to fill in.\n            TrieNode memory newBranch = _makeEmptyBranchNode();\n\n            if (lastNodeKey.length == 0) {\n                // Key remainder was larger than the key for our last node.\n                // The value within our last node is therefore going to be shifted into\n                // a branch value slot.\n                newBranch = _editBranchValue(newBranch, _getNodeValue(lastNode));\n            } else {\n                // Last node key was larger than the key remainder.\n                // We're going to modify some index of our branch.\n                uint8 branchKey = uint8(lastNodeKey[0]);\n                // Move on to the next nibble.\n                lastNodeKey = Lib_BytesUtils.slice(lastNodeKey, 1);\n\n                if (lastNodeType == NodeType.LeafNode) {\n                    // We're dealing with a leaf node.\n                    // We'll modify the key and insert the old leaf node into the branch index.\n                    TrieNode memory modifiedLastNode = _makeLeafNode(\n                        lastNodeKey,\n                        _getNodeValue(lastNode)\n                    );\n                    newBranch = _editBranchIndex(\n                        newBranch,\n                        branchKey,\n                        _getNodeHash(modifiedLastNode.encoded)\n                    );\n                } else if (lastNodeKey.length != 0) {\n                    // We're dealing with a shrinking extension node.\n                    // We need to modify the node to decrease the size of the key.\n                    TrieNode memory modifiedLastNode = _makeExtensionNode(\n                        lastNodeKey,\n                        _getNodeValue(lastNode)\n                    );\n                    newBranch = _editBranchIndex(\n                        newBranch,\n                        branchKey,\n                        _getNodeHash(modifiedLastNode.encoded)\n                    );\n                } else {\n                    // We're dealing with an unnecessary extension node.\n                    // We're going to delete the node entirely.\n                    // Simply insert its current value into the branch index.\n                    newBranch = _editBranchIndex(newBranch, branchKey, _getNodeValue(lastNode));\n                }\n            }\n\n            if (keyRemainder.length == 0) {\n                // We've got nothing left in the key remainder.\n                // Simply insert the value into the branch value slot.\n                newBranch = _editBranchValue(newBranch, _value);\n                // Push the branch into the list of new nodes.\n                newNodes[totalNewNodes] = newBranch;\n                totalNewNodes += 1;\n            } else {\n                // We've got some key remainder to work with.\n                // We'll be inserting a leaf node into the trie.\n                // First, move on to the next nibble.\n                keyRemainder = Lib_BytesUtils.slice(keyRemainder, 1);\n                // Push the branch into the list of new nodes.\n                newNodes[totalNewNodes] = newBranch;\n                totalNewNodes += 1;\n                // Push a new leaf node for our k/v pair.\n                newNodes[totalNewNodes] = _makeLeafNode(keyRemainder, _value);\n                totalNewNodes += 1;\n            }\n        }\n\n        // Finally, join the old path with our newly created nodes.\n        // Since we're overwriting the last node in the path, we use `_pathLength - 1`.\n        return _joinNodeArrays(_path, _pathLength - 1, newNodes, totalNewNodes);\n    }\n\n    /**\n     * @notice Computes the trie root from a given path.\n     * @param _nodes Path to some k/v pair.\n     * @param _key Key for the k/v pair.\n     * @return _updatedRoot Root hash for the updated trie.\n     */\n    function _getUpdatedTrieRoot(TrieNode[] memory _nodes, bytes memory _key)\n        private\n        pure\n        returns (bytes32 _updatedRoot)\n    {\n        bytes memory key = Lib_BytesUtils.toNibbles(_key);\n\n        // Some variables to keep track of during iteration.\n        TrieNode memory currentNode;\n        NodeType currentNodeType;\n        bytes memory previousNodeHash;\n\n        // Run through the path backwards to rebuild our root hash.\n        for (uint256 i = _nodes.length; i > 0; i--) {\n            // Pick out the current node.\n            currentNode = _nodes[i - 1];\n            currentNodeType = _getNodeType(currentNode);\n\n            if (currentNodeType == NodeType.LeafNode) {\n                // Leaf nodes are already correctly encoded.\n                // Shift the key over to account for the nodes key.\n                bytes memory nodeKey = _getNodeKey(currentNode);\n                key = Lib_BytesUtils.slice(key, 0, key.length - nodeKey.length);\n            } else if (currentNodeType == NodeType.ExtensionNode) {\n                // Shift the key over to account for the nodes key.\n                bytes memory nodeKey = _getNodeKey(currentNode);\n                key = Lib_BytesUtils.slice(key, 0, key.length - nodeKey.length);\n\n                // If this node is the last element in the path, it'll be correctly encoded\n                // and we can skip this part.\n                if (previousNodeHash.length > 0) {\n                    // Re-encode the node based on the previous node.\n                    currentNode = _editExtensionNodeValue(currentNode, previousNodeHash);\n                }\n            } else if (currentNodeType == NodeType.BranchNode) {\n                // If this node is the last element in the path, it'll be correctly encoded\n                // and we can skip this part.\n                if (previousNodeHash.length > 0) {\n                    // Re-encode the node based on the previous node.\n                    uint8 branchKey = uint8(key[key.length - 1]);\n                    key = Lib_BytesUtils.slice(key, 0, key.length - 1);\n                    currentNode = _editBranchIndex(currentNode, branchKey, previousNodeHash);\n                }\n            }\n\n            // Compute the node hash for the next iteration.\n            previousNodeHash = _getNodeHash(currentNode.encoded);\n        }\n\n        // Current node should be the root at this point.\n        // Simply return the hash of its encoding.\n        return keccak256(currentNode.encoded);\n    }\n\n    /**\n     * @notice Parses an RLP-encoded proof into something more useful.\n     * @param _proof RLP-encoded proof to parse.\n     * @return _parsed Proof parsed into easily accessible structs.\n     */\n    function _parseProof(bytes memory _proof) private pure returns (TrieNode[] memory _parsed) {\n        Lib_RLPReader.RLPItem[] memory nodes = Lib_RLPReader.readList(_proof);\n        TrieNode[] memory proof = new TrieNode[](nodes.length);\n\n        for (uint256 i = 0; i < nodes.length; i++) {\n            bytes memory encoded = Lib_RLPReader.readBytes(nodes[i]);\n            proof[i] = TrieNode({ encoded: encoded, decoded: Lib_RLPReader.readList(encoded) });\n        }\n\n        return proof;\n    }\n\n    /**\n     * @notice Picks out the ID for a node. Node ID is referred to as the\n     * \"hash\" within the specification, but nodes < 32 bytes are not actually\n     * hashed.\n     * @param _node Node to pull an ID for.\n     * @return _nodeID ID for the node, depending on the size of its contents.\n     */\n    function _getNodeID(Lib_RLPReader.RLPItem memory _node) private pure returns (bytes32 _nodeID) {\n        bytes memory nodeID;\n\n        if (_node.length < 32) {\n            // Nodes smaller than 32 bytes are RLP encoded.\n            nodeID = Lib_RLPReader.readRawBytes(_node);\n        } else {\n            // Nodes 32 bytes or larger are hashed.\n            nodeID = Lib_RLPReader.readBytes(_node);\n        }\n\n        return Lib_BytesUtils.toBytes32(nodeID);\n    }\n\n    /**\n     * @notice Gets the path for a leaf or extension node.\n     * @param _node Node to get a path for.\n     * @return _path Node path, converted to an array of nibbles.\n     */\n    function _getNodePath(TrieNode memory _node) private pure returns (bytes memory _path) {\n        return Lib_BytesUtils.toNibbles(Lib_RLPReader.readBytes(_node.decoded[0]));\n    }\n\n    /**\n     * @notice Gets the key for a leaf or extension node. Keys are essentially\n     * just paths without any prefix.\n     * @param _node Node to get a key for.\n     * @return _key Node key, converted to an array of nibbles.\n     */\n    function _getNodeKey(TrieNode memory _node) private pure returns (bytes memory _key) {\n        return _removeHexPrefix(_getNodePath(_node));\n    }\n\n    /**\n     * @notice Gets the path for a node.\n     * @param _node Node to get a value for.\n     * @return _value Node value, as hex bytes.\n     */\n    function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory _value) {\n        return Lib_RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]);\n    }\n\n    /**\n     * @notice Computes the node hash for an encoded node. Nodes < 32 bytes\n     * are not hashed, all others are keccak256 hashed.\n     * @param _encoded Encoded node to hash.\n     * @return _hash Hash of the encoded node. Simply the input if < 32 bytes.\n     */\n    function _getNodeHash(bytes memory _encoded) private pure returns (bytes memory _hash) {\n        if (_encoded.length < 32) {\n            return _encoded;\n        } else {\n            return abi.encodePacked(keccak256(_encoded));\n        }\n    }\n\n    /**\n     * @notice Determines the type for a given node.\n     * @param _node Node to determine a type for.\n     * @return _type Type of the node; BranchNode/ExtensionNode/LeafNode.\n     */\n    function _getNodeType(TrieNode memory _node) private pure returns (NodeType _type) {\n        if (_node.decoded.length == BRANCH_NODE_LENGTH) {\n            return NodeType.BranchNode;\n        } else if (_node.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n            bytes memory path = _getNodePath(_node);\n            uint8 prefix = uint8(path[0]);\n\n            if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n                return NodeType.LeafNode;\n            } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n                return NodeType.ExtensionNode;\n            }\n        }\n\n        revert(\"Invalid node type\");\n    }\n\n    /**\n     * @notice Utility; determines the number of nibbles shared between two\n     * nibble arrays.\n     * @param _a First nibble array.\n     * @param _b Second nibble array.\n     * @return _shared Number of shared nibbles.\n     */\n    function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n        private\n        pure\n        returns (uint256 _shared)\n    {\n        uint256 i = 0;\n        while (_a.length > i && _b.length > i && _a[i] == _b[i]) {\n            i++;\n        }\n        return i;\n    }\n\n    /**\n     * @notice Utility; converts an RLP-encoded node into our nice struct.\n     * @param _raw RLP-encoded node to convert.\n     * @return _node Node as a TrieNode struct.\n     */\n    function _makeNode(bytes[] memory _raw) private pure returns (TrieNode memory _node) {\n        bytes memory encoded = Lib_RLPWriter.writeList(_raw);\n\n        return TrieNode({ encoded: encoded, decoded: Lib_RLPReader.readList(encoded) });\n    }\n\n    /**\n     * @notice Utility; converts an RLP-decoded node into our nice struct.\n     * @param _items RLP-decoded node to convert.\n     * @return _node Node as a TrieNode struct.\n     */\n    function _makeNode(Lib_RLPReader.RLPItem[] memory _items)\n        private\n        pure\n        returns (TrieNode memory _node)\n    {\n        bytes[] memory raw = new bytes[](_items.length);\n        for (uint256 i = 0; i < _items.length; i++) {\n            raw[i] = Lib_RLPReader.readRawBytes(_items[i]);\n        }\n        return _makeNode(raw);\n    }\n\n    /**\n     * @notice Creates a new extension node.\n     * @param _key Key for the extension node, unprefixed.\n     * @param _value Value for the extension node.\n     * @return _node New extension node with the given k/v pair.\n     */\n    function _makeExtensionNode(bytes memory _key, bytes memory _value)\n        private\n        pure\n        returns (TrieNode memory _node)\n    {\n        bytes[] memory raw = new bytes[](2);\n        bytes memory key = _addHexPrefix(_key, false);\n        raw[0] = Lib_RLPWriter.writeBytes(Lib_BytesUtils.fromNibbles(key));\n        raw[1] = Lib_RLPWriter.writeBytes(_value);\n        return _makeNode(raw);\n    }\n\n    /**\n     * Creates a new extension node with the same key but a different value.\n     * @param _node Extension node to copy and modify.\n     * @param _value New value for the extension node.\n     * @return New node with the same key and different value.\n     */\n    function _editExtensionNodeValue(TrieNode memory _node, bytes memory _value)\n        private\n        pure\n        returns (TrieNode memory)\n    {\n        bytes[] memory raw = new bytes[](2);\n        bytes memory key = _addHexPrefix(_getNodeKey(_node), false);\n        raw[0] = Lib_RLPWriter.writeBytes(Lib_BytesUtils.fromNibbles(key));\n        if (_value.length < 32) {\n            raw[1] = _value;\n        } else {\n            raw[1] = Lib_RLPWriter.writeBytes(_value);\n        }\n        return _makeNode(raw);\n    }\n\n    /**\n     * @notice Creates a new leaf node.\n     * @dev This function is essentially identical to `_makeExtensionNode`.\n     * Although we could route both to a single method with a flag, it's\n     * more gas efficient to keep them separate and duplicate the logic.\n     * @param _key Key for the leaf node, unprefixed.\n     * @param _value Value for the leaf node.\n     * @return _node New leaf node with the given k/v pair.\n     */\n    function _makeLeafNode(bytes memory _key, bytes memory _value)\n        private\n        pure\n        returns (TrieNode memory _node)\n    {\n        bytes[] memory raw = new bytes[](2);\n        bytes memory key = _addHexPrefix(_key, true);\n        raw[0] = Lib_RLPWriter.writeBytes(Lib_BytesUtils.fromNibbles(key));\n        raw[1] = Lib_RLPWriter.writeBytes(_value);\n        return _makeNode(raw);\n    }\n\n    /**\n     * @notice Creates an empty branch node.\n     * @return _node Empty branch node as a TrieNode struct.\n     */\n    function _makeEmptyBranchNode() private pure returns (TrieNode memory _node) {\n        bytes[] memory raw = new bytes[](BRANCH_NODE_LENGTH);\n        for (uint256 i = 0; i < raw.length; i++) {\n            raw[i] = RLP_NULL_BYTES;\n        }\n        return _makeNode(raw);\n    }\n\n    /**\n     * @notice Modifies the value slot for a given branch.\n     * @param _branch Branch node to modify.\n     * @param _value Value to insert into the branch.\n     * @return _updatedNode Modified branch node.\n     */\n    function _editBranchValue(TrieNode memory _branch, bytes memory _value)\n        private\n        pure\n        returns (TrieNode memory _updatedNode)\n    {\n        bytes memory encoded = Lib_RLPWriter.writeBytes(_value);\n        _branch.decoded[_branch.decoded.length - 1] = Lib_RLPReader.toRLPItem(encoded);\n        return _makeNode(_branch.decoded);\n    }\n\n    /**\n     * @notice Modifies a slot at an index for a given branch.\n     * @param _branch Branch node to modify.\n     * @param _index Slot index to modify.\n     * @param _value Value to insert into the slot.\n     * @return _updatedNode Modified branch node.\n     */\n    function _editBranchIndex(\n        TrieNode memory _branch,\n        uint8 _index,\n        bytes memory _value\n    ) private pure returns (TrieNode memory _updatedNode) {\n        bytes memory encoded = _value.length < 32 ? _value : Lib_RLPWriter.writeBytes(_value);\n        _branch.decoded[_index] = Lib_RLPReader.toRLPItem(encoded);\n        return _makeNode(_branch.decoded);\n    }\n\n    /**\n     * @notice Utility; adds a prefix to a key.\n     * @param _key Key to prefix.\n     * @param _isLeaf Whether or not the key belongs to a leaf.\n     * @return _prefixedKey Prefixed key.\n     */\n    function _addHexPrefix(bytes memory _key, bool _isLeaf)\n        private\n        pure\n        returns (bytes memory _prefixedKey)\n    {\n        uint8 prefix = _isLeaf ? uint8(0x02) : uint8(0x00);\n        uint8 offset = uint8(_key.length % 2);\n        bytes memory prefixed = new bytes(2 - offset);\n        prefixed[0] = bytes1(prefix + offset);\n        return abi.encodePacked(prefixed, _key);\n    }\n\n    /**\n     * @notice Utility; removes a prefix from a path.\n     * @param _path Path to remove the prefix from.\n     * @return _unprefixedKey Unprefixed key.\n     */\n    function _removeHexPrefix(bytes memory _path)\n        private\n        pure\n        returns (bytes memory _unprefixedKey)\n    {\n        if (uint8(_path[0]) % 2 == 0) {\n            return Lib_BytesUtils.slice(_path, 2);\n        } else {\n            return Lib_BytesUtils.slice(_path, 1);\n        }\n    }\n\n    /**\n     * @notice Utility; combines two node arrays. Array lengths are required\n     * because the actual lengths may be longer than the filled lengths.\n     * Array resizing is extremely costly and should be avoided.\n     * @param _a First array to join.\n     * @param _aLength Length of the first array.\n     * @param _b Second array to join.\n     * @param _bLength Length of the second array.\n     * @return _joined Combined node array.\n     */\n    function _joinNodeArrays(\n        TrieNode[] memory _a,\n        uint256 _aLength,\n        TrieNode[] memory _b,\n        uint256 _bLength\n    ) private pure returns (TrieNode[] memory _joined) {\n        TrieNode[] memory ret = new TrieNode[](_aLength + _bLength);\n\n        // Copy elements from the first array.\n        for (uint256 i = 0; i < _aLength; i++) {\n            ret[i] = _a[i];\n        }\n\n        // Copy elements from the second array.\n        for (uint256 i = 0; i < _bLength; i++) {\n            ret[i + _aLength] = _b[i];\n        }\n\n        return ret;\n    }\n}\n"
    },
    "contracts/libraries/trie/Lib_SecureMerkleTrie.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_MerkleTrie } from \"./Lib_MerkleTrie.sol\";\n\n/**\n * @title Lib_SecureMerkleTrie\n */\nlibrary Lib_SecureMerkleTrie {\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * @notice Verifies a proof that a given key/value pair is present in the\n     * Merkle trie.\n     * @param _key Key of the node to search for, as a hex string.\n     * @param _value Value of the node to search for, as a hex string.\n     * @param _proof Merkle trie inclusion proof for the desired node. Unlike\n     * traditional Merkle trees, this proof is executed top-down and consists\n     * of a list of RLP-encoded nodes that make a path down to the target node.\n     * @param _root Known root of the Merkle trie. Used to verify that the\n     * included proof is correctly constructed.\n     * @return _verified `true` if the k/v pair exists in the trie, `false` otherwise.\n     */\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool _verified) {\n        bytes memory key = _getSecureKey(_key);\n        return Lib_MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n    }\n\n    /**\n     * @notice Updates a Merkle trie and returns a new root hash.\n     * @param _key Key of the node to update, as a hex string.\n     * @param _value Value of the node to update, as a hex string.\n     * @param _proof Merkle trie inclusion proof for the node *nearest* the\n     * target node. If the key exists, we can simply update the value.\n     * Otherwise, we need to modify the trie to handle the new k/v pair.\n     * @param _root Known root of the Merkle trie. Used to verify that the\n     * included proof is correctly constructed.\n     * @return _updatedRoot Root hash of the newly constructed trie.\n     */\n    function update(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bytes32 _updatedRoot) {\n        bytes memory key = _getSecureKey(_key);\n        return Lib_MerkleTrie.update(key, _value, _proof, _root);\n    }\n\n    /**\n     * @notice Retrieves the value associated with a given key.\n     * @param _key Key to search for, as hex bytes.\n     * @param _proof Merkle trie inclusion proof for the key.\n     * @param _root Known root of the Merkle trie.\n     * @return _exists Whether or not the key exists.\n     * @return _value Value of the key if it exists.\n     */\n    function get(\n        bytes memory _key,\n        bytes memory _proof,\n        bytes32 _root\n    ) internal pure returns (bool _exists, bytes memory _value) {\n        bytes memory key = _getSecureKey(_key);\n        return Lib_MerkleTrie.get(key, _proof, _root);\n    }\n\n    /**\n     * Computes the root hash for a trie with a single node.\n     * @param _key Key for the single node.\n     * @param _value Value for the single node.\n     * @return _updatedRoot Hash of the trie.\n     */\n    function getSingleNodeRootHash(bytes memory _key, bytes memory _value)\n        internal\n        pure\n        returns (bytes32 _updatedRoot)\n    {\n        bytes memory key = _getSecureKey(_key);\n        return Lib_MerkleTrie.getSingleNodeRootHash(key, _value);\n    }\n\n    /*********************\n     * Private Functions *\n     *********************/\n\n    /**\n     * Computes the secure counterpart to a key.\n     * @param _key Key to get a secure key from.\n     * @return _secureKey Secure version of the key.\n     */\n    function _getSecureKey(bytes memory _key) private pure returns (bytes memory _secureKey) {\n        return abi.encodePacked(keccak256(_key));\n    }\n}\n"
    },
    "contracts/libraries/Types.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Types\n/// @notice Contains various types used throughout the Optimism contract system.\nlibrary Types {\n    /// @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1\n    ///         timestamp that the output root is posted. This timestamp is used to verify that the\n    ///         finalization period has passed since the output root was submitted.\n    /// @custom:field outputRoot    Hash of the L2 output.\n    /// @custom:field timestamp     Timestamp of the L1 block that the output root was submitted in.\n    /// @custom:field l2BlockNumber L2 block number that the output corresponds to.\n    struct OutputProposal {\n        bytes32 outputRoot;\n        uint128 timestamp;\n        uint128 l2BlockNumber;\n    }\n\n    /// @notice Struct representing the elements that are hashed together to generate an output root\n    ///         which itself represents a snapshot of the L2 state.\n    /// @custom:field version                  Version of the output root.\n    /// @custom:field stateRoot                Root of the state trie at the block of this output.\n    /// @custom:field messagePasserStorageRoot Root of the message passer storage trie.\n    /// @custom:field latestBlockhash          Hash of the block this output was generated from.\n    struct OutputRootProof {\n        bytes32 version;\n        bytes32 stateRoot;\n        bytes32 messagePasserStorageRoot;\n        bytes32 latestBlockhash;\n    }\n\n    /// @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end\n    ///         user (as opposed to a system deposit transaction generated by the system).\n    /// @custom:field from        Address of the sender of the transaction.\n    /// @custom:field to          Address of the recipient of the transaction.\n    /// @custom:field isCreation  True if the transaction is a contract creation.\n    /// @custom:field value       Value to send to the recipient.\n    /// @custom:field mint        Amount of ETH to mint.\n    /// @custom:field gasLimit    Gas limit of the transaction.\n    /// @custom:field data        Data of the transaction.\n    /// @custom:field l1BlockHash Hash of the block the transaction was submitted in.\n    /// @custom:field logIndex    Index of the log in the block the transaction was submitted in.\n    struct UserDepositTransaction {\n        address from;\n        address to;\n        bool isCreation;\n        uint256 value;\n        uint256 mint;\n        uint64 gasLimit;\n        bytes data;\n        bytes32 l1BlockHash;\n        uint256 logIndex;\n    }\n\n    /// @notice Struct representing a withdrawal transaction.\n    /// @custom:field nonce    Nonce of the withdrawal transaction\n    /// @custom:field sender   Address of the sender of the transaction.\n    /// @custom:field target   Address of the recipient of the transaction.\n    /// @custom:field value    Value to send to the recipient.\n    /// @custom:field gasLimit Gas limit of the transaction.\n    /// @custom:field data     Data of the transaction.\n    struct WithdrawalTransaction {\n        uint256 nonce;\n        address sender;\n        address target;\n        uint256 value;\n        uint256 gasLimit;\n        bytes data;\n    }\n}\n"
    },
    "contracts/libraries/utils/Lib_Buffer.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_Buffer\n * @dev This library implements a bytes32 storage array with some additional gas-optimized\n * functionality. In particular, it encodes its length as a uint40, and tightly packs this with an\n * overwritable \"extra data\" field so we can store more information with a single SSTORE.\n */\nlibrary Lib_Buffer {\n    /*************\n     * Libraries *\n     *************/\n\n    using Lib_Buffer for Buffer;\n\n    /***********\n     * Structs *\n     ***********/\n\n    struct Buffer {\n        bytes32 context;\n        mapping(uint256 => bytes32) buf;\n    }\n\n    struct BufferContext {\n        // Stores the length of the array. Uint40 is way more elements than we'll ever reasonably\n        // need in an array and we get an extra 27 bytes of extra data to play with.\n        uint40 length;\n        // Arbitrary extra data that can be modified whenever the length is updated. Useful for\n        // squeezing out some gas optimizations.\n        bytes27 extraData;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Pushes a single element to the buffer.\n     * @param _self Buffer to access.\n     * @param _value Value to push to the buffer.\n     * @param _extraData Global extra data.\n     */\n    function push(\n        Buffer storage _self,\n        bytes32 _value,\n        bytes27 _extraData\n    ) internal {\n        BufferContext memory ctx = _self.getContext();\n\n        _self.buf[ctx.length] = _value;\n\n        // Bump the global index and insert our extra data, then save the context.\n        ctx.length++;\n        ctx.extraData = _extraData;\n        _self.setContext(ctx);\n    }\n\n    /**\n     * Pushes a single element to the buffer.\n     * @param _self Buffer to access.\n     * @param _value Value to push to the buffer.\n     */\n    function push(Buffer storage _self, bytes32 _value) internal {\n        BufferContext memory ctx = _self.getContext();\n\n        _self.push(_value, ctx.extraData);\n    }\n\n    /**\n     * Retrieves an element from the buffer.\n     * @param _self Buffer to access.\n     * @param _index Element index to retrieve.\n     * @return Value of the element at the given index.\n     */\n    function get(Buffer storage _self, uint256 _index) internal view returns (bytes32) {\n        BufferContext memory ctx = _self.getContext();\n\n        require(_index < ctx.length, \"Index out of bounds.\");\n\n        return _self.buf[_index];\n    }\n\n    /**\n     * Deletes all elements after (and including) a given index.\n     * @param _self Buffer to access.\n     * @param _index Index of the element to delete from (inclusive).\n     * @param _extraData Optional global extra data.\n     */\n    function deleteElementsAfterInclusive(\n        Buffer storage _self,\n        uint40 _index,\n        bytes27 _extraData\n    ) internal {\n        BufferContext memory ctx = _self.getContext();\n\n        require(_index < ctx.length, \"Index out of bounds.\");\n\n        // Set our length and extra data, save the context.\n        ctx.length = _index;\n        ctx.extraData = _extraData;\n        _self.setContext(ctx);\n    }\n\n    /**\n     * Deletes all elements after (and including) a given index.\n     * @param _self Buffer to access.\n     * @param _index Index of the element to delete from (inclusive).\n     */\n    function deleteElementsAfterInclusive(Buffer storage _self, uint40 _index) internal {\n        BufferContext memory ctx = _self.getContext();\n        _self.deleteElementsAfterInclusive(_index, ctx.extraData);\n    }\n\n    /**\n     * Retrieves the current global index.\n     * @param _self Buffer to access.\n     * @return Current global index.\n     */\n    function getLength(Buffer storage _self) internal view returns (uint40) {\n        BufferContext memory ctx = _self.getContext();\n        return ctx.length;\n    }\n\n    /**\n     * Changes current global extra data.\n     * @param _self Buffer to access.\n     * @param _extraData New global extra data.\n     */\n    function setExtraData(Buffer storage _self, bytes27 _extraData) internal {\n        BufferContext memory ctx = _self.getContext();\n        ctx.extraData = _extraData;\n        _self.setContext(ctx);\n    }\n\n    /**\n     * Retrieves the current global extra data.\n     * @param _self Buffer to access.\n     * @return Current global extra data.\n     */\n    function getExtraData(Buffer storage _self) internal view returns (bytes27) {\n        BufferContext memory ctx = _self.getContext();\n        return ctx.extraData;\n    }\n\n    /**\n     * Sets the current buffer context.\n     * @param _self Buffer to access.\n     * @param _ctx Current buffer context.\n     */\n    function setContext(Buffer storage _self, BufferContext memory _ctx) internal {\n        bytes32 context;\n        uint40 length = _ctx.length;\n        bytes27 extraData = _ctx.extraData;\n        assembly {\n            context := length\n            context := or(context, extraData)\n        }\n\n        if (_self.context != context) {\n            _self.context = context;\n        }\n    }\n\n    /**\n     * Retrieves the current buffer context.\n     * @param _self Buffer to access.\n     * @return Current buffer context.\n     */\n    function getContext(Buffer storage _self) internal view returns (BufferContext memory) {\n        bytes32 context = _self.context;\n        uint40 length;\n        bytes27 extraData;\n        assembly {\n            length := and(\n                context,\n                0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n            )\n            extraData := and(\n                context,\n                0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000\n            )\n        }\n\n        return BufferContext({ length: length, extraData: extraData });\n    }\n\n    /**\n     * set elements for a given index.\n     * @param _self Buffer to access.\n     * @param _index Index of the element to set.\n     * @param _value value to set\n     */\n    function set(\n        Buffer storage _self,\n        uint256 _index,\n        bytes32 _value\n    ) internal {\n        BufferContext memory ctx = _self.getContext();\n        require(_index < ctx.length, \"Index out of bounds.\");\n        _self.buf[_index] = _value;\n    }\n}\n"
    },
    "contracts/libraries/utils/Lib_Bytes32Utils.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_Byte32Utils\n */\nlibrary Lib_Bytes32Utils {\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Converts a bytes32 value to a boolean. Anything non-zero will be converted to \"true.\"\n     * @param _in Input bytes32 value.\n     * @return Bytes32 as a boolean.\n     */\n    function toBool(bytes32 _in) internal pure returns (bool) {\n        return _in != 0;\n    }\n\n    /**\n     * Converts a boolean to a bytes32 value.\n     * @param _in Input boolean value.\n     * @return Boolean as a bytes32.\n     */\n    function fromBool(bool _in) internal pure returns (bytes32) {\n        return bytes32(uint256(_in ? 1 : 0));\n    }\n\n    /**\n     * Converts a bytes32 value to an address. Takes the *last* 20 bytes.\n     * @param _in Input bytes32 value.\n     * @return Bytes32 as an address.\n     */\n    function toAddress(bytes32 _in) internal pure returns (address) {\n        return address(uint160(uint256(_in)));\n    }\n\n    /**\n     * Converts an address to a bytes32.\n     * @param _in Input address value.\n     * @return Address as a bytes32.\n     */\n    function fromAddress(address _in) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(_in)));\n    }\n}\n"
    },
    "contracts/libraries/utils/Lib_BytesUtils.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_BytesUtils\n */\nlibrary Lib_BytesUtils {\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    function slice(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    ) internal pure returns (bytes memory) {\n        require(_length + 31 >= _length, \"slice_overflow\");\n        require(_start + _length >= _start, \"slice_overflow\");\n        require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n\n        bytes memory tempBytes;\n\n        assembly {\n            switch iszero(_length)\n            case 0 {\n                // Get a location of some free memory and store it in tempBytes as\n                // Solidity does for memory variables.\n                tempBytes := mload(0x40)\n\n                // The first word of the slice result is potentially a partial\n                // word read from the original array. To read it, we calculate\n                // the length of that partial word and start copying that many\n                // bytes into the array. The first word we copy will start with\n                // data we don't care about, but the last `lengthmod` bytes will\n                // land at the beginning of the contents of the new array. When\n                // we're done copying, we overwrite the full first word with\n                // the actual length of the slice.\n                let lengthmod := and(_length, 31)\n\n                // The multiplication in the next line is necessary\n                // because when slicing multiples of 32 bytes (lengthmod == 0)\n                // the following copy loop was copying the origin's length\n                // and then ending prematurely not copying everything it should.\n                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n                let end := add(mc, _length)\n\n                for {\n                    // The multiplication in the next line has the same exact purpose\n                    // as the one above.\n                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n                } lt(mc, end) {\n                    mc := add(mc, 0x20)\n                    cc := add(cc, 0x20)\n                } {\n                    mstore(mc, mload(cc))\n                }\n\n                mstore(tempBytes, _length)\n\n                //update free-memory pointer\n                //allocating the array padded to 32 bytes like the compiler does now\n                mstore(0x40, and(add(mc, 31), not(31)))\n            }\n            //if we want a zero-length slice let's just return a zero-length array\n            default {\n                tempBytes := mload(0x40)\n\n                //zero out the 32 bytes slice we are about to return\n                //we need to do it because Solidity does not garbage collect\n                mstore(tempBytes, 0)\n\n                mstore(0x40, add(tempBytes, 0x20))\n            }\n        }\n\n        return tempBytes;\n    }\n\n    function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n        if (_start >= _bytes.length) {\n            return bytes(\"\");\n        }\n\n        return slice(_bytes, _start, _bytes.length - _start);\n    }\n\n    function toBytes32(bytes memory _bytes) internal pure returns (bytes32) {\n        if (_bytes.length < 32) {\n            bytes32 ret;\n            assembly {\n                ret := mload(add(_bytes, 32))\n            }\n            return ret;\n        }\n\n        return abi.decode(_bytes, (bytes32)); // will truncate if input length > 32 bytes\n    }\n\n    function toUint256(bytes memory _bytes) internal pure returns (uint256) {\n        return uint256(toBytes32(_bytes));\n    }\n\n    function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n        bytes memory nibbles = new bytes(_bytes.length * 2);\n\n        for (uint256 i = 0; i < _bytes.length; i++) {\n            nibbles[i * 2] = _bytes[i] >> 4;\n            nibbles[i * 2 + 1] = bytes1(uint8(_bytes[i]) % 16);\n        }\n\n        return nibbles;\n    }\n\n    function fromNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n        bytes memory ret = new bytes(_bytes.length / 2);\n\n        for (uint256 i = 0; i < ret.length; i++) {\n            ret[i] = (_bytes[i * 2] << 4) | (_bytes[i * 2 + 1]);\n        }\n\n        return ret;\n    }\n\n    function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n        return keccak256(_bytes) == keccak256(_other);\n    }\n}\n"
    },
    "contracts/libraries/utils/Lib_MerkleTree.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_MerkleTree\n * @author River Keefer\n */\nlibrary Lib_MerkleTree {\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Calculates a merkle root for a list of 32-byte leaf hashes.  WARNING: If the number\n     * of leaves passed in is not a power of two, it pads out the tree with zero hashes.\n     * If you do not know the original length of elements for the tree you are verifying, then\n     * this may allow empty leaves past _elements.length to pass a verification check down the line.\n     * Note that the _elements argument is modified, therefore it must not be used again afterwards\n     * @param _elements Array of hashes from which to generate a merkle root.\n     * @return Merkle root of the leaves, with zero hashes for non-powers-of-two (see above).\n     */\n    function getMerkleRoot(bytes32[] memory _elements) internal pure returns (bytes32) {\n        require(_elements.length > 0, \"Lib_MerkleTree: Must provide at least one leaf hash.\");\n\n        if (_elements.length == 1) {\n            return _elements[0];\n        }\n\n        uint256[16] memory defaults = [\n            0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563,\n            0x633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d,\n            0x890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d,\n            0x3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd8,\n            0xecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da,\n            0xdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da5,\n            0x617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d7,\n            0x292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead,\n            0xe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e10,\n            0x7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f82,\n            0xe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e83636516,\n            0x3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c,\n            0xad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e,\n            0xa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab,\n            0x4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c862,\n            0x2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf10\n        ];\n\n        // Reserve memory space for our hashes.\n        bytes memory buf = new bytes(64);\n\n        // We'll need to keep track of left and right siblings.\n        bytes32 leftSibling;\n        bytes32 rightSibling;\n\n        // Number of non-empty nodes at the current depth.\n        uint256 rowSize = _elements.length;\n\n        // Current depth, counting from 0 at the leaves\n        uint256 depth = 0;\n\n        // Common sub-expressions\n        uint256 halfRowSize; // rowSize / 2\n        bool rowSizeIsOdd; // rowSize % 2 == 1\n\n        while (rowSize > 1) {\n            halfRowSize = rowSize / 2;\n            rowSizeIsOdd = rowSize % 2 == 1;\n\n            for (uint256 i = 0; i < halfRowSize; i++) {\n                leftSibling = _elements[(2 * i)];\n                rightSibling = _elements[(2 * i) + 1];\n                assembly {\n                    mstore(add(buf, 32), leftSibling)\n                    mstore(add(buf, 64), rightSibling)\n                }\n\n                _elements[i] = keccak256(buf);\n            }\n\n            if (rowSizeIsOdd) {\n                leftSibling = _elements[rowSize - 1];\n                rightSibling = bytes32(defaults[depth]);\n                assembly {\n                    mstore(add(buf, 32), leftSibling)\n                    mstore(add(buf, 64), rightSibling)\n                }\n\n                _elements[halfRowSize] = keccak256(buf);\n            }\n\n            rowSize = halfRowSize + (rowSizeIsOdd ? 1 : 0);\n            depth++;\n        }\n\n        return _elements[0];\n    }\n\n    /**\n     * Verifies a merkle branch for the given leaf hash.  Assumes the original length\n     * of leaves generated is a known, correct input, and does not return true for indices\n     * extending past that index (even if _siblings would be otherwise valid.)\n     * @param _root The Merkle root to verify against.\n     * @param _leaf The leaf hash to verify inclusion of.\n     * @param _index The index in the tree of this leaf.\n     * @param _siblings Array of sibline nodes in the inclusion proof, starting from depth 0\n     * (bottom of the tree).\n     * @param _totalLeaves The total number of leaves originally passed into.\n     * @return Whether or not the merkle branch and leaf passes verification.\n     */\n    function verify(\n        bytes32 _root,\n        bytes32 _leaf,\n        uint256 _index,\n        bytes32[] memory _siblings,\n        uint256 _totalLeaves\n    ) internal pure returns (bool) {\n        require(_totalLeaves > 0, \"Lib_MerkleTree: Total leaves must be greater than zero.\");\n\n        require(_index < _totalLeaves, \"Lib_MerkleTree: Index out of bounds.\");\n\n        require(\n            _siblings.length == _ceilLog2(_totalLeaves),\n            \"Lib_MerkleTree: Total siblings does not correctly correspond to total leaves.\"\n        );\n\n        bytes32 computedRoot = _leaf;\n\n        for (uint256 i = 0; i < _siblings.length; i++) {\n            if ((_index & 1) == 1) {\n                computedRoot = keccak256(abi.encodePacked(_siblings[i], computedRoot));\n            } else {\n                computedRoot = keccak256(abi.encodePacked(computedRoot, _siblings[i]));\n            }\n\n            _index >>= 1;\n        }\n\n        return _root == computedRoot;\n    }\n\n    /*********************\n     * Private Functions *\n     *********************/\n\n    /**\n     * Calculates the integer ceiling of the log base 2 of an input.\n     * @param _in Unsigned input to calculate the log.\n     * @return ceil(log_base_2(_in))\n     */\n    function _ceilLog2(uint256 _in) private pure returns (uint256) {\n        require(_in > 0, \"Lib_MerkleTree: Cannot compute ceil(log_2) of 0.\");\n\n        if (_in == 1) {\n            return 0;\n        }\n\n        // Find the highest set bit (will be floor(log_2)).\n        // Borrowed with <3 from https://github.com/ethereum/solidity-examples\n        uint256 val = _in;\n        uint256 highest = 0;\n        for (uint256 i = 128; i >= 1; i >>= 1) {\n            if (val & (((uint256(1) << i) - 1) << i) != 0) {\n                highest += i;\n                val >>= i;\n            }\n        }\n\n        // Increment by one if this is not a perfect logarithm.\n        if ((uint256(1) << highest) != _in) {\n            highest += 1;\n        }\n\n        return highest;\n    }\n}\n"
    },
    "contracts/libraries/utils/Lib_Uint.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_Uint\n * @author\n */\nlibrary Lib_Uint {\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Convert uint to string\n     * @param _i uint value.\n     * @return _uintAsString string momery value.\n     */\n    function uint2str(uint256 _i) internal pure returns (string memory _uintAsString) {\n        if (_i == 0) {\n            return \"0\";\n        }\n        uint256 j = _i;\n        uint256 len;\n        while (j != 0) {\n            len++;\n            j /= 10;\n        }\n        bytes memory bstr = new bytes(len);\n        uint256 k = len;\n        while (_i != 0) {\n            k = k - 1;\n            uint8 temp = (48 + uint8(_i - (_i / 10) * 10));\n            bytes1 b1 = bytes1(temp);\n            bstr[k] = b1;\n            _i /= 10;\n        }\n        return string(bstr);\n    }\n}\n"
    },
    "contracts/MVM/iMVM_CanonicalTransaction.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Contract Imports */\n\n/* External Imports */\n\n/**\n * @title ICanonicalTransactionChain\n */\ninterface iMVM_CanonicalTransaction {\n    /*********\n     * Enums *\n     *********/\n\n    enum STAKESTATUS {\n        INIT,\n        SEQ_SET,\n        VERIFIER_SET,\n        PAYBACK\n    }\n\n    /**********\n     * Events *\n     **********/\n\n    event VerifierStake(\n        address _sender,\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        uint256 _amount\n    );\n\n    // default : stakeAmount=0, verified=true, sequencer=true\n    // sequencer response for stake: stakeAmount>0, verified=true, sequencer=true\n    // verifier response for stake timeout: stakeAmount>0, verified=false, sequencer=false\n    event SetBatchTxData(\n        address _sender,\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        uint256 _stakeAmount,\n        bool _verified,\n        bool _sequencer\n    );\n\n    event AppendBatchElement(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint40 _shouldStartAtElement,\n        uint24 _totalElementsToAppend,\n        uint256 _txBatchSize,\n        uint256 _txBatchTime,\n        bytes32 _root\n    );\n\n    /***********\n     * Structs *\n     ***********/\n\n    // locker the same sender for 30 min\n    struct TxDataSlice {\n        address sender;\n        uint256 blockNumber;\n        uint256 batchIndex;\n        uint256 timestamp;\n        bytes txData;\n        bool verified;\n    }\n\n    struct TxDataRequestStake {\n        address sender;\n        uint256 blockNumber;\n        uint256 batchIndex;\n        uint256 timestamp;\n        uint256 endtime;\n        uint256 amount;\n        STAKESTATUS status;\n    }\n\n    struct BatchElement {\n        uint40 shouldStartAtElement;\n        uint24 totalElementsToAppend;\n        uint256 txBatchSize;\n        uint256 txBatchTime; // sequencer client encode timestamp(ms)\n        bytes32 root; // merkle hash root with [hash(txDataBytes + blockNumber)]\n        uint256 timestamp; // block timestamp\n    }\n\n    /*******************************\n     * Authorized Setter Functions *\n     *******************************/\n\n    /**\n     * Sets address's chain id.\n     * @param _address contract address.\n     * @param _chainId chain id.\n     */\n    // function setAddressChainId(address _address, uint256 _chainId) external;\n\n    /**\n     * Gets address's chain id.\n     */\n    // function getAddressChainId(address _address) external view returns (uint256);\n\n    /**\n     * Sets the verifier stake base cost of ETH.\n     * @param _stakeBaseCost Stake base cost for verifier.\n     */\n    function setStakeBaseCost(uint256 _stakeBaseCost) external;\n\n    /**\n     * Gets the verifier stake base cost of ETH.\n     */\n    function getStakeBaseCost() external view returns (uint256);\n\n    /**\n     * Sets the verifier stake unit cost of ETH.\n     * @param _stakeUnitCost Stake cost for verifier.\n     */\n    function setStakeUnitCost(uint256 _stakeUnitCost) external;\n\n    /**\n     * Gets the verifier stake unit cost of ETH for per storage unit.\n     */\n    function getStakeUnitCost() external view returns (uint256);\n\n    /**\n     * Gets the verifier stake cost of ETH by batch index.\n     */\n    function getStakeCostByBatch(uint256 _chainId, uint256 _batchIndex)\n        external\n        view\n        returns (uint256);\n\n    /**\n     * Sets batch transaction data slice size per submit.\n     * @param _size Slice size of batch transaction data.\n     */\n    function setTxDataSliceSize(uint256 _size) external;\n\n    /**\n     * Gets batch transaction data slice size per submit.\n     */\n    function getTxDataSliceSize() external view returns (uint256);\n\n    /**\n     * Sets batch size per batch.\n     * @param _size Batch size of batch.\n     */\n    function setTxBatchSize(uint256 _size) external;\n\n    /**\n     * Gets batch size per batch.\n     */\n    function getTxBatchSize() external view returns (uint256);\n\n    /**\n     * Sets slice count per batch transaction data.\n     * @param _count Slice count per batch transaction data.\n     */\n    function setTxDataSliceCount(uint256 _count) external;\n\n    /**\n     * Gets slice count per batch transaction data.\n     */\n    function getTxDataSliceCount() external view returns (uint256);\n\n    /**\n     * Sets seconds can submit transaction data after staking.\n     * @param _seconds Seconds the Sequencer can sumbit transaction data after verifier staking.\n     */\n    function setStakeSeqSeconds(uint256 _seconds) external;\n\n    /**\n     * Gets seconds can submit transaction data after staking.\n     * @return Seconds the Sequencer can sumbit transaction data after verifier staking.\n     */\n    function getStakeSeqSeconds() external view returns (uint256);\n\n    function isWhiteListed(address _verifier) external view returns (bool);\n\n    // add the verifier to the whitelist\n    function setWhiteList(address _verifier, bool _allowed) external;\n\n    // allow everyone to be the verifier\n    function disableWhiteList() external;\n\n    /**\n     * Allows the sequencer to append a batch of transactions.\n     * @dev This function uses a custom encoding scheme for efficiency reasons.\n     */\n    function appendSequencerBatchByChainId() external;\n\n    /**\n     * Sets batch tx data for stake.\n     * @param _chainId chain id.\n     * @param _batchIndex batch index of CTC.\n     * @param _blockNumber slice index.\n     * @param _data tx data hex.\n     */\n    function setBatchTxDataForStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data,\n        uint256 _leafIndex,\n        uint256 _totalLeaves,\n        bytes32[] memory _proof\n    ) external;\n\n    /**\n     * Sets batch tx data for verifier.\n     * @param _chainId chain id.\n     * @param _batchIndex batch index of CTC.\n     * @param _blockNumber slice index.\n     * @param _data tx data hex.\n     */\n    function setBatchTxDataForVerifier(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data\n    ) external;\n\n    /**\n     * Gets batch tx data.\n     * @param _chainId chain id.\n     * @param _batchIndex batch index of CTC.\n     * @param _blockNumber block number.\n     * @return txData\n     * @return verified\n     */\n    function getBatchTxData(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) external view returns (bytes memory txData, bool verified);\n\n    function checkBatchTxHash(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data\n    ) external view returns (bytes32 txHash, bool verified);\n\n    function setBatchTxDataVerified(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bool _verified\n    ) external;\n\n    /**\n     * Stake by verifier.\n     * @param _chainId chain id.\n     * @param _batchIndex batch index of CTC.\n     * @param _blockNumber block number.\n     */\n    function verifierStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) external payable;\n\n    /**\n     * Withdraw stake by verifier.\n     * @param _chainId chain id.\n     * @param _batchIndex batch index of CTC.\n     * @param _blockNumber block number.\n     */\n    function withdrawStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) external;\n}\n"
    },
    "contracts/MVM/iMVM_ChainConfig.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Contract Imports */\n/* External Imports */\ninterface iMVM_ChainConfig {\n    event NewChainConfig(address sender, bytes32 key, bytes value);\n    event NewAccountConfig(address sender, address key, bytes value);\n\n    function setConfig(bytes32 key, bytes calldata values) external;\n\n    function setConfig(bytes calldata values) external;\n\n    function getConfig(bytes32 key) external view returns (bytes memory);\n\n    function getConfig() external view returns (bytes memory);\n}\n"
    },
    "contracts/MVM/iMVM_DiscountOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface iMVM_DiscountOracle {\n    function setDiscount(uint256 _discount) external;\n\n    function setMinL2Gas(uint256 _minL2Gas) external;\n\n    function setWhitelistedXDomainSender(address _sender, bool _isWhitelisted) external;\n\n    function isXDomainSenderAllowed(address _sender) external view returns (bool);\n\n    function setAllowAllXDomainSenders(bool _allowAllXDomainSenders) external;\n\n    function getMinL2Gas() external view returns (uint256);\n\n    function getDiscount() external view returns (uint256);\n\n    function processL2SeqGas(address sender, uint256 _chainId) external payable;\n\n    function withdrawToSeq(uint256 _amount, uint256 _chainId) external;\n}\n"
    },
    "contracts/MVM/iMVM_InboxSenderManager.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface iMVM_InboxSenderManager {\n    enum InboxSenderType {\n        InboxSender,\n        InboxBlobSender\n    }\n\n    struct InboxSender {\n        InboxSenderType senderType;\n        address sender;\n    }\n\n    event InboxSenderSet(uint256 indexed blockNumber, address indexed inboxSender, InboxSenderType indexed inboxSenderType);\n\n    function defaultInboxSender(InboxSenderType senderType) external view returns (address);\n\n    function setInboxSenders(uint256 blockNumber, InboxSender[] calldata _inboxSenders) external;\n\n    function overwriteLastInboxSenders(uint256 blockNumber, InboxSender[] calldata _inboxSenders) external;\n\n    function getInboxSender(uint256 blockNumber, InboxSenderType inboxSenderType) external view returns (address);\n}\n"
    },
    "contracts/MVM/iMVM_L2ChainManagerOnL1.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\npragma experimental ABIEncoderV2;\n\n/* Interface Imports */\n\n/* External Imports */\n\n/**\n * @title MVM_L2ChainManagerOnL1\n * @dev if want support multi l2 chain on l1,it should add a manager to desc\n * how many l2 chain now ,and dispatch the l2 chain id to make it is unique.\n *\n * Compiler used: solc\n * Runtime target: EVM\n */\ninterface iMVM_L2ChainManagerOnL1 {\n    event SwitchSeq(uint256 chainid, address wallet, address manager);\n    event PushConfig(uint256 chainid, bytes configs);\n\n    /********************\n     * Public Functions *\n     ********************/\n    function switchSequencer(\n        uint256 _chainId,\n        address wallet,\n        address manager\n    ) external payable;\n\n    function pushConfig(uint256 _chainId, bytes calldata configs) external payable;\n}\n"
    },
    "contracts/MVM/MVM_CanonicalTransaction.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_AddressResolver } from \"../libraries/resolver/Lib_AddressResolver.sol\";\n\n/* Interface Imports */\nimport { iMVM_CanonicalTransaction } from \"./iMVM_CanonicalTransaction.sol\";\nimport { ICanonicalTransactionChain } from \"../L1/rollup/ICanonicalTransactionChain.sol\";\nimport { IChainStorageContainer } from \"../L1/rollup/IChainStorageContainer.sol\";\nimport { StateCommitmentChain } from \"../L1/rollup/StateCommitmentChain.sol\";\nimport { Lib_MerkleTree } from \"../libraries/utils/Lib_MerkleTree.sol\";\nimport { Lib_Uint } from \"../libraries/utils/Lib_Uint.sol\";\n\ncontract MVM_CanonicalTransaction is iMVM_CanonicalTransaction, Lib_AddressResolver {\n    /*************\n     * Constants *\n     *************/\n\n    string public constant CONFIG_OWNER_KEY = \"METIS_MANAGER\";\n\n    // lock seconds when begin to submit batch tx data slice\n    uint256 public constant TXDATA_SUBMIT_TIMEOUT = 1800;\n\n    /*************\n     * Variables *\n     *************/\n\n    // submit tx data slice size (in bytes)\n    uint256 public txDataSliceSize;\n    // stake duration seconds for sequencer submit batch tx data\n    uint256 public stakeSeqSeconds;\n    // verifier stake base cost for a batch tx data requirement (in ETH)\n    uint256 public stakeBaseCost;\n    // submit tx data slice count (a whole tx batch)\n    uint256 public txDataSliceCount;\n    // submit tx batch size (in bytes)\n    uint256 public txBatchSize;\n    // verifier stake unit cost for a batch tx data requirement (in ETH)\n    uint256 public stakeUnitCost;\n\n    bool useWhiteList;\n\n    /***************\n     * Queue State *\n     ***************/\n\n    // white list\n    mapping(address => bool) public whitelist;\n\n    // mapping(address => uint256) private addressChains;\n\n    // verifier stakes statistic\n    mapping(address => uint256) private verifierStakes;\n\n    // batch element information for validation queue\n    mapping(uint256 => mapping(uint256 => BatchElement)) queueBatchElement;\n\n    // tx data request stake queue\n    mapping(uint256 => mapping(uint256 => TxDataRequestStake)) queueTxDataRequestStake;\n\n    // tx data for verification queue\n    mapping(uint256 => mapping(uint256 => TxDataSlice)) queueTxData;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor() Lib_AddressResolver(address(0)) {}\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    modifier onlyManager() {\n        require(\n            msg.sender == resolve(CONFIG_OWNER_KEY),\n            \"MVM_CanonicalTransaction: Function can only be called by the METIS_MANAGER.\"\n        );\n        _;\n    }\n\n    modifier onlyWhitelisted() {\n        require(isWhiteListed(msg.sender), \"only whitelisted verifiers can call\");\n        _;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n    /**\n    receive() external payable {\n        // msg.sender\n        if (msg.sender == resolve('MVM_DiscountOracle')) {\n            uint256 _chainId = getAddressChainId(msg.sender);\n            if (_chainId > 0) {\n                address _to = resolve(string(abi.encodePacked(Lib_Uint.uint2str(_chainId),\"_MVM_Sequencer_Wrapper\")));\n                if (_to != address(0) && _to != address(this)) {\n                    _to.call{value: msg.value}(\"\");\n                }\n            }\n        }\n    }\n\n    function setAddressChainId(address _address, uint256 _chainId)  override public onlyManager {\n        require(_address != address(0), \"address not available\");\n        require(_chainId > 0, \"chainId not available\");\n        require(addressChains[_address] != _chainId, \"no change\");\n        addressChains[_address] = _chainId;\n    }\n\n    function getAddressChainId(address _address) override public view returns (uint256) {\n        return addressChains[_address];\n    }\n    */\n\n    function setStakeBaseCost(uint256 _stakeBaseCost) public override onlyManager {\n        // 1e16 = 0.01 ether\n        // require(_stakeBaseCost >= 1e16, \"stake base cost should gte 1e16\");\n        stakeBaseCost = _stakeBaseCost;\n    }\n\n    function getStakeBaseCost() public view override returns (uint256) {\n        return stakeBaseCost;\n    }\n\n    function setStakeUnitCost(uint256 _stakeUnitCost) public override onlyManager {\n        // 1e16 = 0.01 ether\n        stakeUnitCost = _stakeUnitCost;\n    }\n\n    function getStakeUnitCost() public view override returns (uint256) {\n        return stakeUnitCost;\n    }\n\n    function getStakeCostByBatch(uint256 _chainId, uint256 _batchIndex)\n        public\n        view\n        override\n        returns (uint256)\n    {\n        require(stakeBaseCost > 0, \"stake base cost not config yet\");\n        require(\n            queueBatchElement[_chainId][_batchIndex].txBatchTime > 0,\n            \"batch element does not exist\"\n        );\n        return stakeBaseCost + queueBatchElement[_chainId][_batchIndex].txBatchSize * stakeUnitCost;\n    }\n\n    function setTxDataSliceSize(uint256 _size) public override onlyManager {\n        require(_size > 0, \"slice size should gt 0\");\n        require(_size != txDataSliceSize, \"slice size has not changed\");\n        txDataSliceSize = _size;\n    }\n\n    function getTxDataSliceSize() public view override returns (uint256) {\n        return txDataSliceSize;\n    }\n\n    function setTxDataSliceCount(uint256 _count) public override onlyManager {\n        require(_count > 0, \"slice count should gt 0\");\n        require(_count != txDataSliceCount, \"slice count has not changed\");\n        txDataSliceCount = _count;\n    }\n\n    function getTxDataSliceCount() public view override returns (uint256) {\n        return txDataSliceCount;\n    }\n\n    function setTxBatchSize(uint256 _size) public override onlyManager {\n        require(_size > 0, \"batch size should gt 0\");\n        require(_size != txBatchSize, \"batch size has not changed\");\n        txBatchSize = _size;\n    }\n\n    function getTxBatchSize() public view override returns (uint256) {\n        return txBatchSize;\n    }\n\n    function setStakeSeqSeconds(uint256 _seconds) public override onlyManager {\n        require(_seconds > 0, \"seconds should gt 0\");\n        require(_seconds != stakeSeqSeconds, \"seconds has not changed\");\n        stakeSeqSeconds = _seconds;\n    }\n\n    function getStakeSeqSeconds() public view override returns (uint256) {\n        return stakeSeqSeconds;\n    }\n\n    function isWhiteListed(address _verifier) public view override returns (bool) {\n        return !useWhiteList || whitelist[_verifier];\n    }\n\n    function setWhiteList(address _verifier, bool _allowed) public override onlyManager {\n        whitelist[_verifier] = _allowed;\n        useWhiteList = true;\n    }\n\n    function disableWhiteList() public override onlyManager {\n        useWhiteList = false;\n    }\n\n    function appendSequencerBatchByChainId() public override {\n        uint256 _chainId;\n        uint40 shouldStartAtElement;\n        uint24 totalElementsToAppend;\n        uint24 numContexts;\n        uint256 batchTime;\n        uint256 _dataSize;\n        uint256 txSize;\n        bytes32 root;\n        assembly {\n            _dataSize := calldatasize()\n            _chainId := calldataload(4)\n            shouldStartAtElement := shr(216, calldataload(36))\n            totalElementsToAppend := shr(232, calldataload(41))\n            numContexts := shr(232, calldataload(44))\n        }\n        require(\n            msg.sender ==\n                resolve(\n                    string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Sequencer_Wrapper\"))\n                ),\n            \"Function can only be called by the Sequencer.\"\n        );\n        uint256 posTs = 47 + 16 * numContexts;\n        if (_dataSize > posTs) {\n            // when tx count = 0, there is no hash!\n            // string len: [13]{milliseconds}-[1]{0}-[8]{sizeOfData}-[64]{hash}-[64]{root}\n            uint256 posTxSize = 7 + posTs;\n            uint256 posRoot = 11 + posTs;\n            assembly {\n                batchTime := shr(204, calldataload(posTs))\n                txSize := shr(224, calldataload(posTxSize))\n                root := calldataload(posRoot)\n            }\n\n            // check batch size\n            require(txSize / 2 <= txBatchSize, \"size of tx data is too large\");\n        }\n\n        address ctc = resolve(\"CanonicalTransactionChain\");\n        IChainStorageContainer batchesRef = ICanonicalTransactionChain(ctc).batches();\n        uint256 batchIndex = batchesRef.lengthByChainId(_chainId);\n        {\n            // ctc call\n            (bool success, bytes memory result) = ctc.call(msg.data);\n            if (success == false) {\n                assembly {\n                    let ptr := mload(0x40)\n                    let size := returndatasize()\n                    returndatacopy(ptr, 0, size)\n                    revert(ptr, size)\n                }\n            }\n        }\n\n        // save\n        queueBatchElement[_chainId][batchIndex] = BatchElement({\n            shouldStartAtElement: shouldStartAtElement,\n            totalElementsToAppend: totalElementsToAppend,\n            txBatchSize: txSize,\n            txBatchTime: batchTime,\n            root: root,\n            timestamp: block.timestamp\n        });\n\n        emit AppendBatchElement(\n            _chainId,\n            batchIndex,\n            shouldStartAtElement,\n            totalElementsToAppend,\n            txSize,\n            batchTime,\n            root\n        );\n    }\n\n    function setBatchTxDataForStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data,\n        uint256 _leafIndex,\n        uint256 _totalLeaves,\n        bytes32[] memory _proof\n    ) public override {\n        require(\n            msg.sender ==\n                resolve(\n                    string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Sequencer_Wrapper\"))\n                ),\n            \"Function can only be called by the Sequencer.\"\n        );\n        // check stake\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].timestamp > 0,\n            \"there is no stake for this block number\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].batchIndex == _batchIndex,\n            \"incorrect batch index\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.INIT,\n            \"not allowed to submit\"\n        );\n        // sequencer can submit at any time\n        // require(queueTxDataRequestStake[_chainId][_blockNumber].endtime >= block.timestamp, \"can not submit out of sequencer submit protection\");\n\n        _setBatchTxData(\n            _chainId,\n            _batchIndex,\n            _blockNumber,\n            _data,\n            _leafIndex,\n            _totalLeaves,\n            _proof,\n            true\n        );\n\n        if (queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.INIT) {\n            require(\n                queueTxDataRequestStake[_chainId][_blockNumber].amount <=\n                    verifierStakes[queueTxDataRequestStake[_chainId][_blockNumber].sender],\n                \"insufficient stake\"\n            );\n            require(\n                queueTxDataRequestStake[_chainId][_blockNumber].amount <= address(this).balance,\n                \"insufficient balance\"\n            );\n            queueTxDataRequestStake[_chainId][_blockNumber].status = STAKESTATUS.SEQ_SET;\n            if (queueTxDataRequestStake[_chainId][_blockNumber].amount > 0) {\n                verifierStakes[\n                    queueTxDataRequestStake[_chainId][_blockNumber].sender\n                ] -= queueTxDataRequestStake[_chainId][_blockNumber].amount;\n                // transfer from contract to sender ETHER and record\n                (bool success, ) = payable(msg.sender).call{\n                    value: queueTxDataRequestStake[_chainId][_blockNumber].amount\n                }(\"\");\n                require(success, \"insufficient balance\");\n                queueTxDataRequestStake[_chainId][_blockNumber].amount = 0;\n            }\n        }\n\n        emit SetBatchTxData(\n            msg.sender,\n            _chainId,\n            _batchIndex,\n            _blockNumber,\n            queueTxDataRequestStake[_chainId][_blockNumber].amount,\n            true,\n            true\n        );\n    }\n\n    function setBatchTxDataForVerifier(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data\n    ) public override {\n        require(\n            msg.sender !=\n                resolve(\n                    string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Sequencer_Wrapper\"))\n                ),\n            \"Function can not be called by the Sequencer.\"\n        );\n        // check stake\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].timestamp > 0,\n            \"there is no stake for this block number\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].batchIndex == _batchIndex,\n            \"incorrect batch index\"\n        );\n        // require(queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.INIT, \"not allowed to submit\");\n        // require(queueTxDataRequestStake[_chainId][_blockNumber].sender == msg.sender, \"can not submit with other's stake\");\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].endtime < block.timestamp,\n            \"can not submit during sequencer submit protection\"\n        );\n        if (queueTxDataRequestStake[_chainId][_blockNumber].sender != msg.sender) {\n            // other verifier can submit in double window times\n            require(\n                queueTxDataRequestStake[_chainId][_blockNumber].endtime + stakeSeqSeconds <\n                    block.timestamp,\n                \"can not submit during staker submit protection\"\n            );\n        }\n\n        _setBatchTxData(_chainId, _batchIndex, _blockNumber, _data, 0, 0, new bytes32[](0), false);\n\n        if (queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.INIT) {\n            queueTxDataRequestStake[_chainId][_blockNumber].status = STAKESTATUS.VERIFIER_SET;\n\n            address claimer = queueTxDataRequestStake[_chainId][_blockNumber].sender;\n            if (\n                queueTxDataRequestStake[_chainId][_blockNumber].amount <= verifierStakes[claimer] &&\n                queueTxDataRequestStake[_chainId][_blockNumber].amount > 0\n            ) {\n                require(\n                    queueTxDataRequestStake[_chainId][_blockNumber].amount <= address(this).balance,\n                    \"insufficient balance\"\n                );\n                verifierStakes[claimer] -= queueTxDataRequestStake[_chainId][_blockNumber].amount;\n                // transfer from contract to sender ETHER and record\n                (bool success, ) = payable(claimer).call{\n                    value: queueTxDataRequestStake[_chainId][_blockNumber].amount\n                }(\"\");\n                require(success, \"insufficient balance\");\n                queueTxDataRequestStake[_chainId][_blockNumber].amount = 0;\n            }\n        }\n\n        emit SetBatchTxData(\n            msg.sender,\n            _chainId,\n            _batchIndex,\n            _blockNumber,\n            queueTxDataRequestStake[_chainId][_blockNumber].amount,\n            false,\n            false\n        );\n    }\n\n    function _setBatchTxData(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data,\n        uint256 _leafIndex,\n        uint256 _totalLeaves,\n        bytes32[] memory _proof,\n        bool _requireVerify\n    ) internal {\n        require(_data.length > 0, \"empty data\");\n        // check queue BatchElement\n        require(\n            queueBatchElement[_chainId][_batchIndex].txBatchTime > 0,\n            \"batch element does not exist\"\n        );\n        require(\n            queueBatchElement[_chainId][_batchIndex].totalElementsToAppend > 0,\n            \"batch total element to append should not be zero\"\n        );\n\n        // sequencer protect\n        if (queueTxData[_chainId][_blockNumber].timestamp > 0) {\n            require(queueTxData[_chainId][_blockNumber].verified == false, \"tx data verified\");\n            if (queueTxData[_chainId][_blockNumber].sender != msg.sender) {\n                require(\n                    queueTxData[_chainId][_blockNumber].timestamp + TXDATA_SUBMIT_TIMEOUT >\n                        block.timestamp,\n                    \"in submitting\"\n                );\n\n                // change sumbitter\n                queueTxData[_chainId][_blockNumber].sender = msg.sender;\n                queueTxData[_chainId][_blockNumber].blockNumber = _blockNumber;\n                queueTxData[_chainId][_blockNumber].batchIndex = _batchIndex;\n                queueTxData[_chainId][_blockNumber].timestamp = block.timestamp;\n                queueTxData[_chainId][_blockNumber].txData = _data;\n                queueTxData[_chainId][_blockNumber].verified = false;\n            } else {\n                queueTxData[_chainId][_blockNumber].txData = _data;\n                // verified restore to false\n                queueTxData[_chainId][_blockNumber].verified = false;\n            }\n        } else {\n            queueTxData[_chainId][_blockNumber] = TxDataSlice({\n                sender: msg.sender,\n                blockNumber: _blockNumber,\n                batchIndex: _batchIndex,\n                timestamp: block.timestamp,\n                txData: _data,\n                verified: false\n            });\n        }\n        if (_requireVerify) {\n            bytes32 currLeaf = keccak256(abi.encodePacked(_blockNumber, _data));\n            bool verified = Lib_MerkleTree.verify(\n                queueBatchElement[_chainId][_batchIndex].root,\n                currLeaf,\n                _leafIndex,\n                _proof,\n                _totalLeaves\n            );\n            require(verified == true, \"tx data verify failed\");\n\n            // save verified status\n            queueTxData[_chainId][_blockNumber].verified = true;\n        }\n    }\n\n    function getBatchTxData(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) external view override returns (bytes memory txData, bool verified) {\n        require(queueTxData[_chainId][_blockNumber].timestamp != 0, \"tx data does not exist\");\n        require(\n            queueTxData[_chainId][_blockNumber].batchIndex == _batchIndex,\n            \"incorrect batch index\"\n        );\n        return (\n            queueTxData[_chainId][_blockNumber].txData,\n            queueTxData[_chainId][_blockNumber].verified\n        );\n    }\n\n    function checkBatchTxHash(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bytes memory _data\n    ) external view override returns (bytes32 txHash, bool verified) {\n        require(queueTxData[_chainId][_blockNumber].timestamp != 0, \"tx data does not exist\");\n        require(\n            queueTxData[_chainId][_blockNumber].batchIndex == _batchIndex,\n            \"incorrect batch index\"\n        );\n        return (\n            keccak256(abi.encodePacked(_blockNumber, _data)),\n            queueTxData[_chainId][_blockNumber].verified\n        );\n    }\n\n    function setBatchTxDataVerified(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber,\n        bool _verified\n    ) public override onlyManager {\n        require(queueTxData[_chainId][_blockNumber].timestamp != 0, \"tx data does not exist\");\n        require(\n            queueTxData[_chainId][_blockNumber].batchIndex == _batchIndex,\n            \"incorrect batch index\"\n        );\n        require(\n            queueTxData[_chainId][_blockNumber].verified != _verified,\n            \"verified status not change\"\n        );\n\n        queueTxData[_chainId][_blockNumber].verified = _verified;\n    }\n\n    function verifierStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) public payable override onlyWhitelisted {\n        uint256 _amount = msg.value;\n        uint256 stakeCost = getStakeCostByBatch(_chainId, _batchIndex);\n        require(stakeBaseCost > 0, \"stake base cost not config yet\");\n        require(stakeCost == _amount, \"stake cost incorrect\");\n        require(stakeSeqSeconds > 0, \"sequencer submit seconds not config yet\");\n        // check queue BatchElement\n        require(\n            queueBatchElement[_chainId][_batchIndex].txBatchTime > 0,\n            \"batch element does not exist\"\n        );\n        // check block number in batch range, block number = index + 1\n        require(\n            queueBatchElement[_chainId][_batchIndex].totalElementsToAppend +\n                queueBatchElement[_chainId][_batchIndex].shouldStartAtElement >=\n                _blockNumber &&\n                queueBatchElement[_chainId][_batchIndex].shouldStartAtElement < _blockNumber,\n            \"block number is not in this batch\"\n        );\n        if (queueTxDataRequestStake[_chainId][_blockNumber].timestamp > 0) {\n            require(\n                queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.PAYBACK,\n                \"there is a stake for this batch index\"\n            );\n        }\n\n        //check window\n        StateCommitmentChain stateChain = StateCommitmentChain(resolve(\"StateCommitmentChain\"));\n        require(\n            queueBatchElement[_chainId][_batchIndex].timestamp + stateChain.FRAUD_PROOF_WINDOW() >\n                block.timestamp,\n            \"the batch is outside of the fraud proof window\"\n        );\n\n        queueTxDataRequestStake[_chainId][_blockNumber] = TxDataRequestStake({\n            sender: msg.sender,\n            blockNumber: _blockNumber,\n            batchIndex: _batchIndex,\n            timestamp: block.timestamp,\n            endtime: block.timestamp + stakeSeqSeconds,\n            amount: _amount,\n            status: STAKESTATUS.INIT\n        });\n        verifierStakes[msg.sender] += _amount;\n\n        emit VerifierStake(msg.sender, _chainId, _batchIndex, _blockNumber, _amount);\n    }\n\n    function withdrawStake(\n        uint256 _chainId,\n        uint256 _batchIndex,\n        uint256 _blockNumber\n    ) public override {\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].timestamp > 0,\n            \"there is no stake for this batch index\"\n        );\n        require(queueTxDataRequestStake[_chainId][_blockNumber].amount > 0, \"stake amount is zero\");\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].status == STAKESTATUS.INIT,\n            \"withdrawals are not allowed\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].sender == msg.sender,\n            \"can not withdraw other's stake\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].endtime < block.timestamp,\n            \"can not withdraw during submit protection\"\n        );\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].amount <= verifierStakes[msg.sender],\n            \"insufficient stake\"\n        );\n\n        require(\n            queueTxDataRequestStake[_chainId][_blockNumber].amount <= address(this).balance,\n            \"insufficient balance\"\n        );\n        queueTxDataRequestStake[_chainId][_blockNumber].status = STAKESTATUS.PAYBACK;\n        verifierStakes[msg.sender] -= queueTxDataRequestStake[_chainId][_blockNumber].amount;\n        // transfer from contract to sender ETHER and record\n        (bool success, ) = payable(msg.sender).call{\n            value: queueTxDataRequestStake[_chainId][_blockNumber].amount\n        }(\"\");\n        require(success, \"insufficient balance\");\n        queueTxDataRequestStake[_chainId][_blockNumber].amount = 0;\n    }\n}\n"
    },
    "contracts/MVM/MVM_ChainConfig.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\nimport { iMVM_ChainConfig } from \"./iMVM_ChainConfig.sol\";\n\n/* Contract Imports */\n/* External Imports */\ncontract MVM_ChainConfig is iMVM_ChainConfig {\n    bytes32 public constant DAC_NAME = keccak256(\"DAC_NAME\");\n    bytes32 public constant DAC_CHARTER = keccak256(\"DAC_CHARTER\");\n\n    // Current l2 gas price\n    mapping(bytes32 => bytes) public config;\n    mapping(address => bytes) public account_config;\n\n    constructor() {}\n\n    function setConfig(bytes32 key, bytes calldata values) public {\n        if (config[key].length == 0) {\n            config[key] = values;\n            emit NewChainConfig(msg.sender, key, values);\n        }\n    }\n\n    function setConfig(bytes calldata values) public {\n        account_config[msg.sender] = values;\n        emit NewAccountConfig(msg.sender, msg.sender, values);\n    }\n\n    function getConfig(bytes32 key) public view returns (bytes memory) {\n        return config[key];\n    }\n\n    function getConfig() public view returns (bytes memory) {\n        return account_config[msg.sender];\n    }\n}\n"
    },
    "contracts/MVM/MVM_Coinbase.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_PredeployAddresses } from \"../libraries/constants/Lib_PredeployAddresses.sol\";\n\n/* Contract Imports */\nimport { L2StandardERC20 } from \"../standards/L2StandardERC20.sol\";\n\n/**\n * @title OVM_ETH\n * @dev The ETH predeploy provides an ERC20 interface for ETH deposited to Layer 2. Note that\n * unlike on Layer 1, Layer 2 accounts do not have a balance field.\n *\n * Runtime target: OVM\n */\ncontract MVM_Coinbase is L2StandardERC20 {\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor()\n        L2StandardERC20(\n            Lib_PredeployAddresses.L2_STANDARD_BRIDGE,\n            address(0),\n            \"Metis Token\",\n            \"Metis\"\n        )\n    {}\n}\n"
    },
    "contracts/MVM/MVM_DiscountOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n/* Contract Imports */\n/* External Imports */\n\nimport { iMVM_DiscountOracle } from \"./iMVM_DiscountOracle.sol\";\nimport { Lib_AddressResolver } from \"../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_Uint } from \"../libraries/utils/Lib_Uint.sol\";\n\ncontract MVM_DiscountOracle is iMVM_DiscountOracle, Lib_AddressResolver {\n    // Current l2 gas price\n    uint256 public discount;\n    uint256 public minL2Gas;\n    mapping(address => bool) public xDomainWL;\n    mapping(uint256 => uint256) public l2ChainSeqGas;\n    bool public allowAllXDomainSenders;\n    string public constant CONFIG_OWNER_KEY = \"METIS_MANAGER\";\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    modifier onlyManager() {\n        require(\n            msg.sender == resolve(CONFIG_OWNER_KEY),\n            \"MVM_DiscountOracle: Function can only be called by the METIS_MANAGER.\"\n        );\n        _;\n    }\n\n    constructor(address _addressManager, uint256 _initialDiscount)\n        Lib_AddressResolver(_addressManager)\n    {\n        discount = _initialDiscount;\n        minL2Gas = 200_000;\n        allowAllXDomainSenders = false;\n    }\n\n    function getMinL2Gas() public view override returns (uint256) {\n        return minL2Gas;\n    }\n\n    function getDiscount() public view override returns (uint256) {\n        return discount;\n    }\n\n    function setDiscount(uint256 _discount) public override onlyManager {\n        discount = _discount;\n    }\n\n    function setMinL2Gas(uint256 _minL2Gas) public override onlyManager {\n        minL2Gas = _minL2Gas;\n    }\n\n    function setWhitelistedXDomainSender(address _sender, bool _isWhitelisted)\n        external\n        override\n        onlyManager\n    {\n        xDomainWL[_sender] = _isWhitelisted;\n    }\n\n    function isXDomainSenderAllowed(address _sender) public view override returns (bool) {\n        return (allowAllXDomainSenders || xDomainWL[_sender]);\n    }\n\n    function setAllowAllXDomainSenders(bool _allowAllXDomainSenders) public override onlyManager {\n        allowAllXDomainSenders = _allowAllXDomainSenders;\n    }\n\n    function processL2SeqGas(address sender, uint256 _chainId) public payable override {\n        require(isXDomainSenderAllowed(sender), \"sender is not whitelisted\");\n        require(_chainId > 0, \"incorrect chainId\");\n        l2ChainSeqGas[_chainId] += msg.value;\n    }\n\n    function withdrawToSeq(uint256 _amount, uint256 _chainId) public override onlyManager {\n        require(_amount > 0, \"incorrect amount\");\n        require(_amount <= address(this).balance, \"insufficient balance\");\n        require(_chainId > 0, \"incorrect chainId\");\n        require(_amount <= l2ChainSeqGas[_chainId], \"this chain sequencer gas is not enough\");\n        address _to = resolve(\n            string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_Sequencer_Wrapper\"))\n        );\n        require(_to != address(0) && _to != address(this), \"unknown sequencer address\");\n        l2ChainSeqGas[_chainId] -= _amount;\n        (bool success, ) = _to.call{ value: _amount }(\"\");\n        require(success, \"transfer failed\");\n    }\n}\n"
    },
    "contracts/MVM/MVM_GasOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n/* Contract Imports */\n/* External Imports */\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { MVM_Coinbase } from \"./MVM_Coinbase.sol\";\nimport { Lib_PredeployAddresses } from \"../libraries/constants/Lib_PredeployAddresses.sol\";\n\ncontract MVM_GasOracle is Ownable {\n    // Current l2 gas price\n    uint256 public gasPrice;\n    uint256 public minL1GasLimit;\n\n    constructor(address _owner, uint256 _initialGasPrice) Ownable() {\n        setGasPrice(_initialGasPrice);\n        transferOwnership(_owner);\n    }\n\n    function setGasPrice(uint256 _gasPrice) public onlyOwner {\n        gasPrice = _gasPrice;\n    }\n\n    function setMinL1GasLimit(uint256 gas) public onlyOwner {\n        minL1GasLimit = gas;\n    }\n\n    //for compatibility\n    function setPrice(uint256 _gasPrice) public onlyOwner {\n        gasPrice = _gasPrice;\n    }\n\n    function transferSetter(address newsetter) public onlyOwner {\n        transferOwnership(newsetter);\n    }\n\n    function transferTo(address target, uint256 amount) public onlyOwner {\n        // Transfer fee to relayer.\n        require(\n            MVM_Coinbase(Lib_PredeployAddresses.MVM_COINBASE).transfer(target, amount),\n            \"transfer failed.\"\n        );\n    }\n}\n"
    },
    "contracts/MVM/MVM_InboxSenderManager.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport {Lib_AddressResolver} from \"../libraries/resolver/Lib_AddressResolver.sol\";\nimport {iMVM_InboxSenderManager} from \"./iMVM_InboxSenderManager.sol\";\n\n/* Library Imports */\n\ncontract MVM_InboxSenderManager is iMVM_InboxSenderManager, Lib_AddressResolver {\n    /*************\n     * Constants *\n     *************/\n    string public constant CONFIG_OWNER_KEY = \"METIS_MANAGER\";\n\n    /*************\n     * Variables *\n     *************/\n    // blockNumber => InboxSenderType => inboxSender\n    mapping(uint256 => mapping(InboxSenderType => InboxSender)) public inboxSenders;\n\n    uint256[] public blockNumbers;\n    mapping(InboxSenderType => address) public defaultInboxSender;\n\n    /***************\n     * Constructor *\n     ***************/\n    constructor(address _libAddressManager, InboxSender[] memory _defaultInboxSenders)\n        Lib_AddressResolver(_libAddressManager)\n    {\n        for (uint256 i = 0; i < _defaultInboxSenders.length; ++i) {\n            defaultInboxSender[_defaultInboxSenders[i].senderType] = _defaultInboxSenders[i].sender;\n        }\n    }\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n    modifier onlyManager() {\n        require(\n            msg.sender == resolve(\"METIS_MANAGER\"),\n            \"MVM_InboxSenderManager: Function can only be called by the METIS_MANAGER.\"\n        );\n        _;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n    function setInboxSenders(uint256 blockNumber, InboxSender[] calldata _inboxSenders)\n        external\n        override\n        onlyManager\n    {\n        _setInboxSenders(blockNumber, _inboxSenders);\n    }\n\n    // allow us to overwrite the last block number and its senders, just in case if we made any mistake\n    function overwriteLastInboxSenders(uint256 blockNumber, InboxSender[] calldata _inboxSenders)\n        external\n        override\n        onlyManager\n    {\n        require(blockNumbers.length > 0, \"MVM_InboxSenderManager: No block to update.\");\n\n        // pop the last block\n        uint256 lastBlockNumber = blockNumbers[blockNumbers.length - 1];\n        blockNumbers.pop();\n\n        // clean up the last block senders\n        mapping(InboxSenderType => InboxSender) storage lastInboxSenders = inboxSenders[lastBlockNumber];\n        delete lastInboxSenders[InboxSenderType.InboxSender];\n        delete lastInboxSenders[InboxSenderType.InboxBlobSender];\n\n        // write the new senders\n        _setInboxSenders(blockNumber, _inboxSenders);\n    }\n\n    function getInboxSender(uint256 blockNumber, InboxSenderType inboxSenderType) external view override returns (address) {\n        uint256 blockNumerCounts = blockNumbers.length;\n        if (blockNumerCounts == 0) {\n            return defaultInboxSender[inboxSenderType];\n        }\n\n        for (int256 i = int256(blockNumerCounts) - 1; i >= 0; i--) {\n            if (blockNumbers[uint256(i)] <= blockNumber) {\n                address sender = inboxSenders[blockNumbers[uint256(i)]][inboxSenderType].sender;\n                if (sender != address(0)) {\n                    return sender;\n                }\n            }\n        }\n\n        return defaultInboxSender[inboxSenderType];\n    }\n\n    /********************\n     * Internal Functions *\n     ********************/\n    function _setInboxSenders(uint256 blockNumber, InboxSender[] calldata _inboxSenders)\n    private\n    {\n        require(_inboxSenders.length > 0, \"MVM_InboxSenderManager: Inbox senders cannot be empty.\");\n\n        if (blockNumbers.length > 0) {\n            require(\n                blockNumber > blockNumbers[blockNumbers.length - 1],\n                \"MVM_InboxSenderManager: Block number must be greater than the previous block number.\"\n            );\n        }\n\n        for (uint256 i = 0; i < _inboxSenders.length; ++i) {\n            require(\n                _inboxSenders[i].sender != address(0),\n                \"MVM_InboxSenderManager: Inbox sender cannot be empty.\"\n            );\n            inboxSenders[blockNumber][_inboxSenders[i].senderType] = _inboxSenders[i];\n            emit InboxSenderSet(blockNumber, _inboxSenders[i].sender, _inboxSenders[i].senderType);\n        }\n\n        blockNumbers.push(blockNumber);\n    }\n}\n"
    },
    "contracts/MVM/MVM_L2ChainManagerOnL1.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\npragma experimental ABIEncoderV2;\n\n/* Library Imports */\nimport { CrossDomainEnabled } from \"../libraries/bridge/CrossDomainEnabled.sol\";\nimport { Lib_PredeployAddresses } from \"../libraries/constants/Lib_PredeployAddresses.sol\";\nimport { Lib_AddressManager } from \"../libraries/resolver/Lib_AddressManager.sol\";\nimport { iOVM_SequencerFeeVault } from \"../L2/predeploys/iOVM_SequencerFeeVault.sol\";\nimport { iMVM_L2ChainManagerOnL1 } from \"./iMVM_L2ChainManagerOnL1.sol\";\nimport { iMVM_DiscountOracle } from \"./iMVM_DiscountOracle.sol\";\n\n/* Interface Imports */\n\n/* External Imports */\n\n/**\n * @title MVM_L2ChainManagerOnL1\n * @dev if want support multi l2 chain on l1,it should add a manager to desc\n * how many l2 chain now ,and dispatch the l2 chain id to make it is unique.\n *\n * Compiler used: solc\n * Runtime target: EVM\n */\ncontract MVM_L2ChainManagerOnL1 is iMVM_L2ChainManagerOnL1, CrossDomainEnabled {\n    /*************\n     * Constants *\n     *************/\n    string public constant CONFIG_OWNER_KEY = \"METIS_MANAGER\";\n\n    /*************\n     * Variables *\n     *************/\n    address public addressmgr;\n    // chainid => sequencer\n    mapping(uint256 => address) squencers;\n\n    // chainid => configs (unused for now);\n    mapping(uint256 => bytes) configs;\n\n    /***************\n     * Constructor *\n     ***************/\n    // This contract lives behind a proxy, so the constructor parameters will go unused.\n    constructor() CrossDomainEnabled(address(0)) {}\n\n    /**********************\n     * Function Modifiers *\n     **********************/\n\n    modifier onlyManager() {\n        require(\n            msg.sender == Lib_AddressManager(addressmgr).getAddress(CONFIG_OWNER_KEY),\n            \"MVM_L2ChainManagerOnL1: Function can only be called by the METIS_MANAGER.\"\n        );\n        _;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n    function switchSequencer(\n        uint256 _chainId,\n        address wallet,\n        address manager\n    ) public payable onlyManager {\n        bytes memory message = abi.encodeWithSelector(\n            iOVM_SequencerFeeVault.finalizeChainSwitch.selector,\n            wallet,\n            manager\n        );\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            Lib_PredeployAddresses.SEQUENCER_FEE_WALLET,\n            uint32(1_000_000_000),\n            message,\n            msg.value\n        );\n\n        emit SwitchSeq(_chainId, wallet, manager);\n    }\n\n    function pushConfig(uint256 _chainId, bytes calldata _configs) public payable onlyManager {\n        bytes memory message = abi.encodeWithSelector(\n            iOVM_SequencerFeeVault.finalizeChainConfig.selector,\n            _configs\n        );\n\n        // Send calldata into L2\n        sendCrossDomainMessageViaChainId(\n            _chainId,\n            Lib_PredeployAddresses.SEQUENCER_FEE_WALLET,\n            uint32(1_000_000_000),\n            message,\n            msg.value\n        );\n\n        emit PushConfig(_chainId, _configs);\n    }\n}\n"
    },
    "contracts/MVM/MVM_ProjectMaster.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ncontract MVM_ProjectMaster {\n    address projectOwner;\n    uint256 projectStake;\n    string projectURL;\n\n    constructor(\n        address owner,\n        uint256 stake,\n        string memory url\n    ) public {\n        projectOwner = owner;\n        projectStake = stake;\n        projectURL = url;\n    }\n}\n"
    },
    "contracts/MVM/MVM_StateCommitmentChain.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport \"../L1/dispute/interfaces/IFaultDisputeGame.sol\";\nimport \"contracts/L1/dispute/lib/Types.sol\";\nimport \"contracts/L1/dispute/lib/Errors.sol\";\nimport { IBondManager } from \"../L1/verification/IBondManager.sol\";\nimport { IChainStorageContainer } from \"../L1/rollup/IChainStorageContainer.sol\";\nimport { IMVMStateCommitmentChain } from \"../L1/rollup/IMVMStateCommitmentChain.sol\";\n\n/* Interface Imports */\nimport { IStateCommitmentChain } from \"../L1/rollup/IStateCommitmentChain.sol\";\n// import { ICanonicalTransactionChain } from \"../L1/rollup/ICanonicalTransactionChain.sol\";\nimport { Lib_AddressResolver } from \"../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_MerkleTree } from \"../libraries/utils/Lib_MerkleTree.sol\";\nimport { Lib_OVMCodec } from \"../libraries/codec/Lib_OVMCodec.sol\";\nimport { Lib_Uint } from \"../libraries/utils/Lib_Uint.sol\";\nimport { IDisputeGameFactory } from \"../L1/dispute/interfaces/IDisputeGameFactory.sol\";\n\n/**\n * @title MVM_StateCommitmentChain\n * @dev The State Commitment Chain (SCC) contract contains a list of proposed state roots which\n * Proposers assert to be a result of each transaction in the Canonical Transaction Chain (CTC).\n * Elements here have a 1:1 correspondence with transactions in the CTC, and should be the unique\n * state root calculated off-chain by applying the canonical transactions one by one.\n *\n * Runtime target: EVM\n */\ncontract MVM_StateCommitmentChain is IMVMStateCommitmentChain, Lib_AddressResolver {\n    /*************\n     * Constants *\n     *************/\n\n    uint256 public FRAUD_PROOF_WINDOW;\n    uint256 public SEQUENCER_PUBLISH_WINDOW;\n\n    uint256 public DEFAULT_CHAINID = 1088;\n\n    string constant public DISPUTE_GAME_FACTORY_NAME = \"DisputeGameFactory\";\n\n    /*****************\n     * Public States *\n     *****************/\n    // key: chain id\n    // value: [8B Timestamp][8B Index]\n    mapping(uint256 => bytes16[]) public batchTimes;\n    // key: state batch hash\n    // value: last L2 block number of the given batch\n    mapping(bytes32 => uint256) public batchLastL2BlockNumbers;\n    // key: state batch hash\n    // value: whether the batch is disputed\n    mapping(bytes32 => bool) public disputedBatches;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    /**\n     * @param _libAddressManager Address of the Address Manager.\n     */\n    constructor(\n        address _libAddressManager,\n        uint256 _fraudProofWindow,\n        uint256 _sequencerPublishWindow\n    ) Lib_AddressResolver(_libAddressManager) {\n        FRAUD_PROOF_WINDOW = _fraudProofWindow;\n        SEQUENCER_PUBLISH_WINDOW = _sequencerPublishWindow;\n    }\n\n    function setFraudProofWindow(uint256 window) external {\n        require(msg.sender == resolve(\"METIS_MANAGER\"), \"not allowed\");\n        FRAUD_PROOF_WINDOW = window;\n    }\n\n    /********************\n     * Public Functions *\n     ********************/\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function findEarliestDisputableBatch(uint256 _chainId) public view returns (bytes32, uint256) {\n        uint256 earliestDisputableTime = block.timestamp - FRAUD_PROOF_WINDOW;\n        return _findBatchWithinTimeWindow(_chainId, earliestDisputableTime);\n    }\n\n    /**\n     * Accesses the batch storage container.\n     * @return Reference to the batch storage container.\n     */\n    function batches() public view returns (IChainStorageContainer) {\n        return IChainStorageContainer(resolve(\"ChainStorageContainer-SCC-batches\"));\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function getTotalElements() external view returns (uint256 _totalElements) {\n        return getTotalElementsByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function getTotalBatches() external view returns (uint256 _totalBatches) {\n        return getTotalBatchesByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function getLastSequencerTimestamp() external view returns (uint256 _lastSequencerTimestamp) {\n        return getLastSequencerTimestampByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function appendStateBatch(bytes32[] memory _batch, uint256 _shouldStartAtElement, bytes32 _lastBatchBlockHash, uint256 _lastBatchBlockNumber) external {\n        //require (1==0, \"don't use\");\n        string memory proposer = string(\n            abi.encodePacked(Lib_Uint.uint2str(DEFAULT_CHAINID), \"_MVM_Proposer\")\n        );\n        appendStateBatchByChainId(DEFAULT_CHAINID, _batch, _shouldStartAtElement, proposer, _lastBatchBlockHash, _lastBatchBlockNumber);\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external {\n        deleteStateBatchByChainId(DEFAULT_CHAINID, _batchHeader);\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function verifyStateCommitment(\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) external view returns (bool) {\n        return verifyStateCommitmentByChainId(DEFAULT_CHAINID, _element, _batchHeader, _proof);\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function insideFraudProofWindow(Lib_OVMCodec.ChainBatchHeader memory _batchHeader)\n        public\n        view\n        returns (bool _inside)\n    {\n        (uint256 timestamp, , , ) = _decodeExtraData(_batchHeader.extraData);\n\n        require(timestamp != 0, \"Batch header timestamp cannot be zero\");\n        return (timestamp + FRAUD_PROOF_WINDOW) > block.timestamp;\n    }\n\n    function insideFraudProofWindowByChainId(\n        uint256,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) public view override returns (bool _inside) {\n        (uint256 timestamp, , , ) = _decodeExtraData(_batchHeader.extraData);\n\n        return _insideFraudProofWindowByChainId(timestamp);\n    }\n\n    function isDisputedBatch(bytes32 stateHeaderHash) public view returns (bool) {\n        return disputedBatches[stateHeaderHash];\n    }\n\n    function saveDisputedBatch(bytes32 stateHeaderHash) public {\n        // Grab the game and game data.\n        IFaultDisputeGame game = IFaultDisputeGame(msg.sender);\n        (GameType gameType, Claim rootClaim, bytes memory extraData) = game.gameData();\n\n        // Grab the verified address of the game based on the game data.\n        // slither-disable-next-line unused-return\n        (IDisputeGame factoryRegisteredGame,) =\n                            IDisputeGameFactory(resolve(DISPUTE_GAME_FACTORY_NAME)).games({ _gameType: gameType, _rootClaim: rootClaim, _extraData: extraData });\n\n        // Must be a valid game.\n        if (address(factoryRegisteredGame) != address(game)) revert UnregisteredGame();\n\n        if (disputedBatches[stateHeaderHash]) revert ClaimAlreadyResolved();\n\n        // We only record the disputed batch if the challenger wins.\n        if (game.status() == GameStatus.CHALLENGER_WINS) {\n            disputedBatches[stateHeaderHash] = true;\n        }\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    function _decodeExtraData(bytes memory _extraData) internal pure returns (uint256, address, bytes32, uint256) {\n        uint256 timestamp;\n        address sequencer;\n        bytes32 lastBlockHash;\n        uint256 lastBlockNumber;\n        if (_extraData.length == 0x40) {\n            (timestamp, sequencer) = abi.decode(_extraData, (uint256, address));\n        } else if (_extraData.length == 0x80) {\n            (timestamp, sequencer, lastBlockHash, lastBlockNumber) = abi.decode(_extraData, (uint256, address, bytes32, uint256));\n        } else {\n            revert(\"Invalid extra data length\");\n        }\n        return (timestamp, sequencer, lastBlockHash, lastBlockNumber);\n    }\n\n    function _findBatchWithinTimeWindow(uint256 _chainId, uint256 earliestTime) public view returns (bytes32, uint256) {\n        bytes16[] storage batchTimesOfChain = batchTimes[_chainId];\n\n        require(batchTimesOfChain.length > 0, \"No disputable batch has been appended yet\");\n\n        uint256 found = 0;\n        uint256 lastTimeIndex = batchTimesOfChain.length - 1;\n        uint256 lastElementTime = uint256(uint128(batchTimesOfChain[lastTimeIndex]) >> 64);\n        uint256 firstElementTime = uint256(uint128(batchTimesOfChain[0]) >> 64);\n\n        require(earliestTime <= lastElementTime, \"No batch to dispute\");\n\n        if (earliestTime <= firstElementTime) {\n            found = 0;\n        } else {\n            // binary search the batch times to find the closest time of earliestTime,\n            // but the time must >= earliestTime\n            uint256 left = 0;\n            uint256 right = lastTimeIndex;\n\n            while (left < right) {\n                uint256 mid = left + (right - left) / 2;\n                uint256 time = uint256(uint128(batchTimesOfChain[mid]) >> 64);\n                if (time < earliestTime) {\n                    left = mid + 1;\n                } else {\n                    right = mid;\n                }\n            }\n            found = left;\n        }\n\n        uint256 batchIndex = uint256(uint64(uint128(batchTimesOfChain[found])));\n        bytes32 batchHeaderHash = batches().getByChainId(_chainId, batchIndex);\n        return (batchHeaderHash, batchLastL2BlockNumbers[batchHeaderHash]);\n    }\n\n    /**\n     * Checks whether a given batch is still inside its fraud proof window.\n     * @param _timestamp Timestamp of the batch to check.\n     * @return _inside Whether or not the batch is inside the fraud proof window.\n     */\n    function _insideFraudProofWindowByChainId(\n       uint256 _timestamp\n    ) internal view returns (bool _inside) {\n        require(_timestamp != 0, \"Batch header timestamp cannot be zero\");\n        return _timestamp + FRAUD_PROOF_WINDOW > block.timestamp;\n    }\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Timestamp of the last batch submitted by the sequencer.\n     */\n    function _getBatchExtraData() internal view returns (uint40, uint40) {\n        return _getBatchExtraDataByChainId(DEFAULT_CHAINID);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _lastSequencerTimestamp Timestamp of the last batch submitted by the sequencer.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraData(uint40 _totalElements, uint40 _lastSequencerTimestamp)\n        internal\n        pure\n        returns (bytes27)\n    {\n        bytes27 extraData;\n        assembly {\n            extraData := _totalElements\n            extraData := or(extraData, shl(40, _lastSequencerTimestamp))\n            extraData := shl(40, extraData)\n        }\n\n        return extraData;\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function getTotalElementsByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _totalElements)\n    {\n        (uint40 totalElements, ) = _getBatchExtraDataByChainId(_chainId);\n        return uint256(totalElements);\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function getTotalBatchesByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _totalBatches)\n    {\n        return batches().lengthByChainId(_chainId);\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function getLastSequencerTimestampByChainId(uint256 _chainId)\n        public\n        view\n        override\n        returns (uint256 _lastSequencerTimestamp)\n    {\n        (, uint40 lastSequencerTimestamp) = _getBatchExtraDataByChainId(_chainId);\n        return uint256(lastSequencerTimestamp);\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function appendStateBatchByChainId(\n        uint256 _chainId,\n        bytes32[] memory _batch,\n        uint256 _shouldStartAtElement,\n        string memory _proposer,\n        bytes32 _lastBatchBlockHash,\n        uint256 _lastBatchBlockNumber\n    ) public override {\n        // Fail fast in to make sure our batch roots aren't accidentally made fraudulent by the\n        // publication of batches by some other user.\n        require(\n            _shouldStartAtElement == getTotalElementsByChainId(_chainId),\n            \"Actual batch start index does not match expected start index.\"\n        );\n\n        address proposerAddr = resolve(_proposer);\n\n        // Proposers must have previously staked at the BondManager\n        require(\n            IBondManager(resolve(\"BondManager\")).isCollateralizedByChainId(\n                _chainId,\n                msg.sender,\n                proposerAddr\n            ),\n            \"Proposer does not have enough collateral posted\"\n        );\n\n        require(_batch.length > 0, \"Cannot submit an empty state batch.\");\n\n        // Not check this when submit transaction batch to inbox address\n        // require(\n        //     getTotalElementsByChainId(_chainId) + _batch.length <=\n        //         ICanonicalTransactionChain(resolve(\"CanonicalTransactionChain\"))\n        //             .getTotalElementsByChainId(_chainId),\n        //     \"Number of state roots cannot exceed the number of canonical transactions.\"\n        // );\n\n        // Pass the block's timestamp and the publisher of the data\n        // to be used in the fraud proofs\n        _appendBatchByChainId(\n            _chainId,\n            _batch,\n            abi.encode(block.timestamp, msg.sender, _lastBatchBlockHash, _lastBatchBlockNumber),\n            proposerAddr\n        );\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function deleteStateBatchByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) public override {\n        require(\n            msg.sender ==\n                resolve(\n                    string(abi.encodePacked(Lib_Uint.uint2str(_chainId), \"_MVM_FraudVerifier\"))\n                ),\n            \"State batches can only be deleted by the MVM_FraudVerifier.\"\n        );\n\n        require(\n            insideFraudProofWindow(_batchHeader),\n            \"State batches can only be deleted within the fraud proof window.\"\n        );\n\n        _deleteBatchByChainId(_chainId, _batchHeader);\n    }\n\n    /**\n     * @inheritdoc IMVMStateCommitmentChain\n     */\n    function verifyStateCommitmentByChainId(\n        uint256 _chainId,\n        bytes32 _element,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader,\n        Lib_OVMCodec.ChainInclusionProof memory _proof\n    ) public view override returns (bool) {\n        require(_isValidBatchHeaderByChainId(_chainId, _batchHeader), \"Invalid batch header.\");\n\n        require(\n            Lib_MerkleTree.verify(\n                _batchHeader.batchRoot,\n                _element,\n                _proof.index,\n                _proof.siblings,\n                _batchHeader.batchSize\n            ),\n            \"Invalid inclusion proof.\"\n        );\n\n        return true;\n    }\n\n    /**********************\n     * Internal Functions *\n     **********************/\n\n    /**\n     * Parses the batch context from the extra data.\n     * @return Total number of elements submitted.\n     * @return Timestamp of the last batch submitted by the sequencer.\n     */\n    function _getBatchExtraDataByChainId(uint256 _chainId) internal view returns (uint40, uint40) {\n        bytes27 extraData = batches().getGlobalMetadataByChainId(_chainId);\n\n        uint40 totalElements;\n        uint40 lastSequencerTimestamp;\n        assembly {\n            extraData := shr(40, extraData)\n            totalElements := and(\n                extraData,\n                0x000000000000000000000000000000000000000000000000000000FFFFFFFFFF\n            )\n            lastSequencerTimestamp := shr(\n                40,\n                and(extraData, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000)\n            )\n        }\n\n        return (totalElements, lastSequencerTimestamp);\n    }\n\n    /**\n     * Encodes the batch context for the extra data.\n     * @param _totalElements Total number of elements submitted.\n     * @param _lastSequencerTimestamp Timestamp of the last batch submitted by the sequencer.\n     * @return Encoded batch context.\n     */\n    function _makeBatchExtraDataByChainId(uint40 _totalElements, uint40 _lastSequencerTimestamp)\n        internal\n        pure\n        returns (bytes27)\n    {\n        bytes27 extraData;\n        assembly {\n            extraData := _totalElements\n            extraData := or(extraData, shl(40, _lastSequencerTimestamp))\n            extraData := shl(40, extraData)\n        }\n\n        return extraData;\n    }\n\n    /**\n     * Appends a batch to the chain.\n     * @param _batch Elements within the batch.\n     * @param _extraData Any extra data to append to the batch.\n     */\n    function _appendBatchByChainId(\n        uint256 _chainId,\n        bytes32[] memory _batch,\n        bytes memory _extraData,\n        address\n    ) internal {\n        (uint40 totalElements, uint40 lastSequencerTimestamp) = _getBatchExtraDataByChainId(\n            _chainId\n        );\n\n        lastSequencerTimestamp = uint40(block.timestamp);\n\n        // For efficiency reasons getMerkleRoot modifies the `_batch` argument in place\n        // while calculating the root hash therefore any arguments passed to it must not\n        // be used again afterwards\n        Lib_OVMCodec.ChainBatchHeader memory batchHeader = Lib_OVMCodec.ChainBatchHeader({\n            batchIndex: getTotalBatchesByChainId(_chainId),\n            batchRoot: Lib_MerkleTree.getMerkleRoot(_batch),\n            batchSize: _batch.length,\n            prevTotalElements: totalElements,\n            extraData: _extraData\n        });\n\n        emit StateBatchAppended(\n            _chainId,\n            batchHeader.batchIndex,\n            batchHeader.batchRoot,\n            batchHeader.batchSize,\n            batchHeader.prevTotalElements,\n            batchHeader.extraData\n        );\n\n        bytes32 batchHeaderHash = Lib_OVMCodec.hashBatchHeader(batchHeader);\n\n        batches().pushByChainId(\n            _chainId,\n            batchHeaderHash,\n            _makeBatchExtraDataByChainId(\n                uint40(batchHeader.prevTotalElements + batchHeader.batchSize),\n                lastSequencerTimestamp\n            )\n        );\n\n        bytes16[] storage batchTimesOfChain = batchTimes[_chainId];\n        batchTimesOfChain.push(bytes16(uint128(uint256(lastSequencerTimestamp) << 64) | uint128(batchHeader.batchIndex)));\n        batchLastL2BlockNumbers[batchHeaderHash] = batchHeader.prevTotalElements + batchHeader.batchSize;\n    }\n\n    /**\n     * Removes a batch and all subsequent batches from the chain.\n     * @param _batchHeader Header of the batch to remove.\n     */\n    function _deleteBatchByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) internal {\n        require(\n            _batchHeader.batchIndex < batches().lengthByChainId(_chainId),\n            \"Invalid batch index.\"\n        );\n\n        require(_isValidBatchHeaderByChainId(_chainId, _batchHeader), \"Invalid batch header.\");\n\n        // clear the fdg extra data if needed\n        if (_batchHeader.extraData.length >= 0x80) {\n            (uint256 timestamp, , , ) = abi.decode(_batchHeader.extraData, (uint256, address, bytes32, uint256));\n            (bytes32 anchoredBatchHeaderHash, ) = _findBatchWithinTimeWindow(_chainId, timestamp);\n\n            bytes32 batchHeaderHash = Lib_OVMCodec.hashBatchHeader(_batchHeader);\n            require(\n                batchHeaderHash == anchoredBatchHeaderHash,\n                \"Anchored batch header does not match the submitted.\"\n            );\n            delete batchLastL2BlockNumbers[batchHeaderHash];\n\n            bytes16[] storage batchTimesOfChain = batchTimes[_chainId];\n            uint256 batchesToPop = 0;\n            for (uint256 i = batchTimesOfChain.length - 1; i >= 0; --i) {\n                if (uint64(uint128(batchTimesOfChain[i])) >= _batchHeader.batchIndex) {\n                    ++batchesToPop;\n                } else {\n                    break;\n                }\n            }\n            for (uint256 i = 0; i < batchesToPop; ++i) {\n                batchTimesOfChain.pop();\n            }\n        }\n\n        batches().deleteElementsAfterInclusiveByChainId(\n            _chainId,\n            _batchHeader.batchIndex,\n            _makeBatchExtraDataByChainId(uint40(_batchHeader.prevTotalElements), 0)\n        );\n\n        emit StateBatchDeleted(_chainId, _batchHeader.batchIndex, _batchHeader.batchRoot);\n    }\n\n    /**\n     * Checks that a batch header matches the stored hash for the given index.\n     * @param _batchHeader Batch header to validate.\n     * @return Whether or not the header matches the stored one.\n     */\n    function _isValidBatchHeaderByChainId(\n        uint256 _chainId,\n        Lib_OVMCodec.ChainBatchHeader memory _batchHeader\n    ) internal view returns (bool) {\n        return\n            Lib_OVMCodec.hashBatchHeader(_batchHeader) ==\n            batches().getByChainId(_chainId, _batchHeader.batchIndex);\n    }\n}\n"
    },
    "contracts/MVM/MVM_Verifier.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n/* Contract Imports */\n/* External Imports */\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { iMVM_DiscountOracle } from \"./iMVM_DiscountOracle.sol\";\nimport { Lib_AddressResolver } from \"../libraries/resolver/Lib_AddressResolver.sol\";\nimport { Lib_OVMCodec } from \"../libraries/codec/Lib_OVMCodec.sol\";\nimport { Lib_MerkleTree } from \"../libraries/utils/Lib_MerkleTree.sol\";\nimport { IStateCommitmentChain } from \"../L1/rollup/IStateCommitmentChain.sol\";\n\ncontract MVM_Verifier is Lib_AddressResolver {\n    // second slot\n    address public metis;\n\n    enum SETTLEMENT {\n        NOT_ENOUGH_VERIFIER,\n        SAME_ROOT,\n        AGREE,\n        DISAGREE,\n        PASS\n    }\n\n    event NewChallenge(\n        uint256 cIndex,\n        uint256 chainID,\n        Lib_OVMCodec.ChainBatchHeader header,\n        uint256 timestamp\n    );\n    event Verify1(uint256 cIndex, address verifier);\n    event Verify2(uint256 cIndex, address verifier);\n    event Finalize(uint256 cIndex, address sender, SETTLEMENT result);\n    event Penalize(address sender, uint256 stakeLost);\n    event Reward(address target, uint256 amount);\n    event Claim(address sender, uint256 amount);\n    event Withdraw(address sender, uint256 amount);\n    event Stake(address verifier, uint256 amount);\n    event SlashSequencer(uint256 chainID, address seq);\n\n    /*************\n     * Constants *\n     *************/\n    string public constant CONFIG_OWNER_KEY = \"METIS_MANAGER\";\n\n    //challenge info\n    struct Challenge {\n        address challenger;\n        uint256 chainID;\n        uint256 index;\n        Lib_OVMCodec.ChainBatchHeader header;\n        uint256 timestamp;\n        uint256 numQualifiedVerifiers;\n        uint256 numVerifiers;\n        address[] verifiers;\n        bool done;\n    }\n\n    mapping(address => uint256) public verifier_stakes;\n    mapping(uint256 => mapping(address => bytes)) private challenge_keys;\n    mapping(uint256 => mapping(address => bytes)) private challenge_key_hashes;\n    mapping(uint256 => mapping(address => bytes)) private challenge_hashes;\n\n    mapping(address => uint256) public rewards;\n    mapping(address => uint8) public absence_strikes;\n    mapping(address => uint8) public consensus_strikes;\n\n    // only one active challenge for each chain  chainid=>cIndex\n    mapping(uint256 => uint256) public chain_under_challenge;\n\n    // white list\n    mapping(address => bool) public whitelist;\n    bool useWhiteList;\n\n    address[] public verifiers;\n    Challenge[] public challenges;\n\n    uint256 public verifyWindow = 3600 * 24; // 24 hours of window to complete the each verify phase\n    uint256 public activeChallenges;\n\n    uint256 public minStake;\n    uint256 public seqStake;\n\n    uint256 public numQualifiedVerifiers;\n\n    uint256 FAIL_THRESHOLD = 2; // 1 time grace\n    uint256 ABSENCE_THRESHOLD = 4; // 2 times grace\n\n    modifier onlyManager() {\n        require(\n            msg.sender == resolve(CONFIG_OWNER_KEY),\n            \"MVM_Verifier: Function can only be called by the METIS_MANAGER.\"\n        );\n        _;\n    }\n\n    modifier onlyWhitelisted() {\n        require(isWhiteListed(msg.sender), \"only whitelisted verifiers can call\");\n        _;\n    }\n\n    modifier onlyStaked() {\n        require(isSufficientlyStaked(msg.sender), \"insufficient stake\");\n        _;\n    }\n\n    constructor() Lib_AddressResolver(address(0)) {}\n\n    // add stake as a verifier\n    function verifierStake(uint256 stake) public onlyWhitelisted {\n        require(activeChallenges == 0, \"stake is currently prohibited\"); //ongoing challenge\n        require(stake > 0, \"zero stake not allowed\");\n        require(\n            IERC20(metis).transferFrom(msg.sender, address(this), stake),\n            \"transfer metis failed\"\n        );\n\n        uint256 previousBalance = verifier_stakes[msg.sender];\n        verifier_stakes[msg.sender] += stake;\n\n        require(isSufficientlyStaked(msg.sender), \"insufficient stake to qualify as a verifier\");\n\n        if (previousBalance == 0) {\n            numQualifiedVerifiers++;\n            verifiers.push(msg.sender);\n        }\n\n        emit Stake(msg.sender, stake);\n    }\n\n    // start a new challenge\n    // @param chainID chainid\n    // @param header chainbatch header\n    // @param proposedHash encrypted hash of the correct state\n    // @param keyhash hash of the decryption key\n    //\n    // @dev why do we ask for key and keyhash? because we want verifiers compute the state instead\n    // of just copying from other verifiers.\n    function newChallenge(\n        uint256 chainID,\n        Lib_OVMCodec.ChainBatchHeader calldata header,\n        bytes calldata proposedHash,\n        bytes calldata keyhash\n    ) public onlyWhitelisted onlyStaked {\n        uint256 tempIndex = chain_under_challenge[chainID] - 1;\n        require(\n            tempIndex == 0 || block.timestamp - challenges[tempIndex].timestamp > verifyWindow * 2,\n            \"there is an ongoing challenge\"\n        );\n        if (tempIndex > 0) {\n            finalize(tempIndex);\n        }\n        IStateCommitmentChain stateChain = IStateCommitmentChain(resolve(\"StateCommitmentChain\"));\n\n        // while the root is encrypted, the timestamp is available in the extradata field of the header\n        require(\n            stateChain.insideFraudProofWindow(header),\n            \"the batch is outside of the fraud proof window\"\n        );\n\n        Challenge memory c;\n        c.chainID = chainID;\n        c.challenger = msg.sender;\n        c.timestamp = block.timestamp;\n        c.header = header;\n\n        challenges.push(c);\n        uint256 cIndex = challenges.length - 1;\n\n        // house keeping\n        challenge_hashes[cIndex][msg.sender] = proposedHash;\n        challenge_key_hashes[cIndex][msg.sender] = keyhash;\n        challenges[cIndex].numVerifiers++; // the challenger\n\n        // this will prevent stake change\n        activeChallenges++;\n\n        chain_under_challenge[chainID] = cIndex + 1; // +1 because 0 means no in-progress challenge\n        emit NewChallenge(cIndex, chainID, header, block.timestamp);\n    }\n\n    // phase 1 of the verify, provide an encrypted hash and the hash of the decryption key\n    // @param cIndex index of the challenge\n    // @param hash encrypted hash of the correct state (for the index referred in the challenge)\n    // @param keyhash hash of the decryption key\n    function verify1(\n        uint256 cIndex,\n        bytes calldata hash,\n        bytes calldata keyhash\n    ) public onlyWhitelisted onlyStaked {\n        require(\n            challenge_hashes[cIndex][msg.sender].length == 0,\n            \"verify1 already completed for the sender\"\n        );\n        challenge_hashes[cIndex][msg.sender] = hash;\n        challenge_key_hashes[cIndex][msg.sender] = keyhash;\n        challenges[cIndex].numVerifiers++;\n        emit Verify1(cIndex, msg.sender);\n    }\n\n    // phase 2 of the verify, provide the actual key to decrypt the hash\n    // @param cIndex index of the challenge\n    // @param key the decryption key\n    function verify2(uint256 cIndex, bytes calldata key) public onlyStaked onlyWhitelisted {\n        require(\n            challenges[cIndex].numVerifiers == numQualifiedVerifiers ||\n                block.timestamp - challenges[cIndex].timestamp > verifyWindow,\n            \"phase 2 not ready\"\n        );\n        require(\n            challenge_hashes[cIndex][msg.sender].length > 0,\n            \"you didn't participate in phase 1\"\n        );\n        if (challenge_keys[cIndex][msg.sender].length > 0) {\n            finalize(cIndex);\n            return;\n        }\n\n        //verify whether the key matches the keyhash initially provided.\n        require(\n            sha256(key) == bytes32(challenge_key_hashes[cIndex][msg.sender]),\n            \"key and keyhash don't match\"\n        );\n\n        if (msg.sender == challenges[cIndex].challenger) {\n            //decode the root in the header too\n            challenges[cIndex].header.batchRoot = bytes32(\n                decrypt(abi.encodePacked(challenges[cIndex].header.batchRoot), key)\n            );\n        }\n        challenge_keys[cIndex][msg.sender] = key;\n        challenge_hashes[cIndex][msg.sender] = decrypt(challenge_hashes[cIndex][msg.sender], key);\n        challenges[cIndex].verifiers.push(msg.sender);\n        emit Verify2(cIndex, msg.sender);\n\n        finalize(cIndex);\n    }\n\n    function finalize(uint256 cIndex) internal {\n        Challenge storage challenge = challenges[cIndex];\n\n        require(challenge.done == false, \"challenge is closed\");\n\n        if (\n            challenge.verifiers.length != challenge.numVerifiers &&\n            block.timestamp - challenge.timestamp < verifyWindow * 2\n        ) {\n            // not ready to finalize. do nothing\n            return;\n        }\n\n        IStateCommitmentChain stateChain = IStateCommitmentChain(resolve(\"StateCommitmentChain\"));\n        bytes32 proposedHash = bytes32(challenge_hashes[cIndex][challenge.challenger]);\n\n        uint256 reward = 0;\n\n        address[] memory agrees = new address[](challenge.verifiers.length);\n        uint256 numAgrees = 0;\n        address[] memory disagrees = new address[](challenge.verifiers.length);\n        uint256 numDisagrees = 0;\n        address[] memory penalized = new address[](challenge.verifiers.length);\n        uint256 numPenalized = 0;\n\n        for (uint256 i = 0; i < verifiers.length; i++) {\n            if (!isSufficientlyStaked(verifiers[i]) || !isWhiteListed(verifiers[i])) {\n                // not qualified as a verifier\n                continue;\n            }\n\n            //record the agreement\n            if (bytes32(challenge_hashes[cIndex][verifiers[i]]) == proposedHash) {\n                //agree with the challenger\n                if (absence_strikes[verifiers[i]] > 0) {\n                    absence_strikes[verifiers[i]] -= 1; // slowly clear the strike\n                }\n                agrees[numAgrees] = verifiers[i];\n                numAgrees++;\n            } else if (challenge_keys[cIndex][verifiers[i]].length == 0) {\n                //absent\n                absence_strikes[verifiers[i]] += 2;\n                if (absence_strikes[verifiers[i]] > ABSENCE_THRESHOLD) {\n                    reward += verifier_stakes[verifiers[i]];\n                    penalized[numPenalized] = verifiers[i];\n                    numPenalized++;\n                }\n            } else {\n                //disagree with the challenger\n                if (absence_strikes[verifiers[i]] > 0) {\n                    absence_strikes[verifiers[i]] -= 1; // slowly clear the strike\n                }\n                disagrees[numDisagrees] = verifiers[i];\n                numDisagrees++;\n            }\n        }\n        for (uint256 i = 0; i < numPenalized; i++) {\n            penalize(penalized[i]);\n        }\n\n        if (\n            Lib_OVMCodec.hashBatchHeader(challenge.header) !=\n            stateChain.batches().getByChainId(challenge.chainID, challenge.header.batchIndex)\n        ) {\n            // wrong header, penalize the challenger\n            reward += penalize(challenge.challenger);\n\n            // reward the disagrees. but no penalty on agrees because the input\n            // is garbage.\n            distributeReward(reward, disagrees, challenge.verifiers.length - 1);\n            emit Finalize(cIndex, msg.sender, SETTLEMENT.DISAGREE);\n        } else if (challenge.verifiers.length < (numQualifiedVerifiers * 75) / 100) {\n            // the absent verifiers get a absense strike. no other penalties. already done\n            emit Finalize(cIndex, msg.sender, SETTLEMENT.NOT_ENOUGH_VERIFIER);\n        } else if (proposedHash != challenge.header.batchRoot) {\n            if (numAgrees <= numDisagrees) {\n                // no consensus, challenge failed.\n                for (uint256 i = 0; i < numAgrees; i++) {\n                    consensus_strikes[agrees[i]] += 2;\n                    if (consensus_strikes[agrees[i]] > FAIL_THRESHOLD) {\n                        reward += penalize(agrees[i]);\n                    }\n                }\n                distributeReward(reward, disagrees, disagrees.length);\n                emit Finalize(cIndex, msg.sender, SETTLEMENT.DISAGREE);\n            } else {\n                // reached agreement. delete the batch root and slash the sequencer if the header is still valid\n                if (stateChain.insideFraudProofWindow(challenge.header)) {\n                    // this header needs to be within the window\n                    stateChain.deleteStateBatchByChainId(challenge.chainID, challenge.header);\n\n                    // temporary for the p1 of the decentralization roadmap\n                    if (seqStake > 0) {\n                        reward += seqStake;\n\n                        for (uint256 i = 0; i < numDisagrees; i++) {\n                            consensus_strikes[disagrees[i]] += 2;\n                            if (consensus_strikes[disagrees[i]] > FAIL_THRESHOLD) {\n                                reward += penalize(disagrees[i]);\n                            }\n                        }\n                        distributeReward(reward, agrees, agrees.length);\n                    }\n                    emit Finalize(cIndex, msg.sender, SETTLEMENT.AGREE);\n                } else {\n                    //not in the window anymore. let it pass... no penalty\n                    emit Finalize(cIndex, msg.sender, SETTLEMENT.PASS);\n                }\n            }\n        } else {\n            //wasteful challenge, add consensus_strikes to the challenger\n            consensus_strikes[challenge.challenger] += 2;\n            if (consensus_strikes[challenge.challenger] > FAIL_THRESHOLD) {\n                reward += penalize(challenge.challenger);\n            }\n            distributeReward(reward, challenge.verifiers, challenge.verifiers.length - 1);\n            emit Finalize(cIndex, msg.sender, SETTLEMENT.SAME_ROOT);\n        }\n\n        challenge.done = true;\n        activeChallenges--;\n        chain_under_challenge[challenge.chainID] = 0;\n    }\n\n    function depositSeqStake(uint256 amount) public onlyManager {\n        require(\n            IERC20(metis).transferFrom(msg.sender, address(this), amount),\n            \"transfer metis failed\"\n        );\n        seqStake += amount;\n        emit Stake(msg.sender, amount);\n    }\n\n    function withdrawSeqStake(address to) public onlyManager {\n        require(seqStake > 0, \"no stake\");\n        emit Withdraw(msg.sender, seqStake);\n        uint256 amount = seqStake;\n        seqStake = 0;\n\n        require(IERC20(metis).transfer(to, amount), \"transfer metis failed\");\n    }\n\n    function claim() public {\n        require(rewards[msg.sender] > 0, \"no reward to claim\");\n        uint256 amount = rewards[msg.sender];\n        rewards[msg.sender] = 0;\n\n        require(IERC20(metis).transfer(msg.sender, amount), \"token transfer failed\");\n\n        emit Claim(msg.sender, amount);\n    }\n\n    function withdraw(uint256 amount) public {\n        require(activeChallenges == 0, \"withdraw is currently prohibited\"); //ongoing challenge\n\n        uint256 balance = verifier_stakes[msg.sender];\n        require(balance >= amount, \"insufficient stake to withdraw\");\n\n        if (balance - amount < minStake && balance >= minStake) {\n            numQualifiedVerifiers--;\n            deleteVerifier(msg.sender);\n        }\n        verifier_stakes[msg.sender] -= amount;\n\n        require(IERC20(metis).transfer(msg.sender, amount), \"token transfer failed\");\n    }\n\n    function setMinStake(uint256 _minStake) public onlyManager {\n        minStake = _minStake;\n        uint256 num = 0;\n        if (verifiers.length > 0) {\n            address[] memory arr = new address[](verifiers.length);\n            for (uint256 i = 0; i < verifiers.length; ++i) {\n                if (verifier_stakes[verifiers[i]] >= minStake) {\n                    arr[num] = verifiers[i];\n                    num++;\n                }\n            }\n            if (num < verifiers.length) {\n                delete verifiers;\n                for (uint256 i = 0; i < num; i++) {\n                    verifiers.push(arr[i]);\n                }\n            }\n        }\n        numQualifiedVerifiers = num;\n    }\n\n    // helper\n    function isWhiteListed(address verifier) public view returns (bool) {\n        return !useWhiteList || whitelist[verifier];\n    }\n\n    function isSufficientlyStaked(address target) public view returns (bool) {\n        return (verifier_stakes[target] >= minStake);\n    }\n\n    // set the length of the time windows for each verification phase\n    function setVerifyWindow(uint256 window) public onlyManager {\n        verifyWindow = window;\n    }\n\n    // add the verifier to the whitelist\n    function setWhiteList(address verifier, bool allowed) public onlyManager {\n        whitelist[verifier] = allowed;\n        useWhiteList = true;\n    }\n\n    // allow everyone to be the verifier\n    function disableWhiteList() public onlyManager {\n        useWhiteList = false;\n    }\n\n    function setThreshold(uint256 absence_threshold, uint256 fail_threshold) public onlyManager {\n        ABSENCE_THRESHOLD = absence_threshold;\n        FAIL_THRESHOLD = fail_threshold;\n    }\n\n    function getMerkleRoot(bytes32[] calldata elements) public pure returns (bytes32) {\n        return Lib_MerkleTree.getMerkleRoot(elements);\n    }\n\n    //helper fucntion to encrypt data\n    function encrypt(bytes calldata data, bytes calldata key) public pure returns (bytes memory) {\n        bytes memory encryptedData = data;\n        uint256 j = 0;\n\n        for (uint256 i = 0; i < encryptedData.length; i++) {\n            if (j == key.length) {\n                j = 0;\n            }\n            encryptedData[i] = encryptByte(encryptedData[i], uint8(key[j]));\n            j++;\n        }\n\n        return encryptedData;\n    }\n\n    function encryptByte(bytes1 b, uint8 k) internal pure returns (bytes1) {\n        uint16 temp16 = uint16(uint8(b));\n        temp16 += k;\n\n        if (temp16 > 255) {\n            temp16 -= 256;\n        }\n        return bytes1(uint8(temp16));\n    }\n\n    // helper fucntion to decrypt the data\n    function decrypt(bytes memory data, bytes memory key) public pure returns (bytes memory) {\n        bytes memory decryptedData = data;\n        uint256 j = 0;\n\n        for (uint256 i = 0; i < decryptedData.length; i++) {\n            if (j == key.length) {\n                j = 0;\n            }\n\n            decryptedData[i] = decryptByte(decryptedData[i], uint8(key[j]));\n\n            j++;\n        }\n\n        return decryptedData;\n    }\n\n    function decryptByte(bytes1 b, uint8 k) internal pure returns (bytes1) {\n        uint16 temp16 = uint16(uint8(b));\n        if (temp16 > k) {\n            temp16 -= k;\n        } else {\n            temp16 = 256 - k;\n        }\n\n        return bytes1(uint8(temp16));\n    }\n\n    // calculate the rewards\n    function distributeReward(\n        uint256 amount,\n        address[] memory list,\n        uint256 num\n    ) internal {\n        uint256 reward = amount / num;\n        if (reward == 0) {\n            return;\n        }\n        uint256 total = 0;\n        for (uint256 i; i < list.length; i++) {\n            if (isSufficientlyStaked(list[i])) {\n                rewards[list[i]] += reward;\n                total += reward;\n                emit Reward(list[i], reward);\n            }\n        }\n\n        if (total < amount) {\n            if (isSufficientlyStaked(list[0])) {\n                rewards[list[0]] += total - amount;\n                emit Reward(list[0], total - amount);\n            } else {\n                rewards[list[1]] += total - amount;\n                emit Reward(list[1], total - amount);\n            }\n        }\n    }\n\n    // slash the verifier stake\n    function penalize(address target) internal returns (uint256) {\n        uint256 stake = verifier_stakes[target];\n        verifier_stakes[target] = 0;\n        numQualifiedVerifiers--;\n        deleteVerifier(target);\n        emit Penalize(target, stake);\n\n        return stake;\n    }\n\n    function deleteVerifier(address target) internal {\n        bool hasVerifier = false;\n        uint256 pos = 0;\n        for (uint256 i = 0; i < verifiers.length; i++) {\n            if (verifiers[i] == target) {\n                hasVerifier = true;\n                pos = i;\n                break;\n            }\n        }\n        if (hasVerifier) {\n            for (uint256 i = pos; i < verifiers.length - 1; i++) {\n                verifiers[i] = verifiers[i + 1];\n            }\n            verifiers.pop();\n        }\n    }\n}\n"
    },
    "contracts/standards/AddressAliasHelper.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity ^0.8.7;\n\nlibrary AddressAliasHelper {\n    uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n    /// @notice Utility function that converts the address in the L1 that submitted a tx to\n    /// the inbox to the msg.sender viewed in the L2\n    /// @param l1Address the address in the L1 that triggered the tx to L2\n    /// @return l2Address L2 address as viewed in msg.sender\n    function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n        unchecked {\n            l2Address = address(uint160(l1Address) + offset);\n        }\n    }\n\n    /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n    /// address in the L1 that submitted a tx to the inbox\n    /// @param l2Address L2 address as viewed in msg.sender\n    /// @return l1Address the address in the L1 that triggered the tx to L2\n    function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n        unchecked {\n            l1Address = address(uint160(l2Address) - offset);\n        }\n    }\n}\n"
    },
    "contracts/standards/IL2StandardERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ninterface IL2StandardERC20 is IERC20, IERC165 {\n    function l1Token() external returns (address);\n\n    function mint(address _to, uint256 _amount) external;\n\n    function burn(address _from, uint256 _amount) external;\n\n    event Mint(address indexed _account, uint256 _amount);\n    event Burn(address indexed _account, uint256 _amount);\n}\n"
    },
    "contracts/standards/L2StandardERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./IL2StandardERC20.sol\";\n\ncontract L2StandardERC20 is IL2StandardERC20, ERC20 {\n    address public l1Token;\n    address public l2Bridge;\n\n    /**\n     * @param _l2Bridge Address of the L2 standard bridge.\n     * @param _l1Token Address of the corresponding L1 token.\n     * @param _name ERC20 name.\n     * @param _symbol ERC20 symbol.\n     */\n    constructor(\n        address _l2Bridge,\n        address _l1Token,\n        string memory _name,\n        string memory _symbol\n    ) ERC20(_name, _symbol) {\n        l1Token = _l1Token;\n        l2Bridge = _l2Bridge;\n    }\n\n    modifier onlyL2Bridge() {\n        require(msg.sender == l2Bridge, \"Only L2 Bridge can mint and burn\");\n        _;\n    }\n\n    function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {\n        bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n        bytes4 secondSupportedInterface = IL2StandardERC20.l1Token.selector ^\n            IL2StandardERC20.mint.selector ^\n            IL2StandardERC20.burn.selector;\n        return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n    }\n\n    function mint(address _to, uint256 _amount) public virtual onlyL2Bridge {\n        _mint(_to, _amount);\n\n        emit Mint(_to, _amount);\n    }\n\n    function burn(address _from, uint256 _amount) public virtual onlyL2Bridge {\n        _burn(_from, _amount);\n\n        emit Burn(_from, _amount);\n    }\n}\n"
    },
    "contracts/test-helpers/Helper_GasMeasurer.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ncontract Helper_GasMeasurer {\n    function measureCallGas(address _target, bytes memory _data) public returns (uint256) {\n        uint256 gasBefore;\n        uint256 gasAfter;\n\n        uint256 calldataStart;\n        uint256 calldataLength;\n        assembly {\n            calldataStart := add(_data, 0x20)\n            calldataLength := mload(_data)\n        }\n\n        bool success;\n        assembly {\n            gasBefore := gas()\n            success := call(gas(), _target, 0, calldataStart, calldataLength, 0, 0)\n            gasAfter := gas()\n        }\n        require(success, \"Call failed, but calls we want to measure gas for should succeed!\");\n\n        return gasBefore - gasAfter;\n    }\n}\n"
    },
    "contracts/test-helpers/Helper_SimpleProxy.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ncontract Helper_SimpleProxy {\n    address internal owner;\n    address internal target;\n\n    constructor() {\n        owner = msg.sender;\n    }\n\n    fallback() external {\n        makeExternalCall(target, msg.data);\n    }\n\n    function setTarget(address _target) public {\n        if (msg.sender == owner) {\n            target = _target;\n        } else {\n            makeExternalCall(target, msg.data);\n        }\n    }\n\n    function makeExternalCall(address _target, bytes memory _calldata) internal {\n        (bool success, bytes memory returndata) = _target.call(_calldata);\n\n        if (success) {\n            assembly {\n                return(add(returndata, 0x20), mload(returndata))\n            }\n        } else {\n            assembly {\n                revert(add(returndata, 0x20), mload(returndata))\n            }\n        }\n    }\n}\n"
    },
    "contracts/test-helpers/TestERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n// a test ERC20 token with an open mint function\ncontract TestERC20 {\n    string public constant name = \"Test\";\n    string public constant symbol = \"TST\";\n    uint8 public constant decimals = 18;\n    uint256 public totalSupply;\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    constructor() {}\n\n    function mint(address to, uint256 value) public {\n        totalSupply = totalSupply + value;\n        balanceOf[to] = balanceOf[to] + value;\n        emit Transfer(address(0), to, value);\n    }\n\n    function _approve(\n        address owner,\n        address spender,\n        uint256 value\n    ) private {\n        allowance[owner][spender] = value;\n        emit Approval(owner, spender, value);\n    }\n\n    function _transfer(\n        address from,\n        address to,\n        uint256 value\n    ) private {\n        balanceOf[from] = balanceOf[from] - value;\n        balanceOf[to] = balanceOf[to] + value;\n        emit Transfer(from, to, value);\n    }\n\n    function approve(address spender, uint256 value) external returns (bool) {\n        _approve(msg.sender, spender, value);\n        return true;\n    }\n\n    function transfer(address to, uint256 value) external returns (bool) {\n        _transfer(msg.sender, to, value);\n        return true;\n    }\n\n    function transferFrom(\n        address from,\n        address to,\n        uint256 value\n    ) external returns (bool) {\n        if (allowance[from][msg.sender] != type(uint256).max) {\n            allowance[from][msg.sender] = allowance[from][msg.sender] - value;\n        }\n        _transfer(from, to, value);\n        return true;\n    }\n}\n"
    },
    "contracts/test-libraries/codec/TestLib_OVMCodec.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_OVMCodec } from \"../../libraries/codec/Lib_OVMCodec.sol\";\n\n/**\n * @title TestLib_OVMCodec\n */\ncontract TestLib_OVMCodec {\n    function encodeTransaction(Lib_OVMCodec.Transaction memory _transaction)\n        public\n        pure\n        returns (bytes memory _encoded)\n    {\n        return Lib_OVMCodec.encodeTransaction(_transaction);\n    }\n\n    function hashTransaction(Lib_OVMCodec.Transaction memory _transaction)\n        public\n        pure\n        returns (bytes32 _hash)\n    {\n        return Lib_OVMCodec.hashTransaction(_transaction);\n    }\n}\n"
    },
    "contracts/test-libraries/rlp/TestLib_RLPReader.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_RLPReader } from \"../../libraries/rlp/Lib_RLPReader.sol\";\n\n/**\n * @title TestLib_RLPReader\n */\ncontract TestLib_RLPReader {\n    function readList(bytes memory _in) public pure returns (bytes[] memory) {\n        Lib_RLPReader.RLPItem[] memory decoded = Lib_RLPReader.readList(_in);\n        bytes[] memory out = new bytes[](decoded.length);\n        for (uint256 i = 0; i < out.length; i++) {\n            out[i] = Lib_RLPReader.readRawBytes(decoded[i]);\n        }\n        return out;\n    }\n\n    function readString(bytes memory _in) public pure returns (string memory) {\n        return Lib_RLPReader.readString(_in);\n    }\n\n    function readBytes(bytes memory _in) public pure returns (bytes memory) {\n        return Lib_RLPReader.readBytes(_in);\n    }\n\n    function readBytes32(bytes memory _in) public pure returns (bytes32) {\n        return Lib_RLPReader.readBytes32(_in);\n    }\n\n    function readUint256(bytes memory _in) public pure returns (uint256) {\n        return Lib_RLPReader.readUint256(_in);\n    }\n\n    function readBool(bytes memory _in) public pure returns (bool) {\n        return Lib_RLPReader.readBool(_in);\n    }\n\n    function readAddress(bytes memory _in) public pure returns (address) {\n        return Lib_RLPReader.readAddress(_in);\n    }\n}\n"
    },
    "contracts/test-libraries/rlp/TestLib_RLPWriter.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_RLPWriter } from \"../../libraries/rlp/Lib_RLPWriter.sol\";\nimport { TestERC20 } from \"../../test-helpers/TestERC20.sol\";\n\n/**\n * @title TestLib_RLPWriter\n */\ncontract TestLib_RLPWriter {\n    function writeBytes(bytes memory _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeBytes(_in);\n    }\n\n    function writeList(bytes[] memory _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeList(_in);\n    }\n\n    function writeString(string memory _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeString(_in);\n    }\n\n    function writeAddress(address _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeAddress(_in);\n    }\n\n    function writeUint(uint256 _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeUint(_in);\n    }\n\n    function writeBool(bool _in) public pure returns (bytes memory _out) {\n        return Lib_RLPWriter.writeBool(_in);\n    }\n\n    function writeAddressWithTaintedMemory(address _in) public returns (bytes memory _out) {\n        new TestERC20();\n        return Lib_RLPWriter.writeAddress(_in);\n    }\n}\n"
    },
    "contracts/test-libraries/standards/TestLib_AddressAliasHelper.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/* Library Imports */\nimport { AddressAliasHelper } from \"../../standards/AddressAliasHelper.sol\";\n\n/**\n * @title TestLib_AddressAliasHelper\n */\ncontract TestLib_AddressAliasHelper {\n    function applyL1ToL2Alias(address _address) public pure returns (address) {\n        return AddressAliasHelper.applyL1ToL2Alias(_address);\n    }\n\n    function undoL1ToL2Alias(address _address) public pure returns (address) {\n        return AddressAliasHelper.undoL1ToL2Alias(_address);\n    }\n}\n"
    },
    "contracts/test-libraries/trie/TestLib_MerkleTrie.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_MerkleTrie } from \"../../libraries/trie/Lib_MerkleTrie.sol\";\n\n/**\n * @title TestLib_MerkleTrie\n */\ncontract TestLib_MerkleTrie {\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bool) {\n        return Lib_MerkleTrie.verifyInclusionProof(_key, _value, _proof, _root);\n    }\n\n    function update(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bytes32) {\n        return Lib_MerkleTrie.update(_key, _value, _proof, _root);\n    }\n\n    function get(\n        bytes memory _key,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bool, bytes memory) {\n        return Lib_MerkleTrie.get(_key, _proof, _root);\n    }\n\n    function getSingleNodeRootHash(bytes memory _key, bytes memory _value)\n        public\n        pure\n        returns (bytes32)\n    {\n        return Lib_MerkleTrie.getSingleNodeRootHash(_key, _value);\n    }\n}\n"
    },
    "contracts/test-libraries/trie/TestLib_SecureMerkleTrie.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_SecureMerkleTrie } from \"../../libraries/trie/Lib_SecureMerkleTrie.sol\";\n\n/**\n * @title TestLib_SecureMerkleTrie\n */\ncontract TestLib_SecureMerkleTrie {\n    function verifyInclusionProof(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bool) {\n        return Lib_SecureMerkleTrie.verifyInclusionProof(_key, _value, _proof, _root);\n    }\n\n    function update(\n        bytes memory _key,\n        bytes memory _value,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bytes32) {\n        return Lib_SecureMerkleTrie.update(_key, _value, _proof, _root);\n    }\n\n    function get(\n        bytes memory _key,\n        bytes memory _proof,\n        bytes32 _root\n    ) public pure returns (bool, bytes memory) {\n        return Lib_SecureMerkleTrie.get(_key, _proof, _root);\n    }\n\n    function getSingleNodeRootHash(bytes memory _key, bytes memory _value)\n        public\n        pure\n        returns (bytes32)\n    {\n        return Lib_SecureMerkleTrie.getSingleNodeRootHash(_key, _value);\n    }\n}\n"
    },
    "contracts/test-libraries/utils/TestLib_Bytes32Utils.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_Bytes32Utils } from \"../../libraries/utils/Lib_Bytes32Utils.sol\";\n\n/**\n * @title TestLib_Byte32Utils\n */\ncontract TestLib_Bytes32Utils {\n    function toBool(bytes32 _in) public pure returns (bool _out) {\n        return Lib_Bytes32Utils.toBool(_in);\n    }\n\n    function fromBool(bool _in) public pure returns (bytes32 _out) {\n        return Lib_Bytes32Utils.fromBool(_in);\n    }\n\n    function toAddress(bytes32 _in) public pure returns (address _out) {\n        return Lib_Bytes32Utils.toAddress(_in);\n    }\n\n    function fromAddress(address _in) public pure returns (bytes32 _out) {\n        return Lib_Bytes32Utils.fromAddress(_in);\n    }\n}\n"
    },
    "contracts/test-libraries/utils/TestLib_BytesUtils.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_BytesUtils } from \"../../libraries/utils/Lib_BytesUtils.sol\";\nimport { TestERC20 } from \"../../test-helpers/TestERC20.sol\";\n\n/**\n * @title TestLib_BytesUtils\n */\ncontract TestLib_BytesUtils {\n    function concat(bytes memory _preBytes, bytes memory _postBytes)\n        public\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(_preBytes, _postBytes);\n    }\n\n    function slice(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    ) public pure returns (bytes memory) {\n        return Lib_BytesUtils.slice(_bytes, _start, _length);\n    }\n\n    function toBytes32(bytes memory _bytes) public pure returns (bytes32) {\n        return Lib_BytesUtils.toBytes32(_bytes);\n    }\n\n    function toUint256(bytes memory _bytes) public pure returns (uint256) {\n        return Lib_BytesUtils.toUint256(_bytes);\n    }\n\n    function toNibbles(bytes memory _bytes) public pure returns (bytes memory) {\n        return Lib_BytesUtils.toNibbles(_bytes);\n    }\n\n    function fromNibbles(bytes memory _bytes) public pure returns (bytes memory) {\n        return Lib_BytesUtils.fromNibbles(_bytes);\n    }\n\n    function equal(bytes memory _bytes, bytes memory _other) public pure returns (bool) {\n        return Lib_BytesUtils.equal(_bytes, _other);\n    }\n\n    function sliceWithTaintedMemory(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    ) public returns (bytes memory) {\n        new TestERC20();\n        return Lib_BytesUtils.slice(_bytes, _start, _length);\n    }\n}\n"
    },
    "contracts/test-libraries/utils/TestLib_MerkleTree.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/* Library Imports */\nimport { Lib_MerkleTree } from \"../../libraries/utils/Lib_MerkleTree.sol\";\n\n/**\n * @title TestLib_MerkleTree\n */\ncontract TestLib_MerkleTree {\n    function getMerkleRoot(bytes32[] memory _elements) public pure returns (bytes32) {\n        return Lib_MerkleTree.getMerkleRoot(_elements);\n    }\n\n    function verify(\n        bytes32 _root,\n        bytes32 _leaf,\n        uint256 _index,\n        bytes32[] memory _siblings,\n        uint256 _totalLeaves\n    ) public pure returns (bool) {\n        return Lib_MerkleTree.verify(_root, _leaf, _index, _siblings, _totalLeaves);\n    }\n}\n"
    },
    "contracts/universal/ISemver.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title ISemver\n/// @notice ISemver is a simple contract for ensuring that contracts are\n///         versioned using semantic versioning.\ninterface ISemver {\n    /// @notice Getter for the semantic version of the contract. This is not\n    ///         meant to be used onchain but instead meant to be used by offchain\n    ///         tooling.\n    /// @return Semver contract version as a string.\n    function version() external view returns (string memory);\n}\n"
    },
    "solady/src/utils/Clone.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Class with helper read functions for clone with immutable args.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Clone.sol)\n/// @author Adapted from clones with immutable args by zefram.eth, Saw-mon & Natalie\n/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)\nabstract contract Clone {\n    /// @dev Reads all of the immutable args.\n    function _getArgBytes() internal pure returns (bytes memory arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := mload(0x40)\n            let length := sub(calldatasize(), add(2, offset)) // 2 bytes are used for the length.\n            mstore(arg, length) // Store the length.\n            calldatacopy(add(arg, 0x20), offset, length)\n            let o := add(add(arg, 0x20), length)\n            mstore(o, 0) // Zeroize the slot after the bytes.\n            mstore(0x40, add(o, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /// @dev Reads an immutable arg with type bytes.\n    function _getArgBytes(uint256 argOffset, uint256 length)\n        internal\n        pure\n        returns (bytes memory arg)\n    {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := mload(0x40)\n            mstore(arg, length) // Store the length.\n            calldatacopy(add(arg, 0x20), add(offset, argOffset), length)\n            let o := add(add(arg, 0x20), length)\n            mstore(o, 0) // Zeroize the slot after the bytes.\n            mstore(0x40, add(o, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /// @dev Reads an immutable arg with type address.\n    function _getArgAddress(uint256 argOffset) internal pure returns (address arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(96, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads a uint256 array stored in the immutable args.\n    function _getArgUint256Array(uint256 argOffset, uint256 length)\n        internal\n        pure\n        returns (uint256[] memory arg)\n    {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := mload(0x40)\n            mstore(arg, length) // Store the length.\n            calldatacopy(add(arg, 0x20), add(offset, argOffset), shl(5, length))\n            mstore(0x40, add(add(arg, 0x20), shl(5, length))) // Allocate the memory.\n        }\n    }\n\n    /// @dev Reads a bytes32 array stored in the immutable args.\n    function _getArgBytes32Array(uint256 argOffset, uint256 length)\n        internal\n        pure\n        returns (bytes32[] memory arg)\n    {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := mload(0x40)\n            mstore(arg, length) // Store the length.\n            calldatacopy(add(arg, 0x20), add(offset, argOffset), shl(5, length))\n            mstore(0x40, add(add(arg, 0x20), shl(5, length))) // Allocate the memory.\n        }\n    }\n\n    /// @dev Reads an immutable arg with type bytes32.\n    function _getArgBytes32(uint256 argOffset) internal pure returns (bytes32 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := calldataload(add(offset, argOffset))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint256.\n    function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := calldataload(add(offset, argOffset))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint248.\n    function _getArgUint248(uint256 argOffset) internal pure returns (uint248 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(8, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint240.\n    function _getArgUint240(uint256 argOffset) internal pure returns (uint240 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(16, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint232.\n    function _getArgUint232(uint256 argOffset) internal pure returns (uint232 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(24, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint224.\n    function _getArgUint224(uint256 argOffset) internal pure returns (uint224 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(0x20, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint216.\n    function _getArgUint216(uint256 argOffset) internal pure returns (uint216 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(40, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint208.\n    function _getArgUint208(uint256 argOffset) internal pure returns (uint208 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(48, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint200.\n    function _getArgUint200(uint256 argOffset) internal pure returns (uint200 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(56, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint192.\n    function _getArgUint192(uint256 argOffset) internal pure returns (uint192 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(64, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint184.\n    function _getArgUint184(uint256 argOffset) internal pure returns (uint184 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(72, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint176.\n    function _getArgUint176(uint256 argOffset) internal pure returns (uint176 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(80, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint168.\n    function _getArgUint168(uint256 argOffset) internal pure returns (uint168 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(88, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint160.\n    function _getArgUint160(uint256 argOffset) internal pure returns (uint160 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(96, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint152.\n    function _getArgUint152(uint256 argOffset) internal pure returns (uint152 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(104, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint144.\n    function _getArgUint144(uint256 argOffset) internal pure returns (uint144 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(112, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint136.\n    function _getArgUint136(uint256 argOffset) internal pure returns (uint136 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(120, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint128.\n    function _getArgUint128(uint256 argOffset) internal pure returns (uint128 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(128, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint120.\n    function _getArgUint120(uint256 argOffset) internal pure returns (uint120 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(136, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint112.\n    function _getArgUint112(uint256 argOffset) internal pure returns (uint112 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(144, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint104.\n    function _getArgUint104(uint256 argOffset) internal pure returns (uint104 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(152, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint96.\n    function _getArgUint96(uint256 argOffset) internal pure returns (uint96 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(160, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint88.\n    function _getArgUint88(uint256 argOffset) internal pure returns (uint88 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(168, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint80.\n    function _getArgUint80(uint256 argOffset) internal pure returns (uint80 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(176, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint72.\n    function _getArgUint72(uint256 argOffset) internal pure returns (uint72 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(184, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint64.\n    function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(192, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint56.\n    function _getArgUint56(uint256 argOffset) internal pure returns (uint56 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(200, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint48.\n    function _getArgUint48(uint256 argOffset) internal pure returns (uint48 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(208, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint40.\n    function _getArgUint40(uint256 argOffset) internal pure returns (uint40 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(216, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint32.\n    function _getArgUint32(uint256 argOffset) internal pure returns (uint32 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(224, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint24.\n    function _getArgUint24(uint256 argOffset) internal pure returns (uint24 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(232, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint16.\n    function _getArgUint16(uint256 argOffset) internal pure returns (uint16 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(240, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @dev Reads an immutable arg with type uint8.\n    function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) {\n        uint256 offset = _getImmutableArgsOffset();\n        /// @solidity memory-safe-assembly\n        assembly {\n            arg := shr(248, calldataload(add(offset, argOffset)))\n        }\n    }\n\n    /// @return offset The offset of the packed immutable args in calldata.\n    function _getImmutableArgsOffset() internal pure returns (uint256 offset) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            offset := sub(calldatasize(), shr(240, calldataload(sub(calldatasize(), 2))))\n        }\n    }\n}\n"
    },
    "solady/src/utils/FixedPointMathLib.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       CUSTOM ERRORS                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The operation failed, as the output exceeds the maximum value of uint256.\n    error ExpOverflow();\n\n    /// @dev The operation failed, as the output exceeds the maximum value of uint256.\n    error FactorialOverflow();\n\n    /// @dev The operation failed, due to an overflow.\n    error RPowOverflow();\n\n    /// @dev The mantissa is too big to fit.\n    error MantissaOverflow();\n\n    /// @dev The operation failed, due to an multiplication overflow.\n    error MulWadFailed();\n\n    /// @dev The operation failed, due to an multiplication overflow.\n    error SMulWadFailed();\n\n    /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero.\n    error DivWadFailed();\n\n    /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero.\n    error SDivWadFailed();\n\n    /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero.\n    error MulDivFailed();\n\n    /// @dev The division failed, as the denominator is zero.\n    error DivFailed();\n\n    /// @dev The full precision multiply-divide operation failed, either due\n    /// to the result being larger than 256 bits, or a division by a zero.\n    error FullMulDivFailed();\n\n    /// @dev The output is undefined, as the input is less-than-or-equal to zero.\n    error LnWadUndefined();\n\n    /// @dev The input outside the acceptable domain.\n    error OutOfDomain();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         CONSTANTS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The scalar of ETH and most ERC20s.\n    uint256 internal constant WAD = 1e18;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*              SIMPLIFIED FIXED POINT OPERATIONS             */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded down.\n    function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.\n            if mul(y, gt(x, div(not(0), y))) {\n                mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := div(mul(x, y), WAD)\n        }\n    }\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded down.\n    function sMulWad(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(x, y)\n            // Equivalent to `require((x == 0 || z / x == y) && !(x == -1 && y == type(int256).min))`.\n            if iszero(gt(or(iszero(x), eq(sdiv(z, x), y)), lt(not(x), eq(y, shl(255, 1))))) {\n                mstore(0x00, 0xedcd4dd4) // `SMulWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := sdiv(z, WAD)\n        }\n    }\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded down, but without overflow checks.\n    function rawMulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := div(mul(x, y), WAD)\n        }\n    }\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded down, but without overflow checks.\n    function rawSMulWad(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := sdiv(mul(x, y), WAD)\n        }\n    }\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded up.\n    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.\n            if mul(y, gt(x, div(not(0), y))) {\n                mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))\n        }\n    }\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded up, but without overflow checks.\n    function rawMulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded down.\n    function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.\n            if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {\n                mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := div(mul(x, WAD), y)\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded down.\n    function sDivWad(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(x, WAD)\n            // Equivalent to `require(y != 0 && ((x * WAD) / WAD == x))`.\n            if iszero(and(iszero(iszero(y)), eq(sdiv(z, WAD), x))) {\n                mstore(0x00, 0x5c43740d) // `SDivWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := sdiv(mul(x, WAD), y)\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks.\n    function rawDivWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := div(mul(x, WAD), y)\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks.\n    function rawSDivWad(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := sdiv(mul(x, WAD), y)\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded up.\n    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.\n            if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {\n                mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded up, but without overflow and divide by zero checks.\n    function rawDivWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))\n        }\n    }\n\n    /// @dev Equivalent to `x` to the power of `y`.\n    /// because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`.\n    function powWad(int256 x, int256 y) internal pure returns (int256) {\n        // Using `ln(x)` means `x` must be greater than 0.\n        return expWad((lnWad(x) * y) / int256(WAD));\n    }\n\n    /// @dev Returns `exp(x)`, denominated in `WAD`.\n    /// Credit to Remco Bloemen under MIT license: https://2π.com/21/exp-ln\n    function expWad(int256 x) internal pure returns (int256 r) {\n        unchecked {\n            // When the result is less than 0.5 we return zero.\n            // This happens when `x <= floor(log(0.5e18) * 1e18) ≈ -42e18`.\n            if (x <= -41446531673892822313) return r;\n\n            /// @solidity memory-safe-assembly\n            assembly {\n                // When the result is greater than `(2**255 - 1) / 1e18` we can not represent it as\n                // an int. This happens when `x >= floor(log((2**255 - 1) / 1e18) * 1e18) ≈ 135`.\n                if iszero(slt(x, 135305999368893231589)) {\n                    mstore(0x00, 0xa37bfec9) // `ExpOverflow()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n\n            // `x` is now in the range `(-42, 136) * 1e18`. Convert to `(-42, 136) * 2**96`\n            // for more intermediate precision and a binary basis. This base conversion\n            // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n            x = (x << 78) / 5 ** 18;\n\n            // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n            // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n            // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n            int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96;\n            x = x - k * 54916777467707473351141471128;\n\n            // `k` is in the range `[-61, 195]`.\n\n            // Evaluate using a (6, 7)-term rational approximation.\n            // `p` is made monic, we'll multiply by a scale factor later.\n            int256 y = x + 1346386616545796478920950773328;\n            y = ((y * x) >> 96) + 57155421227552351082224309758442;\n            int256 p = y + x - 94201549194550492254356042504812;\n            p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n            p = p * x + (4385272521454847904659076985693276 << 96);\n\n            // We leave `p` in `2**192` basis so we don't need to scale it back up for the division.\n            int256 q = x - 2855989394907223263936484059900;\n            q = ((q * x) >> 96) + 50020603652535783019961831881945;\n            q = ((q * x) >> 96) - 533845033583426703283633433725380;\n            q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n            q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n            q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n            /// @solidity memory-safe-assembly\n            assembly {\n                // Div in assembly because solidity adds a zero check despite the unchecked.\n                // The q polynomial won't have zeros in the domain as all its roots are complex.\n                // No scaling is necessary because p is already `2**96` too large.\n                r := sdiv(p, q)\n            }\n\n            // r should be in the range `(0.09, 0.25) * 2**96`.\n\n            // We now need to multiply r by:\n            // - The scale factor `s ≈ 6.031367120`.\n            // - The `2**k` factor from the range reduction.\n            // - The `1e18 / 2**96` factor for base conversion.\n            // We do this all at once, with an intermediate result in `2**213`\n            // basis, so the final right shift is always by a positive amount.\n            r = int256(\n                (uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)\n            );\n        }\n    }\n\n    /// @dev Returns `ln(x)`, denominated in `WAD`.\n    /// Credit to Remco Bloemen under MIT license: https://2π.com/21/exp-ln\n    function lnWad(int256 x) internal pure returns (int256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // We want to convert `x` from `10**18` fixed point to `2**96` fixed point.\n            // We do this by multiplying by `2**96 / 10**18`. But since\n            // `ln(x * C) = ln(x) + ln(C)`, we can simply do nothing here\n            // and add `ln(2**96 / 10**18)` at the end.\n\n            // Compute `k = log2(x) - 96`, `r = 159 - k = 255 - log2(x) = 255 ^ log2(x)`.\n            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(r, shl(3, lt(0xff, shr(r, x))))\n            // We place the check here for more optimal stack operations.\n            if iszero(sgt(x, 0)) {\n                mstore(0x00, 0x1615e638) // `LnWadUndefined()`.\n                revert(0x1c, 0x04)\n            }\n            // forgefmt: disable-next-item\n            r := xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),\n                0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff))\n\n            // Reduce range of x to (1, 2) * 2**96\n            // ln(2^k * x) = k * ln(2) + ln(x)\n            x := shr(159, shl(r, x))\n\n            // Evaluate using a (8, 8)-term rational approximation.\n            // `p` is made monic, we will multiply by a scale factor later.\n            // forgefmt: disable-next-item\n            let p := sub( // This heavily nested expression is to avoid stack-too-deep for via-ir.\n                sar(96, mul(add(43456485725739037958740375743393,\n                sar(96, mul(add(24828157081833163892658089445524,\n                sar(96, mul(add(3273285459638523848632254066296,\n                    x), x))), x))), x)), 11111509109440967052023855526967)\n            p := sub(sar(96, mul(p, x)), 45023709667254063763336534515857)\n            p := sub(sar(96, mul(p, x)), 14706773417378608786704636184526)\n            p := sub(mul(p, x), shl(96, 795164235651350426258249787498))\n            // We leave `p` in `2**192` basis so we don't need to scale it back up for the division.\n\n            // `q` is monic by convention.\n            let q := add(5573035233440673466300451813936, x)\n            q := add(71694874799317883764090561454958, sar(96, mul(x, q)))\n            q := add(283447036172924575727196451306956, sar(96, mul(x, q)))\n            q := add(401686690394027663651624208769553, sar(96, mul(x, q)))\n            q := add(204048457590392012362485061816622, sar(96, mul(x, q)))\n            q := add(31853899698501571402653359427138, sar(96, mul(x, q)))\n            q := add(909429971244387300277376558375, sar(96, mul(x, q)))\n\n            // `p / q` is in the range `(0, 0.125) * 2**96`.\n\n            // Finalization, we need to:\n            // - Multiply by the scale factor `s = 5.549…`.\n            // - Add `ln(2**96 / 10**18)`.\n            // - Add `k * ln(2)`.\n            // - Multiply by `10**18 / 2**96 = 5**18 >> 78`.\n\n            // The q polynomial is known not to have zeros in the domain.\n            // No scaling required because p is already `2**96` too large.\n            p := sdiv(p, q)\n            // Multiply by the scaling factor: `s * 5**18 * 2**96`, base is now `5**18 * 2**192`.\n            p := mul(1677202110996718588342820967067443963516166, p)\n            // Add `ln(2) * k * 5**18 * 2**192`.\n            // forgefmt: disable-next-item\n            p := add(mul(16597577552685614221487285958193947469193820559219878177908093499208371, sub(159, r)), p)\n            // Add `ln(2**96 / 10**18) * 5**18 * 2**192`.\n            p := add(600920179829731861736702779321621459595472258049074101567377883020018308, p)\n            // Base conversion: mul `2**18 / 2**192`.\n            r := sar(174, p)\n        }\n    }\n\n    /// @dev Returns `W_0(x)`, denominated in `WAD`.\n    /// See: https://en.wikipedia.org/wiki/Lambert_W_function\n    /// a.k.a. Product log function. This is an approximation of the principal branch.\n    function lambertW0Wad(int256 x) internal pure returns (int256 w) {\n        // forgefmt: disable-next-item\n        unchecked {\n            if ((w = x) <= -367879441171442322) revert OutOfDomain(); // `x` less than `-1/e`.\n            int256 wad = int256(WAD);\n            int256 p = x;\n            uint256 c; // Whether we need to avoid catastrophic cancellation.\n            uint256 i = 4; // Number of iterations.\n            if (w <= 0x1ffffffffffff) {\n                if (-0x4000000000000 <= w) {\n                    i = 1; // Inputs near zero only take one step to converge.\n                } else if (w <= -0x3ffffffffffffff) {\n                    i = 32; // Inputs near `-1/e` take very long to converge.\n                }\n            } else if (w >> 63 == 0) {\n                /// @solidity memory-safe-assembly\n                assembly {\n                    // Inline log2 for more performance, since the range is small.\n                    let v := shr(49, w)\n                    let l := shl(3, lt(0xff, v))\n                    l := add(or(l, byte(and(0x1f, shr(shr(l, v), 0x8421084210842108cc6318c6db6d54be)),\n                        0x0706060506020504060203020504030106050205030304010505030400000000)), 49)\n                    w := sdiv(shl(l, 7), byte(sub(l, 31), 0x0303030303030303040506080c13))\n                    c := gt(l, 60)\n                    i := add(2, add(gt(l, 53), c))\n                }\n            } else {\n                int256 ll = lnWad(w = lnWad(w));\n                /// @solidity memory-safe-assembly\n                assembly {\n                    // `w = ln(x) - ln(ln(x)) + b * ln(ln(x)) / ln(x)`.\n                    w := add(sdiv(mul(ll, 1023715080943847266), w), sub(w, ll))\n                    i := add(3, iszero(shr(68, x)))\n                    c := iszero(shr(143, x))\n                }\n                if (c == 0) {\n                    do { // If `x` is big, use Newton's so that intermediate values won't overflow.\n                        int256 e = expWad(w);\n                        /// @solidity memory-safe-assembly\n                        assembly {\n                            let t := mul(w, div(e, wad))\n                            w := sub(w, sdiv(sub(t, x), div(add(e, t), wad)))\n                        }\n                        if (p <= w) break;\n                        p = w;\n                    } while (--i != 0);\n                    /// @solidity memory-safe-assembly\n                    assembly {\n                        w := sub(w, sgt(w, 2))\n                    }\n                    return w;\n                }\n            }\n            do { // Otherwise, use Halley's for faster convergence.\n                int256 e = expWad(w);\n                /// @solidity memory-safe-assembly\n                assembly {\n                    let t := add(w, wad)\n                    let s := sub(mul(w, e), mul(x, wad))\n                    w := sub(w, sdiv(mul(s, wad), sub(mul(e, t), sdiv(mul(add(t, wad), s), add(t, t)))))\n                }\n                if (p <= w) break;\n                p = w;\n            } while (--i != c);\n            /// @solidity memory-safe-assembly\n            assembly {\n                w := sub(w, sgt(w, 2))\n            }\n            // For certain ranges of `x`, we'll use the quadratic-rate recursive formula of\n            // R. Iacono and J.P. Boyd for the last iteration, to avoid catastrophic cancellation.\n            if (c != 0) {\n                int256 t = w | 1;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    x := sdiv(mul(x, wad), t)\n                }\n                x = (t * (wad + lnWad(x)));\n                /// @solidity memory-safe-assembly\n                assembly {\n                    w := sdiv(x, add(wad, t))\n                }\n            }\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  GENERAL NUMBER UTILITIES                  */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Calculates `floor(a * b / d)` with full precision.\n    /// Throws if result overflows a uint256 or when `d` is zero.\n    /// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv\n    function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for {} 1 {} {\n                // 512-bit multiply `[p1 p0] = x * y`.\n                // Compute the product mod `2**256` and mod `2**256 - 1`\n                // then use the Chinese Remainder Theorem to reconstruct\n                // the 512 bit result. The result is stored in two 256\n                // variables such that `product = p1 * 2**256 + p0`.\n\n                // Least significant 256 bits of the product.\n                result := mul(x, y) // Temporarily use `result` as `p0` to save gas.\n                let mm := mulmod(x, y, not(0))\n                // Most significant 256 bits of the product.\n                let p1 := sub(mm, add(result, lt(mm, result)))\n\n                // Handle non-overflow cases, 256 by 256 division.\n                if iszero(p1) {\n                    if iszero(d) {\n                        mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.\n                        revert(0x1c, 0x04)\n                    }\n                    result := div(result, d)\n                    break\n                }\n\n                // Make sure the result is less than `2**256`. Also prevents `d == 0`.\n                if iszero(gt(d, p1)) {\n                    mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.\n                    revert(0x1c, 0x04)\n                }\n\n                /*------------------- 512 by 256 division --------------------*/\n\n                // Make division exact by subtracting the remainder from `[p1 p0]`.\n                // Compute remainder using mulmod.\n                let r := mulmod(x, y, d)\n                // `t` is the least significant bit of `d`.\n                // Always greater or equal to 1.\n                let t := and(d, sub(0, d))\n                // Divide `d` by `t`, which is a power of two.\n                d := div(d, t)\n                // Invert `d mod 2**256`\n                // Now that `d` is an odd number, it has an inverse\n                // modulo `2**256` such that `d * inv = 1 mod 2**256`.\n                // Compute the inverse by starting with a seed that is correct\n                // correct for four bits. That is, `d * inv = 1 mod 2**4`.\n                let inv := xor(2, mul(3, d))\n                // Now use Newton-Raphson iteration to improve the precision.\n                // Thanks to Hensel's lifting lemma, this also works in modular\n                // arithmetic, doubling the correct bits in each step.\n                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8\n                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16\n                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32\n                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64\n                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128\n                result :=\n                    mul(\n                        // Divide [p1 p0] by the factors of two.\n                        // Shift in bits from `p1` into `p0`. For this we need\n                        // to flip `t` such that it is `2**256 / t`.\n                        or(\n                            mul(sub(p1, gt(r, result)), add(div(sub(0, t), t), 1)),\n                            div(sub(result, r), t)\n                        ),\n                        // inverse mod 2**256\n                        mul(inv, sub(2, mul(d, inv)))\n                    )\n                break\n            }\n        }\n    }\n\n    /// @dev Calculates `floor(x * y / d)` with full precision, rounded up.\n    /// Throws if result overflows a uint256 or when `d` is zero.\n    /// Credit to Uniswap-v3-core under MIT license:\n    /// https://github.com/Uniswap/v3-core/blob/contracts/libraries/FullMath.sol\n    function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {\n        result = fullMulDiv(x, y, d);\n        /// @solidity memory-safe-assembly\n        assembly {\n            if mulmod(x, y, d) {\n                result := add(result, 1)\n                if iszero(result) {\n                    mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n        }\n    }\n\n    /// @dev Returns `floor(x * y / d)`.\n    /// Reverts if `x * y` overflows, or `d` is zero.\n    function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {\n                mstore(0x00, 0xad251c27) // `MulDivFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := div(mul(x, y), d)\n        }\n    }\n\n    /// @dev Returns `ceil(x * y / d)`.\n    /// Reverts if `x * y` overflows, or `d` is zero.\n    function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {\n                mstore(0x00, 0xad251c27) // `MulDivFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(mul(x, y), d))), div(mul(x, y), d))\n        }\n    }\n\n    /// @dev Returns `ceil(x / d)`.\n    /// Reverts if `d` is zero.\n    function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(d) {\n                mstore(0x00, 0x65244e4e) // `DivFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(x, d))), div(x, d))\n        }\n    }\n\n    /// @dev Returns `max(0, x - y)`.\n    function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(gt(x, y), sub(x, y))\n        }\n    }\n\n    /// @dev Exponentiate `x` to `y` by squaring, denominated in base `b`.\n    /// Reverts if the computation overflows.\n    function rpow(uint256 x, uint256 y, uint256 b) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(b, iszero(y)) // `0 ** 0 = 1`. Otherwise, `0 ** n = 0`.\n            if x {\n                z := xor(b, mul(xor(b, x), and(y, 1))) // `z = isEven(y) ? scale : x`\n                let half := shr(1, b) // Divide `b` by 2.\n                // Divide `y` by 2 every iteration.\n                for { y := shr(1, y) } y { y := shr(1, y) } {\n                    let xx := mul(x, x) // Store x squared.\n                    let xxRound := add(xx, half) // Round to the nearest number.\n                    // Revert if `xx + half` overflowed, or if `x ** 2` overflows.\n                    if or(lt(xxRound, xx), shr(128, x)) {\n                        mstore(0x00, 0x49f7642b) // `RPowOverflow()`.\n                        revert(0x1c, 0x04)\n                    }\n                    x := div(xxRound, b) // Set `x` to scaled `xxRound`.\n                    // If `y` is odd:\n                    if and(y, 1) {\n                        let zx := mul(z, x) // Compute `z * x`.\n                        let zxRound := add(zx, half) // Round to the nearest number.\n                        // If `z * x` overflowed or `zx + half` overflowed:\n                        if or(xor(div(zx, x), z), lt(zxRound, zx)) {\n                            // Revert if `x` is non-zero.\n                            if iszero(iszero(x)) {\n                                mstore(0x00, 0x49f7642b) // `RPowOverflow()`.\n                                revert(0x1c, 0x04)\n                            }\n                        }\n                        z := div(zxRound, b) // Return properly scaled `zxRound`.\n                    }\n                }\n            }\n        }\n    }\n\n    /// @dev Returns the square root of `x`.\n    function sqrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`.\n            z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n            // Let `y = x / 2**r`. We check `y >= 2**(k + 8)`\n            // but shift right by `k` bits to ensure that if `x >= 256`, then `y >= 256`.\n            let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffffff, shr(r, x))))\n            z := shl(shr(1, r), z)\n\n            // Goal was to get `z*z*y` within a small factor of `x`. More iterations could\n            // get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`.\n            // We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small.\n            // That's not possible if `x < 256` but we can just verify those cases exhaustively.\n\n            // Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`.\n            // Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`.\n            // Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps.\n\n            // For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)`\n            // is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`,\n            // with largest error when `s = 1` and when `s = 256` or `1/256`.\n\n            // Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`.\n            // Then we can estimate `sqrt(y)` using\n            // `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`.\n\n            // There is no overflow risk here since `y < 2**136` after the first branch above.\n            z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181.\n\n            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n\n            // If `x+1` is a perfect square, the Babylonian method cycles between\n            // `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor.\n            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n            z := sub(z, lt(div(x, z), z))\n        }\n    }\n\n    /// @dev Returns the cube root of `x`.\n    /// Credit to bout3fiddy and pcaversaccio under AGPLv3 license:\n    /// https://github.com/pcaversaccio/snekmate/blob/main/src/utils/Math.vy\n    function cbrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(r, shl(3, lt(0xff, shr(r, x))))\n\n            z := div(shl(div(r, 3), shl(lt(0xf, shr(r, x)), 0xf)), xor(7, mod(r, 3)))\n\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n\n            z := sub(z, lt(div(x, mul(z, z)), z))\n        }\n    }\n\n    /// @dev Returns the square root of `x`, denominated in `WAD`.\n    function sqrtWad(uint256 x) internal pure returns (uint256 z) {\n        unchecked {\n            z = 10 ** 9;\n            if (x <= type(uint256).max / 10 ** 36 - 1) {\n                x *= 10 ** 18;\n                z = 1;\n            }\n            z *= sqrt(x);\n        }\n    }\n\n    /// @dev Returns the cube root of `x`, denominated in `WAD`.\n    function cbrtWad(uint256 x) internal pure returns (uint256 z) {\n        unchecked {\n            z = 10 ** 12;\n            if (x <= (type(uint256).max / 10 ** 36) * 10 ** 18 - 1) {\n                if (x >= type(uint256).max / 10 ** 36) {\n                    x *= 10 ** 18;\n                    z = 10 ** 6;\n                } else {\n                    x *= 10 ** 36;\n                    z = 1;\n                }\n            }\n            z *= cbrt(x);\n        }\n    }\n\n    /// @dev Returns the factorial of `x`.\n    function factorial(uint256 x) internal pure returns (uint256 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(lt(x, 58)) {\n                mstore(0x00, 0xaba0f2a2) // `FactorialOverflow()`.\n                revert(0x1c, 0x04)\n            }\n            for { result := 1 } x { x := sub(x, 1) } { result := mul(result, x) }\n        }\n    }\n\n    /// @dev Returns the log2 of `x`.\n    /// Equivalent to computing the index of the most significant bit (MSB) of `x`.\n    /// Returns 0 if `x` is zero.\n    function log2(uint256 x) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(r, shl(3, lt(0xff, shr(r, x))))\n            // forgefmt: disable-next-item\n            r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),\n                0x0706060506020504060203020504030106050205030304010505030400000000))\n        }\n    }\n\n    /// @dev Returns the log2 of `x`, rounded up.\n    /// Returns 0 if `x` is zero.\n    function log2Up(uint256 x) internal pure returns (uint256 r) {\n        r = log2(x);\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := add(r, lt(shl(r, 1), x))\n        }\n    }\n\n    /// @dev Returns the log10 of `x`.\n    /// Returns 0 if `x` is zero.\n    function log10(uint256 x) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(lt(x, 100000000000000000000000000000000000000)) {\n                x := div(x, 100000000000000000000000000000000000000)\n                r := 38\n            }\n            if iszero(lt(x, 100000000000000000000)) {\n                x := div(x, 100000000000000000000)\n                r := add(r, 20)\n            }\n            if iszero(lt(x, 10000000000)) {\n                x := div(x, 10000000000)\n                r := add(r, 10)\n            }\n            if iszero(lt(x, 100000)) {\n                x := div(x, 100000)\n                r := add(r, 5)\n            }\n            r := add(r, add(gt(x, 9), add(gt(x, 99), add(gt(x, 999), gt(x, 9999)))))\n        }\n    }\n\n    /// @dev Returns the log10 of `x`, rounded up.\n    /// Returns 0 if `x` is zero.\n    function log10Up(uint256 x) internal pure returns (uint256 r) {\n        r = log10(x);\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := add(r, lt(exp(10, r), x))\n        }\n    }\n\n    /// @dev Returns the log256 of `x`.\n    /// Returns 0 if `x` is zero.\n    function log256(uint256 x) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(shr(3, r), lt(0xff, shr(r, x)))\n        }\n    }\n\n    /// @dev Returns the log256 of `x`, rounded up.\n    /// Returns 0 if `x` is zero.\n    function log256Up(uint256 x) internal pure returns (uint256 r) {\n        r = log256(x);\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := add(r, lt(shl(shl(3, r), 1), x))\n        }\n    }\n\n    /// @dev Returns the scientific notation format `mantissa * 10 ** exponent` of `x`.\n    /// Useful for compressing prices (e.g. using 25 bit mantissa and 7 bit exponent).\n    function sci(uint256 x) internal pure returns (uint256 mantissa, uint256 exponent) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mantissa := x\n            if mantissa {\n                if iszero(mod(mantissa, 1000000000000000000000000000000000)) {\n                    mantissa := div(mantissa, 1000000000000000000000000000000000)\n                    exponent := 33\n                }\n                if iszero(mod(mantissa, 10000000000000000000)) {\n                    mantissa := div(mantissa, 10000000000000000000)\n                    exponent := add(exponent, 19)\n                }\n                if iszero(mod(mantissa, 1000000000000)) {\n                    mantissa := div(mantissa, 1000000000000)\n                    exponent := add(exponent, 12)\n                }\n                if iszero(mod(mantissa, 1000000)) {\n                    mantissa := div(mantissa, 1000000)\n                    exponent := add(exponent, 6)\n                }\n                if iszero(mod(mantissa, 10000)) {\n                    mantissa := div(mantissa, 10000)\n                    exponent := add(exponent, 4)\n                }\n                if iszero(mod(mantissa, 100)) {\n                    mantissa := div(mantissa, 100)\n                    exponent := add(exponent, 2)\n                }\n                if iszero(mod(mantissa, 10)) {\n                    mantissa := div(mantissa, 10)\n                    exponent := add(exponent, 1)\n                }\n            }\n        }\n    }\n\n    /// @dev Convenience function for packing `x` into a smaller number using `sci`.\n    /// The `mantissa` will be in bits [7..255] (the upper 249 bits).\n    /// The `exponent` will be in bits [0..6] (the lower 7 bits).\n    /// Use `SafeCastLib` to safely ensure that the `packed` number is small\n    /// enough to fit in the desired unsigned integer type:\n    /// ```\n    ///     uint32 packed = SafeCastLib.toUint32(FixedPointMathLib.packSci(777 ether));\n    /// ```\n    function packSci(uint256 x) internal pure returns (uint256 packed) {\n        (x, packed) = sci(x); // Reuse for `mantissa` and `exponent`.\n        /// @solidity memory-safe-assembly\n        assembly {\n            if shr(249, x) {\n                mstore(0x00, 0xce30380c) // `MantissaOverflow()`.\n                revert(0x1c, 0x04)\n            }\n            packed := or(shl(7, x), packed)\n        }\n    }\n\n    /// @dev Convenience function for unpacking a packed number from `packSci`.\n    function unpackSci(uint256 packed) internal pure returns (uint256 unpacked) {\n        unchecked {\n            unpacked = (packed >> 7) * 10 ** (packed & 0x7f);\n        }\n    }\n\n    /// @dev Returns the average of `x` and `y`.\n    function avg(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = (x & y) + ((x ^ y) >> 1);\n        }\n    }\n\n    /// @dev Returns the average of `x` and `y`.\n    function avg(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = (x >> 1) + (y >> 1) + (((x & 1) + (y & 1)) >> 1);\n        }\n    }\n\n    /// @dev Returns the absolute value of `x`.\n    function abs(int256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(sub(0, shr(255, x)), add(sub(0, shr(255, x)), x))\n        }\n    }\n\n    /// @dev Returns the absolute distance between `x` and `y`.\n    function dist(int256 x, int256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(mul(xor(sub(y, x), sub(x, y)), sgt(x, y)), sub(y, x))\n        }\n    }\n\n    /// @dev Returns the minimum of `x` and `y`.\n    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), lt(y, x)))\n        }\n    }\n\n    /// @dev Returns the minimum of `x` and `y`.\n    function min(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), slt(y, x)))\n        }\n    }\n\n    /// @dev Returns the maximum of `x` and `y`.\n    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), gt(y, x)))\n        }\n    }\n\n    /// @dev Returns the maximum of `x` and `y`.\n    function max(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), sgt(y, x)))\n        }\n    }\n\n    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.\n    function clamp(uint256 x, uint256 minValue, uint256 maxValue)\n        internal\n        pure\n        returns (uint256 z)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, minValue), gt(minValue, x)))\n            z := xor(z, mul(xor(z, maxValue), lt(maxValue, z)))\n        }\n    }\n\n    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.\n    function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, minValue), sgt(minValue, x)))\n            z := xor(z, mul(xor(z, maxValue), slt(maxValue, z)))\n        }\n    }\n\n    /// @dev Returns greatest common divisor of `x` and `y`.\n    function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for { z := x } y {} {\n                let t := y\n                y := mod(z, y)\n                z := t\n            }\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   RAW NUMBER OPERATIONS                    */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns `x + y`, without checking for overflow.\n    function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = x + y;\n        }\n    }\n\n    /// @dev Returns `x + y`, without checking for overflow.\n    function rawAdd(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = x + y;\n        }\n    }\n\n    /// @dev Returns `x - y`, without checking for underflow.\n    function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = x - y;\n        }\n    }\n\n    /// @dev Returns `x - y`, without checking for underflow.\n    function rawSub(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = x - y;\n        }\n    }\n\n    /// @dev Returns `x * y`, without checking for overflow.\n    function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = x * y;\n        }\n    }\n\n    /// @dev Returns `x * y`, without checking for overflow.\n    function rawMul(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = x * y;\n        }\n    }\n\n    /// @dev Returns `x / y`, returning 0 if `y` is zero.\n    function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := div(x, y)\n        }\n    }\n\n    /// @dev Returns `x / y`, returning 0 if `y` is zero.\n    function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := sdiv(x, y)\n        }\n    }\n\n    /// @dev Returns `x % y`, returning 0 if `y` is zero.\n    function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mod(x, y)\n        }\n    }\n\n    /// @dev Returns `x % y`, returning 0 if `y` is zero.\n    function rawSMod(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := smod(x, y)\n        }\n    }\n\n    /// @dev Returns `(x + y) % d`, return 0 if `d` if zero.\n    function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := addmod(x, y, d)\n        }\n    }\n\n    /// @dev Returns `(x * y) % d`, return 0 if `d` if zero.\n    function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mulmod(x, y, d)\n        }\n    }\n}\n"
    },
    "solady/src/utils/LibClone.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Minimal proxy library.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)\n/// @author Minimal proxy by 0age (https://github.com/0age)\n/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie\n/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)\n/// @author Minimal ERC1967 proxy by jtriley-eth (https://github.com/jtriley-eth/minimum-viable-proxy)\n///\n/// @dev Minimal proxy:\n/// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime,\n/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,\n/// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode.\n///\n/// @dev Minimal proxy (PUSH0 variant):\n/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.\n/// It is optimized first for minimal runtime gas, then for minimal bytecode.\n/// The PUSH0 clone functions are intentionally postfixed with a jarring \"_PUSH0\" as\n/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.\n/// Please use with caution.\n///\n/// @dev Clones with immutable args (CWIA):\n/// The implementation of CWIA here implements a `receive()` method that emits the\n/// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata,\n/// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards\n/// composability. The minimal proxy implementation does not offer this feature.\n///\n/// @dev Minimal ERC1967 proxy:\n/// An minimal ERC1967 proxy, intended to be upgraded with UUPS.\n/// This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.\nlibrary LibClone {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       CUSTOM ERRORS                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Unable to deploy the clone.\n    error DeploymentFailed();\n\n    /// @dev The salt must start with either the zero address or `by`.\n    error SaltDoesNotStartWith();\n\n    /// @dev The ETH transfer has failed.\n    error ETHTransferFailed();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  MINIMAL PROXY OPERATIONS                  */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Deploys a clone of `implementation`.\n    function clone(address implementation) internal returns (address instance) {\n        instance = clone(0, implementation);\n    }\n\n    /// @dev Deploys a clone of `implementation`.\n    function clone(uint256 value, address implementation) internal returns (address instance) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            /**\n             * --------------------------------------------------------------------------+\n             * CREATION (9 bytes)                                                        |\n             * --------------------------------------------------------------------------|\n             * Opcode     | Mnemonic          | Stack     | Memory                       |\n             * --------------------------------------------------------------------------|\n             * 60 runSize | PUSH1 runSize     | r         |                              |\n             * 3d         | RETURNDATASIZE    | 0 r       |                              |\n             * 81         | DUP2              | r 0 r     |                              |\n             * 60 offset  | PUSH1 offset      | o r 0 r   |                              |\n             * 3d         | RETURNDATASIZE    | 0 o r 0 r |                              |\n             * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code   |\n             * f3         | RETURN            |           | [0..runSize): runtime code   |\n             * --------------------------------------------------------------------------|\n             * RUNTIME (44 bytes)                                                        |\n             * --------------------------------------------------------------------------|\n             * Opcode  | Mnemonic       | Stack                  | Memory                |\n             * --------------------------------------------------------------------------|\n             *                                                                           |\n             * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\n             * 3d      | RETURNDATASIZE | 0                      |                       |\n             * 3d      | RETURNDATASIZE | 0 0                    |                       |\n             * 3d      | RETURNDATASIZE | 0 0 0                  |                       |\n             * 3d      | RETURNDATASIZE | 0 0 0 0                |                       |\n             *                                                                           |\n             * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\n             * 36      | CALLDATASIZE   | cds 0 0 0 0            |                       |\n             * 3d      | RETURNDATASIZE | 0 cds 0 0 0 0          |                       |\n             * 3d      | RETURNDATASIZE | 0 0 cds 0 0 0 0        |                       |\n             * 37      | CALLDATACOPY   | 0 0 0 0                | [0..cds): calldata    |\n             *                                                                           |\n             * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\n             * 36      | CALLDATASIZE   | cds 0 0 0 0            | [0..cds): calldata    |\n             * 3d      | RETURNDATASIZE | 0 cds 0 0 0 0          | [0..cds): calldata    |\n             * 73 addr | PUSH20 addr    | addr 0 cds 0 0 0 0     | [0..cds): calldata    |\n             * 5a      | GAS            | gas addr 0 cds 0 0 0 0 | [0..cds): calldata    |\n             * f4      | DELEGATECALL   | success 0 0            | [0..cds): calldata    |\n             *                                                                           |\n             * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\n             * 3d      | RETURNDATASIZE | rds success 0 0        | [0..cds): calldata    |\n             * 3d      | RETURNDATASIZE | rds rds success 0 0    | [0..cds): calldata    |\n             * 93      | SWAP4          | 0 rds success 0 rds    | [0..cds): calldata    |\n             * 80      | DUP1           | 0 0 rds success 0 rds  | [0..cds): calldata    |\n             * 3e      | RETURNDATACOPY | success 0 rds          | [0..rds): returndata  |\n             *                                                                           |\n             * 60 0x2a | PUSH1 0x2a     | 0x2a success 0 rds     | [0..rds): returndata  |\n             * 57      | JUMPI          | 0 rds                  | [0..rds): returndata  |\n             *                                                                           |\n             * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * fd      | REVERT         |                        | [0..rds): returndata  |\n             *                                                                           |\n             * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 5b      | JUMPDEST       | 0 rds                  | [0..rds): returndata  |\n             * f3      | RETURN         |                        | [0..rds): returndata  |\n             * --------------------------------------------------------------------------+\n             */\n            mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n            mstore(0x14, implementation)\n            mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n            instance := create(value, 0x0c, 0x35)\n            if iszero(instance) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.\n        }\n    }\n\n    /// @dev Deploys a deterministic clone of `implementation` with `salt`.\n    function cloneDeterministic(address implementation, bytes32 salt)\n        internal\n        returns (address instance)\n    {\n        instance = cloneDeterministic(0, implementation, salt);\n    }\n\n    /// @dev Deploys a deterministic clone of `implementation` with `salt`.\n    function cloneDeterministic(uint256 value, address implementation, bytes32 salt)\n        internal\n        returns (address instance)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n            mstore(0x14, implementation)\n            mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n            instance := create2(value, 0x0c, 0x35, salt)\n            if iszero(instance) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.\n        }\n    }\n\n    /// @dev Returns the initialization code hash of the clone of `implementation`.\n    /// Used for mining vanity addresses with create2crunch.\n    function initCodeHash(address implementation) internal pure returns (bytes32 hash) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n            mstore(0x14, implementation)\n            mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n            hash := keccak256(0x0c, 0x35)\n            mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.\n        }\n    }\n\n    /// @dev Returns the address of the deterministic clone of `implementation`,\n    /// with `salt` by `deployer`.\n    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n    function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)\n        internal\n        pure\n        returns (address predicted)\n    {\n        bytes32 hash = initCodeHash(implementation);\n        predicted = predictDeterministicAddress(hash, salt, deployer);\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*          MINIMAL PROXY OPERATIONS (PUSH0 VARIANT)          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Deploys a PUSH0 clone of `implementation`.\n    function clone_PUSH0(address implementation) internal returns (address instance) {\n        instance = clone_PUSH0(0, implementation);\n    }\n\n    /// @dev Deploys a PUSH0 clone of `implementation`.\n    function clone_PUSH0(uint256 value, address implementation)\n        internal\n        returns (address instance)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            /**\n             * --------------------------------------------------------------------------+\n             * CREATION (9 bytes)                                                        |\n             * --------------------------------------------------------------------------|\n             * Opcode     | Mnemonic          | Stack     | Memory                       |\n             * --------------------------------------------------------------------------|\n             * 60 runSize | PUSH1 runSize     | r         |                              |\n             * 5f         | PUSH0             | 0 r       |                              |\n             * 81         | DUP2              | r 0 r     |                              |\n             * 60 offset  | PUSH1 offset      | o r 0 r   |                              |\n             * 5f         | PUSH0             | 0 o r 0 r |                              |\n             * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code   |\n             * f3         | RETURN            |           | [0..runSize): runtime code   |\n             * --------------------------------------------------------------------------|\n             * RUNTIME (45 bytes)                                                        |\n             * --------------------------------------------------------------------------|\n             * Opcode  | Mnemonic       | Stack                  | Memory                |\n             * --------------------------------------------------------------------------|\n             *                                                                           |\n             * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\n             * 5f      | PUSH0          | 0                      |                       |\n             * 5f      | PUSH0          | 0 0                    |                       |\n             *                                                                           |\n             * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\n             * 36      | CALLDATASIZE   | cds 0 0                |                       |\n             * 5f      | PUSH0          | 0 cds 0 0              |                       |\n             * 5f      | PUSH0          | 0 0 cds 0 0            |                       |\n             * 37      | CALLDATACOPY   | 0 0                    | [0..cds): calldata    |\n             *                                                                           |\n             * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\n             * 36      | CALLDATASIZE   | cds 0 0                | [0..cds): calldata    |\n             * 5f      | PUSH0          | 0 cds 0 0              | [0..cds): calldata    |\n             * 73 addr | PUSH20 addr    | addr 0 cds 0 0         | [0..cds): calldata    |\n             * 5a      | GAS            | gas addr 0 cds 0 0     | [0..cds): calldata    |\n             * f4      | DELEGATECALL   | success                | [0..cds): calldata    |\n             *                                                                           |\n             * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\n             * 3d      | RETURNDATASIZE | rds success            | [0..cds): calldata    |\n             * 5f      | PUSH0          | 0 rds success          | [0..cds): calldata    |\n             * 5f      | PUSH0          | 0 0 rds success        | [0..cds): calldata    |\n             * 3e      | RETURNDATACOPY | success                | [0..rds): returndata  |\n             *                                                                           |\n             * 60 0x29 | PUSH1 0x29     | 0x29 success           | [0..rds): returndata  |\n             * 57      | JUMPI          |                        | [0..rds): returndata  |\n             *                                                                           |\n             * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 3d      | RETURNDATASIZE | rds                    | [0..rds): returndata  |\n             * 5f      | PUSH0          | 0 rds                  | [0..rds): returndata  |\n             * fd      | REVERT         |                        | [0..rds): returndata  |\n             *                                                                           |\n             * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 5b      | JUMPDEST       |                        | [0..rds): returndata  |\n             * 3d      | RETURNDATASIZE | rds                    | [0..rds): returndata  |\n             * 5f      | PUSH0          | 0 rds                  | [0..rds): returndata  |\n             * f3      | RETURN         |                        | [0..rds): returndata  |\n             * --------------------------------------------------------------------------+\n             */\n            mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n            mstore(0x14, implementation) // 20\n            mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n            instance := create(value, 0x0e, 0x36)\n            if iszero(instance) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.\n        }\n    }\n\n    /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.\n    function cloneDeterministic_PUSH0(address implementation, bytes32 salt)\n        internal\n        returns (address instance)\n    {\n        instance = cloneDeterministic_PUSH0(0, implementation, salt);\n    }\n\n    /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.\n    function cloneDeterministic_PUSH0(uint256 value, address implementation, bytes32 salt)\n        internal\n        returns (address instance)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n            mstore(0x14, implementation) // 20\n            mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n            instance := create2(value, 0x0e, 0x36, salt)\n            if iszero(instance) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.\n        }\n    }\n\n    /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.\n    /// Used for mining vanity addresses with create2crunch.\n    function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n            mstore(0x14, implementation) // 20\n            mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n            hash := keccak256(0x0e, 0x36)\n            mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.\n        }\n    }\n\n    /// @dev Returns the address of the deterministic PUSH0 clone of `implementation`,\n    /// with `salt` by `deployer`.\n    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n    function predictDeterministicAddress_PUSH0(\n        address implementation,\n        bytes32 salt,\n        address deployer\n    ) internal pure returns (address predicted) {\n        bytes32 hash = initCodeHash_PUSH0(implementation);\n        predicted = predictDeterministicAddress(hash, salt, deployer);\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*           CLONES WITH IMMUTABLE ARGS OPERATIONS            */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // Note: This implementation of CWIA differs from the original implementation.\n    // If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\n\n    /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `data`.\n    function clone(address implementation, bytes memory data) internal returns (address instance) {\n        instance = clone(0, implementation, data);\n    }\n\n    /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `data`.\n    function clone(uint256 value, address implementation, bytes memory data)\n        internal\n        returns (address instance)\n    {\n        assembly {\n            // Compute the boundaries of the data and cache the memory slots around it.\n            let mBefore3 := mload(sub(data, 0x60))\n            let mBefore2 := mload(sub(data, 0x40))\n            let mBefore1 := mload(sub(data, 0x20))\n            let dataLength := mload(data)\n            let dataEnd := add(add(data, 0x20), dataLength)\n            let mAfter1 := mload(dataEnd)\n\n            // +2 bytes for telling how much data there is appended to the call.\n            let extraLength := add(dataLength, 2)\n            // The `creationSize` is `extraLength + 108`\n            // The `runSize` is `creationSize - 10`.\n\n            /**\n             * ---------------------------------------------------------------------------------------------------+\n             * CREATION (10 bytes)                                                                                |\n             * ---------------------------------------------------------------------------------------------------|\n             * Opcode     | Mnemonic          | Stack     | Memory                                                |\n             * ---------------------------------------------------------------------------------------------------|\n             * 61 runSize | PUSH2 runSize     | r         |                                                       |\n             * 3d         | RETURNDATASIZE    | 0 r       |                                                       |\n             * 81         | DUP2              | r 0 r     |                                                       |\n             * 60 offset  | PUSH1 offset      | o r 0 r   |                                                       |\n             * 3d         | RETURNDATASIZE    | 0 o r 0 r |                                                       |\n             * 39         | CODECOPY          | 0 r       | [0..runSize): runtime code                            |\n             * f3         | RETURN            |           | [0..runSize): runtime code                            |\n             * ---------------------------------------------------------------------------------------------------|\n             * RUNTIME (98 bytes + extraLength)                                                                   |\n             * ---------------------------------------------------------------------------------------------------|\n             * Opcode   | Mnemonic       | Stack                    | Memory                                      |\n             * ---------------------------------------------------------------------------------------------------|\n             *                                                                                                    |\n             * ::: if no calldata, emit event & return w/o `DELEGATECALL` ::::::::::::::::::::::::::::::::::::::: |\n             * 36       | CALLDATASIZE   | cds                      |                                             |\n             * 60 0x2c  | PUSH1 0x2c     | 0x2c cds                 |                                             |\n             * 57       | JUMPI          |                          |                                             |\n             * 34       | CALLVALUE      | cv                       |                                             |\n             * 3d       | RETURNDATASIZE | 0 cv                     |                                             |\n             * 52       | MSTORE         |                          | [0..0x20): callvalue                        |\n             * 7f sig   | PUSH32 0x9e..  | sig                      | [0..0x20): callvalue                        |\n             * 59       | MSIZE          | 0x20 sig                 | [0..0x20): callvalue                        |\n             * 3d       | RETURNDATASIZE | 0 0x20 sig               | [0..0x20): callvalue                        |\n             * a1       | LOG1           |                          | [0..0x20): callvalue                        |\n             * 00       | STOP           |                          | [0..0x20): callvalue                        |\n             * 5b       | JUMPDEST       |                          |                                             |\n             *                                                                                                    |\n             * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 36       | CALLDATASIZE   | cds                      |                                             |\n             * 3d       | RETURNDATASIZE | 0 cds                    |                                             |\n             * 3d       | RETURNDATASIZE | 0 0 cds                  |                                             |\n             * 37       | CALLDATACOPY   |                          | [0..cds): calldata                          |\n             *                                                                                                    |\n             * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 3d       | RETURNDATASIZE | 0                        | [0..cds): calldata                          |\n             * 3d       | RETURNDATASIZE | 0 0                      | [0..cds): calldata                          |\n             * 3d       | RETURNDATASIZE | 0 0 0                    | [0..cds): calldata                          |\n             * 3d       | RETURNDATASIZE | 0 0 0 0                  | [0..cds): calldata                          |\n             * 61 extra | PUSH2 extra    | e 0 0 0 0                | [0..cds): calldata                          |\n             *                                                                                                    |\n             * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 80       | DUP1           | e e 0 0 0 0              | [0..cds): calldata                          |\n             * 60 0x62  | PUSH1 0x62     | 0x62 e e 0 0 0 0         | [0..cds): calldata                          |\n             * 36       | CALLDATASIZE   | cds 0x62 e e 0 0 0 0     | [0..cds): calldata                          |\n             * 39       | CODECOPY       | e 0 0 0 0                | [0..cds): calldata, [cds..cds+e): extraData |\n             *                                                                                                    |\n             * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 36       | CALLDATASIZE   | cds e 0 0 0 0            | [0..cds): calldata, [cds..cds+e): extraData |\n             * 01       | ADD            | cds+e 0 0 0 0            | [0..cds): calldata, [cds..cds+e): extraData |\n             * 3d       | RETURNDATASIZE | 0 cds+e 0 0 0 0          | [0..cds): calldata, [cds..cds+e): extraData |\n             * 73 addr  | PUSH20 addr    | addr 0 cds+e 0 0 0 0     | [0..cds): calldata, [cds..cds+e): extraData |\n             * 5a       | GAS            | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n             * f4       | DELEGATECALL   | success 0 0              | [0..cds): calldata, [cds..cds+e): extraData |\n             *                                                                                                    |\n             * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 3d       | RETURNDATASIZE | rds success 0 0          | [0..cds): calldata, [cds..cds+e): extraData |\n             * 3d       | RETURNDATASIZE | rds rds success 0 0      | [0..cds): calldata, [cds..cds+e): extraData |\n             * 93       | SWAP4          | 0 rds success 0 rds      | [0..cds): calldata, [cds..cds+e): extraData |\n             * 80       | DUP1           | 0 0 rds success 0 rds    | [0..cds): calldata, [cds..cds+e): extraData |\n             * 3e       | RETURNDATACOPY | success 0 rds            | [0..rds): returndata                        |\n             *                                                                                                    |\n             * 60 0x60  | PUSH1 0x60     | 0x60 success 0 rds       | [0..rds): returndata                        |\n             * 57       | JUMPI          | 0 rds                    | [0..rds): returndata                        |\n             *                                                                                                    |\n             * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * fd       | REVERT         |                          | [0..rds): returndata                        |\n             *                                                                                                    |\n             * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 5b       | JUMPDEST       | 0 rds                    | [0..rds): returndata                        |\n             * f3       | RETURN         |                          | [0..rds): returndata                        |\n             * ---------------------------------------------------------------------------------------------------+\n             */\n            mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data.\n            mstore(sub(data, 0x0d), implementation) // Write the address of the implementation.\n            // Write the rest of the bytecode.\n            mstore(\n                sub(data, 0x21),\n                or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n            )\n            // `keccak256(\"ReceiveETH(uint256)\")`\n            mstore(\n                sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n            )\n            mstore(\n                // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\n                // The actual EVM limit may be smaller and may change over time.\n                sub(data, add(0x59, lt(extraLength, 0xff9e))),\n                or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\n            )\n            mstore(dataEnd, shl(0xf0, extraLength))\n\n            instance := create(value, sub(data, 0x4c), add(extraLength, 0x6c))\n            if iszero(instance) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n\n            // Restore the overwritten memory surrounding `data`.\n            mstore(dataEnd, mAfter1)\n            mstore(data, dataLength)\n            mstore(sub(data, 0x20), mBefore1)\n            mstore(sub(data, 0x40), mBefore2)\n            mstore(sub(data, 0x60), mBefore3)\n        }\n    }\n\n    /// @dev Deploys a deterministic clone of `implementation`\n    /// with immutable arguments encoded in `data` and `salt`.\n    function cloneDeterministic(address implementation, bytes memory data, bytes32 salt)\n        internal\n        returns (address instance)\n    {\n        instance = cloneDeterministic(0, implementation, data, salt);\n    }\n\n    /// @dev Deploys a deterministic clone of `implementation`\n    /// with immutable arguments encoded in `data` and `salt`.\n    function cloneDeterministic(\n        uint256 value,\n        address implementation,\n        bytes memory data,\n        bytes32 salt\n    ) internal returns (address instance) {\n        assembly {\n            // Compute the boundaries of the data and cache the memory slots around it.\n            let mBefore3 := mload(sub(data, 0x60))\n            let mBefore2 := mload(sub(data, 0x40))\n            let mBefore1 := mload(sub(data, 0x20))\n            let dataLength := mload(data)\n            let dataEnd := add(add(data, 0x20), dataLength)\n            let mAfter1 := mload(dataEnd)\n\n            // +2 bytes for telling how much data there is appended to the call.\n            let extraLength := add(dataLength, 2)\n\n            mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data.\n            mstore(sub(data, 0x0d), implementation) // Write the address of the implementation.\n            // Write the rest of the bytecode.\n            mstore(\n                sub(data, 0x21),\n                or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n            )\n            // `keccak256(\"ReceiveETH(uint256)\")`\n            mstore(\n                sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n            )\n            mstore(\n                // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\n                // The actual EVM limit may be smaller and may change over time.\n                sub(data, add(0x59, lt(extraLength, 0xff9e))),\n                or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\n            )\n            mstore(dataEnd, shl(0xf0, extraLength))\n\n            instance := create2(value, sub(data, 0x4c), add(extraLength, 0x6c), salt)\n            if iszero(instance) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n\n            // Restore the overwritten memory surrounding `data`.\n            mstore(dataEnd, mAfter1)\n            mstore(data, dataLength)\n            mstore(sub(data, 0x20), mBefore1)\n            mstore(sub(data, 0x40), mBefore2)\n            mstore(sub(data, 0x60), mBefore3)\n        }\n    }\n\n    /// @dev Returns the initialization code hash of the clone of `implementation`\n    /// using immutable arguments encoded in `data`.\n    /// Used for mining vanity addresses with create2crunch.\n    function initCodeHash(address implementation, bytes memory data)\n        internal\n        pure\n        returns (bytes32 hash)\n    {\n        assembly {\n            // Compute the boundaries of the data and cache the memory slots around it.\n            let mBefore3 := mload(sub(data, 0x60))\n            let mBefore2 := mload(sub(data, 0x40))\n            let mBefore1 := mload(sub(data, 0x20))\n            let dataLength := mload(data)\n            let dataEnd := add(add(data, 0x20), dataLength)\n            let mAfter1 := mload(dataEnd)\n\n            // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b.\n            // The actual EVM limit may be smaller and may change over time.\n            returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b))\n\n            // +2 bytes for telling how much data there is appended to the call.\n            let extraLength := add(dataLength, 2)\n\n            mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data.\n            mstore(sub(data, 0x0d), implementation) // Write the address of the implementation.\n            // Write the rest of the bytecode.\n            mstore(\n                sub(data, 0x21),\n                or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n            )\n            // `keccak256(\"ReceiveETH(uint256)\")`\n            mstore(\n                sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n            )\n            mstore(\n                sub(data, 0x5a),\n                or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)\n            )\n            mstore(dataEnd, shl(0xf0, extraLength))\n\n            hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c))\n\n            // Restore the overwritten memory surrounding `data`.\n            mstore(dataEnd, mAfter1)\n            mstore(data, dataLength)\n            mstore(sub(data, 0x20), mBefore1)\n            mstore(sub(data, 0x40), mBefore2)\n            mstore(sub(data, 0x60), mBefore3)\n        }\n    }\n\n    /// @dev Returns the address of the deterministic clone of\n    /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`.\n    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n    function predictDeterministicAddress(\n        address implementation,\n        bytes memory data,\n        bytes32 salt,\n        address deployer\n    ) internal pure returns (address predicted) {\n        bytes32 hash = initCodeHash(implementation, data);\n        predicted = predictDeterministicAddress(hash, salt, deployer);\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*              MINIMAL ERC1967 PROXY OPERATIONS              */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // Note: The ERC1967 proxy here is intended to be upgraded with UUPS.\n    // This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.\n\n    /// @dev Deploys a minimal ERC1967 proxy with `implementation`.\n    function deployERC1967(address implementation) internal returns (address instance) {\n        instance = deployERC1967(0, implementation);\n    }\n\n    /// @dev Deploys a minimal ERC1967 proxy with `implementation`.\n    function deployERC1967(uint256 value, address implementation)\n        internal\n        returns (address instance)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            /**\n             * ---------------------------------------------------------------------------------+\n             * CREATION (34 bytes)                                                              |\n             * ---------------------------------------------------------------------------------|\n             * Opcode     | Mnemonic       | Stack            | Memory                          |\n             * ---------------------------------------------------------------------------------|\n             * 60 runSize | PUSH1 runSize  | r                |                                 |\n             * 3d         | RETURNDATASIZE | 0 r              |                                 |\n             * 81         | DUP2           | r 0 r            |                                 |\n             * 60 offset  | PUSH1 offset   | o r 0 r          |                                 |\n             * 3d         | RETURNDATASIZE | 0 o r 0 r        |                                 |\n             * 39         | CODECOPY       | 0 r              | [0..runSize): runtime code      |\n             * 73 impl    | PUSH20 impl    | impl 0 r         | [0..runSize): runtime code      |\n             * 60 slotPos | PUSH1 slotPos  | slotPos impl 0 r | [0..runSize): runtime code      |\n             * 51         | MLOAD          | slot impl 0 r    | [0..runSize): runtime code      |\n             * 55         | SSTORE         | 0 r              | [0..runSize): runtime code      |\n             * f3         | RETURN         |                  | [0..runSize): runtime code      |\n             * ---------------------------------------------------------------------------------|\n             * RUNTIME (62 bytes)                                                               |\n             * ---------------------------------------------------------------------------------|\n             * Opcode     | Mnemonic       | Stack            | Memory                          |\n             * ---------------------------------------------------------------------------------|\n             *                                                                                  |\n             * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 36         | CALLDATASIZE   | cds              |                                 |\n             * 3d         | RETURNDATASIZE | 0 cds            |                                 |\n             * 3d         | RETURNDATASIZE | 0 0 cds          |                                 |\n             * 37         | CALLDATACOPY   |                  | [0..calldatasize): calldata     |\n             *                                                                                  |\n             * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |\n             * 3d         | RETURNDATASIZE | 0                |                                 |\n             * 3d         | RETURNDATASIZE | 0 0              |                                 |\n             * 36         | CALLDATASIZE   | cds 0 0          | [0..calldatasize): calldata     |\n             * 3d         | RETURNDATASIZE | 0 cds 0 0        | [0..calldatasize): calldata     |\n             * 7f slot    | PUSH32 slot    | s 0 cds 0 0      | [0..calldatasize): calldata     |\n             * 54         | SLOAD          | i 0 cds 0 0      | [0..calldatasize): calldata     |\n             * 5a         | GAS            | g i 0 cds 0 0    | [0..calldatasize): calldata     |\n             * f4         | DELEGATECALL   | succ             | [0..calldatasize): calldata     |\n             *                                                                                  |\n             * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 3d         | RETURNDATASIZE | rds succ         | [0..calldatasize): calldata     |\n             * 60 0x00    | PUSH1 0x00     | 0 rds succ       | [0..calldatasize): calldata     |\n             * 80         | DUP1           | 0 0 rds succ     | [0..calldatasize): calldata     |\n             * 3e         | RETURNDATACOPY | succ             | [0..returndatasize): returndata |\n             *                                                                                  |\n             * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |\n             * 60 0x38    | PUSH1 0x38     | dest succ        | [0..returndatasize): returndata |\n             * 57         | JUMPI          |                  | [0..returndatasize): returndata |\n             *                                                                                  |\n             * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |\n             * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |\n             * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |\n             * fd         | REVERT         |                  | [0..returndatasize): returndata |\n             *                                                                                  |\n             * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |\n             * 5b         | JUMPDEST       |                  | [0..returndatasize): returndata |\n             * 3d         | RETURNDATASIZE | rds              | [0..returndatasize): returndata |\n             * 60 0x00    | PUSH1 0x00     | 0 rds            | [0..returndatasize): returndata |\n             * f3         | RETURN         |                  | [0..returndatasize): returndata |\n             * ---------------------------------------------------------------------------------+\n             */\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n            mstore(0x20, 0x6009)\n            mstore(0x1e, implementation)\n            mstore(0x0a, 0x603d3d8160223d3973)\n            instance := create(value, 0x21, 0x5f)\n            if iszero(instance) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x40, m) // Restore the free memory pointer.\n            mstore(0x60, 0) // Restore the zero slot.\n        }\n    }\n\n    /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.\n    function deployDeterministicERC1967(address implementation, bytes32 salt)\n        internal\n        returns (address instance)\n    {\n        instance = deployDeterministicERC1967(0, implementation, salt);\n    }\n\n    /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.\n    function deployDeterministicERC1967(uint256 value, address implementation, bytes32 salt)\n        internal\n        returns (address instance)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n            mstore(0x20, 0x6009)\n            mstore(0x1e, implementation)\n            mstore(0x0a, 0x603d3d8160223d3973)\n            instance := create2(value, 0x21, 0x5f, salt)\n            if iszero(instance) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x40, m) // Restore the free memory pointer.\n            mstore(0x60, 0) // Restore the zero slot.\n        }\n    }\n\n    /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.\n    /// Note: This method is intended for use in ERC4337 factories,\n    /// which are expected to NOT revert if the proxy is already deployed.\n    function createDeterministicERC1967(address implementation, bytes32 salt)\n        internal\n        returns (bool alreadyDeployed, address instance)\n    {\n        return createDeterministicERC1967(0, implementation, salt);\n    }\n\n    /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.\n    /// Note: This method is intended for use in ERC4337 factories,\n    /// which are expected to NOT revert if the proxy is already deployed.\n    function createDeterministicERC1967(uint256 value, address implementation, bytes32 salt)\n        internal\n        returns (bool alreadyDeployed, address instance)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n            mstore(0x20, 0x6009)\n            mstore(0x1e, implementation)\n            mstore(0x0a, 0x603d3d8160223d3973)\n            // Compute and store the bytecode hash.\n            mstore(add(m, 0x35), keccak256(0x21, 0x5f))\n            mstore(m, shl(88, address()))\n            mstore8(m, 0xff) // Write the prefix.\n            mstore(add(m, 0x15), salt)\n            instance := keccak256(m, 0x55)\n            for {} 1 {} {\n                if iszero(extcodesize(instance)) {\n                    instance := create2(value, 0x21, 0x5f, salt)\n                    if iszero(instance) {\n                        mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                        revert(0x1c, 0x04)\n                    }\n                    break\n                }\n                alreadyDeployed := 1\n                if iszero(value) { break }\n                if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {\n                    mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n                    revert(0x1c, 0x04)\n                }\n                break\n            }\n            mstore(0x40, m) // Restore the free memory pointer.\n            mstore(0x60, 0) // Restore the zero slot.\n        }\n    }\n\n    /// @dev Returns the initialization code hash of the clone of `implementation`\n    /// using immutable arguments encoded in `data`.\n    /// Used for mining vanity addresses with create2crunch.\n    function initCodeHashERC1967(address implementation) internal pure returns (bytes32 hash) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)\n            mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)\n            mstore(0x20, 0x6009)\n            mstore(0x1e, implementation)\n            mstore(0x0a, 0x603d3d8160223d3973)\n            hash := keccak256(0x21, 0x5f)\n            mstore(0x40, m) // Restore the free memory pointer.\n            mstore(0x60, 0) // Restore the zero slot.\n        }\n    }\n\n    /// @dev Returns the address of the deterministic clone of\n    /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`.\n    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n    function predictDeterministicAddressERC1967(\n        address implementation,\n        bytes32 salt,\n        address deployer\n    ) internal pure returns (address predicted) {\n        bytes32 hash = initCodeHashERC1967(implementation);\n        predicted = predictDeterministicAddress(hash, salt, deployer);\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                      OTHER OPERATIONS                      */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the address when a contract with initialization code hash,\n    /// `hash`, is deployed with `salt`, by `deployer`.\n    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n    function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)\n        internal\n        pure\n        returns (address predicted)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute and store the bytecode hash.\n            mstore8(0x00, 0xff) // Write the prefix.\n            mstore(0x35, hash)\n            mstore(0x01, shl(96, deployer))\n            mstore(0x15, salt)\n            predicted := keccak256(0x00, 0x55)\n            mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.\n        }\n    }\n\n    /// @dev Requires that `salt` starts with either the zero address or `by`.\n    function checkStartsWith(bytes32 salt, address by) internal pure {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // If the salt does not start with the zero address or `by`.\n            if iszero(or(iszero(shr(96, salt)), eq(shr(96, shl(96, by)), shr(96, salt)))) {\n                mstore(0x00, 0x0c4549ef) // `SaltDoesNotStartWith()`.\n                revert(0x1c, 0x04)\n            }\n        }\n    }\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 5000
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "storageLayout",
          "devdoc",
          "userdoc",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    }
  }
}