ETH Price: $1,890.33 (-1.36%)

Transaction Decoder

Block:
15340278 at Aug-14-2022 02:26:40 PM +UTC
Transaction Fee:
0.000849745760665038 ETH $1.61
Gas Used:
91,317 Gas / 9.305449814 Gwei

Emitted Events:

55 TransparentUpgradeableProxy.0x5e3c1311ea442664e8b1611bfabef659120ea7a0a2cfc0667700bebc69cbffe1( 0x5e3c1311ea442664e8b1611bfabef659120ea7a0a2cfc0667700bebc69cbffe1, 0x00000000000000000000000000000000000000000000000000000000000021bf, 0x119a9b5795330cdb70a1bdb1a5b6b31cbda80fb1d363e3194d819d6676b8f63a, 000000000000000000000000c4448b71118c9071bcb9734a0eac55d18a153949, 000000000000000000000000000000000000000000000000000000000000000c, 000000000000000000000000a41e14b3f6f0f90e967df4a942128fadc53de55c, a0fcf880fbe1bde988f5c6cfb2bfb6894b37f113be4a6e29e3cdda61fb912071, 00000000000000000000000000000000000000000000000000000001d13db656, 0000000000000000000000000000000000000000000000000000000062f90620 )
56 TransparentUpgradeableProxy.0xff64905f73a67fb594e0f940a8075a860db489ad991e032f48c81123eb52d60b( 0xff64905f73a67fb594e0f940a8075a860db489ad991e032f48c81123eb52d60b, 0x00000000000000000000000000000000000000000000000000000000000021bf, 0000000000000000000000000000000000000000000000000000000000000020, 0000000000000000000000000000000000000000000000000000000000000034, 930d14b3f6f0f90e967df4a942128fadc53dd44b000000000000000000000000, 000000000000000000000000001c6bf526340000000000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x930D14B3...Dc53dd44b
0.02915901883608364 Eth
Nonce: 15
0.020309273075418602 Eth
Nonce: 16
0.008849745760665038
(Miner: 0xab3...83a)
1,472.961326137974180222 Eth1,472.961463113474180222 Eth0.0001369755
0xC1Ebd02f...7DdE276Bd
(Arbitrum Nova: Bridge)
637.346156392024198552 Eth637.354156392024198552 Eth0.008

Execution Trace

ETH 0.008 TransparentUpgradeableProxy.CALL( )
  • ETH 0.008 Inbox.DELEGATECALL( )
    • ETH 0.008 TransparentUpgradeableProxy.8db5993b( )
      • ETH 0.008 Bridge.enqueueDelayedMessage( kind=12, sender=0xa41E14B3f6f0f90e967df4A942128fAdC53DE55c, messageDataHash=A0FCF880FBE1BDE988F5C6CFB2BFB6894B37F113BE4A6E29E3CDDA61FB912071 ) => ( 8639 )
        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: Inbox
        // 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 {
            AlreadyInit,
            NotOrigin,
            DataTooLarge,
            AlreadyPaused,
            AlreadyUnpaused,
            Paused,
            InsufficientValue,
            InsufficientSubmissionCost,
            NotAllowedOrigin,
            RetryableData,
            NotRollupOrOwner
        } from "../libraries/Error.sol";
        import "./IInbox.sol";
        import "./ISequencerInbox.sol";
        import "./IBridge.sol";
        import "./Messages.sol";
        import "../libraries/AddressAliasHelper.sol";
        import "../libraries/DelegateCallAware.sol";
        import {
            L2_MSG,
            L1MessageType_L2FundedByL1,
            L1MessageType_submitRetryableTx,
            L1MessageType_ethDeposit,
            L2MessageType_unsignedEOATx,
            L2MessageType_unsignedContractTx
        } from "../libraries/MessageTypes.sol";
        import {MAX_DATA_SIZE} from "../libraries/Constants.sol";
        import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
        import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
        /**
         * @title Inbox for user and contract originated messages
         * @notice Messages created via this inbox are enqueued in the delayed accumulator
         * to await inclusion in the SequencerInbox
         */
        contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
            IBridge public override bridge;
            ISequencerInbox public sequencerInbox;
            /// ------------------------------------ allow list start ------------------------------------ ///
            bool public allowListEnabled;
            mapping(address => bool) public isAllowed;
            event AllowListAddressSet(address indexed user, bool val);
            event AllowListEnabledUpdated(bool isEnabled);
            function setAllowList(address[] memory user, bool[] memory val) external onlyRollupOrOwner {
                require(user.length == val.length, "INVALID_INPUT");
                for (uint256 i = 0; i < user.length; i++) {
                    isAllowed[user[i]] = val[i];
                    emit AllowListAddressSet(user[i], val[i]);
                }
            }
            function setAllowListEnabled(bool _allowListEnabled) external onlyRollupOrOwner {
                require(_allowListEnabled != allowListEnabled, "ALREADY_SET");
                allowListEnabled = _allowListEnabled;
                emit AllowListEnabledUpdated(_allowListEnabled);
            }
            /// @dev this modifier checks the tx.origin instead of msg.sender for convenience (ie it allows
            /// allowed users to interact with the token bridge without needing the token bridge to be allowList aware).
            /// this modifier is not intended to use to be used for security (since this opens the allowList to
            /// a smart contract phishing risk).
            modifier onlyAllowed() {
                // solhint-disable-next-line avoid-tx-origin
                if (allowListEnabled && !isAllowed[tx.origin]) revert NotAllowedOrigin(tx.origin);
                _;
            }
            /// ------------------------------------ allow list end ------------------------------------ ///
            modifier onlyRollupOrOwner() {
                IOwnable rollup = bridge.rollup();
                if (msg.sender != address(rollup)) {
                    address rollupOwner = rollup.owner();
                    if (msg.sender != rollupOwner) {
                        revert NotRollupOrOwner(msg.sender, address(rollup), rollupOwner);
                    }
                }
                _;
            }
            /// @notice pauses all inbox functionality
            function pause() external onlyRollupOrOwner {
                _pause();
            }
            /// @notice unpauses all inbox functionality
            function unpause() external onlyRollupOrOwner {
                _unpause();
            }
            function initialize(IBridge _bridge, ISequencerInbox _sequencerInbox)
                external
                initializer
                onlyDelegated
            {
                if (address(bridge) != address(0)) revert AlreadyInit();
                bridge = _bridge;
                sequencerInbox = _sequencerInbox;
                allowListEnabled = false;
                __Pausable_init();
            }
            /// @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 onlyDelegated onlyProxyOwner {
                uint8 slotsToWipe = 3;
                for (uint8 i = 0; i < slotsToWipe; i++) {
                    assembly {
                        sstore(i, 0)
                    }
                }
                allowListEnabled = false;
                bridge = _bridge;
            }
            /**
             * @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
             * @param messageData Data of the message being sent
             */
            function sendL2MessageFromOrigin(bytes calldata messageData)
                external
                whenNotPaused
                onlyAllowed
                returns (uint256)
            {
                // solhint-disable-next-line avoid-tx-origin
                if (msg.sender != tx.origin) revert NotOrigin();
                if (messageData.length > MAX_DATA_SIZE)
                    revert DataTooLarge(messageData.length, MAX_DATA_SIZE);
                uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(messageData));
                emit InboxMessageDeliveredFromOrigin(msgNum);
                return msgNum;
            }
            /**
             * @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
             * @param messageData Data of the message being sent
             */
            function sendL2Message(bytes calldata messageData)
                external
                override
                whenNotPaused
                onlyAllowed
                returns (uint256)
            {
                return _deliverMessage(L2_MSG, msg.sender, messageData);
            }
            function sendL1FundedUnsignedTransaction(
                uint256 gasLimit,
                uint256 maxFeePerGas,
                uint256 nonce,
                address to,
                bytes calldata data
            ) external payable virtual override whenNotPaused onlyAllowed returns (uint256) {
                return
                    _deliverMessage(
                        L1MessageType_L2FundedByL1,
                        msg.sender,
                        abi.encodePacked(
                            L2MessageType_unsignedEOATx,
                            gasLimit,
                            maxFeePerGas,
                            nonce,
                            uint256(uint160(to)),
                            msg.value,
                            data
                        )
                    );
            }
            function sendL1FundedContractTransaction(
                uint256 gasLimit,
                uint256 maxFeePerGas,
                address to,
                bytes calldata data
            ) external payable virtual override whenNotPaused onlyAllowed returns (uint256) {
                return
                    _deliverMessage(
                        L1MessageType_L2FundedByL1,
                        msg.sender,
                        abi.encodePacked(
                            L2MessageType_unsignedContractTx,
                            gasLimit,
                            maxFeePerGas,
                            uint256(uint160(to)),
                            msg.value,
                            data
                        )
                    );
            }
            function sendUnsignedTransaction(
                uint256 gasLimit,
                uint256 maxFeePerGas,
                uint256 nonce,
                address to,
                uint256 value,
                bytes calldata data
            ) external virtual override whenNotPaused onlyAllowed returns (uint256) {
                return
                    _deliverMessage(
                        L2_MSG,
                        msg.sender,
                        abi.encodePacked(
                            L2MessageType_unsignedEOATx,
                            gasLimit,
                            maxFeePerGas,
                            nonce,
                            uint256(uint160(to)),
                            value,
                            data
                        )
                    );
            }
            function sendContractTransaction(
                uint256 gasLimit,
                uint256 maxFeePerGas,
                address to,
                uint256 value,
                bytes calldata data
            ) external virtual override whenNotPaused onlyAllowed returns (uint256) {
                return
                    _deliverMessage(
                        L2_MSG,
                        msg.sender,
                        abi.encodePacked(
                            L2MessageType_unsignedContractTx,
                            gasLimit,
                            maxFeePerGas,
                            uint256(uint160(to)),
                            value,
                            data
                        )
                    );
            }
            /**
             * @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)
                public
                view
                returns (uint256)
            {
                // Use current block basefee if baseFee parameter is 0
                return (1400 + 6 * dataLength) * (baseFee == 0 ? block.basefee : baseFee);
            }
            /// @notice deposit eth from L1 to L2
            /// @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() public payable override whenNotPaused onlyAllowed returns (uint256) {
                address dest = msg.sender;
                // solhint-disable-next-line avoid-tx-origin
                if (AddressUpgradeable.isContract(msg.sender) || tx.origin != msg.sender) {
                    // isContract check fails if this function is called during a contract's constructor.
                    // We don't adjust the address for calls coming from L1 contracts since their addresses get remapped
                    // If the caller is an EOA, we adjust the address.
                    // This is needed because unsigned messages to the L2 (such as retryables)
                    // have the L1 sender address mapped.
                    dest = AddressAliasHelper.applyL1ToL2Alias(msg.sender);
                }
                return
                    _deliverMessage(
                        L1MessageType_ethDeposit,
                        msg.sender,
                        abi.encodePacked(dest, msg.value)
                    );
            }
            /// @notice deprecated in favour of depositEth with no parameters
            function depositEth(uint256)
                external
                payable
                virtual
                override
                whenNotPaused
                onlyAllowed
                returns (uint256)
            {
                return depositEth();
            }
            /**
             * @notice deprecated in favour of unsafeCreateRetryableTicket
             * @dev deprecated in favour of unsafeCreateRetryableTicket
             * @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 id for retryable transaction (keccak256(requestID, uint(0) )
             */
            function createRetryableTicketNoRefundAliasRewrite(
                address to,
                uint256 l2CallValue,
                uint256 maxSubmissionCost,
                address excessFeeRefundAddress,
                address callValueRefundAddress,
                uint256 gasLimit,
                uint256 maxFeePerGas,
                bytes calldata data
            ) external payable virtual whenNotPaused onlyAllowed returns (uint256) {
                return
                    unsafeCreateRetryableTicket(
                        to,
                        l2CallValue,
                        maxSubmissionCost,
                        excessFeeRefundAddress,
                        callValueRefundAddress,
                        gasLimit,
                        maxFeePerGas,
                        data
                    );
            }
            /**
             * @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 id for retryable transaction (keccak256(requestID, uint(0) )
             */
            function createRetryableTicket(
                address to,
                uint256 l2CallValue,
                uint256 maxSubmissionCost,
                address excessFeeRefundAddress,
                address callValueRefundAddress,
                uint256 gasLimit,
                uint256 maxFeePerGas,
                bytes calldata data
            ) external payable virtual override whenNotPaused onlyAllowed returns (uint256) {
                // ensure the user's deposit alone will make submission succeed
                if (msg.value < (maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas)) {
                    revert InsufficientValue(
                        maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas,
                        msg.value
                    );
                }
                // if a refund address is a contract, we apply the alias to it
                // so that it can access its funds on the L2
                // since the beneficiary and other refund addresses don't get rewritten by arb-os
                if (AddressUpgradeable.isContract(excessFeeRefundAddress)) {
                    excessFeeRefundAddress = AddressAliasHelper.applyL1ToL2Alias(excessFeeRefundAddress);
                }
                if (AddressUpgradeable.isContract(callValueRefundAddress)) {
                    // this is the beneficiary. be careful since this is the address that can cancel the retryable in the L2
                    callValueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(callValueRefundAddress);
                }
                return
                    unsafeCreateRetryableTicket(
                        to,
                        l2CallValue,
                        maxSubmissionCost,
                        excessFeeRefundAddress,
                        callValueRefundAddress,
                        gasLimit,
                        maxFeePerGas,
                        data
                    );
            }
            /**
             * @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 id for retryable transaction (keccak256(requestID, uint(0) )
             */
            function unsafeCreateRetryableTicket(
                address to,
                uint256 l2CallValue,
                uint256 maxSubmissionCost,
                address excessFeeRefundAddress,
                address callValueRefundAddress,
                uint256 gasLimit,
                uint256 maxFeePerGas,
                bytes calldata data
            ) public payable virtual override whenNotPaused onlyAllowed returns (uint256) {
                // gas price and limit of 1 should never be a valid input, so instead they are used as
                // magic values to trigger a revert in eth calls that surface data without requiring a tx trace
                if (gasLimit == 1 || maxFeePerGas == 1)
                    revert RetryableData(
                        msg.sender,
                        to,
                        l2CallValue,
                        msg.value,
                        maxSubmissionCost,
                        excessFeeRefundAddress,
                        callValueRefundAddress,
                        gasLimit,
                        maxFeePerGas,
                        data
                    );
                uint256 submissionFee = calculateRetryableSubmissionFee(data.length, block.basefee);
                if (maxSubmissionCost < submissionFee)
                    revert InsufficientSubmissionCost(submissionFee, maxSubmissionCost);
                return
                    _deliverMessage(
                        L1MessageType_submitRetryableTx,
                        msg.sender,
                        abi.encodePacked(
                            uint256(uint160(to)),
                            l2CallValue,
                            msg.value,
                            maxSubmissionCost,
                            uint256(uint160(excessFeeRefundAddress)),
                            uint256(uint160(callValueRefundAddress)),
                            gasLimit,
                            maxFeePerGas,
                            data.length,
                            data
                        )
                    );
            }
            function _deliverMessage(
                uint8 _kind,
                address _sender,
                bytes memory _messageData
            ) internal returns (uint256) {
                if (_messageData.length > MAX_DATA_SIZE)
                    revert DataTooLarge(_messageData.length, MAX_DATA_SIZE);
                uint256 msgNum = deliverToBridge(_kind, _sender, keccak256(_messageData));
                emit InboxMessageDelivered(msgNum, _messageData);
                return msgNum;
            }
            function deliverToBridge(
                uint8 kind,
                address sender,
                bytes32 messageDataHash
            ) internal returns (uint256) {
                return
                    bridge.enqueueDelayedMessage{value: msg.value}(
                        kind,
                        AddressAliasHelper.applyL1ToL2Alias(sender),
                        messageDataHash
                    );
            }
        }
        // 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 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 "./IBridge.sol";
        import "./IDelayedMessageProvider.sol";
        interface IInbox is IDelayedMessageProvider {
            function sendL2Message(bytes calldata messageData) external 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);
            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);
            /// @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
            function createRetryableTicket(
                address to,
                uint256 arbTxCallValue,
                uint256 maxSubmissionCost,
                address submissionRefundAddress,
                address valueRefundAddress,
                uint256 gasLimit,
                uint256 maxFeePerGas,
                bytes calldata data
            ) external payable returns (uint256);
            /// @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
            function unsafeCreateRetryableTicket(
                address to,
                uint256 arbTxCallValue,
                uint256 maxSubmissionCost,
                address submissionRefundAddress,
                address valueRefundAddress,
                uint256 gasLimit,
                uint256 maxFeePerGas,
                bytes calldata data
            ) external payable returns (uint256);
            function depositEth() external payable returns (uint256);
            /// @notice deprecated in favour of depositEth with no parameters
            function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);
            function bridge() external view returns (IBridge);
            function postUpgradeInit(IBridge _bridge) 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";
        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 inboxAccs(uint256 index) external view returns (bytes32);
            function batchCount() external view returns (uint256);
            function addSequencerL2Batch(
                uint256 sequenceNumber,
                bytes calldata data,
                uint256 afterDelayedMessagesRead,
                IGasRefunder gasRefunder
            ) external;
            // Methods only callable by rollup owner
            /**
             * @notice Set max time variation from actual time for sequencer inbox
             * @param timeVariation the maximum time variation parameters
             */
            function setMaxTimeVariation(MaxTimeVariation memory timeVariation) 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;
            function setValidKeyset(bytes calldata keysetBytes) external;
            function invalidateKeysetHash(bytes32 ksHash) 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 "./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 enqueueDelayedMessage(
                uint8 kind,
                address sender,
                bytes32 messageDataHash
            ) external payable returns (uint256);
            function enqueueSequencerMessage(bytes32 dataHash, uint256 afterDelayedMessagesRead)
                external
                returns (
                    uint256 seqMessageIndex,
                    bytes32 beforeAcc,
                    bytes32 delayedAcc,
                    bytes32 acc
                );
            function submitBatchSpendingReport(address batchPoster, bytes32 dataHash)
                external
                returns (uint256 msgNum);
            function executeCall(
                address to,
                uint256 value,
                bytes calldata data
            ) external returns (bool success, bytes memory returnData);
            // These are only callable by the admin
            function setDelayedInbox(address inbox, bool enabled) external;
            function setOutbox(address inbox, bool enabled) external;
            function setSequencerInbox(address _sequencerInbox) external;
            // View functions
            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 delayedInboxAccs(uint256 index) external view returns (bytes32);
            function sequencerInboxAccs(uint256 index) external view returns (bytes32);
            function delayedMessageCount() external view returns (uint256);
            function sequencerMessageCount() external view returns (uint256);
            function rollup() external view returns (IOwnable);
            function acceptFundsFromOldBridge() external payable;
        }
        // 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;
        library AddressAliasHelper {
            uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111);
            /// @notice Utility function that converts the address in the L1 that submitted a tx to
            /// the inbox to the msg.sender viewed in the L2
            /// @param l1Address the address in the L1 that triggered the tx to L2
            /// @return l2Address L2 address as viewed in msg.sender
            function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {
                unchecked {
                    l2Address = address(uint160(l1Address) + OFFSET);
                }
            }
            /// @notice Utility function that converts the msg.sender viewed in the L2 to the
            /// address in the L1 that submitted a tx to the inbox
            /// @param l2Address L2 address as viewed in msg.sender
            /// @return l1Address the address in the L1 that triggered the tx to L2
            function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {
                unchecked {
                    l1Address = address(uint160(l2Address) - OFFSET);
                }
            }
        }
        // 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
        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;
        // 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);
                    }
                }
            }
        }
        // SPDX-License-Identifier: MIT
        // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)
        pragma solidity ^0.8.0;
        import "../utils/ContextUpgradeable.sol";
        import "../proxy/utils/Initializable.sol";
        /**
         * @dev Contract module which allows children to implement an emergency stop
         * mechanism that can be triggered by an authorized account.
         *
         * This module is used through inheritance. It will make available the
         * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
         * the functions of your contract. Note that they will not be pausable by
         * simply including this module, only once the modifiers are put in place.
         */
        abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
            /**
             * @dev Emitted when the pause is triggered by `account`.
             */
            event Paused(address account);
            /**
             * @dev Emitted when the pause is lifted by `account`.
             */
            event Unpaused(address account);
            bool private _paused;
            /**
             * @dev Initializes the contract in unpaused state.
             */
            function __Pausable_init() internal onlyInitializing {
                __Pausable_init_unchained();
            }
            function __Pausable_init_unchained() internal onlyInitializing {
                _paused = false;
            }
            /**
             * @dev Returns true if the contract is paused, and false otherwise.
             */
            function paused() public view virtual returns (bool) {
                return _paused;
            }
            /**
             * @dev Modifier to make a function callable only when the contract is not paused.
             *
             * Requirements:
             *
             * - The contract must not be paused.
             */
            modifier whenNotPaused() {
                require(!paused(), "Pausable: paused");
                _;
            }
            /**
             * @dev Modifier to make a function callable only when the contract is paused.
             *
             * Requirements:
             *
             * - The contract must be paused.
             */
            modifier whenPaused() {
                require(paused(), "Pausable: not paused");
                _;
            }
            /**
             * @dev Triggers stopped state.
             *
             * Requirements:
             *
             * - The contract must not be paused.
             */
            function _pause() internal virtual whenNotPaused {
                _paused = true;
                emit Paused(_msgSender());
            }
            /**
             * @dev Returns to normal state.
             *
             * Requirements:
             *
             * - The contract must be paused.
             */
            function _unpause() internal virtual whenPaused {
                _paused = false;
                emit Unpaused(_msgSender());
            }
            /**
             * @dev This empty reserved space is put in place to allow future versions to add new
             * variables without shifting down storage in the inheritance chain.
             * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
             */
            uint256[49] private __gap;
        }
        // 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
        // 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 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);
                }
            }
        }
        // SPDX-License-Identifier: MIT
        // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
        pragma solidity ^0.8.0;
        import "../proxy/utils/Initializable.sol";
        /**
         * @dev Provides information about the current execution context, including the
         * sender of the transaction and its data. While these are generally available
         * via msg.sender and msg.data, they should not be accessed in such a direct
         * manner, since when dealing with meta-transactions the account sending and
         * paying for execution may not be the actual sender (as far as an application
         * is concerned).
         *
         * This contract is only required for intermediate, library-like contracts.
         */
        abstract contract ContextUpgradeable is Initializable {
            function __Context_init() internal onlyInitializing {
            }
            function __Context_init_unchained() internal onlyInitializing {
            }
            function _msgSender() internal view virtual returns (address) {
                return msg.sender;
            }
            function _msgData() internal view virtual returns (bytes calldata) {
                return msg.data;
            }
            /**
             * @dev This empty reserved space is put in place to allow future versions to add new
             * variables without shifting down storage in the inheritance chain.
             * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
             */
            uint256[50] private __gap;
        }
        // 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));
            }
        }
        

        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 "./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;
            /// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
            bytes32[] public override delayedInboxAccs;
            /// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
            bytes32[] public override sequencerInboxAccs;
            IOwnable public override rollup;
            address public sequencerInbox;
            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 override returns (bool) {
                return allowedDelayedInboxesMap[inbox].allowed;
            }
            function allowedOutboxes(address outbox) external view override returns (bool) {
                return allowedOutboxesMap[outbox].allowed;
            }
            modifier onlySequencerInbox() {
                if (msg.sender != sequencerInbox) revert NotSequencerInbox(msg.sender);
                _;
            }
            function enqueueSequencerMessage(bytes32 dataHash, uint256 afterDelayedMessagesRead)
                external
                override
                onlySequencerInbox
                returns (
                    uint256 seqMessageIndex,
                    bytes32 beforeAcc,
                    bytes32 delayedAcc,
                    bytes32 acc
                )
            {
                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);
            }
            /**
             * @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 sender, bytes32 messageDataHash)
                external
                override
                onlySequencerInbox
                returns (uint256)
            {
                return
                    addMessageToDelayedAccumulator(
                        L1MessageType_batchPostingReport,
                        sender,
                        uint64(block.number),
                        uint64(block.timestamp), // solhint-disable-line not-rely-on-time,
                        block.basefee,
                        messageDataHash
                    );
            }
            /**
             * @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 override 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 override 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 override onlyRollupOrOwner {
                sequencerInbox = _sequencerInbox;
                emit SequencerInboxUpdated(_sequencerInbox);
            }
            function setDelayedInbox(address inbox, bool enabled) external override 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 override 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 delayedMessageCount() external view override returns (uint256) {
                return delayedInboxAccs.length;
            }
            function sequencerMessageCount() external view override returns (uint256) {
                return sequencerInboxAccs.length;
            }
        }
        // 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;
        import {NotContract, NotRollupOrOwner} from "../libraries/Error.sol";
        import "./IOwnable.sol";
        /// @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);
        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 enqueueDelayedMessage(
                uint8 kind,
                address sender,
                bytes32 messageDataHash
            ) external payable returns (uint256);
            function enqueueSequencerMessage(bytes32 dataHash, uint256 afterDelayedMessagesRead)
                external
                returns (
                    uint256 seqMessageIndex,
                    bytes32 beforeAcc,
                    bytes32 delayedAcc,
                    bytes32 acc
                );
            function submitBatchSpendingReport(address batchPoster, bytes32 dataHash)
                external
                returns (uint256 msgNum);
            function executeCall(
                address to,
                uint256 value,
                bytes calldata data
            ) external returns (bool success, bytes memory returnData);
            // These are only callable by the admin
            function setDelayedInbox(address inbox, bool enabled) external;
            function setOutbox(address inbox, bool enabled) external;
            function setSequencerInbox(address _sequencerInbox) external;
            // View functions
            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 delayedInboxAccs(uint256 index) external view returns (bytes32);
            function sequencerInboxAccs(uint256 index) external view returns (bytes32);
            function delayedMessageCount() external view returns (uint256);
            function sequencerMessageCount() external view returns (uint256);
            function rollup() external view returns (IOwnable);
        }
        // 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
        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);
        // 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;
        interface IOwnable {
            function owner() external view returns (address);
        }