ETH Price: $2,233.58 (-2.36%)

Transaction Decoder

Block:
15711937 at Oct-09-2022 05:09:59 PM +UTC
Transaction Fee:
0.0046996278457128 ETH $10.50
Gas Used:
151,745 Gas / 30.97056144 Gwei

Emitted Events:

429 TransparentUpgradeableProxy.0x5e3c1311ea442664e8b1611bfabef659120ea7a0a2cfc0667700bebc69cbffe1( 0x5e3c1311ea442664e8b1611bfabef659120ea7a0a2cfc0667700bebc69cbffe1, 0x000000000000000000000000000000000000000000000000000000000000bbad, 0x1a94b7b7e43e860aa57726a5ba854c5161b3e12cf4ebd490ac53fef9f0b20f75, 000000000000000000000000211e1c4c7f1bf5351ac850ed10fd68cffcf6c21b, 000000000000000000000000000000000000000000000000000000000000000d, 000000000000000000000000a4baa0cf4e84967ff0c01790778d65b2889da503, d1d06ea3270ae98410c5ef506cae3d562a524adb7cca7ec9c9441befbd454fbd, 000000000000000000000000000000000000000000000000000000071becba09, 0000000000000000000000000000000000000000000000000000000063430067 )
430 TransparentUpgradeableProxy.0xff64905f73a67fb594e0f940a8075a860db489ad991e032f48c81123eb52d60b( 0xff64905f73a67fb594e0f940a8075a860db489ad991e032f48c81123eb52d60b, 0x000000000000000000000000000000000000000000000000000000000000bbad, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000094, 0000000000000000000000000000000000000000000000000000000063430067, a4baa0cf4e84967ff0c01790778d65b2889da5033c03b30868655b1ddf369066, 6d9bb8465e4815aed13c579adba7b5e604f6a25b000000000000000000000000, 0000000000000000000000000000000000000c42000000000000000000000000, 000000000000000000000000000000071becba09000000000000000000000000 )
431 TransparentUpgradeableProxy.0x7394f4a19a13c7b92b5bb71033245305946ef78452f7b4986ac1390b5df4ebd7( 0x7394f4a19a13c7b92b5bb71033245305946ef78452f7b4986ac1390b5df4ebd7, 0x0000000000000000000000000000000000000000000000000000000000000c42, 0x44dd3f5f126be73fc9594f005cc09b220f38006f4941eebcbb124bf41ab46d5d, 0x5e46b7ac5e50dc2596588c25c7b91248a65e3e6d581c37b937a9935e02255099, 0c3009bb04e0ab56b1ecab9a9f13636adbf8768e2cae33948fc5cbacc3f28469, 000000000000000000000000000000000000000000000000000000000000bbac, 000000000000000000000000000000000000000000000000000000006341aee7, 0000000000000000000000000000000000000000000000000000000063430e77, 0000000000000000000000000000000000000000000000000000000000efa841, 0000000000000000000000000000000000000000000000000000000000efbecd, 0000000000000000000000000000000000000000000000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x211E1c4c...FfCF6c21b
(Arbitrum Nova: Sequencer Inbox)
(Coinbase: MEV Builder)
0.1069266213564078 Eth0.106992978142176975 Eth0.000066356785769175
0xa4baa0CF...2889da503
9.20033545967193708 Eth
Nonce: 3168
9.19563583182622428 Eth
Nonce: 3169
0.0046996278457128
0xC1Ebd02f...7DdE276Bd
(Arbitrum Nova: Bridge)

Execution Trace

TransparentUpgradeableProxy.8f111f3c( )
  • SequencerInbox.addSequencerL2BatchFromOrigin( sequenceNumber=3138, data=0x88FEE434CDCA7BBDFF8F4C5236033A466D458B89B972FE8226D7BC7DA630096BB0E30DA10B039F90D1B6CE0E108088F572676F43E8C6D9B730BD10DE6A595AB404000000006356C6E001000000000000005F06B77F4B23FF25447662529BDDB4635C276673A3951010DB3FE4EC9DBF6BB8C7A2D49739997A1E77AB646C0FF394D41916F91945D2AA43F092179B137A63A58BF17506259BF4D6E1A8CC7F0AFCB30A634D4CD9E4E26A8BECA543B0354421D467, afterDelayedMessagesRead=48044, gasRefunder=0x0000000000000000000000000000000000000000, prevMessageCount=568474, newMessageCount=568615 )
    • TransparentUpgradeableProxy.STATICCALL( )
      • Bridge.DELEGATECALL( )
      • TransparentUpgradeableProxy.86598a56( )
        • Bridge.enqueueSequencerMessage( dataHash=3C03B30868655B1DDF3690666D9BB8465E4815AED13C579ADBA7B5E604F6A25B, afterDelayedMessagesRead=48044, prevMessageCount=568474, newMessageCount=568615 ) => ( seqMessageIndex=3138, beforeAcc=44DD3F5F126BE73FC9594F005CC09B220F38006F4941EEBCBB124BF41AB46D5D, delayedAcc=0C3009BB04E0AB56B1ECAB9A9F13636ADBF8768E2CAE33948FC5CBACC3F28469, acc=5E46B7AC5E50DC2596588C25C7B91248A65E3E6D581C37B937A9935E02255099 )
        • TransparentUpgradeableProxy.7a88b107( )
          • Bridge.submitBatchSpendingReport( sender=0xa4baa0CF4e84967fF0c01790778D65B2889da503, messageDataHash=D1D06EA3270AE98410C5EF506CAE3D562A524ADB7CCA7EC9C9441BEFBD454FBD ) => ( 48045 )
            addSequencerL2BatchFromOrigin[SequencerInbox (ln:154)]
            File 1 of 4: TransparentUpgradeableProxy
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)
            pragma solidity ^0.8.0;
            import "../ERC1967/ERC1967Proxy.sol";
            /**
             * @dev This contract implements a proxy that is upgradeable by an admin.
             *
             * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
             * clashing], which can potentially be used in an attack, this contract uses the
             * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
             * things that go hand in hand:
             *
             * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
             * that call matches one of the admin functions exposed by the proxy itself.
             * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
             * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
             * "admin cannot fallback to proxy target".
             *
             * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
             * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
             * to sudden errors when trying to call a function from the proxy implementation.
             *
             * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
             * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
             */
            contract TransparentUpgradeableProxy is ERC1967Proxy {
                /**
                 * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
                 * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
                 */
                constructor(
                    address _logic,
                    address admin_,
                    bytes memory _data
                ) payable ERC1967Proxy(_logic, _data) {
                    assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
                    _changeAdmin(admin_);
                }
                /**
                 * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
                 */
                modifier ifAdmin() {
                    if (msg.sender == _getAdmin()) {
                        _;
                    } else {
                        _fallback();
                    }
                }
                /**
                 * @dev Returns the current admin.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
                 *
                 * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                 * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                 * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
                 */
                function admin() external ifAdmin returns (address admin_) {
                    admin_ = _getAdmin();
                }
                /**
                 * @dev Returns the current implementation.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
                 *
                 * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                 * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                 * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
                 */
                function implementation() external ifAdmin returns (address implementation_) {
                    implementation_ = _implementation();
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {AdminChanged} event.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
                 */
                function changeAdmin(address newAdmin) external virtual ifAdmin {
                    _changeAdmin(newAdmin);
                }
                /**
                 * @dev Upgrade the implementation of the proxy.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
                 */
                function upgradeTo(address newImplementation) external ifAdmin {
                    _upgradeToAndCall(newImplementation, bytes(""), false);
                }
                /**
                 * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
                 * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
                 * proxied contract.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
                 */
                function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {
                    _upgradeToAndCall(newImplementation, data, true);
                }
                /**
                 * @dev Returns the current admin.
                 */
                function _admin() internal view virtual returns (address) {
                    return _getAdmin();
                }
                /**
                 * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
                 */
                function _beforeFallback() internal virtual override {
                    require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
                    super._beforeFallback();
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)
            pragma solidity ^0.8.0;
            import "../Proxy.sol";
            import "./ERC1967Upgrade.sol";
            /**
             * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
             * implementation address that can be changed. This address is stored in storage in the location specified by
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
             * implementation behind the proxy.
             */
            contract ERC1967Proxy is Proxy, ERC1967Upgrade {
                /**
                 * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
                 *
                 * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
                 * function call, and allows initializating the storage of the proxy like a Solidity constructor.
                 */
                constructor(address _logic, bytes memory _data) payable {
                    assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
                    _upgradeToAndCall(_logic, _data, false);
                }
                /**
                 * @dev Returns the current implementation address.
                 */
                function _implementation() internal view virtual override returns (address impl) {
                    return ERC1967Upgrade._getImplementation();
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
             * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
             * be specified by overriding the virtual {_implementation} function.
             *
             * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
             * different contract through the {_delegate} function.
             *
             * The success and return data of the delegated call will be returned back to the caller of the proxy.
             */
            abstract contract Proxy {
                /**
                 * @dev Delegates the current call to `implementation`.
                 *
                 * This function does not return to its internal call site, it will return directly to the external caller.
                 */
                function _delegate(address implementation) internal virtual {
                    assembly {
                        // Copy msg.data. We take full control of memory in this inline assembly
                        // block because it will not return to Solidity code. We overwrite the
                        // Solidity scratch pad at memory position 0.
                        calldatacopy(0, 0, calldatasize())
                        // Call the implementation.
                        // out and outsize are 0 because we don't know the size yet.
                        let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                        // Copy the returned data.
                        returndatacopy(0, 0, returndatasize())
                        switch result
                        // delegatecall returns 0 on error.
                        case 0 {
                            revert(0, returndatasize())
                        }
                        default {
                            return(0, returndatasize())
                        }
                    }
                }
                /**
                 * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
                 * and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual returns (address);
                /**
                 * @dev Delegates the current call to the address returned by `_implementation()`.
                 *
                 * This function does not return to its internall call site, it will return directly to the external caller.
                 */
                function _fallback() internal virtual {
                    _beforeFallback();
                    _delegate(_implementation());
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                 * function in the contract matches the call data.
                 */
                fallback() external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                 * is empty.
                 */
                receive() external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                 * call, or as part of the Solidity `fallback` or `receive` functions.
                 *
                 * If overriden should call `super._beforeFallback()`.
                 */
                function _beforeFallback() internal virtual {}
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
            pragma solidity ^0.8.2;
            import "../beacon/IBeacon.sol";
            import "../../interfaces/draft-IERC1822.sol";
            import "../../utils/Address.sol";
            import "../../utils/StorageSlot.sol";
            /**
             * @dev This abstract contract provides getters and event emitting update functions for
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
             *
             * _Available since v4.1._
             *
             * @custom:oz-upgrades-unsafe-allow delegatecall
             */
            abstract contract ERC1967Upgrade {
                // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
                bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
                /**
                 * @dev Storage slot with the address of the current implementation.
                 * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                /**
                 * @dev Emitted when the implementation is upgraded.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Returns the current implementation address.
                 */
                function _getImplementation() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 implementation slot.
                 */
                function _setImplementation(address newImplementation) private {
                    require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                    StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                }
                /**
                 * @dev Perform implementation upgrade
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeTo(address newImplementation) internal {
                    _setImplementation(newImplementation);
                    emit Upgraded(newImplementation);
                }
                /**
                 * @dev Perform implementation upgrade with additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCall(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _upgradeTo(newImplementation);
                    if (data.length > 0 || forceCall) {
                        Address.functionDelegateCall(newImplementation, data);
                    }
                }
                /**
                 * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCallUUPS(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    // Upgrades from old implementations will perform a rollback test. This test requires the new
                    // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
                    // this special case will break upgrade paths from old UUPS implementation to new ones.
                    if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
                        _setImplementation(newImplementation);
                    } else {
                        try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                            require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
                        } catch {
                            revert("ERC1967Upgrade: new implementation is not UUPS");
                        }
                        _upgradeToAndCall(newImplementation, data, forceCall);
                    }
                }
                /**
                 * @dev Storage slot with the admin of the contract.
                 * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                /**
                 * @dev Emitted when the admin account has changed.
                 */
                event AdminChanged(address previousAdmin, address newAdmin);
                /**
                 * @dev Returns the current admin.
                 */
                function _getAdmin() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 admin slot.
                 */
                function _setAdmin(address newAdmin) private {
                    require(newAdmin != address(0), "ERC1967: new admin is the zero address");
                    StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {AdminChanged} event.
                 */
                function _changeAdmin(address newAdmin) internal {
                    emit AdminChanged(_getAdmin(), newAdmin);
                    _setAdmin(newAdmin);
                }
                /**
                 * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                 * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
                 */
                bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                /**
                 * @dev Emitted when the beacon is upgraded.
                 */
                event BeaconUpgraded(address indexed beacon);
                /**
                 * @dev Returns the current beacon.
                 */
                function _getBeacon() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
                }
                /**
                 * @dev Stores a new beacon in the EIP1967 beacon slot.
                 */
                function _setBeacon(address newBeacon) private {
                    require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
                    require(
                        Address.isContract(IBeacon(newBeacon).implementation()),
                        "ERC1967: beacon implementation is not a contract"
                    );
                    StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
                }
                /**
                 * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
                 * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
                 *
                 * Emits a {BeaconUpgraded} event.
                 */
                function _upgradeBeaconToAndCall(
                    address newBeacon,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _setBeacon(newBeacon);
                    emit BeaconUpgraded(newBeacon);
                    if (data.length > 0 || forceCall) {
                        Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This is the interface that {BeaconProxy} expects of its beacon.
             */
            interface IBeacon {
                /**
                 * @dev Must return an address that can be used as a delegate call target.
                 *
                 * {BeaconProxy} will check that this address is a contract.
                 */
                function implementation() external view returns (address);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
             * proxy whose upgrades are fully controlled by the current implementation.
             */
            interface IERC1822Proxiable {
                /**
                 * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
                 * address.
                 *
                 * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                 * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                 * function revert if invoked through a proxy.
                 */
                function proxiableUUID() external view returns (bytes32);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
            pragma solidity ^0.8.1;
            /**
             * @dev Collection of functions related to the address type
             */
            library Address {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 *
                 * [IMPORTANT]
                 * ====
                 * You shouldn't rely on `isContract` to protect against flash loan attacks!
                 *
                 * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                 * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                 * constructor.
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize/address.code.length, which returns 0
                    // for contracts in construction, since the code is only stored at the end
                    // of the constructor execution.
                    return account.code.length > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    (bool success, ) = recipient.call{value: amount}("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain `call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionCall(target, data, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    require(isContract(target), "Address: call to non-contract");
                    (bool success, bytes memory returndata) = target.call{value: value}(data);
                    return verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    require(isContract(target), "Address: static call to non-contract");
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(isContract(target), "Address: delegate call to non-contract");
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
                 * revert reason using the provided one.
                 *
                 * _Available since v4.3._
                 */
                function verifyCallResult(
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal pure returns (bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        // Look for revert reason and bubble it up if present
                        if (returndata.length > 0) {
                            // The easiest way to bubble the revert reason is using memory via assembly
                            assembly {
                                let returndata_size := mload(returndata)
                                revert(add(32, returndata), returndata_size)
                            }
                        } else {
                            revert(errorMessage);
                        }
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Library for reading and writing primitive types to specific storage slots.
             *
             * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
             * This library helps with reading and writing to such slots without the need for inline assembly.
             *
             * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
             *
             * Example usage to set ERC1967 implementation slot:
             * ```
             * contract ERC1967 {
             *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
             *
             *     function _getImplementation() internal view returns (address) {
             *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
             *     }
             *
             *     function _setImplementation(address newImplementation) internal {
             *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
             *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
             *     }
             * }
             * ```
             *
             * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
             */
            library StorageSlot {
                struct AddressSlot {
                    address value;
                }
                struct BooleanSlot {
                    bool value;
                }
                struct Bytes32Slot {
                    bytes32 value;
                }
                struct Uint256Slot {
                    uint256 value;
                }
                /**
                 * @dev Returns an `AddressSlot` with member `value` located at `slot`.
                 */
                function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                 */
                function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                 */
                function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                 */
                function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                    assembly {
                        r.slot := slot
                    }
                }
            }
            

            File 2 of 4: TransparentUpgradeableProxy
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)
            pragma solidity ^0.8.0;
            import "../ERC1967/ERC1967Proxy.sol";
            /**
             * @dev This contract implements a proxy that is upgradeable by an admin.
             *
             * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
             * clashing], which can potentially be used in an attack, this contract uses the
             * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
             * things that go hand in hand:
             *
             * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
             * that call matches one of the admin functions exposed by the proxy itself.
             * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
             * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
             * "admin cannot fallback to proxy target".
             *
             * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
             * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
             * to sudden errors when trying to call a function from the proxy implementation.
             *
             * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
             * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
             */
            contract TransparentUpgradeableProxy is ERC1967Proxy {
                /**
                 * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
                 * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
                 */
                constructor(
                    address _logic,
                    address admin_,
                    bytes memory _data
                ) payable ERC1967Proxy(_logic, _data) {
                    assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
                    _changeAdmin(admin_);
                }
                /**
                 * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
                 */
                modifier ifAdmin() {
                    if (msg.sender == _getAdmin()) {
                        _;
                    } else {
                        _fallback();
                    }
                }
                /**
                 * @dev Returns the current admin.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
                 *
                 * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                 * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                 * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
                 */
                function admin() external ifAdmin returns (address admin_) {
                    admin_ = _getAdmin();
                }
                /**
                 * @dev Returns the current implementation.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
                 *
                 * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
                 * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                 * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
                 */
                function implementation() external ifAdmin returns (address implementation_) {
                    implementation_ = _implementation();
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {AdminChanged} event.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
                 */
                function changeAdmin(address newAdmin) external virtual ifAdmin {
                    _changeAdmin(newAdmin);
                }
                /**
                 * @dev Upgrade the implementation of the proxy.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
                 */
                function upgradeTo(address newImplementation) external ifAdmin {
                    _upgradeToAndCall(newImplementation, bytes(""), false);
                }
                /**
                 * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
                 * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
                 * proxied contract.
                 *
                 * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
                 */
                function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {
                    _upgradeToAndCall(newImplementation, data, true);
                }
                /**
                 * @dev Returns the current admin.
                 */
                function _admin() internal view virtual returns (address) {
                    return _getAdmin();
                }
                /**
                 * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
                 */
                function _beforeFallback() internal virtual override {
                    require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
                    super._beforeFallback();
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)
            pragma solidity ^0.8.0;
            import "../Proxy.sol";
            import "./ERC1967Upgrade.sol";
            /**
             * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
             * implementation address that can be changed. This address is stored in storage in the location specified by
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
             * implementation behind the proxy.
             */
            contract ERC1967Proxy is Proxy, ERC1967Upgrade {
                /**
                 * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
                 *
                 * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
                 * function call, and allows initializating the storage of the proxy like a Solidity constructor.
                 */
                constructor(address _logic, bytes memory _data) payable {
                    assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
                    _upgradeToAndCall(_logic, _data, false);
                }
                /**
                 * @dev Returns the current implementation address.
                 */
                function _implementation() internal view virtual override returns (address impl) {
                    return ERC1967Upgrade._getImplementation();
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
             * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
             * be specified by overriding the virtual {_implementation} function.
             *
             * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
             * different contract through the {_delegate} function.
             *
             * The success and return data of the delegated call will be returned back to the caller of the proxy.
             */
            abstract contract Proxy {
                /**
                 * @dev Delegates the current call to `implementation`.
                 *
                 * This function does not return to its internal call site, it will return directly to the external caller.
                 */
                function _delegate(address implementation) internal virtual {
                    assembly {
                        // Copy msg.data. We take full control of memory in this inline assembly
                        // block because it will not return to Solidity code. We overwrite the
                        // Solidity scratch pad at memory position 0.
                        calldatacopy(0, 0, calldatasize())
                        // Call the implementation.
                        // out and outsize are 0 because we don't know the size yet.
                        let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                        // Copy the returned data.
                        returndatacopy(0, 0, returndatasize())
                        switch result
                        // delegatecall returns 0 on error.
                        case 0 {
                            revert(0, returndatasize())
                        }
                        default {
                            return(0, returndatasize())
                        }
                    }
                }
                /**
                 * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
                 * and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual returns (address);
                /**
                 * @dev Delegates the current call to the address returned by `_implementation()`.
                 *
                 * This function does not return to its internall call site, it will return directly to the external caller.
                 */
                function _fallback() internal virtual {
                    _beforeFallback();
                    _delegate(_implementation());
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                 * function in the contract matches the call data.
                 */
                fallback() external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
                 * is empty.
                 */
                receive() external payable virtual {
                    _fallback();
                }
                /**
                 * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
                 * call, or as part of the Solidity `fallback` or `receive` functions.
                 *
                 * If overriden should call `super._beforeFallback()`.
                 */
                function _beforeFallback() internal virtual {}
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
            pragma solidity ^0.8.2;
            import "../beacon/IBeacon.sol";
            import "../../interfaces/draft-IERC1822.sol";
            import "../../utils/Address.sol";
            import "../../utils/StorageSlot.sol";
            /**
             * @dev This abstract contract provides getters and event emitting update functions for
             * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
             *
             * _Available since v4.1._
             *
             * @custom:oz-upgrades-unsafe-allow delegatecall
             */
            abstract contract ERC1967Upgrade {
                // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
                bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
                /**
                 * @dev Storage slot with the address of the current implementation.
                 * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                /**
                 * @dev Emitted when the implementation is upgraded.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Returns the current implementation address.
                 */
                function _getImplementation() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 implementation slot.
                 */
                function _setImplementation(address newImplementation) private {
                    require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
                    StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
                }
                /**
                 * @dev Perform implementation upgrade
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeTo(address newImplementation) internal {
                    _setImplementation(newImplementation);
                    emit Upgraded(newImplementation);
                }
                /**
                 * @dev Perform implementation upgrade with additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCall(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _upgradeTo(newImplementation);
                    if (data.length > 0 || forceCall) {
                        Address.functionDelegateCall(newImplementation, data);
                    }
                }
                /**
                 * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
                 *
                 * Emits an {Upgraded} event.
                 */
                function _upgradeToAndCallUUPS(
                    address newImplementation,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    // Upgrades from old implementations will perform a rollback test. This test requires the new
                    // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
                    // this special case will break upgrade paths from old UUPS implementation to new ones.
                    if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
                        _setImplementation(newImplementation);
                    } else {
                        try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                            require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
                        } catch {
                            revert("ERC1967Upgrade: new implementation is not UUPS");
                        }
                        _upgradeToAndCall(newImplementation, data, forceCall);
                    }
                }
                /**
                 * @dev Storage slot with the admin of the contract.
                 * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
                 * validated in the constructor.
                 */
                bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                /**
                 * @dev Emitted when the admin account has changed.
                 */
                event AdminChanged(address previousAdmin, address newAdmin);
                /**
                 * @dev Returns the current admin.
                 */
                function _getAdmin() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the EIP1967 admin slot.
                 */
                function _setAdmin(address newAdmin) private {
                    require(newAdmin != address(0), "ERC1967: new admin is the zero address");
                    StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {AdminChanged} event.
                 */
                function _changeAdmin(address newAdmin) internal {
                    emit AdminChanged(_getAdmin(), newAdmin);
                    _setAdmin(newAdmin);
                }
                /**
                 * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                 * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
                 */
                bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                /**
                 * @dev Emitted when the beacon is upgraded.
                 */
                event BeaconUpgraded(address indexed beacon);
                /**
                 * @dev Returns the current beacon.
                 */
                function _getBeacon() internal view returns (address) {
                    return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
                }
                /**
                 * @dev Stores a new beacon in the EIP1967 beacon slot.
                 */
                function _setBeacon(address newBeacon) private {
                    require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
                    require(
                        Address.isContract(IBeacon(newBeacon).implementation()),
                        "ERC1967: beacon implementation is not a contract"
                    );
                    StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
                }
                /**
                 * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
                 * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
                 *
                 * Emits a {BeaconUpgraded} event.
                 */
                function _upgradeBeaconToAndCall(
                    address newBeacon,
                    bytes memory data,
                    bool forceCall
                ) internal {
                    _setBeacon(newBeacon);
                    emit BeaconUpgraded(newBeacon);
                    if (data.length > 0 || forceCall) {
                        Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev This is the interface that {BeaconProxy} expects of its beacon.
             */
            interface IBeacon {
                /**
                 * @dev Must return an address that can be used as a delegate call target.
                 *
                 * {BeaconProxy} will check that this address is a contract.
                 */
                function implementation() external view returns (address);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
             * proxy whose upgrades are fully controlled by the current implementation.
             */
            interface IERC1822Proxiable {
                /**
                 * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
                 * address.
                 *
                 * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
                 * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
                 * function revert if invoked through a proxy.
                 */
                function proxiableUUID() external view returns (bytes32);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
            pragma solidity ^0.8.1;
            /**
             * @dev Collection of functions related to the address type
             */
            library Address {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 *
                 * [IMPORTANT]
                 * ====
                 * You shouldn't rely on `isContract` to protect against flash loan attacks!
                 *
                 * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                 * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                 * constructor.
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize/address.code.length, which returns 0
                    // for contracts in construction, since the code is only stored at the end
                    // of the constructor execution.
                    return account.code.length > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    (bool success, ) = recipient.call{value: amount}("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain `call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionCall(target, data, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    require(isContract(target), "Address: call to non-contract");
                    (bool success, bytes memory returndata) = target.call{value: value}(data);
                    return verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    require(isContract(target), "Address: static call to non-contract");
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(isContract(target), "Address: delegate call to non-contract");
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
                 * revert reason using the provided one.
                 *
                 * _Available since v4.3._
                 */
                function verifyCallResult(
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal pure returns (bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        // Look for revert reason and bubble it up if present
                        if (returndata.length > 0) {
                            // The easiest way to bubble the revert reason is using memory via assembly
                            assembly {
                                let returndata_size := mload(returndata)
                                revert(add(32, returndata), returndata_size)
                            }
                        } else {
                            revert(errorMessage);
                        }
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Library for reading and writing primitive types to specific storage slots.
             *
             * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
             * This library helps with reading and writing to such slots without the need for inline assembly.
             *
             * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
             *
             * Example usage to set ERC1967 implementation slot:
             * ```
             * contract ERC1967 {
             *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
             *
             *     function _getImplementation() internal view returns (address) {
             *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
             *     }
             *
             *     function _setImplementation(address newImplementation) internal {
             *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
             *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
             *     }
             * }
             * ```
             *
             * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
             */
            library StorageSlot {
                struct AddressSlot {
                    address value;
                }
                struct BooleanSlot {
                    bool value;
                }
                struct Bytes32Slot {
                    bytes32 value;
                }
                struct Uint256Slot {
                    uint256 value;
                }
                /**
                 * @dev Returns an `AddressSlot` with member `value` located at `slot`.
                 */
                function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                 */
                function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                 */
                function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                 */
                function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                    assembly {
                        r.slot := slot
                    }
                }
            }
            

            File 3 of 4: SequencerInbox
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import {
                AlreadyInit,
                HadZeroInit,
                NotOrigin,
                DataTooLarge,
                NotRollup,
                DelayedBackwards,
                DelayedTooFar,
                ForceIncludeBlockTooSoon,
                ForceIncludeTimeTooSoon,
                IncorrectMessagePreimage,
                NotBatchPoster,
                BadSequencerNumber,
                DataNotAuthenticated,
                AlreadyValidDASKeyset,
                NoSuchKeyset,
                NotForked
            } from "../libraries/Error.sol";
            import "./IBridge.sol";
            import "./IInbox.sol";
            import "./ISequencerInbox.sol";
            import "../rollup/IRollupLogic.sol";
            import "./Messages.sol";
            import {L1MessageType_batchPostingReport} from "../libraries/MessageTypes.sol";
            import {GasRefundEnabled, IGasRefunder} from "../libraries/IGasRefunder.sol";
            import "../libraries/DelegateCallAware.sol";
            import {MAX_DATA_SIZE} from "../libraries/Constants.sol";
            /**
             * @title Accepts batches from the sequencer and adds them to the rollup inbox.
             * @notice Contains the inbox accumulator which is the ordering of all data and transactions to be processed by the rollup.
             * As part of submitting a batch the sequencer is also expected to include items enqueued
             * in the delayed inbox (Bridge.sol). If items in the delayed inbox are not included by a
             * sequencer within a time limit they can be force included into the rollup inbox by anyone.
             */
            contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox {
                uint256 public totalDelayedMessagesRead;
                IBridge public bridge;
                /// @inheritdoc ISequencerInbox
                uint256 public constant HEADER_LENGTH = 40;
                /// @inheritdoc ISequencerInbox
                bytes1 public constant DATA_AUTHENTICATED_FLAG = 0x40;
                IOwnable public rollup;
                mapping(address => bool) public isBatchPoster;
                ISequencerInbox.MaxTimeVariation public maxTimeVariation;
                mapping(bytes32 => DasKeySetInfo) public dasKeySetInfo;
                modifier onlyRollupOwner() {
                    if (msg.sender != rollup.owner()) revert NotOwner(msg.sender, address(rollup));
                    _;
                }
                uint256 internal immutable deployTimeChainId = block.chainid;
                function _chainIdChanged() internal view returns (bool) {
                    return deployTimeChainId != block.chainid;
                }
                function initialize(
                    IBridge bridge_,
                    ISequencerInbox.MaxTimeVariation calldata maxTimeVariation_
                ) external onlyDelegated {
                    if (bridge != IBridge(address(0))) revert AlreadyInit();
                    if (bridge_ == IBridge(address(0))) revert HadZeroInit();
                    bridge = bridge_;
                    rollup = bridge_.rollup();
                    maxTimeVariation = maxTimeVariation_;
                }
                function getTimeBounds() internal view virtual returns (TimeBounds memory) {
                    TimeBounds memory bounds;
                    if (block.timestamp > maxTimeVariation.delaySeconds) {
                        bounds.minTimestamp = uint64(block.timestamp - maxTimeVariation.delaySeconds);
                    }
                    bounds.maxTimestamp = uint64(block.timestamp + maxTimeVariation.futureSeconds);
                    if (block.number > maxTimeVariation.delayBlocks) {
                        bounds.minBlockNumber = uint64(block.number - maxTimeVariation.delayBlocks);
                    }
                    bounds.maxBlockNumber = uint64(block.number + maxTimeVariation.futureBlocks);
                    return bounds;
                }
                /// @inheritdoc ISequencerInbox
                function removeDelayAfterFork() external {
                    if (!_chainIdChanged()) revert NotForked();
                    maxTimeVariation = ISequencerInbox.MaxTimeVariation({
                        delayBlocks: 1,
                        futureBlocks: 1,
                        delaySeconds: 1,
                        futureSeconds: 1
                    });
                }
                /// @inheritdoc ISequencerInbox
                function forceInclusion(
                    uint256 _totalDelayedMessagesRead,
                    uint8 kind,
                    uint64[2] calldata l1BlockAndTime,
                    uint256 baseFeeL1,
                    address sender,
                    bytes32 messageDataHash
                ) external {
                    if (_totalDelayedMessagesRead <= totalDelayedMessagesRead) revert DelayedBackwards();
                    bytes32 messageHash = Messages.messageHash(
                        kind,
                        sender,
                        l1BlockAndTime[0],
                        l1BlockAndTime[1],
                        _totalDelayedMessagesRead - 1,
                        baseFeeL1,
                        messageDataHash
                    );
                    // Can only force-include after the Sequencer-only window has expired.
                    if (l1BlockAndTime[0] + maxTimeVariation.delayBlocks >= block.number)
                        revert ForceIncludeBlockTooSoon();
                    if (l1BlockAndTime[1] + maxTimeVariation.delaySeconds >= block.timestamp)
                        revert ForceIncludeTimeTooSoon();
                    // Verify that message hash represents the last message sequence of delayed message to be included
                    bytes32 prevDelayedAcc = 0;
                    if (_totalDelayedMessagesRead > 1) {
                        prevDelayedAcc = bridge.delayedInboxAccs(_totalDelayedMessagesRead - 2);
                    }
                    if (
                        bridge.delayedInboxAccs(_totalDelayedMessagesRead - 1) !=
                        Messages.accumulateInboxMessage(prevDelayedAcc, messageHash)
                    ) revert IncorrectMessagePreimage();
                    (bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(
                        _totalDelayedMessagesRead
                    );
                    uint256 __totalDelayedMessagesRead = _totalDelayedMessagesRead;
                    uint256 prevSeqMsgCount = bridge.sequencerReportedSubMessageCount();
                    uint256 newSeqMsgCount = prevSeqMsgCount +
                        _totalDelayedMessagesRead -
                        totalDelayedMessagesRead;
                    (
                        uint256 seqMessageIndex,
                        bytes32 beforeAcc,
                        bytes32 delayedAcc,
                        bytes32 afterAcc
                    ) = addSequencerL2BatchImpl(
                            dataHash,
                            __totalDelayedMessagesRead,
                            0,
                            prevSeqMsgCount,
                            newSeqMsgCount
                        );
                    emit SequencerBatchDelivered(
                        seqMessageIndex,
                        beforeAcc,
                        afterAcc,
                        delayedAcc,
                        totalDelayedMessagesRead,
                        timeBounds,
                        BatchDataLocation.NoData
                    );
                }
                /// @dev Deprecated in favor of the variant specifying message counts for consistency
                function addSequencerL2BatchFromOrigin(
                    uint256 sequenceNumber,
                    bytes calldata data,
                    uint256 afterDelayedMessagesRead,
                    IGasRefunder gasRefunder
                ) external refundsGas(gasRefunder) {
                    // solhint-disable-next-line avoid-tx-origin
                    if (msg.sender != tx.origin) revert NotOrigin();
                    if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
                    (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
                        data,
                        afterDelayedMessagesRead
                    );
                    (
                        uint256 seqMessageIndex,
                        bytes32 beforeAcc,
                        bytes32 delayedAcc,
                        bytes32 afterAcc
                    ) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, data.length, 0, 0);
                    if (seqMessageIndex != sequenceNumber)
                        revert BadSequencerNumber(seqMessageIndex, sequenceNumber);
                    emit SequencerBatchDelivered(
                        sequenceNumber,
                        beforeAcc,
                        afterAcc,
                        delayedAcc,
                        totalDelayedMessagesRead,
                        timeBounds,
                        BatchDataLocation.TxInput
                    );
                }
                function addSequencerL2BatchFromOrigin(
                    uint256 sequenceNumber,
                    bytes calldata data,
                    uint256 afterDelayedMessagesRead,
                    IGasRefunder gasRefunder,
                    uint256 prevMessageCount,
                    uint256 newMessageCount
                ) external refundsGas(gasRefunder) {
                    // solhint-disable-next-line avoid-tx-origin
                    if (msg.sender != tx.origin) revert NotOrigin();
                    if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
                    (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
                        data,
                        afterDelayedMessagesRead
                    );
                    // Reformat the stack to prevent "Stack too deep"
                    uint256 sequenceNumber_ = sequenceNumber;
                    TimeBounds memory timeBounds_ = timeBounds;
                    bytes32 dataHash_ = dataHash;
                    uint256 dataLength = data.length;
                    uint256 afterDelayedMessagesRead_ = afterDelayedMessagesRead;
                    uint256 prevMessageCount_ = prevMessageCount;
                    uint256 newMessageCount_ = newMessageCount;
                    (
                        uint256 seqMessageIndex,
                        bytes32 beforeAcc,
                        bytes32 delayedAcc,
                        bytes32 afterAcc
                    ) = addSequencerL2BatchImpl(
                            dataHash_,
                            afterDelayedMessagesRead_,
                            dataLength,
                            prevMessageCount_,
                            newMessageCount_
                        );
                    if (seqMessageIndex != sequenceNumber_ && sequenceNumber_ != ~uint256(0))
                        revert BadSequencerNumber(seqMessageIndex, sequenceNumber_);
                    emit SequencerBatchDelivered(
                        seqMessageIndex,
                        beforeAcc,
                        afterAcc,
                        delayedAcc,
                        totalDelayedMessagesRead,
                        timeBounds_,
                        BatchDataLocation.TxInput
                    );
                }
                function addSequencerL2Batch(
                    uint256 sequenceNumber,
                    bytes calldata data,
                    uint256 afterDelayedMessagesRead,
                    IGasRefunder gasRefunder,
                    uint256 prevMessageCount,
                    uint256 newMessageCount
                ) external override refundsGas(gasRefunder) {
                    if (!isBatchPoster[msg.sender] && msg.sender != address(rollup)) revert NotBatchPoster();
                    (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
                        data,
                        afterDelayedMessagesRead
                    );
                    uint256 seqMessageIndex;
                    {
                        // Reformat the stack to prevent "Stack too deep"
                        uint256 sequenceNumber_ = sequenceNumber;
                        TimeBounds memory timeBounds_ = timeBounds;
                        bytes32 dataHash_ = dataHash;
                        uint256 afterDelayedMessagesRead_ = afterDelayedMessagesRead;
                        uint256 prevMessageCount_ = prevMessageCount;
                        uint256 newMessageCount_ = newMessageCount;
                        // we set the calldata length posted to 0 here since the caller isn't the origin
                        // of the tx, so they might have not paid tx input cost for the calldata
                        bytes32 beforeAcc;
                        bytes32 delayedAcc;
                        bytes32 afterAcc;
                        (seqMessageIndex, beforeAcc, delayedAcc, afterAcc) = addSequencerL2BatchImpl(
                            dataHash_,
                            afterDelayedMessagesRead_,
                            0,
                            prevMessageCount_,
                            newMessageCount_
                        );
                        if (seqMessageIndex != sequenceNumber_ && sequenceNumber_ != ~uint256(0))
                            revert BadSequencerNumber(seqMessageIndex, sequenceNumber_);
                        emit SequencerBatchDelivered(
                            seqMessageIndex,
                            beforeAcc,
                            afterAcc,
                            delayedAcc,
                            totalDelayedMessagesRead,
                            timeBounds_,
                            BatchDataLocation.SeparateBatchEvent
                        );
                    }
                    emit SequencerBatchData(seqMessageIndex, data);
                }
                modifier validateBatchData(bytes calldata data) {
                    uint256 fullDataLen = HEADER_LENGTH + data.length;
                    if (fullDataLen > MAX_DATA_SIZE) revert DataTooLarge(fullDataLen, MAX_DATA_SIZE);
                    if (data.length > 0 && (data[0] & DATA_AUTHENTICATED_FLAG) == DATA_AUTHENTICATED_FLAG) {
                        revert DataNotAuthenticated();
                    }
                    // the first byte is used to identify the type of batch data
                    // das batches expect to have the type byte set, followed by the keyset (so they should have at least 33 bytes)
                    if (data.length >= 33 && data[0] & 0x80 != 0) {
                        // we skip the first byte, then read the next 32 bytes for the keyset
                        bytes32 dasKeysetHash = bytes32(data[1:33]);
                        if (!dasKeySetInfo[dasKeysetHash].isValidKeyset) revert NoSuchKeyset(dasKeysetHash);
                    }
                    _;
                }
                function packHeader(uint256 afterDelayedMessagesRead)
                    internal
                    view
                    returns (bytes memory, TimeBounds memory)
                {
                    TimeBounds memory timeBounds = getTimeBounds();
                    bytes memory header = abi.encodePacked(
                        timeBounds.minTimestamp,
                        timeBounds.maxTimestamp,
                        timeBounds.minBlockNumber,
                        timeBounds.maxBlockNumber,
                        uint64(afterDelayedMessagesRead)
                    );
                    // This must always be true from the packed encoding
                    assert(header.length == HEADER_LENGTH);
                    return (header, timeBounds);
                }
                function formDataHash(bytes calldata data, uint256 afterDelayedMessagesRead)
                    internal
                    view
                    validateBatchData(data)
                    returns (bytes32, TimeBounds memory)
                {
                    (bytes memory header, TimeBounds memory timeBounds) = packHeader(afterDelayedMessagesRead);
                    bytes32 dataHash = keccak256(bytes.concat(header, data));
                    return (dataHash, timeBounds);
                }
                function formEmptyDataHash(uint256 afterDelayedMessagesRead)
                    internal
                    view
                    returns (bytes32, TimeBounds memory)
                {
                    (bytes memory header, TimeBounds memory timeBounds) = packHeader(afterDelayedMessagesRead);
                    return (keccak256(header), timeBounds);
                }
                function addSequencerL2BatchImpl(
                    bytes32 dataHash,
                    uint256 afterDelayedMessagesRead,
                    uint256 calldataLengthPosted,
                    uint256 prevMessageCount,
                    uint256 newMessageCount
                )
                    internal
                    returns (
                        uint256 seqMessageIndex,
                        bytes32 beforeAcc,
                        bytes32 delayedAcc,
                        bytes32 acc
                    )
                {
                    if (afterDelayedMessagesRead < totalDelayedMessagesRead) revert DelayedBackwards();
                    if (afterDelayedMessagesRead > bridge.delayedMessageCount()) revert DelayedTooFar();
                    (seqMessageIndex, beforeAcc, delayedAcc, acc) = bridge.enqueueSequencerMessage(
                        dataHash,
                        afterDelayedMessagesRead,
                        prevMessageCount,
                        newMessageCount
                    );
                    totalDelayedMessagesRead = afterDelayedMessagesRead;
                    if (calldataLengthPosted > 0) {
                        // this msg isn't included in the current sequencer batch, but instead added to
                        // the delayed messages queue that is yet to be included
                        address batchPoster = msg.sender;
                        bytes memory spendingReportMsg = abi.encodePacked(
                            block.timestamp,
                            batchPoster,
                            dataHash,
                            seqMessageIndex,
                            block.basefee
                        );
                        uint256 msgNum = bridge.submitBatchSpendingReport(
                            batchPoster,
                            keccak256(spendingReportMsg)
                        );
                        // this is the same event used by Inbox.sol after including a message to the delayed message accumulator
                        emit InboxMessageDelivered(msgNum, spendingReportMsg);
                    }
                }
                function inboxAccs(uint256 index) external view returns (bytes32) {
                    return bridge.sequencerInboxAccs(index);
                }
                function batchCount() external view returns (uint256) {
                    return bridge.sequencerMessageCount();
                }
                /// @inheritdoc ISequencerInbox
                function setMaxTimeVariation(ISequencerInbox.MaxTimeVariation memory maxTimeVariation_)
                    external
                    onlyRollupOwner
                {
                    maxTimeVariation = maxTimeVariation_;
                    emit OwnerFunctionCalled(0);
                }
                /// @inheritdoc ISequencerInbox
                function setIsBatchPoster(address addr, bool isBatchPoster_) external onlyRollupOwner {
                    isBatchPoster[addr] = isBatchPoster_;
                    emit OwnerFunctionCalled(1);
                }
                /// @inheritdoc ISequencerInbox
                function setValidKeyset(bytes calldata keysetBytes) external onlyRollupOwner {
                    uint256 ksWord = uint256(keccak256(bytes.concat(hex"fe", keccak256(keysetBytes))));
                    bytes32 ksHash = bytes32(ksWord ^ (1 << 255));
                    require(keysetBytes.length < 64 * 1024, "keyset is too large");
                    if (dasKeySetInfo[ksHash].isValidKeyset) revert AlreadyValidDASKeyset(ksHash);
                    dasKeySetInfo[ksHash] = DasKeySetInfo({
                        isValidKeyset: true,
                        creationBlock: uint64(block.number)
                    });
                    emit SetValidKeyset(ksHash, keysetBytes);
                    emit OwnerFunctionCalled(2);
                }
                /// @inheritdoc ISequencerInbox
                function invalidateKeysetHash(bytes32 ksHash) external onlyRollupOwner {
                    if (!dasKeySetInfo[ksHash].isValidKeyset) revert NoSuchKeyset(ksHash);
                    // we don't delete the block creation value since its used to fetch the SetValidKeyset
                    // event efficiently. The event provides the hash preimage of the key.
                    // this is still needed when syncing the chain after a keyset is invalidated.
                    dasKeySetInfo[ksHash].isValidKeyset = false;
                    emit InvalidateKeyset(ksHash);
                    emit OwnerFunctionCalled(3);
                }
                function isValidKeysetHash(bytes32 ksHash) external view returns (bool) {
                    return dasKeySetInfo[ksHash].isValidKeyset;
                }
                /// @inheritdoc ISequencerInbox
                function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256) {
                    DasKeySetInfo memory ksInfo = dasKeySetInfo[ksHash];
                    if (ksInfo.creationBlock == 0) revert NoSuchKeyset(ksHash);
                    return uint256(ksInfo.creationBlock);
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.4;
            /// @dev Init was already called
            error AlreadyInit();
            /// Init was called with param set to zero that must be nonzero
            error HadZeroInit();
            /// @dev Thrown when non owner tries to access an only-owner function
            /// @param sender The msg.sender who is not the owner
            /// @param owner The owner address
            error NotOwner(address sender, address owner);
            /// @dev Thrown when an address that is not the rollup tries to call an only-rollup function
            /// @param sender The sender who is not the rollup
            /// @param rollup The rollup address authorized to call this function
            error NotRollup(address sender, address rollup);
            /// @dev Thrown when the contract was not called directly from the origin ie msg.sender != tx.origin
            error NotOrigin();
            /// @dev Provided data was too large
            /// @param dataLength The length of the data that is too large
            /// @param maxDataLength The max length the data can be
            error DataTooLarge(uint256 dataLength, uint256 maxDataLength);
            /// @dev The provided is not a contract and was expected to be
            /// @param addr The adddress in question
            error NotContract(address addr);
            /// @dev The merkle proof provided was too long
            /// @param actualLength The length of the merkle proof provided
            /// @param maxProofLength The max length a merkle proof can have
            error MerkleProofTooLong(uint256 actualLength, uint256 maxProofLength);
            /// @dev Thrown when an un-authorized address tries to access an admin function
            /// @param sender The un-authorized sender
            /// @param rollup The rollup, which would be authorized
            /// @param owner The rollup's owner, which would be authorized
            error NotRollupOrOwner(address sender, address rollup, address owner);
            // Bridge Errors
            /// @dev Thrown when an un-authorized address tries to access an only-inbox function
            /// @param sender The un-authorized sender
            error NotDelayedInbox(address sender);
            /// @dev Thrown when an un-authorized address tries to access an only-sequencer-inbox function
            /// @param sender The un-authorized sender
            error NotSequencerInbox(address sender);
            /// @dev Thrown when an un-authorized address tries to access an only-outbox function
            /// @param sender The un-authorized sender
            error NotOutbox(address sender);
            /// @dev the provided outbox address isn't valid
            /// @param outbox address of outbox being set
            error InvalidOutboxSet(address outbox);
            // Inbox Errors
            /// @dev The contract is paused, so cannot be paused
            error AlreadyPaused();
            /// @dev The contract is unpaused, so cannot be unpaused
            error AlreadyUnpaused();
            /// @dev The contract is paused
            error Paused();
            /// @dev msg.value sent to the inbox isn't high enough
            error InsufficientValue(uint256 expected, uint256 actual);
            /// @dev submission cost provided isn't enough to create retryable ticket
            error InsufficientSubmissionCost(uint256 expected, uint256 actual);
            /// @dev address not allowed to interact with the given contract
            error NotAllowedOrigin(address origin);
            /// @dev used to convey retryable tx data in eth calls without requiring a tx trace
            /// this follows a pattern similar to EIP-3668 where reverts surface call information
            error RetryableData(
                address from,
                address to,
                uint256 l2CallValue,
                uint256 deposit,
                uint256 maxSubmissionCost,
                address excessFeeRefundAddress,
                address callValueRefundAddress,
                uint256 gasLimit,
                uint256 maxFeePerGas,
                bytes data
            );
            /// @dev Thrown when a L1 chainId fork is detected
            error L1Forked();
            /// @dev Thrown when a L1 chainId fork is not detected
            error NotForked();
            // Outbox Errors
            /// @dev The provided proof was too long
            /// @param proofLength The length of the too-long proof
            error ProofTooLong(uint256 proofLength);
            /// @dev The output index was greater than the maximum
            /// @param index The output index
            /// @param maxIndex The max the index could be
            error PathNotMinimal(uint256 index, uint256 maxIndex);
            /// @dev The calculated root does not exist
            /// @param root The calculated root
            error UnknownRoot(bytes32 root);
            /// @dev The record has already been spent
            /// @param index The index of the spent record
            error AlreadySpent(uint256 index);
            /// @dev A call to the bridge failed with no return data
            error BridgeCallFailed();
            // Sequencer Inbox Errors
            /// @dev Thrown when someone attempts to read fewer messages than have already been read
            error DelayedBackwards();
            /// @dev Thrown when someone attempts to read more messages than exist
            error DelayedTooFar();
            /// @dev Force include can only read messages more blocks old than the delay period
            error ForceIncludeBlockTooSoon();
            /// @dev Force include can only read messages more seconds old than the delay period
            error ForceIncludeTimeTooSoon();
            /// @dev The message provided did not match the hash in the delayed inbox
            error IncorrectMessagePreimage();
            /// @dev This can only be called by the batch poster
            error NotBatchPoster();
            /// @dev The sequence number provided to this message was inconsistent with the number of batches already included
            error BadSequencerNumber(uint256 stored, uint256 received);
            /// @dev The sequence message number provided to this message was inconsistent with the previous one
            error BadSequencerMessageNumber(uint256 stored, uint256 received);
            /// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox
            error DataNotAuthenticated();
            /// @dev Tried to create an already valid Data Availability Service keyset
            error AlreadyValidDASKeyset(bytes32);
            /// @dev Tried to use or invalidate an already invalid Data Availability Service keyset
            error NoSuchKeyset(bytes32);
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            // solhint-disable-next-line compiler-version
            pragma solidity >=0.6.9 <0.9.0;
            import "./IOwnable.sol";
            interface IBridge {
                event MessageDelivered(
                    uint256 indexed messageIndex,
                    bytes32 indexed beforeInboxAcc,
                    address inbox,
                    uint8 kind,
                    address sender,
                    bytes32 messageDataHash,
                    uint256 baseFeeL1,
                    uint64 timestamp
                );
                event BridgeCallTriggered(
                    address indexed outbox,
                    address indexed to,
                    uint256 value,
                    bytes data
                );
                event InboxToggle(address indexed inbox, bool enabled);
                event OutboxToggle(address indexed outbox, bool enabled);
                event SequencerInboxUpdated(address newSequencerInbox);
                function allowedDelayedInboxList(uint256) external returns (address);
                function allowedOutboxList(uint256) external returns (address);
                /// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
                function delayedInboxAccs(uint256) external view returns (bytes32);
                /// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
                function sequencerInboxAccs(uint256) external view returns (bytes32);
                function rollup() external view returns (IOwnable);
                function sequencerInbox() external view returns (address);
                function activeOutbox() external view returns (address);
                function allowedDelayedInboxes(address inbox) external view returns (bool);
                function allowedOutboxes(address outbox) external view returns (bool);
                function sequencerReportedSubMessageCount() external view returns (uint256);
                /**
                 * @dev Enqueue a message in the delayed inbox accumulator.
                 *      These messages are later sequenced in the SequencerInbox, either
                 *      by the sequencer as part of a normal batch, or by force inclusion.
                 */
                function enqueueDelayedMessage(
                    uint8 kind,
                    address sender,
                    bytes32 messageDataHash
                ) external payable returns (uint256);
                function executeCall(
                    address to,
                    uint256 value,
                    bytes calldata data
                ) external returns (bool success, bytes memory returnData);
                function delayedMessageCount() external view returns (uint256);
                function sequencerMessageCount() external view returns (uint256);
                // ---------- onlySequencerInbox functions ----------
                function enqueueSequencerMessage(
                    bytes32 dataHash,
                    uint256 afterDelayedMessagesRead,
                    uint256 prevMessageCount,
                    uint256 newMessageCount
                )
                    external
                    returns (
                        uint256 seqMessageIndex,
                        bytes32 beforeAcc,
                        bytes32 delayedAcc,
                        bytes32 acc
                    );
                /**
                 * @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type
                 *      This is done through a separate function entrypoint instead of allowing the sequencer inbox
                 *      to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either
                 *      every delayed inbox or every sequencer inbox call.
                 */
                function submitBatchSpendingReport(address batchPoster, bytes32 dataHash)
                    external
                    returns (uint256 msgNum);
                // ---------- onlyRollupOrOwner functions ----------
                function setSequencerInbox(address _sequencerInbox) external;
                function setDelayedInbox(address inbox, bool enabled) external;
                function setOutbox(address inbox, bool enabled) external;
                // ---------- initializer ----------
                function initialize(IOwnable rollup_) external;
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            // solhint-disable-next-line compiler-version
            pragma solidity >=0.6.9 <0.9.0;
            import "./IBridge.sol";
            import "./IDelayedMessageProvider.sol";
            import "./ISequencerInbox.sol";
            interface IInbox is IDelayedMessageProvider {
                function bridge() external view returns (IBridge);
                function sequencerInbox() external view returns (ISequencerInbox);
                /**
                 * @notice Send a generic L2 message to the chain
                 * @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input
                 *      This method will be disabled upon L1 fork to prevent replay attacks on L2
                 * @param messageData Data of the message being sent
                 */
                function sendL2MessageFromOrigin(bytes calldata messageData) external returns (uint256);
                /**
                 * @notice Send a generic L2 message to the chain
                 * @dev This method can be used to send any type of message that doesn't require L1 validation
                 *      This method will be disabled upon L1 fork to prevent replay attacks on L2
                 * @param messageData Data of the message being sent
                 */
                function sendL2Message(bytes calldata messageData) external returns (uint256);
                function sendL1FundedUnsignedTransaction(
                    uint256 gasLimit,
                    uint256 maxFeePerGas,
                    uint256 nonce,
                    address to,
                    bytes calldata data
                ) external payable returns (uint256);
                function sendL1FundedContractTransaction(
                    uint256 gasLimit,
                    uint256 maxFeePerGas,
                    address to,
                    bytes calldata data
                ) external payable returns (uint256);
                function sendUnsignedTransaction(
                    uint256 gasLimit,
                    uint256 maxFeePerGas,
                    uint256 nonce,
                    address to,
                    uint256 value,
                    bytes calldata data
                ) external returns (uint256);
                function sendContractTransaction(
                    uint256 gasLimit,
                    uint256 maxFeePerGas,
                    address to,
                    uint256 value,
                    bytes calldata data
                ) external returns (uint256);
                /**
                 * @dev This method can only be called upon L1 fork and will not alias the caller
                 *      This method will revert if not called from origin
                 */
                function sendL1FundedUnsignedTransactionToFork(
                    uint256 gasLimit,
                    uint256 maxFeePerGas,
                    uint256 nonce,
                    address to,
                    bytes calldata data
                ) external payable returns (uint256);
                /**
                 * @dev This method can only be called upon L1 fork and will not alias the caller
                 *      This method will revert if not called from origin
                 */
                function sendUnsignedTransactionToFork(
                    uint256 gasLimit,
                    uint256 maxFeePerGas,
                    uint256 nonce,
                    address to,
                    uint256 value,
                    bytes calldata data
                ) external returns (uint256);
                /**
                 * @notice Send a message to initiate L2 withdrawal
                 * @dev This method can only be called upon L1 fork and will not alias the caller
                 *      This method will revert if not called from origin
                 */
                function sendWithdrawEthToFork(
                    uint256 gasLimit,
                    uint256 maxFeePerGas,
                    uint256 nonce,
                    uint256 value,
                    address withdrawTo
                ) external returns (uint256);
                /**
                 * @notice Get the L1 fee for submitting a retryable
                 * @dev This fee can be paid by funds already in the L2 aliased address or by the current message value
                 * @dev This formula may change in the future, to future proof your code query this method instead of inlining!!
                 * @param dataLength The length of the retryable's calldata, in bytes
                 * @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used
                 */
                function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee)
                    external
                    view
                    returns (uint256);
                /**
                 * @notice Deposit eth from L1 to L2 to address of the sender if sender is an EOA, and to its aliased address if the sender is a contract
                 * @dev This does not trigger the fallback function when receiving in the L2 side.
                 *      Look into retryable tickets if you are interested in this functionality.
                 * @dev This function should not be called inside contract constructors
                 */
                function depositEth() external payable returns (uint256);
                /**
                 * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
                 * @dev all msg.value will deposited to callValueRefundAddress on L2
                 * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
                 * @param to destination L2 contract address
                 * @param l2CallValue call value for retryable L2 message
                 * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
                 * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
                 * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
                 * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
                 * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
                 * @param data ABI encoded data of L2 message
                 * @return unique message number of the retryable transaction
                 */
                function createRetryableTicket(
                    address to,
                    uint256 l2CallValue,
                    uint256 maxSubmissionCost,
                    address excessFeeRefundAddress,
                    address callValueRefundAddress,
                    uint256 gasLimit,
                    uint256 maxFeePerGas,
                    bytes calldata data
                ) external payable returns (uint256);
                /**
                 * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
                 * @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds
                 * come from the deposit alone, rather than falling back on the user's L2 balance
                 * @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress).
                 * createRetryableTicket method is the recommended standard.
                 * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
                 * @param to destination L2 contract address
                 * @param l2CallValue call value for retryable L2 message
                 * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
                 * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
                 * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
                 * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
                 * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
                 * @param data ABI encoded data of L2 message
                 * @return unique message number of the retryable transaction
                 */
                function unsafeCreateRetryableTicket(
                    address to,
                    uint256 l2CallValue,
                    uint256 maxSubmissionCost,
                    address excessFeeRefundAddress,
                    address callValueRefundAddress,
                    uint256 gasLimit,
                    uint256 maxFeePerGas,
                    bytes calldata data
                ) external payable returns (uint256);
                // ---------- onlyRollupOrOwner functions ----------
                /// @notice pauses all inbox functionality
                function pause() external;
                /// @notice unpauses all inbox functionality
                function unpause() external;
                // ---------- initializer ----------
                /**
                 * @dev function to be called one time during the inbox upgrade process
                 *      this is used to fix the storage slots
                 */
                function postUpgradeInit(IBridge _bridge) external;
                function initialize(IBridge _bridge, ISequencerInbox _sequencerInbox) external;
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            // solhint-disable-next-line compiler-version
            pragma solidity >=0.6.9 <0.9.0;
            pragma experimental ABIEncoderV2;
            import "../libraries/IGasRefunder.sol";
            import "./IDelayedMessageProvider.sol";
            import "./IBridge.sol";
            interface ISequencerInbox is IDelayedMessageProvider {
                struct MaxTimeVariation {
                    uint256 delayBlocks;
                    uint256 futureBlocks;
                    uint256 delaySeconds;
                    uint256 futureSeconds;
                }
                struct TimeBounds {
                    uint64 minTimestamp;
                    uint64 maxTimestamp;
                    uint64 minBlockNumber;
                    uint64 maxBlockNumber;
                }
                enum BatchDataLocation {
                    TxInput,
                    SeparateBatchEvent,
                    NoData
                }
                event SequencerBatchDelivered(
                    uint256 indexed batchSequenceNumber,
                    bytes32 indexed beforeAcc,
                    bytes32 indexed afterAcc,
                    bytes32 delayedAcc,
                    uint256 afterDelayedMessagesRead,
                    TimeBounds timeBounds,
                    BatchDataLocation dataLocation
                );
                event OwnerFunctionCalled(uint256 indexed id);
                /// @dev a separate event that emits batch data when this isn't easily accessible in the tx.input
                event SequencerBatchData(uint256 indexed batchSequenceNumber, bytes data);
                /// @dev a valid keyset was added
                event SetValidKeyset(bytes32 indexed keysetHash, bytes keysetBytes);
                /// @dev a keyset was invalidated
                event InvalidateKeyset(bytes32 indexed keysetHash);
                function totalDelayedMessagesRead() external view returns (uint256);
                function bridge() external view returns (IBridge);
                /// @dev The size of the batch header
                // solhint-disable-next-line func-name-mixedcase
                function HEADER_LENGTH() external view returns (uint256);
                /// @dev If the first batch data byte after the header has this bit set,
                ///      the sequencer inbox has authenticated the data. Currently not used.
                // solhint-disable-next-line func-name-mixedcase
                function DATA_AUTHENTICATED_FLAG() external view returns (bytes1);
                function rollup() external view returns (IOwnable);
                function isBatchPoster(address) external view returns (bool);
                struct DasKeySetInfo {
                    bool isValidKeyset;
                    uint64 creationBlock;
                }
                // https://github.com/ethereum/solidity/issues/11826
                // function maxTimeVariation() external view returns (MaxTimeVariation calldata);
                // function dasKeySetInfo(bytes32) external view returns (DasKeySetInfo calldata);
                /// @notice Remove force inclusion delay after a L1 chainId fork
                function removeDelayAfterFork() external;
                /// @notice Force messages from the delayed inbox to be included in the chain
                ///         Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and
                ///         maxTimeVariation.delaySeconds has elapsed. As part of normal behaviour the sequencer will include these
                ///         messages so it's only necessary to call this if the sequencer is down, or not including any delayed messages.
                /// @param _totalDelayedMessagesRead The total number of messages to read up to
                /// @param kind The kind of the last message to be included
                /// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included
                /// @param baseFeeL1 The l1 gas price of the last message to be included
                /// @param sender The sender of the last message to be included
                /// @param messageDataHash The messageDataHash of the last message to be included
                function forceInclusion(
                    uint256 _totalDelayedMessagesRead,
                    uint8 kind,
                    uint64[2] calldata l1BlockAndTime,
                    uint256 baseFeeL1,
                    address sender,
                    bytes32 messageDataHash
                ) external;
                function inboxAccs(uint256 index) external view returns (bytes32);
                function batchCount() external view returns (uint256);
                function isValidKeysetHash(bytes32 ksHash) external view returns (bool);
                /// @notice the creation block is intended to still be available after a keyset is deleted
                function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256);
                // ---------- BatchPoster functions ----------
                function addSequencerL2BatchFromOrigin(
                    uint256 sequenceNumber,
                    bytes calldata data,
                    uint256 afterDelayedMessagesRead,
                    IGasRefunder gasRefunder
                ) external;
                function addSequencerL2Batch(
                    uint256 sequenceNumber,
                    bytes calldata data,
                    uint256 afterDelayedMessagesRead,
                    IGasRefunder gasRefunder,
                    uint256 prevMessageCount,
                    uint256 newMessageCount
                ) external;
                // ---------- onlyRollupOrOwner functions ----------
                /**
                 * @notice Set max delay for sequencer inbox
                 * @param maxTimeVariation_ the maximum time variation parameters
                 */
                function setMaxTimeVariation(MaxTimeVariation memory maxTimeVariation_) external;
                /**
                 * @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox
                 * @param addr the address
                 * @param isBatchPoster_ if the specified address should be authorized as a batch poster
                 */
                function setIsBatchPoster(address addr, bool isBatchPoster_) external;
                /**
                 * @notice Makes Data Availability Service keyset valid
                 * @param keysetBytes bytes of the serialized keyset
                 */
                function setValidKeyset(bytes calldata keysetBytes) external;
                /**
                 * @notice Invalidates a Data Availability Service keyset
                 * @param ksHash hash of the keyset
                 */
                function invalidateKeysetHash(bytes32 ksHash) external;
                // ---------- initializer ----------
                function initialize(IBridge bridge_, MaxTimeVariation calldata maxTimeVariation_) external;
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "./RollupLib.sol";
            import "./IRollupCore.sol";
            import "../bridge/ISequencerInbox.sol";
            import "../bridge/IOutbox.sol";
            import "../bridge/IOwnable.sol";
            interface IRollupUserAbs is IRollupCore, IOwnable {
                /// @dev the user logic just validated configuration and shouldn't write to state during init
                /// this allows the admin logic to ensure consistency on parameters.
                function initialize(address stakeToken) external view;
                function removeWhitelistAfterFork() external;
                function removeWhitelistAfterValidatorAfk() external;
                function isERC20Enabled() external view returns (bool);
                function rejectNextNode(address stakerAddress) external;
                function confirmNextNode(bytes32 blockHash, bytes32 sendRoot) external;
                function stakeOnExistingNode(uint64 nodeNum, bytes32 nodeHash) external;
                function stakeOnNewNode(
                    RollupLib.Assertion memory assertion,
                    bytes32 expectedNodeHash,
                    uint256 prevNodeInboxMaxCount
                ) external;
                function returnOldDeposit(address stakerAddress) external;
                function reduceDeposit(uint256 target) external;
                function removeZombie(uint256 zombieNum, uint256 maxNodes) external;
                function removeOldZombies(uint256 startIndex) external;
                function requiredStake(
                    uint256 blockNumber,
                    uint64 firstUnresolvedNodeNum,
                    uint64 latestCreatedNode
                ) external view returns (uint256);
                function currentRequiredStake() external view returns (uint256);
                function countStakedZombies(uint64 nodeNum) external view returns (uint256);
                function countZombiesStakedOnChildren(uint64 nodeNum) external view returns (uint256);
                function requireUnresolvedExists() external view;
                function requireUnresolved(uint256 nodeNum) external view;
                function withdrawStakerFunds() external returns (uint256);
                function createChallenge(
                    address[2] calldata stakers,
                    uint64[2] calldata nodeNums,
                    MachineStatus[2] calldata machineStatuses,
                    GlobalState[2] calldata globalStates,
                    uint64 numBlocks,
                    bytes32 secondExecutionHash,
                    uint256[2] calldata proposedTimes,
                    bytes32[2] calldata wasmModuleRoots
                ) external;
            }
            interface IRollupUser is IRollupUserAbs {
                function newStakeOnExistingNode(uint64 nodeNum, bytes32 nodeHash) external payable;
                function newStakeOnNewNode(
                    RollupLib.Assertion calldata assertion,
                    bytes32 expectedNodeHash,
                    uint256 prevNodeInboxMaxCount
                ) external payable;
                function addToDeposit(address stakerAddress) external payable;
            }
            interface IRollupUserERC20 is IRollupUserAbs {
                function newStakeOnExistingNode(
                    uint256 tokenAmount,
                    uint64 nodeNum,
                    bytes32 nodeHash
                ) external;
                function newStakeOnNewNode(
                    uint256 tokenAmount,
                    RollupLib.Assertion calldata assertion,
                    bytes32 expectedNodeHash,
                    uint256 prevNodeInboxMaxCount
                ) external;
                function addToDeposit(address stakerAddress, uint256 tokenAmount) external;
            }
            interface IRollupAdmin {
                event OwnerFunctionCalled(uint256 indexed id);
                function initialize(Config calldata config, ContractDependencies calldata connectedContracts)
                    external;
                /**
                 * @notice Add a contract authorized to put messages into this rollup's inbox
                 * @param _outbox Outbox contract to add
                 */
                function setOutbox(IOutbox _outbox) external;
                /**
                 * @notice Disable an old outbox from interacting with the bridge
                 * @param _outbox Outbox contract to remove
                 */
                function removeOldOutbox(address _outbox) external;
                /**
                 * @notice Enable or disable an inbox contract
                 * @param _inbox Inbox contract to add or remove
                 * @param _enabled New status of inbox
                 */
                function setDelayedInbox(address _inbox, bool _enabled) external;
                /**
                 * @notice Pause interaction with the rollup contract
                 */
                function pause() external;
                /**
                 * @notice Resume interaction with the rollup contract
                 */
                function resume() external;
                /**
                 * @notice Set the addresses of the validator whitelist
                 * @dev It is expected that both arrays are same length, and validator at
                 * position i corresponds to the value at position i
                 * @param _validator addresses to set in the whitelist
                 * @param _val value to set in the whitelist for corresponding address
                 */
                function setValidator(address[] memory _validator, bool[] memory _val) external;
                /**
                 * @notice Set a new owner address for the rollup proxy
                 * @param newOwner address of new rollup owner
                 */
                function setOwner(address newOwner) external;
                /**
                 * @notice Set minimum assertion period for the rollup
                 * @param newPeriod new minimum period for assertions
                 */
                function setMinimumAssertionPeriod(uint256 newPeriod) external;
                /**
                 * @notice Set number of blocks until a node is considered confirmed
                 * @param newConfirmPeriod new number of blocks until a node is confirmed
                 */
                function setConfirmPeriodBlocks(uint64 newConfirmPeriod) external;
                /**
                 * @notice Set number of extra blocks after a challenge
                 * @param newExtraTimeBlocks new number of blocks
                 */
                function setExtraChallengeTimeBlocks(uint64 newExtraTimeBlocks) external;
                /**
                 * @notice Set base stake required for an assertion
                 * @param newBaseStake maximum avmgas to be used per block
                 */
                function setBaseStake(uint256 newBaseStake) external;
                /**
                 * @notice Set the token used for stake, where address(0) == eth
                 * @dev Before changing the base stake token, you might need to change the
                 * implementation of the Rollup User logic!
                 * @param newStakeToken address of token used for staking
                 */
                function setStakeToken(address newStakeToken) external;
                /**
                 * @notice Upgrades the implementation of a beacon controlled by the rollup
                 * @param beacon address of beacon to be upgraded
                 * @param newImplementation new address of implementation
                 */
                function upgradeBeacon(address beacon, address newImplementation) external;
                function forceResolveChallenge(address[] memory stackerA, address[] memory stackerB) external;
                function forceRefundStaker(address[] memory stacker) external;
                function forceCreateNode(
                    uint64 prevNode,
                    uint256 prevNodeInboxMaxCount,
                    RollupLib.Assertion memory assertion,
                    bytes32 expectedNodeHash
                ) external;
                function forceConfirmNode(
                    uint64 nodeNum,
                    bytes32 blockHash,
                    bytes32 sendRoot
                ) external;
                function setLoserStakeEscrow(address newLoserStakerEscrow) external;
                /**
                 * @notice Set the proving WASM module root
                 * @param newWasmModuleRoot new module root
                 */
                function setWasmModuleRoot(bytes32 newWasmModuleRoot) external;
                /**
                 * @notice set a new sequencer inbox contract
                 * @param _sequencerInbox new address of sequencer inbox
                 */
                function setSequencerInbox(address _sequencerInbox) external;
                /**
                 * @notice set the validatorWhitelistDisabled flag
                 * @param _validatorWhitelistDisabled new value of validatorWhitelistDisabled, i.e. true = disabled
                 */
                function setValidatorWhitelistDisabled(bool _validatorWhitelistDisabled) external;
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            library Messages {
                function messageHash(
                    uint8 kind,
                    address sender,
                    uint64 blockNumber,
                    uint64 timestamp,
                    uint256 inboxSeqNum,
                    uint256 baseFeeL1,
                    bytes32 messageDataHash
                ) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                kind,
                                sender,
                                blockNumber,
                                timestamp,
                                inboxSeqNum,
                                baseFeeL1,
                                messageDataHash
                            )
                        );
                }
                function accumulateInboxMessage(bytes32 prevAcc, bytes32 message)
                    internal
                    pure
                    returns (bytes32)
                {
                    return keccak256(abi.encodePacked(prevAcc, message));
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.4;
            uint8 constant L2_MSG = 3;
            uint8 constant L1MessageType_L2FundedByL1 = 7;
            uint8 constant L1MessageType_submitRetryableTx = 9;
            uint8 constant L1MessageType_ethDeposit = 12;
            uint8 constant L1MessageType_batchPostingReport = 13;
            uint8 constant L2MessageType_unsignedEOATx = 0;
            uint8 constant L2MessageType_unsignedContractTx = 1;
            uint8 constant ROLLUP_PROTOCOL_EVENT_TYPE = 8;
            uint8 constant INITIALIZATION_MSG_TYPE = 11;
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            // solhint-disable-next-line compiler-version
            pragma solidity >=0.6.9 <0.9.0;
            interface IGasRefunder {
                function onGasSpent(
                    address payable spender,
                    uint256 gasUsed,
                    uint256 calldataSize
                ) external returns (bool success);
            }
            abstract contract GasRefundEnabled {
                /// @dev this refunds the sender for execution costs of the tx
                /// calldata costs are only refunded if `msg.sender == tx.origin` to guarantee the value refunded relates to charging
                /// for the `tx.input`. this avoids a possible attack where you generate large calldata from a contract and get over-refunded
                modifier refundsGas(IGasRefunder gasRefunder) {
                    uint256 startGasLeft = gasleft();
                    _;
                    if (address(gasRefunder) != address(0)) {
                        uint256 calldataSize = 0;
                        // if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call
                        // so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input
                        // solhint-disable-next-line avoid-tx-origin
                        if (msg.sender == tx.origin) {
                            assembly {
                                calldataSize := calldatasize()
                            }
                        }
                        gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize);
                    }
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import {NotOwner} from "./Error.sol";
            /// @dev A stateless contract that allows you to infer if the current call has been delegated or not
            /// Pattern used here is from UUPS implementation by the OpenZeppelin team
            abstract contract DelegateCallAware {
                address private immutable __self = address(this);
                /**
                 * @dev Check that the execution is being performed through a delegate call. This allows a function to be
                 * callable on the proxy contract but not on the logic contract.
                 */
                modifier onlyDelegated() {
                    require(address(this) != __self, "Function must be called through delegatecall");
                    _;
                }
                /**
                 * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
                 * callable on the implementing contract but not through proxies.
                 */
                modifier notDelegated() {
                    require(address(this) == __self, "Function must not be called through delegatecall");
                    _;
                }
                /// @dev Check that msg.sender is the current EIP 1967 proxy admin
                modifier onlyProxyOwner() {
                    // Storage slot with the admin of the proxy contract
                    // This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1
                    bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                    address admin;
                    assembly {
                        admin := sload(slot)
                    }
                    if (msg.sender != admin) revert NotOwner(msg.sender, admin);
                    _;
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.4;
            // 90% of Geth's 128KB tx size limit, leaving ~13KB for proving
            uint256 constant MAX_DATA_SIZE = 117964;
            uint64 constant NO_CHAL_INDEX = 0;
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            // solhint-disable-next-line compiler-version
            pragma solidity >=0.4.21 <0.9.0;
            interface IOwnable {
                function owner() external view returns (address);
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            // solhint-disable-next-line compiler-version
            pragma solidity >=0.6.9 <0.9.0;
            interface IDelayedMessageProvider {
                /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator
                event InboxMessageDelivered(uint256 indexed messageNum, bytes data);
                /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator
                /// same as InboxMessageDelivered but the batch data is available in tx.input
                event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "../challenge/IChallengeManager.sol";
            import "../challenge/ChallengeLib.sol";
            import "../state/GlobalState.sol";
            import "../bridge/ISequencerInbox.sol";
            import "../bridge/IBridge.sol";
            import "../bridge/IOutbox.sol";
            import "../bridge/IInbox.sol";
            import "./IRollupEventInbox.sol";
            import "./IRollupLogic.sol";
            struct Config {
                uint64 confirmPeriodBlocks;
                uint64 extraChallengeTimeBlocks;
                address stakeToken;
                uint256 baseStake;
                bytes32 wasmModuleRoot;
                address owner;
                address loserStakeEscrow;
                uint256 chainId;
                uint64 genesisBlockNum;
                ISequencerInbox.MaxTimeVariation sequencerInboxMaxTimeVariation;
            }
            struct ContractDependencies {
                IBridge bridge;
                ISequencerInbox sequencerInbox;
                IInbox inbox;
                IOutbox outbox;
                IRollupEventInbox rollupEventInbox;
                IChallengeManager challengeManager;
                IRollupAdmin rollupAdminLogic;
                IRollupUser rollupUserLogic;
                // misc contracts that are useful when interacting with the rollup
                address validatorUtils;
                address validatorWalletCreator;
            }
            library RollupLib {
                using GlobalStateLib for GlobalState;
                struct ExecutionState {
                    GlobalState globalState;
                    MachineStatus machineStatus;
                }
                function stateHash(ExecutionState calldata execState, uint256 inboxMaxCount)
                    internal
                    pure
                    returns (bytes32)
                {
                    return
                        keccak256(
                            abi.encodePacked(
                                execState.globalState.hash(),
                                inboxMaxCount,
                                execState.machineStatus
                            )
                        );
                }
                /// @dev same as stateHash but expects execState in memory instead of calldata
                function stateHashMem(ExecutionState memory execState, uint256 inboxMaxCount)
                    internal
                    pure
                    returns (bytes32)
                {
                    return
                        keccak256(
                            abi.encodePacked(
                                execState.globalState.hash(),
                                inboxMaxCount,
                                execState.machineStatus
                            )
                        );
                }
                struct Assertion {
                    ExecutionState beforeState;
                    ExecutionState afterState;
                    uint64 numBlocks;
                }
                function executionHash(Assertion memory assertion) internal pure returns (bytes32) {
                    MachineStatus[2] memory statuses;
                    statuses[0] = assertion.beforeState.machineStatus;
                    statuses[1] = assertion.afterState.machineStatus;
                    GlobalState[2] memory globalStates;
                    globalStates[0] = assertion.beforeState.globalState;
                    globalStates[1] = assertion.afterState.globalState;
                    // TODO: benchmark how much this abstraction adds of gas overhead
                    return executionHash(statuses, globalStates, assertion.numBlocks);
                }
                function executionHash(
                    MachineStatus[2] memory statuses,
                    GlobalState[2] memory globalStates,
                    uint64 numBlocks
                ) internal pure returns (bytes32) {
                    bytes32[] memory segments = new bytes32[](2);
                    segments[0] = ChallengeLib.blockStateHash(statuses[0], globalStates[0].hash());
                    segments[1] = ChallengeLib.blockStateHash(statuses[1], globalStates[1].hash());
                    return ChallengeLib.hashChallengeState(0, numBlocks, segments);
                }
                function challengeRootHash(
                    bytes32 execution,
                    uint256 proposedTime,
                    bytes32 wasmModuleRoot
                ) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(execution, proposedTime, wasmModuleRoot));
                }
                function confirmHash(Assertion memory assertion) internal pure returns (bytes32) {
                    return
                        confirmHash(
                            assertion.afterState.globalState.getBlockHash(),
                            assertion.afterState.globalState.getSendRoot()
                        );
                }
                function confirmHash(bytes32 blockHash, bytes32 sendRoot) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(blockHash, sendRoot));
                }
                function nodeHash(
                    bool hasSibling,
                    bytes32 lastHash,
                    bytes32 assertionExecHash,
                    bytes32 inboxAcc,
                    bytes32 wasmModuleRoot
                ) internal pure returns (bytes32) {
                    uint8 hasSiblingInt = hasSibling ? 1 : 0;
                    return
                        keccak256(
                            abi.encodePacked(
                                hasSiblingInt,
                                lastHash,
                                assertionExecHash,
                                inboxAcc,
                                wasmModuleRoot
                            )
                        );
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "./Node.sol";
            import "./RollupLib.sol";
            interface IRollupCore {
                struct Staker {
                    uint256 amountStaked;
                    uint64 index;
                    uint64 latestStakedNode;
                    // currentChallenge is 0 if staker is not in a challenge
                    uint64 currentChallenge;
                    bool isStaked;
                }
                event RollupInitialized(bytes32 machineHash, uint256 chainId);
                event NodeCreated(
                    uint64 indexed nodeNum,
                    bytes32 indexed parentNodeHash,
                    bytes32 indexed nodeHash,
                    bytes32 executionHash,
                    RollupLib.Assertion assertion,
                    bytes32 afterInboxBatchAcc,
                    bytes32 wasmModuleRoot,
                    uint256 inboxMaxCount
                );
                event NodeConfirmed(uint64 indexed nodeNum, bytes32 blockHash, bytes32 sendRoot);
                event NodeRejected(uint64 indexed nodeNum);
                event RollupChallengeStarted(
                    uint64 indexed challengeIndex,
                    address asserter,
                    address challenger,
                    uint64 challengedNode
                );
                event UserStakeUpdated(address indexed user, uint256 initialBalance, uint256 finalBalance);
                event UserWithdrawableFundsUpdated(
                    address indexed user,
                    uint256 initialBalance,
                    uint256 finalBalance
                );
                function confirmPeriodBlocks() external view returns (uint64);
                function extraChallengeTimeBlocks() external view returns (uint64);
                function chainId() external view returns (uint256);
                function baseStake() external view returns (uint256);
                function wasmModuleRoot() external view returns (bytes32);
                function bridge() external view returns (IBridge);
                function sequencerInbox() external view returns (ISequencerInbox);
                function outbox() external view returns (IOutbox);
                function rollupEventInbox() external view returns (IRollupEventInbox);
                function challengeManager() external view returns (IChallengeManager);
                function loserStakeEscrow() external view returns (address);
                function stakeToken() external view returns (address);
                function minimumAssertionPeriod() external view returns (uint256);
                function isValidator(address) external view returns (bool);
                function validatorWhitelistDisabled() external view returns (bool);
                /**
                 * @notice Get the Node for the given index.
                 */
                function getNode(uint64 nodeNum) external view returns (Node memory);
                /**
                 * @notice Check if the specified node has been staked on by the provided staker.
                 * Only accurate at the latest confirmed node and afterwards.
                 */
                function nodeHasStaker(uint64 nodeNum, address staker) external view returns (bool);
                /**
                 * @notice Get the address of the staker at the given index
                 * @param stakerNum Index of the staker
                 * @return Address of the staker
                 */
                function getStakerAddress(uint64 stakerNum) external view returns (address);
                /**
                 * @notice Check whether the given staker is staked
                 * @param staker Staker address to check
                 * @return True or False for whether the staker was staked
                 */
                function isStaked(address staker) external view returns (bool);
                /**
                 * @notice Get the latest staked node of the given staker
                 * @param staker Staker address to lookup
                 * @return Latest node staked of the staker
                 */
                function latestStakedNode(address staker) external view returns (uint64);
                /**
                 * @notice Get the current challenge of the given staker
                 * @param staker Staker address to lookup
                 * @return Current challenge of the staker
                 */
                function currentChallenge(address staker) external view returns (uint64);
                /**
                 * @notice Get the amount staked of the given staker
                 * @param staker Staker address to lookup
                 * @return Amount staked of the staker
                 */
                function amountStaked(address staker) external view returns (uint256);
                /**
                 * @notice Retrieves stored information about a requested staker
                 * @param staker Staker address to retrieve
                 * @return A structure with information about the requested staker
                 */
                function getStaker(address staker) external view returns (Staker memory);
                /**
                 * @notice Get the original staker address of the zombie at the given index
                 * @param zombieNum Index of the zombie to lookup
                 * @return Original staker address of the zombie
                 */
                function zombieAddress(uint256 zombieNum) external view returns (address);
                /**
                 * @notice Get Latest node that the given zombie at the given index is staked on
                 * @param zombieNum Index of the zombie to lookup
                 * @return Latest node that the given zombie is staked on
                 */
                function zombieLatestStakedNode(uint256 zombieNum) external view returns (uint64);
                /// @return Current number of un-removed zombies
                function zombieCount() external view returns (uint256);
                function isZombie(address staker) external view returns (bool);
                /**
                 * @notice Get the amount of funds withdrawable by the given address
                 * @param owner Address to check the funds of
                 * @return Amount of funds withdrawable by owner
                 */
                function withdrawableFunds(address owner) external view returns (uint256);
                /**
                 * @return Index of the first unresolved node
                 * @dev If all nodes have been resolved, this will be latestNodeCreated + 1
                 */
                function firstUnresolvedNode() external view returns (uint64);
                /// @return Index of the latest confirmed node
                function latestConfirmed() external view returns (uint64);
                /// @return Index of the latest rollup node created
                function latestNodeCreated() external view returns (uint64);
                /// @return Ethereum block that the most recent stake was created
                function lastStakeBlock() external view returns (uint64);
                /// @return Number of active stakers currently staked
                function stakerCount() external view returns (uint64);
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            // solhint-disable-next-line compiler-version
            pragma solidity >=0.6.9 <0.9.0;
            import "./IBridge.sol";
            interface IOutbox {
                event SendRootUpdated(bytes32 indexed blockHash, bytes32 indexed outputRoot);
                event OutBoxTransactionExecuted(
                    address indexed to,
                    address indexed l2Sender,
                    uint256 indexed zero,
                    uint256 transactionIndex
                );
                function rollup() external view returns (address); // the rollup contract
                function bridge() external view returns (IBridge); // the bridge contract
                function spent(uint256) external view returns (bytes32); // packed spent bitmap
                function roots(bytes32) external view returns (bytes32); // maps root hashes => L2 block hash
                // solhint-disable-next-line func-name-mixedcase
                function OUTBOX_VERSION() external view returns (uint128); // the outbox version
                function updateSendRoot(bytes32 sendRoot, bytes32 l2BlockHash) external;
                /// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account
                ///         When the return value is zero, that means this is a system message
                /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
                function l2ToL1Sender() external view returns (address);
                /// @return l2Block return L2 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
                function l2ToL1Block() external view returns (uint256);
                /// @return l1Block return L1 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
                function l2ToL1EthBlock() external view returns (uint256);
                /// @return timestamp return L2 timestamp when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
                function l2ToL1Timestamp() external view returns (uint256);
                /// @return outputId returns the unique output identifier of the L2 to L1 tx or 0 if no L2 to L1 transaction is active
                function l2ToL1OutputId() external view returns (bytes32);
                /**
                 * @notice Executes a messages in an Outbox entry.
                 * @dev Reverts if dispute period hasn't expired, since the outbox entry
                 *      is only created once the rollup confirms the respective assertion.
                 * @dev it is not possible to execute any L2-to-L1 transaction which contains data
                 *      to a contract address without any code (as enforced by the Bridge contract).
                 * @param proof Merkle proof of message inclusion in send root
                 * @param index Merkle path to message
                 * @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
                 * @param to destination address for L1 contract call
                 * @param l2Block l2 block number at which sendTxToL1 call was made
                 * @param l1Block l1 block number at which sendTxToL1 call was made
                 * @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made
                 * @param value wei in L1 message
                 * @param data abi-encoded L1 message data
                 */
                function executeTransaction(
                    bytes32[] calldata proof,
                    uint256 index,
                    address l2Sender,
                    address to,
                    uint256 l2Block,
                    uint256 l1Block,
                    uint256 l2Timestamp,
                    uint256 value,
                    bytes calldata data
                ) external;
                /**
                 *  @dev function used to simulate the result of a particular function call from the outbox
                 *       it is useful for things such as gas estimates. This function includes all costs except for
                 *       proof validation (which can be considered offchain as a somewhat of a fixed cost - it's
                 *       not really a fixed cost, but can be treated as so with a fixed overhead for gas estimation).
                 *       We can't include the cost of proof validation since this is intended to be used to simulate txs
                 *       that are included in yet-to-be confirmed merkle roots. The simulation entrypoint could instead pretend
                 *       to confirm a pending merkle root, but that would be less practical for integrating with tooling.
                 *       It is only possible to trigger it when the msg sender is address zero, which should be impossible
                 *       unless under simulation in an eth_call or eth_estimateGas
                 */
                function executeTransactionSimulation(
                    uint256 index,
                    address l2Sender,
                    address to,
                    uint256 l2Block,
                    uint256 l1Block,
                    uint256 l2Timestamp,
                    uint256 value,
                    bytes calldata data
                ) external;
                /**
                 * @param index Merkle path to message
                 * @return true if the message has been spent
                 */
                function isSpent(uint256 index) external view returns (bool);
                function calculateItemHash(
                    address l2Sender,
                    address to,
                    uint256 l2Block,
                    uint256 l1Block,
                    uint256 l2Timestamp,
                    uint256 value,
                    bytes calldata data
                ) external pure returns (bytes32);
                function calculateMerkleRoot(
                    bytes32[] memory proof,
                    uint256 path,
                    bytes32 item
                ) external pure returns (bytes32);
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "../state/Machine.sol";
            import "../bridge/IBridge.sol";
            import "../bridge/ISequencerInbox.sol";
            import "../osp/IOneStepProofEntry.sol";
            import "./IChallengeResultReceiver.sol";
            import "./ChallengeLib.sol";
            interface IChallengeManager {
                enum ChallengeTerminationType {
                    TIMEOUT,
                    BLOCK_PROOF,
                    EXECUTION_PROOF,
                    CLEARED
                }
                event InitiatedChallenge(
                    uint64 indexed challengeIndex,
                    GlobalState startState,
                    GlobalState endState
                );
                event Bisected(
                    uint64 indexed challengeIndex,
                    bytes32 indexed challengeRoot,
                    uint256 challengedSegmentStart,
                    uint256 challengedSegmentLength,
                    bytes32[] chainHashes
                );
                event ExecutionChallengeBegun(uint64 indexed challengeIndex, uint256 blockSteps);
                event OneStepProofCompleted(uint64 indexed challengeIndex);
                event ChallengeEnded(uint64 indexed challengeIndex, ChallengeTerminationType kind);
                function initialize(
                    IChallengeResultReceiver resultReceiver_,
                    ISequencerInbox sequencerInbox_,
                    IBridge bridge_,
                    IOneStepProofEntry osp_
                ) external;
                function createChallenge(
                    bytes32 wasmModuleRoot_,
                    MachineStatus[2] calldata startAndEndMachineStatuses_,
                    GlobalState[2] calldata startAndEndGlobalStates_,
                    uint64 numBlocks,
                    address asserter_,
                    address challenger_,
                    uint256 asserterTimeLeft_,
                    uint256 challengerTimeLeft_
                ) external returns (uint64);
                function challengeInfo(uint64 challengeIndex_)
                    external
                    view
                    returns (ChallengeLib.Challenge memory);
                function currentResponder(uint64 challengeIndex) external view returns (address);
                function isTimedOut(uint64 challengeIndex) external view returns (bool);
                function currentResponderTimeLeft(uint64 challengeIndex_) external view returns (uint256);
                function clearChallenge(uint64 challengeIndex_) external;
                function timeout(uint64 challengeIndex_) external;
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "../state/Machine.sol";
            import "../state/GlobalState.sol";
            library ChallengeLib {
                using MachineLib for Machine;
                using ChallengeLib for Challenge;
                /// @dev It's assumed that that uninitialzed challenges have mode NONE
                enum ChallengeMode {
                    NONE,
                    BLOCK,
                    EXECUTION
                }
                struct Participant {
                    address addr;
                    uint256 timeLeft;
                }
                struct Challenge {
                    Participant current;
                    Participant next;
                    uint256 lastMoveTimestamp;
                    bytes32 wasmModuleRoot;
                    bytes32 challengeStateHash;
                    uint64 maxInboxMessages;
                    ChallengeMode mode;
                }
                struct SegmentSelection {
                    uint256 oldSegmentsStart;
                    uint256 oldSegmentsLength;
                    bytes32[] oldSegments;
                    uint256 challengePosition;
                }
                function timeUsedSinceLastMove(Challenge storage challenge) internal view returns (uint256) {
                    return block.timestamp - challenge.lastMoveTimestamp;
                }
                function isTimedOut(Challenge storage challenge) internal view returns (bool) {
                    return challenge.timeUsedSinceLastMove() > challenge.current.timeLeft;
                }
                function getStartMachineHash(bytes32 globalStateHash, bytes32 wasmModuleRoot)
                    internal
                    pure
                    returns (bytes32)
                {
                    // Start the value stack with the function call ABI for the entrypoint
                    Value[] memory startingValues = new Value[](3);
                    startingValues[0] = ValueLib.newRefNull();
                    startingValues[1] = ValueLib.newI32(0);
                    startingValues[2] = ValueLib.newI32(0);
                    ValueArray memory valuesArray = ValueArray({inner: startingValues});
                    ValueStack memory values = ValueStack({proved: valuesArray, remainingHash: 0});
                    ValueStack memory internalStack;
                    StackFrameWindow memory frameStack;
                    Machine memory mach = Machine({
                        status: MachineStatus.RUNNING,
                        valueStack: values,
                        internalStack: internalStack,
                        frameStack: frameStack,
                        globalStateHash: globalStateHash,
                        moduleIdx: 0,
                        functionIdx: 0,
                        functionPc: 0,
                        modulesRoot: wasmModuleRoot
                    });
                    return mach.hash();
                }
                function getEndMachineHash(MachineStatus status, bytes32 globalStateHash)
                    internal
                    pure
                    returns (bytes32)
                {
                    if (status == MachineStatus.FINISHED) {
                        return keccak256(abi.encodePacked("Machine finished:", globalStateHash));
                    } else if (status == MachineStatus.ERRORED) {
                        return keccak256(abi.encodePacked("Machine errored:"));
                    } else if (status == MachineStatus.TOO_FAR) {
                        return keccak256(abi.encodePacked("Machine too far:"));
                    } else {
                        revert("BAD_BLOCK_STATUS");
                    }
                }
                function extractChallengeSegment(SegmentSelection calldata selection)
                    internal
                    pure
                    returns (uint256 segmentStart, uint256 segmentLength)
                {
                    uint256 oldChallengeDegree = selection.oldSegments.length - 1;
                    segmentLength = selection.oldSegmentsLength / oldChallengeDegree;
                    // Intentionally done before challengeLength is potentially added to for the final segment
                    segmentStart = selection.oldSegmentsStart + segmentLength * selection.challengePosition;
                    if (selection.challengePosition == selection.oldSegments.length - 2) {
                        segmentLength += selection.oldSegmentsLength % oldChallengeDegree;
                    }
                }
                function hashChallengeState(
                    uint256 segmentsStart,
                    uint256 segmentsLength,
                    bytes32[] memory segments
                ) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked(segmentsStart, segmentsLength, segments));
                }
                function blockStateHash(MachineStatus status, bytes32 globalStateHash)
                    internal
                    pure
                    returns (bytes32)
                {
                    if (status == MachineStatus.FINISHED) {
                        return keccak256(abi.encodePacked("Block state:", globalStateHash));
                    } else if (status == MachineStatus.ERRORED) {
                        return keccak256(abi.encodePacked("Block state, errored:", globalStateHash));
                    } else if (status == MachineStatus.TOO_FAR) {
                        return keccak256(abi.encodePacked("Block state, too far:"));
                    } else {
                        revert("BAD_BLOCK_STATUS");
                    }
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            struct GlobalState {
                bytes32[2] bytes32Vals;
                uint64[2] u64Vals;
            }
            library GlobalStateLib {
                uint16 internal constant BYTES32_VALS_NUM = 2;
                uint16 internal constant U64_VALS_NUM = 2;
                function hash(GlobalState memory state) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                "Global state:",
                                state.bytes32Vals[0],
                                state.bytes32Vals[1],
                                state.u64Vals[0],
                                state.u64Vals[1]
                            )
                        );
                }
                function getBlockHash(GlobalState memory state) internal pure returns (bytes32) {
                    return state.bytes32Vals[0];
                }
                function getSendRoot(GlobalState memory state) internal pure returns (bytes32) {
                    return state.bytes32Vals[1];
                }
                function getInboxPosition(GlobalState memory state) internal pure returns (uint64) {
                    return state.u64Vals[0];
                }
                function getPositionInMessage(GlobalState memory state) internal pure returns (uint64) {
                    return state.u64Vals[1];
                }
                function isEmpty(GlobalState calldata state) internal pure returns (bool) {
                    return (state.bytes32Vals[0] == bytes32(0) &&
                        state.bytes32Vals[1] == bytes32(0) &&
                        state.u64Vals[0] == 0 &&
                        state.u64Vals[1] == 0);
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "../bridge/IBridge.sol";
            interface IRollupEventInbox {
                function bridge() external view returns (IBridge);
                function initialize(IBridge _bridge) external;
                function rollup() external view returns (address);
                function rollupInitialized(uint256 chainId) external;
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "./ValueStack.sol";
            import "./Instructions.sol";
            import "./StackFrame.sol";
            enum MachineStatus {
                RUNNING,
                FINISHED,
                ERRORED,
                TOO_FAR
            }
            struct Machine {
                MachineStatus status;
                ValueStack valueStack;
                ValueStack internalStack;
                StackFrameWindow frameStack;
                bytes32 globalStateHash;
                uint32 moduleIdx;
                uint32 functionIdx;
                uint32 functionPc;
                bytes32 modulesRoot;
            }
            library MachineLib {
                using StackFrameLib for StackFrameWindow;
                using ValueStackLib for ValueStack;
                function hash(Machine memory mach) internal pure returns (bytes32) {
                    // Warning: the non-running hashes are replicated in Challenge
                    if (mach.status == MachineStatus.RUNNING) {
                        return
                            keccak256(
                                abi.encodePacked(
                                    "Machine running:",
                                    mach.valueStack.hash(),
                                    mach.internalStack.hash(),
                                    mach.frameStack.hash(),
                                    mach.globalStateHash,
                                    mach.moduleIdx,
                                    mach.functionIdx,
                                    mach.functionPc,
                                    mach.modulesRoot
                                )
                            );
                    } else if (mach.status == MachineStatus.FINISHED) {
                        return keccak256(abi.encodePacked("Machine finished:", mach.globalStateHash));
                    } else if (mach.status == MachineStatus.ERRORED) {
                        return keccak256(abi.encodePacked("Machine errored:"));
                    } else if (mach.status == MachineStatus.TOO_FAR) {
                        return keccak256(abi.encodePacked("Machine too far:"));
                    } else {
                        revert("BAD_MACH_STATUS");
                    }
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "./IOneStepProver.sol";
            library OneStepProofEntryLib {
                uint256 internal constant MAX_STEPS = 1 << 43;
            }
            interface IOneStepProofEntry {
                function proveOneStep(
                    ExecutionContext calldata execCtx,
                    uint256 machineStep,
                    bytes32 beforeHash,
                    bytes calldata proof
                ) external view returns (bytes32 afterHash);
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            interface IChallengeResultReceiver {
                function completeChallenge(
                    uint256 challengeIndex,
                    address winner,
                    address loser
                ) external;
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "./Value.sol";
            import "./ValueArray.sol";
            struct ValueStack {
                ValueArray proved;
                bytes32 remainingHash;
            }
            library ValueStackLib {
                using ValueLib for Value;
                using ValueArrayLib for ValueArray;
                function hash(ValueStack memory stack) internal pure returns (bytes32 h) {
                    h = stack.remainingHash;
                    uint256 len = stack.proved.length();
                    for (uint256 i = 0; i < len; i++) {
                        h = keccak256(abi.encodePacked("Value stack:", stack.proved.get(i).hash(), h));
                    }
                }
                function peek(ValueStack memory stack) internal pure returns (Value memory) {
                    uint256 len = stack.proved.length();
                    return stack.proved.get(len - 1);
                }
                function pop(ValueStack memory stack) internal pure returns (Value memory) {
                    return stack.proved.pop();
                }
                function push(ValueStack memory stack, Value memory val) internal pure {
                    return stack.proved.push(val);
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            struct Instruction {
                uint16 opcode;
                uint256 argumentData;
            }
            library Instructions {
                uint16 internal constant UNREACHABLE = 0x00;
                uint16 internal constant NOP = 0x01;
                uint16 internal constant RETURN = 0x0F;
                uint16 internal constant CALL = 0x10;
                uint16 internal constant CALL_INDIRECT = 0x11;
                uint16 internal constant LOCAL_GET = 0x20;
                uint16 internal constant LOCAL_SET = 0x21;
                uint16 internal constant GLOBAL_GET = 0x23;
                uint16 internal constant GLOBAL_SET = 0x24;
                uint16 internal constant I32_LOAD = 0x28;
                uint16 internal constant I64_LOAD = 0x29;
                uint16 internal constant F32_LOAD = 0x2A;
                uint16 internal constant F64_LOAD = 0x2B;
                uint16 internal constant I32_LOAD8_S = 0x2C;
                uint16 internal constant I32_LOAD8_U = 0x2D;
                uint16 internal constant I32_LOAD16_S = 0x2E;
                uint16 internal constant I32_LOAD16_U = 0x2F;
                uint16 internal constant I64_LOAD8_S = 0x30;
                uint16 internal constant I64_LOAD8_U = 0x31;
                uint16 internal constant I64_LOAD16_S = 0x32;
                uint16 internal constant I64_LOAD16_U = 0x33;
                uint16 internal constant I64_LOAD32_S = 0x34;
                uint16 internal constant I64_LOAD32_U = 0x35;
                uint16 internal constant I32_STORE = 0x36;
                uint16 internal constant I64_STORE = 0x37;
                uint16 internal constant F32_STORE = 0x38;
                uint16 internal constant F64_STORE = 0x39;
                uint16 internal constant I32_STORE8 = 0x3A;
                uint16 internal constant I32_STORE16 = 0x3B;
                uint16 internal constant I64_STORE8 = 0x3C;
                uint16 internal constant I64_STORE16 = 0x3D;
                uint16 internal constant I64_STORE32 = 0x3E;
                uint16 internal constant MEMORY_SIZE = 0x3F;
                uint16 internal constant MEMORY_GROW = 0x40;
                uint16 internal constant DROP = 0x1A;
                uint16 internal constant SELECT = 0x1B;
                uint16 internal constant I32_CONST = 0x41;
                uint16 internal constant I64_CONST = 0x42;
                uint16 internal constant F32_CONST = 0x43;
                uint16 internal constant F64_CONST = 0x44;
                uint16 internal constant I32_EQZ = 0x45;
                uint16 internal constant I32_RELOP_BASE = 0x46;
                uint16 internal constant IRELOP_EQ = 0;
                uint16 internal constant IRELOP_NE = 1;
                uint16 internal constant IRELOP_LT_S = 2;
                uint16 internal constant IRELOP_LT_U = 3;
                uint16 internal constant IRELOP_GT_S = 4;
                uint16 internal constant IRELOP_GT_U = 5;
                uint16 internal constant IRELOP_LE_S = 6;
                uint16 internal constant IRELOP_LE_U = 7;
                uint16 internal constant IRELOP_GE_S = 8;
                uint16 internal constant IRELOP_GE_U = 9;
                uint16 internal constant IRELOP_LAST = IRELOP_GE_U;
                uint16 internal constant I64_EQZ = 0x50;
                uint16 internal constant I64_RELOP_BASE = 0x51;
                uint16 internal constant I32_UNOP_BASE = 0x67;
                uint16 internal constant IUNOP_CLZ = 0;
                uint16 internal constant IUNOP_CTZ = 1;
                uint16 internal constant IUNOP_POPCNT = 2;
                uint16 internal constant IUNOP_LAST = IUNOP_POPCNT;
                uint16 internal constant I32_ADD = 0x6A;
                uint16 internal constant I32_SUB = 0x6B;
                uint16 internal constant I32_MUL = 0x6C;
                uint16 internal constant I32_DIV_S = 0x6D;
                uint16 internal constant I32_DIV_U = 0x6E;
                uint16 internal constant I32_REM_S = 0x6F;
                uint16 internal constant I32_REM_U = 0x70;
                uint16 internal constant I32_AND = 0x71;
                uint16 internal constant I32_OR = 0x72;
                uint16 internal constant I32_XOR = 0x73;
                uint16 internal constant I32_SHL = 0x74;
                uint16 internal constant I32_SHR_S = 0x75;
                uint16 internal constant I32_SHR_U = 0x76;
                uint16 internal constant I32_ROTL = 0x77;
                uint16 internal constant I32_ROTR = 0x78;
                uint16 internal constant I64_UNOP_BASE = 0x79;
                uint16 internal constant I64_ADD = 0x7C;
                uint16 internal constant I64_SUB = 0x7D;
                uint16 internal constant I64_MUL = 0x7E;
                uint16 internal constant I64_DIV_S = 0x7F;
                uint16 internal constant I64_DIV_U = 0x80;
                uint16 internal constant I64_REM_S = 0x81;
                uint16 internal constant I64_REM_U = 0x82;
                uint16 internal constant I64_AND = 0x83;
                uint16 internal constant I64_OR = 0x84;
                uint16 internal constant I64_XOR = 0x85;
                uint16 internal constant I64_SHL = 0x86;
                uint16 internal constant I64_SHR_S = 0x87;
                uint16 internal constant I64_SHR_U = 0x88;
                uint16 internal constant I64_ROTL = 0x89;
                uint16 internal constant I64_ROTR = 0x8A;
                uint16 internal constant I32_WRAP_I64 = 0xA7;
                uint16 internal constant I64_EXTEND_I32_S = 0xAC;
                uint16 internal constant I64_EXTEND_I32_U = 0xAD;
                uint16 internal constant I32_REINTERPRET_F32 = 0xBC;
                uint16 internal constant I64_REINTERPRET_F64 = 0xBD;
                uint16 internal constant F32_REINTERPRET_I32 = 0xBE;
                uint16 internal constant F64_REINTERPRET_I64 = 0xBF;
                uint16 internal constant I32_EXTEND_8S = 0xC0;
                uint16 internal constant I32_EXTEND_16S = 0xC1;
                uint16 internal constant I64_EXTEND_8S = 0xC2;
                uint16 internal constant I64_EXTEND_16S = 0xC3;
                uint16 internal constant I64_EXTEND_32S = 0xC4;
                uint16 internal constant INIT_FRAME = 0x8002;
                uint16 internal constant ARBITRARY_JUMP = 0x8003;
                uint16 internal constant ARBITRARY_JUMP_IF = 0x8004;
                uint16 internal constant MOVE_FROM_STACK_TO_INTERNAL = 0x8005;
                uint16 internal constant MOVE_FROM_INTERNAL_TO_STACK = 0x8006;
                uint16 internal constant DUP = 0x8008;
                uint16 internal constant CROSS_MODULE_CALL = 0x8009;
                uint16 internal constant CALLER_MODULE_INTERNAL_CALL = 0x800A;
                uint16 internal constant GET_GLOBAL_STATE_BYTES32 = 0x8010;
                uint16 internal constant SET_GLOBAL_STATE_BYTES32 = 0x8011;
                uint16 internal constant GET_GLOBAL_STATE_U64 = 0x8012;
                uint16 internal constant SET_GLOBAL_STATE_U64 = 0x8013;
                uint16 internal constant READ_PRE_IMAGE = 0x8020;
                uint16 internal constant READ_INBOX_MESSAGE = 0x8021;
                uint16 internal constant HALT_AND_SET_FINISHED = 0x8022;
                uint256 internal constant INBOX_INDEX_SEQUENCER = 0;
                uint256 internal constant INBOX_INDEX_DELAYED = 1;
                function hash(Instruction memory inst) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked("Instruction:", inst.opcode, inst.argumentData));
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "./Value.sol";
            struct StackFrame {
                Value returnPc;
                bytes32 localsMerkleRoot;
                uint32 callerModule;
                uint32 callerModuleInternals;
            }
            struct StackFrameWindow {
                StackFrame[] proved;
                bytes32 remainingHash;
            }
            library StackFrameLib {
                using ValueLib for Value;
                function hash(StackFrame memory frame) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                "Stack frame:",
                                frame.returnPc.hash(),
                                frame.localsMerkleRoot,
                                frame.callerModule,
                                frame.callerModuleInternals
                            )
                        );
                }
                function hash(StackFrameWindow memory window) internal pure returns (bytes32 h) {
                    h = window.remainingHash;
                    for (uint256 i = 0; i < window.proved.length; i++) {
                        h = keccak256(abi.encodePacked("Stack frame stack:", hash(window.proved[i]), h));
                    }
                }
                function peek(StackFrameWindow memory window) internal pure returns (StackFrame memory) {
                    require(window.proved.length == 1, "BAD_WINDOW_LENGTH");
                    return window.proved[0];
                }
                function pop(StackFrameWindow memory window) internal pure returns (StackFrame memory frame) {
                    require(window.proved.length == 1, "BAD_WINDOW_LENGTH");
                    frame = window.proved[0];
                    window.proved = new StackFrame[](0);
                }
                function push(StackFrameWindow memory window, StackFrame memory frame) internal pure {
                    StackFrame[] memory newProved = new StackFrame[](window.proved.length + 1);
                    for (uint256 i = 0; i < window.proved.length; i++) {
                        newProved[i] = window.proved[i];
                    }
                    newProved[window.proved.length] = frame;
                    window.proved = newProved;
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            enum ValueType {
                I32,
                I64,
                F32,
                F64,
                REF_NULL,
                FUNC_REF,
                INTERNAL_REF
            }
            struct Value {
                ValueType valueType;
                uint256 contents;
            }
            library ValueLib {
                function hash(Value memory val) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked("Value:", val.valueType, val.contents));
                }
                function maxValueType() internal pure returns (ValueType) {
                    return ValueType.INTERNAL_REF;
                }
                function assumeI32(Value memory val) internal pure returns (uint32) {
                    uint256 uintval = uint256(val.contents);
                    require(val.valueType == ValueType.I32, "NOT_I32");
                    require(uintval < (1 << 32), "BAD_I32");
                    return uint32(uintval);
                }
                function assumeI64(Value memory val) internal pure returns (uint64) {
                    uint256 uintval = uint256(val.contents);
                    require(val.valueType == ValueType.I64, "NOT_I64");
                    require(uintval < (1 << 64), "BAD_I64");
                    return uint64(uintval);
                }
                function newRefNull() internal pure returns (Value memory) {
                    return Value({valueType: ValueType.REF_NULL, contents: 0});
                }
                function newI32(uint32 x) internal pure returns (Value memory) {
                    return Value({valueType: ValueType.I32, contents: uint256(x)});
                }
                function newI64(uint64 x) internal pure returns (Value memory) {
                    return Value({valueType: ValueType.I64, contents: uint256(x)});
                }
                function newBoolean(bool x) internal pure returns (Value memory) {
                    if (x) {
                        return newI32(uint32(1));
                    } else {
                        return newI32(uint32(0));
                    }
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "./Value.sol";
            struct ValueArray {
                Value[] inner;
            }
            library ValueArrayLib {
                function get(ValueArray memory arr, uint256 index) internal pure returns (Value memory) {
                    return arr.inner[index];
                }
                function set(
                    ValueArray memory arr,
                    uint256 index,
                    Value memory val
                ) internal pure {
                    arr.inner[index] = val;
                }
                function length(ValueArray memory arr) internal pure returns (uint256) {
                    return arr.inner.length;
                }
                function push(ValueArray memory arr, Value memory val) internal pure {
                    Value[] memory newInner = new Value[](arr.inner.length + 1);
                    for (uint256 i = 0; i < arr.inner.length; i++) {
                        newInner[i] = arr.inner[i];
                    }
                    newInner[arr.inner.length] = val;
                    arr.inner = newInner;
                }
                function pop(ValueArray memory arr) internal pure returns (Value memory popped) {
                    popped = arr.inner[arr.inner.length - 1];
                    Value[] memory newInner = new Value[](arr.inner.length - 1);
                    for (uint256 i = 0; i < newInner.length; i++) {
                        newInner[i] = arr.inner[i];
                    }
                    arr.inner = newInner;
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "../state/Machine.sol";
            import "../state/Module.sol";
            import "../state/Instructions.sol";
            import "../bridge/ISequencerInbox.sol";
            import "../bridge/IBridge.sol";
            struct ExecutionContext {
                uint256 maxInboxMessagesRead;
                IBridge bridge;
            }
            abstract contract IOneStepProver {
                function executeOneStep(
                    ExecutionContext memory execCtx,
                    Machine calldata mach,
                    Module calldata mod,
                    Instruction calldata instruction,
                    bytes calldata proof
                ) external view virtual returns (Machine memory result, Module memory resultMod);
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "./ModuleMemory.sol";
            struct Module {
                bytes32 globalsMerkleRoot;
                ModuleMemory moduleMemory;
                bytes32 tablesMerkleRoot;
                bytes32 functionsMerkleRoot;
                uint32 internalsOffset;
            }
            library ModuleLib {
                using ModuleMemoryLib for ModuleMemory;
                function hash(Module memory mod) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                "Module:",
                                mod.globalsMerkleRoot,
                                mod.moduleMemory.hash(),
                                mod.tablesMerkleRoot,
                                mod.functionsMerkleRoot,
                                mod.internalsOffset
                            )
                        );
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "./MerkleProof.sol";
            import "./Deserialize.sol";
            struct ModuleMemory {
                uint64 size;
                uint64 maxSize;
                bytes32 merkleRoot;
            }
            library ModuleMemoryLib {
                using MerkleProofLib for MerkleProof;
                function hash(ModuleMemory memory mem) internal pure returns (bytes32) {
                    return keccak256(abi.encodePacked("Memory:", mem.size, mem.maxSize, mem.merkleRoot));
                }
                function proveLeaf(
                    ModuleMemory memory mem,
                    uint256 leafIdx,
                    bytes calldata proof,
                    uint256 startOffset
                )
                    internal
                    pure
                    returns (
                        bytes32 contents,
                        uint256 offset,
                        MerkleProof memory merkle
                    )
                {
                    offset = startOffset;
                    (contents, offset) = Deserialize.b32(proof, offset);
                    (merkle, offset) = Deserialize.merkleProof(proof, offset);
                    bytes32 recomputedRoot = merkle.computeRootFromMemory(leafIdx, contents);
                    require(recomputedRoot == mem.merkleRoot, "WRONG_MEM_ROOT");
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "./Value.sol";
            import "./Instructions.sol";
            import "./Module.sol";
            struct MerkleProof {
                bytes32[] counterparts;
            }
            library MerkleProofLib {
                using ModuleLib for Module;
                using ValueLib for Value;
                function computeRootFromValue(
                    MerkleProof memory proof,
                    uint256 index,
                    Value memory leaf
                ) internal pure returns (bytes32) {
                    return computeRootUnsafe(proof, index, leaf.hash(), "Value merkle tree:");
                }
                function computeRootFromInstruction(
                    MerkleProof memory proof,
                    uint256 index,
                    Instruction memory inst
                ) internal pure returns (bytes32) {
                    return computeRootUnsafe(proof, index, Instructions.hash(inst), "Instruction merkle tree:");
                }
                function computeRootFromFunction(
                    MerkleProof memory proof,
                    uint256 index,
                    bytes32 codeRoot
                ) internal pure returns (bytes32) {
                    bytes32 h = keccak256(abi.encodePacked("Function:", codeRoot));
                    return computeRootUnsafe(proof, index, h, "Function merkle tree:");
                }
                function computeRootFromMemory(
                    MerkleProof memory proof,
                    uint256 index,
                    bytes32 contents
                ) internal pure returns (bytes32) {
                    bytes32 h = keccak256(abi.encodePacked("Memory leaf:", contents));
                    return computeRootUnsafe(proof, index, h, "Memory merkle tree:");
                }
                function computeRootFromElement(
                    MerkleProof memory proof,
                    uint256 index,
                    bytes32 funcTypeHash,
                    Value memory val
                ) internal pure returns (bytes32) {
                    bytes32 h = keccak256(abi.encodePacked("Table element:", funcTypeHash, val.hash()));
                    return computeRootUnsafe(proof, index, h, "Table element merkle tree:");
                }
                function computeRootFromTable(
                    MerkleProof memory proof,
                    uint256 index,
                    uint8 tableType,
                    uint64 tableSize,
                    bytes32 elementsRoot
                ) internal pure returns (bytes32) {
                    bytes32 h = keccak256(abi.encodePacked("Table:", tableType, tableSize, elementsRoot));
                    return computeRootUnsafe(proof, index, h, "Table merkle tree:");
                }
                function computeRootFromModule(
                    MerkleProof memory proof,
                    uint256 index,
                    Module memory mod
                ) internal pure returns (bytes32) {
                    return computeRootUnsafe(proof, index, mod.hash(), "Module merkle tree:");
                }
                // WARNING: leafHash must be computed in such a way that it cannot be a non-leaf hash.
                function computeRootUnsafe(
                    MerkleProof memory proof,
                    uint256 index,
                    bytes32 leafHash,
                    string memory prefix
                ) internal pure returns (bytes32 h) {
                    h = leafHash;
                    for (uint256 layer = 0; layer < proof.counterparts.length; layer++) {
                        if (index & 1 == 0) {
                            h = keccak256(abi.encodePacked(prefix, h, proof.counterparts[layer]));
                        } else {
                            h = keccak256(abi.encodePacked(prefix, proof.counterparts[layer], h));
                        }
                        index >>= 1;
                    }
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import "./Value.sol";
            import "./ValueStack.sol";
            import "./Machine.sol";
            import "./Instructions.sol";
            import "./StackFrame.sol";
            import "./MerkleProof.sol";
            import "./ModuleMemory.sol";
            import "./Module.sol";
            import "./GlobalState.sol";
            library Deserialize {
                function u8(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (uint8 ret, uint256 offset)
                {
                    offset = startOffset;
                    ret = uint8(proof[offset]);
                    offset++;
                }
                function u16(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (uint16 ret, uint256 offset)
                {
                    offset = startOffset;
                    for (uint256 i = 0; i < 16 / 8; i++) {
                        ret <<= 8;
                        ret |= uint8(proof[offset]);
                        offset++;
                    }
                }
                function u32(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (uint32 ret, uint256 offset)
                {
                    offset = startOffset;
                    for (uint256 i = 0; i < 32 / 8; i++) {
                        ret <<= 8;
                        ret |= uint8(proof[offset]);
                        offset++;
                    }
                }
                function u64(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (uint64 ret, uint256 offset)
                {
                    offset = startOffset;
                    for (uint256 i = 0; i < 64 / 8; i++) {
                        ret <<= 8;
                        ret |= uint8(proof[offset]);
                        offset++;
                    }
                }
                function u256(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (uint256 ret, uint256 offset)
                {
                    offset = startOffset;
                    for (uint256 i = 0; i < 256 / 8; i++) {
                        ret <<= 8;
                        ret |= uint8(proof[offset]);
                        offset++;
                    }
                }
                function b32(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (bytes32 ret, uint256 offset)
                {
                    offset = startOffset;
                    uint256 retInt;
                    (retInt, offset) = u256(proof, offset);
                    ret = bytes32(retInt);
                }
                function value(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (Value memory val, uint256 offset)
                {
                    offset = startOffset;
                    uint8 typeInt = uint8(proof[offset]);
                    offset++;
                    require(typeInt <= uint8(ValueLib.maxValueType()), "BAD_VALUE_TYPE");
                    uint256 contents;
                    (contents, offset) = u256(proof, offset);
                    val = Value({valueType: ValueType(typeInt), contents: contents});
                }
                function valueStack(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (ValueStack memory stack, uint256 offset)
                {
                    offset = startOffset;
                    bytes32 remainingHash;
                    (remainingHash, offset) = b32(proof, offset);
                    uint256 provedLength;
                    (provedLength, offset) = u256(proof, offset);
                    Value[] memory proved = new Value[](provedLength);
                    for (uint256 i = 0; i < proved.length; i++) {
                        (proved[i], offset) = value(proof, offset);
                    }
                    stack = ValueStack({proved: ValueArray(proved), remainingHash: remainingHash});
                }
                function instruction(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (Instruction memory inst, uint256 offset)
                {
                    offset = startOffset;
                    uint16 opcode;
                    uint256 data;
                    (opcode, offset) = u16(proof, offset);
                    (data, offset) = u256(proof, offset);
                    inst = Instruction({opcode: opcode, argumentData: data});
                }
                function stackFrame(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (StackFrame memory window, uint256 offset)
                {
                    offset = startOffset;
                    Value memory returnPc;
                    bytes32 localsMerkleRoot;
                    uint32 callerModule;
                    uint32 callerModuleInternals;
                    (returnPc, offset) = value(proof, offset);
                    (localsMerkleRoot, offset) = b32(proof, offset);
                    (callerModule, offset) = u32(proof, offset);
                    (callerModuleInternals, offset) = u32(proof, offset);
                    window = StackFrame({
                        returnPc: returnPc,
                        localsMerkleRoot: localsMerkleRoot,
                        callerModule: callerModule,
                        callerModuleInternals: callerModuleInternals
                    });
                }
                function stackFrameWindow(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (StackFrameWindow memory window, uint256 offset)
                {
                    offset = startOffset;
                    bytes32 remainingHash;
                    (remainingHash, offset) = b32(proof, offset);
                    StackFrame[] memory proved;
                    if (proof[offset] != 0) {
                        offset++;
                        proved = new StackFrame[](1);
                        (proved[0], offset) = stackFrame(proof, offset);
                    } else {
                        offset++;
                        proved = new StackFrame[](0);
                    }
                    window = StackFrameWindow({proved: proved, remainingHash: remainingHash});
                }
                function moduleMemory(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (ModuleMemory memory mem, uint256 offset)
                {
                    offset = startOffset;
                    uint64 size;
                    uint64 maxSize;
                    bytes32 root;
                    (size, offset) = u64(proof, offset);
                    (maxSize, offset) = u64(proof, offset);
                    (root, offset) = b32(proof, offset);
                    mem = ModuleMemory({size: size, maxSize: maxSize, merkleRoot: root});
                }
                function module(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (Module memory mod, uint256 offset)
                {
                    offset = startOffset;
                    bytes32 globalsMerkleRoot;
                    ModuleMemory memory mem;
                    bytes32 tablesMerkleRoot;
                    bytes32 functionsMerkleRoot;
                    uint32 internalsOffset;
                    (globalsMerkleRoot, offset) = b32(proof, offset);
                    (mem, offset) = moduleMemory(proof, offset);
                    (tablesMerkleRoot, offset) = b32(proof, offset);
                    (functionsMerkleRoot, offset) = b32(proof, offset);
                    (internalsOffset, offset) = u32(proof, offset);
                    mod = Module({
                        globalsMerkleRoot: globalsMerkleRoot,
                        moduleMemory: mem,
                        tablesMerkleRoot: tablesMerkleRoot,
                        functionsMerkleRoot: functionsMerkleRoot,
                        internalsOffset: internalsOffset
                    });
                }
                function globalState(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (GlobalState memory state, uint256 offset)
                {
                    offset = startOffset;
                    // using constant ints for array size requires newer solidity
                    bytes32[2] memory bytes32Vals;
                    uint64[2] memory u64Vals;
                    for (uint8 i = 0; i < GlobalStateLib.BYTES32_VALS_NUM; i++) {
                        (bytes32Vals[i], offset) = b32(proof, offset);
                    }
                    for (uint8 i = 0; i < GlobalStateLib.U64_VALS_NUM; i++) {
                        (u64Vals[i], offset) = u64(proof, offset);
                    }
                    state = GlobalState({bytes32Vals: bytes32Vals, u64Vals: u64Vals});
                }
                function machine(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (Machine memory mach, uint256 offset)
                {
                    offset = startOffset;
                    MachineStatus status;
                    {
                        uint8 statusU8;
                        (statusU8, offset) = u8(proof, offset);
                        if (statusU8 == 0) {
                            status = MachineStatus.RUNNING;
                        } else if (statusU8 == 1) {
                            status = MachineStatus.FINISHED;
                        } else if (statusU8 == 2) {
                            status = MachineStatus.ERRORED;
                        } else if (statusU8 == 3) {
                            status = MachineStatus.TOO_FAR;
                        } else {
                            revert("UNKNOWN_MACH_STATUS");
                        }
                    }
                    ValueStack memory values;
                    ValueStack memory internalStack;
                    bytes32 globalStateHash;
                    uint32 moduleIdx;
                    uint32 functionIdx;
                    uint32 functionPc;
                    StackFrameWindow memory frameStack;
                    bytes32 modulesRoot;
                    (values, offset) = valueStack(proof, offset);
                    (internalStack, offset) = valueStack(proof, offset);
                    (frameStack, offset) = stackFrameWindow(proof, offset);
                    (globalStateHash, offset) = b32(proof, offset);
                    (moduleIdx, offset) = u32(proof, offset);
                    (functionIdx, offset) = u32(proof, offset);
                    (functionPc, offset) = u32(proof, offset);
                    (modulesRoot, offset) = b32(proof, offset);
                    mach = Machine({
                        status: status,
                        valueStack: values,
                        internalStack: internalStack,
                        frameStack: frameStack,
                        globalStateHash: globalStateHash,
                        moduleIdx: moduleIdx,
                        functionIdx: functionIdx,
                        functionPc: functionPc,
                        modulesRoot: modulesRoot
                    });
                }
                function merkleProof(bytes calldata proof, uint256 startOffset)
                    internal
                    pure
                    returns (MerkleProof memory merkle, uint256 offset)
                {
                    offset = startOffset;
                    uint8 length;
                    (length, offset) = u8(proof, offset);
                    bytes32[] memory counterparts = new bytes32[](length);
                    for (uint8 i = 0; i < length; i++) {
                        (counterparts[i], offset) = b32(proof, offset);
                    }
                    merkle = MerkleProof(counterparts);
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            struct Node {
                // Hash of the state of the chain as of this node
                bytes32 stateHash;
                // Hash of the data that can be challenged
                bytes32 challengeHash;
                // Hash of the data that will be committed if this node is confirmed
                bytes32 confirmData;
                // Index of the node previous to this one
                uint64 prevNum;
                // Deadline at which this node can be confirmed
                uint64 deadlineBlock;
                // Deadline at which a child of this node can be confirmed
                uint64 noChildConfirmedBeforeBlock;
                // Number of stakers staked on this node. This includes real stakers and zombies
                uint64 stakerCount;
                // Number of stakers staked on a child node. This includes real stakers and zombies
                uint64 childStakerCount;
                // This value starts at zero and is set to a value when the first child is created. After that it is constant until the node is destroyed or the owner destroys pending nodes
                uint64 firstChildBlock;
                // The number of the latest child of this node to be created
                uint64 latestChildNumber;
                // The block number when this node was created
                uint64 createdAtBlock;
                // A hash of all the data needed to determine this node's validity, to protect against reorgs
                bytes32 nodeHash;
            }
            /**
             * @notice Utility functions for Node
             */
            library NodeLib {
                /**
                 * @notice Initialize a Node
                 * @param _stateHash Initial value of stateHash
                 * @param _challengeHash Initial value of challengeHash
                 * @param _confirmData Initial value of confirmData
                 * @param _prevNum Initial value of prevNum
                 * @param _deadlineBlock Initial value of deadlineBlock
                 * @param _nodeHash Initial value of nodeHash
                 */
                function createNode(
                    bytes32 _stateHash,
                    bytes32 _challengeHash,
                    bytes32 _confirmData,
                    uint64 _prevNum,
                    uint64 _deadlineBlock,
                    bytes32 _nodeHash
                ) internal view returns (Node memory) {
                    Node memory node;
                    node.stateHash = _stateHash;
                    node.challengeHash = _challengeHash;
                    node.confirmData = _confirmData;
                    node.prevNum = _prevNum;
                    node.deadlineBlock = _deadlineBlock;
                    node.noChildConfirmedBeforeBlock = _deadlineBlock;
                    node.createdAtBlock = uint64(block.number);
                    node.nodeHash = _nodeHash;
                    return node;
                }
                /**
                 * @notice Update child properties
                 * @param number The child number to set
                 */
                function childCreated(Node storage self, uint64 number) internal {
                    if (self.firstChildBlock == 0) {
                        self.firstChildBlock = uint64(block.number);
                    }
                    self.latestChildNumber = number;
                }
                /**
                 * @notice Update the child confirmed deadline
                 * @param deadline The new deadline to set
                 */
                function newChildConfirmDeadline(Node storage self, uint64 deadline) internal {
                    self.noChildConfirmedBeforeBlock = deadline;
                }
                /**
                 * @notice Check whether the current block number has met or passed the node's deadline
                 */
                function requirePastDeadline(Node memory self) internal view {
                    require(block.number >= self.deadlineBlock, "BEFORE_DEADLINE");
                }
                /**
                 * @notice Check whether the current block number has met or passed deadline for children of this node to be confirmed
                 */
                function requirePastChildConfirmDeadline(Node memory self) internal view {
                    require(block.number >= self.noChildConfirmedBeforeBlock, "CHILD_TOO_RECENT");
                }
            }
            

            File 4 of 4: Bridge
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.4;
            import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
            import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
            import {
                NotContract,
                NotRollupOrOwner,
                NotDelayedInbox,
                NotSequencerInbox,
                NotOutbox,
                InvalidOutboxSet,
                BadSequencerMessageNumber
            } from "../libraries/Error.sol";
            import "./IBridge.sol";
            import "./Messages.sol";
            import "../libraries/DelegateCallAware.sol";
            import {L1MessageType_batchPostingReport} from "../libraries/MessageTypes.sol";
            /**
             * @title Staging ground for incoming and outgoing messages
             * @notice Holds the inbox accumulator for sequenced and delayed messages.
             * It is also the ETH escrow for value sent with these messages.
             * Since the escrow is held here, this contract also contains a list of allowed
             * outboxes that can make calls from here and withdraw this escrow.
             */
            contract Bridge is Initializable, DelegateCallAware, IBridge {
                using AddressUpgradeable for address;
                struct InOutInfo {
                    uint256 index;
                    bool allowed;
                }
                mapping(address => InOutInfo) private allowedDelayedInboxesMap;
                mapping(address => InOutInfo) private allowedOutboxesMap;
                address[] public allowedDelayedInboxList;
                address[] public allowedOutboxList;
                address private _activeOutbox;
                /// @inheritdoc IBridge
                bytes32[] public delayedInboxAccs;
                /// @inheritdoc IBridge
                bytes32[] public sequencerInboxAccs;
                IOwnable public rollup;
                address public sequencerInbox;
                uint256 public override sequencerReportedSubMessageCount;
                address private constant EMPTY_ACTIVEOUTBOX = address(type(uint160).max);
                function initialize(IOwnable rollup_) external initializer onlyDelegated {
                    _activeOutbox = EMPTY_ACTIVEOUTBOX;
                    rollup = rollup_;
                }
                modifier onlyRollupOrOwner() {
                    if (msg.sender != address(rollup)) {
                        address rollupOwner = rollup.owner();
                        if (msg.sender != rollupOwner) {
                            revert NotRollupOrOwner(msg.sender, address(rollup), rollupOwner);
                        }
                    }
                    _;
                }
                /// @dev returns the address of current active Outbox, or zero if no outbox is active
                function activeOutbox() public view returns (address) {
                    address outbox = _activeOutbox;
                    // address zero is returned if no outbox is set, but the value used in storage
                    // is non-zero to save users some gas (as storage refunds are usually maxed out)
                    // EIP-1153 would help here.
                    // we don't return `EMPTY_ACTIVEOUTBOX` to avoid a breaking change on the current api
                    if (outbox == EMPTY_ACTIVEOUTBOX) return address(0);
                    return outbox;
                }
                function allowedDelayedInboxes(address inbox) external view returns (bool) {
                    return allowedDelayedInboxesMap[inbox].allowed;
                }
                function allowedOutboxes(address outbox) external view returns (bool) {
                    return allowedOutboxesMap[outbox].allowed;
                }
                modifier onlySequencerInbox() {
                    if (msg.sender != sequencerInbox) revert NotSequencerInbox(msg.sender);
                    _;
                }
                function enqueueSequencerMessage(
                    bytes32 dataHash,
                    uint256 afterDelayedMessagesRead,
                    uint256 prevMessageCount,
                    uint256 newMessageCount
                )
                    external
                    onlySequencerInbox
                    returns (
                        uint256 seqMessageIndex,
                        bytes32 beforeAcc,
                        bytes32 delayedAcc,
                        bytes32 acc
                    )
                {
                    if (
                        sequencerReportedSubMessageCount != prevMessageCount &&
                        prevMessageCount != 0 &&
                        sequencerReportedSubMessageCount != 0
                    ) {
                        revert BadSequencerMessageNumber(sequencerReportedSubMessageCount, prevMessageCount);
                    }
                    sequencerReportedSubMessageCount = newMessageCount;
                    seqMessageIndex = sequencerInboxAccs.length;
                    if (sequencerInboxAccs.length > 0) {
                        beforeAcc = sequencerInboxAccs[sequencerInboxAccs.length - 1];
                    }
                    if (afterDelayedMessagesRead > 0) {
                        delayedAcc = delayedInboxAccs[afterDelayedMessagesRead - 1];
                    }
                    acc = keccak256(abi.encodePacked(beforeAcc, dataHash, delayedAcc));
                    sequencerInboxAccs.push(acc);
                }
                /// @inheritdoc IBridge
                function submitBatchSpendingReport(address sender, bytes32 messageDataHash)
                    external
                    onlySequencerInbox
                    returns (uint256)
                {
                    return
                        addMessageToDelayedAccumulator(
                            L1MessageType_batchPostingReport,
                            sender,
                            uint64(block.number),
                            uint64(block.timestamp), // solhint-disable-line not-rely-on-time,
                            block.basefee,
                            messageDataHash
                        );
                }
                /// @inheritdoc IBridge
                function enqueueDelayedMessage(
                    uint8 kind,
                    address sender,
                    bytes32 messageDataHash
                ) external payable returns (uint256) {
                    if (!allowedDelayedInboxesMap[msg.sender].allowed) revert NotDelayedInbox(msg.sender);
                    return
                        addMessageToDelayedAccumulator(
                            kind,
                            sender,
                            uint64(block.number),
                            uint64(block.timestamp), // solhint-disable-line not-rely-on-time
                            block.basefee,
                            messageDataHash
                        );
                }
                function addMessageToDelayedAccumulator(
                    uint8 kind,
                    address sender,
                    uint64 blockNumber,
                    uint64 blockTimestamp,
                    uint256 baseFeeL1,
                    bytes32 messageDataHash
                ) internal returns (uint256) {
                    uint256 count = delayedInboxAccs.length;
                    bytes32 messageHash = Messages.messageHash(
                        kind,
                        sender,
                        blockNumber,
                        blockTimestamp,
                        count,
                        baseFeeL1,
                        messageDataHash
                    );
                    bytes32 prevAcc = 0;
                    if (count > 0) {
                        prevAcc = delayedInboxAccs[count - 1];
                    }
                    delayedInboxAccs.push(Messages.accumulateInboxMessage(prevAcc, messageHash));
                    emit MessageDelivered(
                        count,
                        prevAcc,
                        msg.sender,
                        kind,
                        sender,
                        messageDataHash,
                        baseFeeL1,
                        blockTimestamp
                    );
                    return count;
                }
                function executeCall(
                    address to,
                    uint256 value,
                    bytes calldata data
                ) external returns (bool success, bytes memory returnData) {
                    if (!allowedOutboxesMap[msg.sender].allowed) revert NotOutbox(msg.sender);
                    if (data.length > 0 && !to.isContract()) revert NotContract(to);
                    address prevOutbox = _activeOutbox;
                    _activeOutbox = msg.sender;
                    // We set and reset active outbox around external call so activeOutbox remains valid during call
                    // We use a low level call here since we want to bubble up whether it succeeded or failed to the caller
                    // rather than reverting on failure as well as allow contract and non-contract calls
                    // solhint-disable-next-line avoid-low-level-calls
                    (success, returnData) = to.call{value: value}(data);
                    _activeOutbox = prevOutbox;
                    emit BridgeCallTriggered(msg.sender, to, value, data);
                }
                function setSequencerInbox(address _sequencerInbox) external onlyRollupOrOwner {
                    sequencerInbox = _sequencerInbox;
                    emit SequencerInboxUpdated(_sequencerInbox);
                }
                function setDelayedInbox(address inbox, bool enabled) external onlyRollupOrOwner {
                    InOutInfo storage info = allowedDelayedInboxesMap[inbox];
                    bool alreadyEnabled = info.allowed;
                    emit InboxToggle(inbox, enabled);
                    if ((alreadyEnabled && enabled) || (!alreadyEnabled && !enabled)) {
                        return;
                    }
                    if (enabled) {
                        allowedDelayedInboxesMap[inbox] = InOutInfo(allowedDelayedInboxList.length, true);
                        allowedDelayedInboxList.push(inbox);
                    } else {
                        allowedDelayedInboxList[info.index] = allowedDelayedInboxList[
                            allowedDelayedInboxList.length - 1
                        ];
                        allowedDelayedInboxesMap[allowedDelayedInboxList[info.index]].index = info.index;
                        allowedDelayedInboxList.pop();
                        delete allowedDelayedInboxesMap[inbox];
                    }
                }
                function setOutbox(address outbox, bool enabled) external onlyRollupOrOwner {
                    if (outbox == EMPTY_ACTIVEOUTBOX) revert InvalidOutboxSet(outbox);
                    InOutInfo storage info = allowedOutboxesMap[outbox];
                    bool alreadyEnabled = info.allowed;
                    emit OutboxToggle(outbox, enabled);
                    if ((alreadyEnabled && enabled) || (!alreadyEnabled && !enabled)) {
                        return;
                    }
                    if (enabled) {
                        allowedOutboxesMap[outbox] = InOutInfo(allowedOutboxList.length, true);
                        allowedOutboxList.push(outbox);
                    } else {
                        allowedOutboxList[info.index] = allowedOutboxList[allowedOutboxList.length - 1];
                        allowedOutboxesMap[allowedOutboxList[info.index]].index = info.index;
                        allowedOutboxList.pop();
                        delete allowedOutboxesMap[outbox];
                    }
                }
                function setSequencerReportedSubMessageCount(uint256 newMsgCount) external onlyRollupOrOwner {
                    sequencerReportedSubMessageCount = newMsgCount;
                }
                function delayedMessageCount() external view override returns (uint256) {
                    return delayedInboxAccs.length;
                }
                function sequencerMessageCount() external view returns (uint256) {
                    return sequencerInboxAccs.length;
                }
                /// @dev For the classic -> nitro migration. TODO: remove post-migration.
                function acceptFundsFromOldBridge() external payable {}
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)
            pragma solidity ^0.8.0;
            import "../../utils/AddressUpgradeable.sol";
            /**
             * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
             * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
             * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
             * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
             *
             * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
             * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
             *
             * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
             * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
             *
             * [CAUTION]
             * ====
             * Avoid leaving a contract uninitialized.
             *
             * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
             * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
             * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
             *
             * [.hljs-theme-light.nopadding]
             * ```
             * /// @custom:oz-upgrades-unsafe-allow constructor
             * constructor() initializer {}
             * ```
             * ====
             */
            abstract contract Initializable {
                /**
                 * @dev Indicates that the contract has been initialized.
                 */
                bool private _initialized;
                /**
                 * @dev Indicates that the contract is in the process of being initialized.
                 */
                bool private _initializing;
                /**
                 * @dev Modifier to protect an initializer function from being invoked twice.
                 */
                modifier initializer() {
                    // If the contract is initializing we ignore whether _initialized is set in order to support multiple
                    // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
                    // contract may have been reentered.
                    require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");
                    bool isTopLevelCall = !_initializing;
                    if (isTopLevelCall) {
                        _initializing = true;
                        _initialized = true;
                    }
                    _;
                    if (isTopLevelCall) {
                        _initializing = false;
                    }
                }
                /**
                 * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
                 * {initializer} modifier, directly or indirectly.
                 */
                modifier onlyInitializing() {
                    require(_initializing, "Initializable: contract is not initializing");
                    _;
                }
                function _isConstructor() private view returns (bool) {
                    return !AddressUpgradeable.isContract(address(this));
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
            pragma solidity ^0.8.1;
            /**
             * @dev Collection of functions related to the address type
             */
            library AddressUpgradeable {
                /**
                 * @dev Returns true if `account` is a contract.
                 *
                 * [IMPORTANT]
                 * ====
                 * It is unsafe to assume that an address for which this function returns
                 * false is an externally-owned account (EOA) and not a contract.
                 *
                 * Among others, `isContract` will return false for the following
                 * types of addresses:
                 *
                 *  - an externally-owned account
                 *  - a contract in construction
                 *  - an address where a contract will be created
                 *  - an address where a contract lived, but was destroyed
                 * ====
                 *
                 * [IMPORTANT]
                 * ====
                 * You shouldn't rely on `isContract` to protect against flash loan attacks!
                 *
                 * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                 * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                 * constructor.
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize/address.code.length, which returns 0
                    // for contracts in construction, since the code is only stored at the end
                    // of the constructor execution.
                    return account.code.length > 0;
                }
                /**
                 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                 * `recipient`, forwarding all available gas and reverting on errors.
                 *
                 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                 * of certain opcodes, possibly making contracts go over the 2300 gas limit
                 * imposed by `transfer`, making them unable to receive funds via
                 * `transfer`. {sendValue} removes this limitation.
                 *
                 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                 *
                 * IMPORTANT: because control is transferred to `recipient`, care must be
                 * taken to not create reentrancy vulnerabilities. Consider using
                 * {ReentrancyGuard} or the
                 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                 */
                function sendValue(address payable recipient, uint256 amount) internal {
                    require(address(this).balance >= amount, "Address: insufficient balance");
                    (bool success, ) = recipient.call{value: amount}("");
                    require(success, "Address: unable to send value, recipient may have reverted");
                }
                /**
                 * @dev Performs a Solidity function call using a low level `call`. A
                 * plain `call` is an unsafe replacement for a function call: use this
                 * function instead.
                 *
                 * If `target` reverts with a revert reason, it is bubbled up by this
                 * function (like regular Solidity function calls).
                 *
                 * Returns the raw returned data. To convert to the expected return value,
                 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                 *
                 * Requirements:
                 *
                 * - `target` must be a contract.
                 * - calling `target` with `data` must not revert.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionCall(target, data, "Address: low-level call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                 * `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, 0, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but also transferring `value` wei to `target`.
                 *
                 * Requirements:
                 *
                 * - the calling contract must have an ETH balance of at least `value`.
                 * - the called Solidity function must be `payable`.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value
                ) internal returns (bytes memory) {
                    return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                 * with `errorMessage` as a fallback revert reason when `target` reverts.
                 *
                 * _Available since v3.1._
                 */
                function functionCallWithValue(
                    address target,
                    bytes memory data,
                    uint256 value,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    require(address(this).balance >= value, "Address: insufficient balance for call");
                    require(isContract(target), "Address: call to non-contract");
                    (bool success, bytes memory returndata) = target.call{value: value}(data);
                    return verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    require(isContract(target), "Address: static call to non-contract");
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return verifyCallResult(success, returndata, errorMessage);
                }
                /**
                 * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
                 * revert reason using the provided one.
                 *
                 * _Available since v4.3._
                 */
                function verifyCallResult(
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal pure returns (bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        // Look for revert reason and bubble it up if present
                        if (returndata.length > 0) {
                            // The easiest way to bubble the revert reason is using memory via assembly
                            assembly {
                                let returndata_size := mload(returndata)
                                revert(add(32, returndata), returndata_size)
                            }
                        } else {
                            revert(errorMessage);
                        }
                    }
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.4;
            /// @dev Init was already called
            error AlreadyInit();
            /// Init was called with param set to zero that must be nonzero
            error HadZeroInit();
            /// @dev Thrown when non owner tries to access an only-owner function
            /// @param sender The msg.sender who is not the owner
            /// @param owner The owner address
            error NotOwner(address sender, address owner);
            /// @dev Thrown when an address that is not the rollup tries to call an only-rollup function
            /// @param sender The sender who is not the rollup
            /// @param rollup The rollup address authorized to call this function
            error NotRollup(address sender, address rollup);
            /// @dev Thrown when the contract was not called directly from the origin ie msg.sender != tx.origin
            error NotOrigin();
            /// @dev Provided data was too large
            /// @param dataLength The length of the data that is too large
            /// @param maxDataLength The max length the data can be
            error DataTooLarge(uint256 dataLength, uint256 maxDataLength);
            /// @dev The provided is not a contract and was expected to be
            /// @param addr The adddress in question
            error NotContract(address addr);
            /// @dev The merkle proof provided was too long
            /// @param actualLength The length of the merkle proof provided
            /// @param maxProofLength The max length a merkle proof can have
            error MerkleProofTooLong(uint256 actualLength, uint256 maxProofLength);
            /// @dev Thrown when an un-authorized address tries to access an admin function
            /// @param sender The un-authorized sender
            /// @param rollup The rollup, which would be authorized
            /// @param owner The rollup's owner, which would be authorized
            error NotRollupOrOwner(address sender, address rollup, address owner);
            // Bridge Errors
            /// @dev Thrown when an un-authorized address tries to access an only-inbox function
            /// @param sender The un-authorized sender
            error NotDelayedInbox(address sender);
            /// @dev Thrown when an un-authorized address tries to access an only-sequencer-inbox function
            /// @param sender The un-authorized sender
            error NotSequencerInbox(address sender);
            /// @dev Thrown when an un-authorized address tries to access an only-outbox function
            /// @param sender The un-authorized sender
            error NotOutbox(address sender);
            /// @dev the provided outbox address isn't valid
            /// @param outbox address of outbox being set
            error InvalidOutboxSet(address outbox);
            // Inbox Errors
            /// @dev The contract is paused, so cannot be paused
            error AlreadyPaused();
            /// @dev The contract is unpaused, so cannot be unpaused
            error AlreadyUnpaused();
            /// @dev The contract is paused
            error Paused();
            /// @dev msg.value sent to the inbox isn't high enough
            error InsufficientValue(uint256 expected, uint256 actual);
            /// @dev submission cost provided isn't enough to create retryable ticket
            error InsufficientSubmissionCost(uint256 expected, uint256 actual);
            /// @dev address not allowed to interact with the given contract
            error NotAllowedOrigin(address origin);
            /// @dev used to convey retryable tx data in eth calls without requiring a tx trace
            /// this follows a pattern similar to EIP-3668 where reverts surface call information
            error RetryableData(
                address from,
                address to,
                uint256 l2CallValue,
                uint256 deposit,
                uint256 maxSubmissionCost,
                address excessFeeRefundAddress,
                address callValueRefundAddress,
                uint256 gasLimit,
                uint256 maxFeePerGas,
                bytes data
            );
            // Outbox Errors
            /// @dev The provided proof was too long
            /// @param proofLength The length of the too-long proof
            error ProofTooLong(uint256 proofLength);
            /// @dev The output index was greater than the maximum
            /// @param index The output index
            /// @param maxIndex The max the index could be
            error PathNotMinimal(uint256 index, uint256 maxIndex);
            /// @dev The calculated root does not exist
            /// @param root The calculated root
            error UnknownRoot(bytes32 root);
            /// @dev The record has already been spent
            /// @param index The index of the spent record
            error AlreadySpent(uint256 index);
            /// @dev A call to the bridge failed with no return data
            error BridgeCallFailed();
            // Sequencer Inbox Errors
            /// @dev Thrown when someone attempts to read fewer messages than have already been read
            error DelayedBackwards();
            /// @dev Thrown when someone attempts to read more messages than exist
            error DelayedTooFar();
            /// @dev Force include can only read messages more blocks old than the delay period
            error ForceIncludeBlockTooSoon();
            /// @dev Force include can only read messages more seconds old than the delay period
            error ForceIncludeTimeTooSoon();
            /// @dev The message provided did not match the hash in the delayed inbox
            error IncorrectMessagePreimage();
            /// @dev This can only be called by the batch poster
            error NotBatchPoster();
            /// @dev The sequence number provided to this message was inconsistent with the number of batches already included
            error BadSequencerNumber(uint256 stored, uint256 received);
            /// @dev The sequence message number provided to this message was inconsistent with the previous one
            error BadSequencerMessageNumber(uint256 stored, uint256 received);
            /// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox
            error DataNotAuthenticated();
            /// @dev Tried to create an already valid Data Availability Service keyset
            error AlreadyValidDASKeyset(bytes32);
            /// @dev Tried to use or invalidate an already invalid Data Availability Service keyset
            error NoSuchKeyset(bytes32);
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            // solhint-disable-next-line compiler-version
            pragma solidity >=0.6.9 <0.9.0;
            import "./IOwnable.sol";
            interface IBridge {
                event MessageDelivered(
                    uint256 indexed messageIndex,
                    bytes32 indexed beforeInboxAcc,
                    address inbox,
                    uint8 kind,
                    address sender,
                    bytes32 messageDataHash,
                    uint256 baseFeeL1,
                    uint64 timestamp
                );
                event BridgeCallTriggered(
                    address indexed outbox,
                    address indexed to,
                    uint256 value,
                    bytes data
                );
                event InboxToggle(address indexed inbox, bool enabled);
                event OutboxToggle(address indexed outbox, bool enabled);
                event SequencerInboxUpdated(address newSequencerInbox);
                function allowedDelayedInboxList(uint256) external returns (address);
                function allowedOutboxList(uint256) external returns (address);
                /// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
                function delayedInboxAccs(uint256) external view returns (bytes32);
                /// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
                function sequencerInboxAccs(uint256) external view returns (bytes32);
                function rollup() external view returns (IOwnable);
                function sequencerInbox() external view returns (address);
                function activeOutbox() external view returns (address);
                function allowedDelayedInboxes(address inbox) external view returns (bool);
                function allowedOutboxes(address outbox) external view returns (bool);
                function sequencerReportedSubMessageCount() external view returns (uint256);
                /**
                 * @dev Enqueue a message in the delayed inbox accumulator.
                 *      These messages are later sequenced in the SequencerInbox, either
                 *      by the sequencer as part of a normal batch, or by force inclusion.
                 */
                function enqueueDelayedMessage(
                    uint8 kind,
                    address sender,
                    bytes32 messageDataHash
                ) external payable returns (uint256);
                function executeCall(
                    address to,
                    uint256 value,
                    bytes calldata data
                ) external returns (bool success, bytes memory returnData);
                function delayedMessageCount() external view returns (uint256);
                function sequencerMessageCount() external view returns (uint256);
                // ---------- onlySequencerInbox functions ----------
                function enqueueSequencerMessage(
                    bytes32 dataHash,
                    uint256 afterDelayedMessagesRead,
                    uint256 prevMessageCount,
                    uint256 newMessageCount
                )
                    external
                    returns (
                        uint256 seqMessageIndex,
                        bytes32 beforeAcc,
                        bytes32 delayedAcc,
                        bytes32 acc
                    );
                /**
                 * @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type
                 *      This is done through a separate function entrypoint instead of allowing the sequencer inbox
                 *      to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either
                 *      every delayed inbox or every sequencer inbox call.
                 */
                function submitBatchSpendingReport(address batchPoster, bytes32 dataHash)
                    external
                    returns (uint256 msgNum);
                // ---------- onlyRollupOrOwner functions ----------
                function setSequencerInbox(address _sequencerInbox) external;
                function setDelayedInbox(address inbox, bool enabled) external;
                function setOutbox(address inbox, bool enabled) external;
                // ---------- initializer ----------
                function initialize(IOwnable rollup_) external;
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            library Messages {
                function messageHash(
                    uint8 kind,
                    address sender,
                    uint64 blockNumber,
                    uint64 timestamp,
                    uint256 inboxSeqNum,
                    uint256 baseFeeL1,
                    bytes32 messageDataHash
                ) internal pure returns (bytes32) {
                    return
                        keccak256(
                            abi.encodePacked(
                                kind,
                                sender,
                                blockNumber,
                                timestamp,
                                inboxSeqNum,
                                baseFeeL1,
                                messageDataHash
                            )
                        );
                }
                function accumulateInboxMessage(bytes32 prevAcc, bytes32 message)
                    internal
                    pure
                    returns (bytes32)
                {
                    return keccak256(abi.encodePacked(prevAcc, message));
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.0;
            import {NotOwner} from "./Error.sol";
            /// @dev A stateless contract that allows you to infer if the current call has been delegated or not
            /// Pattern used here is from UUPS implementation by the OpenZeppelin team
            abstract contract DelegateCallAware {
                address private immutable __self = address(this);
                /**
                 * @dev Check that the execution is being performed through a delegate call. This allows a function to be
                 * callable on the proxy contract but not on the logic contract.
                 */
                modifier onlyDelegated() {
                    require(address(this) != __self, "Function must be called through delegatecall");
                    _;
                }
                /**
                 * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
                 * callable on the implementing contract but not through proxies.
                 */
                modifier notDelegated() {
                    require(address(this) == __self, "Function must not be called through delegatecall");
                    _;
                }
                /// @dev Check that msg.sender is the current EIP 1967 proxy admin
                modifier onlyProxyOwner() {
                    // Storage slot with the admin of the proxy contract
                    // This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1
                    bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                    address admin;
                    assembly {
                        admin := sload(slot)
                    }
                    if (msg.sender != admin) revert NotOwner(msg.sender, admin);
                    _;
                }
            }
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            pragma solidity ^0.8.4;
            uint8 constant L2_MSG = 3;
            uint8 constant L1MessageType_L2FundedByL1 = 7;
            uint8 constant L1MessageType_submitRetryableTx = 9;
            uint8 constant L1MessageType_ethDeposit = 12;
            uint8 constant L1MessageType_batchPostingReport = 13;
            uint8 constant L2MessageType_unsignedEOATx = 0;
            uint8 constant L2MessageType_unsignedContractTx = 1;
            uint8 constant ROLLUP_PROTOCOL_EVENT_TYPE = 8;
            uint8 constant INITIALIZATION_MSG_TYPE = 11;
            // Copyright 2021-2022, Offchain Labs, Inc.
            // For license information, see https://github.com/nitro/blob/master/LICENSE
            // SPDX-License-Identifier: BUSL-1.1
            // solhint-disable-next-line compiler-version
            pragma solidity >=0.4.21 <0.9.0;
            interface IOwnable {
                function owner() external view returns (address);
            }