ETH Price: $3,342.43 (-0.73%)
Gas: 3 Gwei

Contract

0xd151C9ef49cE2d30B829a98A07767E3280F70961
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Process Message ...173286882023-05-24 11:15:59432 days ago1684926959IN
0xd151C9ef...280F70961
0 ETH0.0081193546.39659973
Process Message ...171337152023-04-26 23:39:11460 days ago1682552351IN
0xd151C9ef...280F70961
0 ETH0.0085657148.73278901
Process Message ...171334562023-04-26 22:47:11460 days ago1682549231IN
0xd151C9ef...280F70961
0 ETH0.008323547.35158377
Process Message ...171334252023-04-26 22:40:59460 days ago1682548859IN
0xd151C9ef...280F70961
0 ETH0.0077182843.90904787
Process Message ...171301622023-04-26 11:40:35460 days ago1682509235IN
0xd151C9ef...280F70961
0 ETH0.0086895249.12025725
Process Message ...171298602023-04-26 10:39:11460 days ago1682505551IN
0xd151C9ef...280F70961
0 ETH0.007892744.52240505
Process Message ...171296062023-04-26 9:46:35460 days ago1682502395IN
0xd151C9ef...280F70961
0 ETH0.008561348.50458137
Process Message ...171295982023-04-26 9:44:59460 days ago1682502299IN
0xd151C9ef...280F70961
0 ETH0.0081646746.05655441
Process Message ...171292802023-04-26 8:41:11460 days ago1682498471IN
0xd151C9ef...280F70961
0 ETH0.0074768142.26265522
Process Message ...171292722023-04-26 8:39:35460 days ago1682498375IN
0xd151C9ef...280F70961
0 ETH0.0083876647.51759603
Process Message ...171289812023-04-26 7:41:11461 days ago1682494871IN
0xd151C9ef...280F70961
0 ETH0.0085319248.54002023
Process Message ...171286852023-04-26 6:41:23461 days ago1682491283IN
0xd151C9ef...280F70961
0 ETH0.0099451156.21852045
Process Message ...171286762023-04-26 6:39:35461 days ago1682491175IN
0xd151C9ef...280F70961
0 ETH0.007959445.28281998
Process Message ...170835822023-04-19 22:25:11467 days ago1681943111IN
0xd151C9ef...280F70961
0 ETH0.0121127668.7681982
Set Max Submissi...168050502023-03-11 13:09:59506 days ago1678540199IN
0xd151C9ef...280F70961
0 ETH0.0017887558.90464273
Set Max Gas Cap168050492023-03-11 13:09:47506 days ago1678540187IN
0xd151C9ef...280F70961
0 ETH0.0017586357.99666356
Set Gas Price Ca...168050492023-03-11 13:09:47506 days ago1678540187IN
0xd151C9ef...280F70961
0 ETH0.0018834457.99666356
Process Message ...167756132023-03-07 9:44:11510 days ago1678182251IN
0xd151C9ef...280F70961
0 ETH0.0049693228.24056573
Process Message ...167714392023-03-06 19:39:11511 days ago1678131551IN
0xd151C9ef...280F70961
0 ETH0.0088814850.46699081
Process Message ...167664012023-03-06 2:39:11512 days ago1678070351IN
0xd151C9ef...280F70961
0 ETH0.0106635260.33998869
Process Message ...166779742023-02-21 16:09:35524 days ago1676995775IN
0xd151C9ef...280F70961
0 ETH0.0089309150.86232979
Process Message ...166770952023-02-21 13:12:23524 days ago1676985143IN
0xd151C9ef...280F70961
0 ETH0.0073408141.97677947
Process Message ...166770792023-02-21 13:09:11524 days ago1676984951IN
0xd151C9ef...280F70961
0 ETH0.0059201733.70935319
Propose New Owne...166729142023-02-20 23:05:47525 days ago1676934347IN
0xd151C9ef...280F70961
0 ETH0.0020620329.57464974
Process Message ...166455332023-02-17 2:41:11529 days ago1676601671IN
0xd151C9ef...280F70961
0 ETH0.0061633735.09815569
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
188125822023-12-18 11:28:59224 days ago1702898939
0xd151C9ef...280F70961
0.00322669 ETH
188125822023-12-18 11:28:59224 days ago1702898939
0xd151C9ef...280F70961
0.00322669 ETH
188119872023-12-18 9:28:59224 days ago1702891739
0xd151C9ef...280F70961
0.00355875 ETH
188119872023-12-18 9:28:59224 days ago1702891739
0xd151C9ef...280F70961
0.00355875 ETH
188114192023-12-18 7:33:47225 days ago1702884827
0xd151C9ef...280F70961
0.00267118 ETH
188114192023-12-18 7:33:47225 days ago1702884827
0xd151C9ef...280F70961
0.00267118 ETH
188108022023-12-18 5:29:11225 days ago1702877351
0xd151C9ef...280F70961
0.00267281 ETH
188108022023-12-18 5:29:11225 days ago1702877351
0xd151C9ef...280F70961
0.00267281 ETH
188102062023-12-18 3:29:11225 days ago1702870151
0xd151C9ef...280F70961
0.00464074 ETH
188102062023-12-18 3:29:11225 days ago1702870151
0xd151C9ef...280F70961
0.00464074 ETH
188096112023-12-18 1:29:23225 days ago1702862963
0xd151C9ef...280F70961
0.00272327 ETH
188096112023-12-18 1:29:23225 days ago1702862963
0xd151C9ef...280F70961
0.00272327 ETH
188090132023-12-17 23:29:11225 days ago1702855751
0xd151C9ef...280F70961
0.00286601 ETH
188090132023-12-17 23:29:11225 days ago1702855751
0xd151C9ef...280F70961
0.00286601 ETH
188060452023-12-17 13:29:11225 days ago1702819751
0xd151C9ef...280F70961
0.00367476 ETH
188060452023-12-17 13:29:11225 days ago1702819751
0xd151C9ef...280F70961
0.00367476 ETH
188054492023-12-17 11:28:59225 days ago1702812539
0xd151C9ef...280F70961
0.00363805 ETH
188054492023-12-17 11:28:59225 days ago1702812539
0xd151C9ef...280F70961
0.00363805 ETH
188048572023-12-17 9:29:11225 days ago1702805351
0xd151C9ef...280F70961
0.00254293 ETH
188048572023-12-17 9:29:11225 days ago1702805351
0xd151C9ef...280F70961
0.00254293 ETH
188042702023-12-17 7:29:11226 days ago1702798151
0xd151C9ef...280F70961
0.00269298 ETH
188042702023-12-17 7:29:11226 days ago1702798151
0xd151C9ef...280F70961
0.00269298 ETH
188036772023-12-17 5:29:11226 days ago1702790951
0xd151C9ef...280F70961
0.00252537 ETH
188036772023-12-17 5:29:11226 days ago1702790951
0xd151C9ef...280F70961
0.00252537 ETH
188030812023-12-17 3:29:11226 days ago1702783751
0xd151C9ef...280F70961
0.00298892 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ArbitrumHubConnector

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
File 1 of 15 : ArbitrumHubConnector.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;

import {LibArbitrumL1} from "@openzeppelin/contracts/crosschain/arbitrum/LibArbitrumL1.sol";

import {TypedMemView} from "../../../shared/libraries/TypedMemView.sol";

import {IRootManager} from "../../interfaces/IRootManager.sol";
import {IArbitrumInbox} from "../../interfaces/ambs/arbitrum/IArbitrumInbox.sol";
import {IArbitrumOutbox} from "../../interfaces/ambs/arbitrum/IArbitrumOutbox.sol";
import {IArbitrumRollup, Node} from "../../interfaces/ambs/arbitrum/IArbitrumRollup.sol";

import {HubConnector} from "../HubConnector.sol";
import {Connector} from "../Connector.sol";

struct L2Message {
  address l2Sender;
  address to;
  uint256 l2Block;
  uint256 l1Block;
  uint256 l2Timestamp;
  uint256 value;
  bytes callData;
}

contract ArbitrumHubConnector is HubConnector {
  // ============ Libraries ============
  using TypedMemView for bytes;
  using TypedMemView for bytes29;

  // ============ Storage ============

  IArbitrumOutbox public outbox;
  IArbitrumRollup public rollup;

  /**
   * @notice Sets cap on maxSubmissionCost used in `createRetryableTicket`
   * @dev The value used in `createRetryableTicket` is the lesser of the cap or
   * a value passed in via `_encodedData` in `_sendMessage`.
   *
   * This value represents amount of ETH allocated to pay for the base submission fee
   */
  uint256 public maxSubmissionCostCap;

  /**
   * @notice Sets cap on maxGas used in `createRetryableTicket`
   * @dev The value used in `createRetryableTicket` is the lesser of the cap or
   * a value passed in via `_encodedData` in `_sendMessage`.
   *
   * This value represents gas limit for immediate L2 execution attempt
   */
  uint256 public maxGasCap;

  /**
   * @notice Sets cap on gasPrice used in `createRetryableTicket`
   * @dev The value used in `createRetryableTicket` is the lesser of the cap or
   * a value passed in via `_encodedData` in `_sendMessage`.
   *
   * This value represents L2 gas price bid for immediate L2 execution attempt
   */
  uint256 public gasPriceCap;

  /**
   * @notice Tracks which messages have been processed from bridge
   */
  mapping(uint256 => bool) public processed;

  // ============ Events ============
  // TODO: do we need any other information from the ticket to link to message?
  event RetryableTicketCreated(uint256 indexed ticketId);

  /**
   * @notice Emitted when admin updates the maxSubmissionCap
   * @param _previous The starting value
   * @param _updated The final value
   */
  event MaxSubmissionCapUpdated(uint256 _previous, uint256 _updated);

  /**
   * @notice Emitted when admin updates the maxGasCap
   * @param _previous The starting value
   * @param _updated The final value
   */
  event MaxGasCapUpdated(uint256 _previous, uint256 _updated);

  /**
   * @notice Emitted when admin updates the gasPriceCap
   * @param _previous The starting value
   * @param _updated The final value
   */
  event GasPriceCapUpdated(uint256 _previous, uint256 _updated);

  // ============ Constructor ============
  constructor(
    uint32 _domain,
    uint32 _mirrorDomain,
    address _amb,
    address _rootManager,
    address _mirrorConnector,
    address _outbox,
    uint256 _maxSubmissionCostCap,
    uint256 _maxGasCap,
    uint256 _gasPriceCap
  ) HubConnector(_domain, _mirrorDomain, _amb, _rootManager, _mirrorConnector) {
    outbox = IArbitrumOutbox(_outbox);
    rollup = IArbitrumRollup(outbox.rollup());

    // Set initial caps for L1 -> L2 messages
    maxSubmissionCostCap = _maxSubmissionCostCap;
    maxGasCap = _maxGasCap;
    gasPriceCap = _gasPriceCap;
  }

  // ============ Admin fns ============

  /**
   * @notice Used (by admin) to update the maxSubmissionCostCap
   * @param _updated The new value
   */
  function setMaxSubmissionCostCap(uint256 _updated) public onlyOwner {
    emit MaxSubmissionCapUpdated(maxSubmissionCostCap, _updated);
    maxSubmissionCostCap = _updated;
  }

  /**
   * @notice Used (by admin) to update the maxGasCap
   * @param _updated The new value
   */
  function setMaxGasCap(uint256 _updated) public onlyOwner {
    emit MaxGasCapUpdated(maxGasCap, _updated);
    maxGasCap = _updated;
  }

  /**
   * @notice Used (by admin) to update the gasPriceCap
   * @param _updated The new value
   */
  function setGasPriceCap(uint256 _updated) public onlyOwner {
    emit GasPriceCapUpdated(maxSubmissionCostCap, _updated);
    gasPriceCap = _updated;
  }

  // ============ Private fns ============

  function _verifySender(address _expected) internal view override returns (bool) {
    return _expected == LibArbitrumL1.crossChainSender(AMB);
  }

  /**
   * @notice Helper to return the lesser of two values
   * @param _a Some number
   * @param _b Some number
   */
  function _lesserOf(uint256 _a, uint256 _b) internal pure returns (uint256) {
    return _a < _b ? _a : _b;
  }

  function _sendMessage(bytes memory _data, bytes memory _encodedData) internal override {
    // Should always be dispatching the aggregate root
    require(_data.length == 32, "!length");
    // Get the calldata
    bytes memory _calldata = abi.encodeWithSelector(Connector.processMessage.selector, _data);

    // Should include specialized calldata
    require(_encodedData.length == (32 * 3), "!data length");

    // Decode all of the gas-related parameters
    (uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPrice) = abi.decode(
      _encodedData,
      (uint256, uint256, uint256)
    );

    // dispatch to l2
    uint256 ticketID = IArbitrumInbox(AMB).createRetryableTicket{value: msg.value}(
      mirrorConnector, // destAddr
      0, // arbTxCallValue
      _lesserOf(maxSubmissionCost, maxSubmissionCostCap), // maxSubmissionCost: Amount of ETH allocated to pay for the base submission fee
      mirrorConnector, // submissionRefundAddress: Address to which all excess gas is credited on L2
      mirrorConnector, // valueRefundAddress: Address to which CallValue will be credited to on L2 if the retryable ticket times out or is cancelled
      _lesserOf(maxGas, maxGasCap), // maxGas: Gas limit for immediate L2 execution attempt
      _lesserOf(gasPrice, gasPriceCap), // gasPriceBid: L2 Gas price bid for immediate L2 execution attempt
      _calldata // data
    );
    emit RetryableTicketCreated(ticketID);
  }

  // DO NOT override _processMessage, should revert from `Connector` class. All messages must use the
  // `processMessageFromRoot` flow.

  function processMessageFromRoot(
    uint64 _nodeNum,
    bytes32 _sendRoot,
    bytes32 _blockHash,
    bytes32[] calldata _proof,
    uint256 _index,
    L2Message calldata _message
  ) external {
    // Ensure the send root corresponds to an arbitrum node that exists onchain
    _validateSendRoot(_nodeNum, _sendRoot, _blockHash);

    // Ensure the given l2 message is included in the send root
    _validateMessage(_sendRoot, _proof, _index, _message);

    // Message has been proven within the send root, process the message
    // data itself. The message data is defined in the spoke connector as:
    //
    // `abi.encodeWithSelector(Connector.processMessage.selector, _data);`
    //
    // so to get the root data, we need to decode the _calldata. we can do this
    // by dropping the 4-byte selector, then using the rest as the raw _data.
    require(_message.callData.length == 100, "!length");

    // NOTE: TypedMemView only loads 32-byte chunks onto stack, which is fine in this case
    // the calldata is 100 bytes long, the last 32 bytes represent the root to be aggregated.
    bytes32 _data = _message.callData.ref(0).index(68, 32);

    // Update root manager
    IRootManager(ROOT_MANAGER).aggregate(MIRROR_DOMAIN, _data);

    // Emit event
    emit MessageProcessed(abi.encode(_data), msg.sender);
  }

  function _validateSendRoot(
    uint64 _nodeNum,
    bytes32 _sendRoot,
    bytes32 _blockHash
  ) internal view {
    // Get the confirm data to ensure the node has been put on L1 with
    // the given block hash and send root
    bytes32 confirmData = _confirmHash(_blockHash, _sendRoot);

    // Validate inputs by checking against the stored none confirm data
    Node memory node = rollup.getNode(_nodeNum);
    require(node.confirmData == confirmData, "!confirmData");

    // Validate the node is staked / not in dispute
    // NOTE: a dispute can happen at any point within the timeout window, so the closest
    // we can get is to ensure the staker count > 0 and that there have been stakes on child
    // nodes as well, meaning the node is less likely to be staked incorrectly (and thus less
    // likely to be disputed)
    require(node.stakerCount > 0 && node.childStakerCount > 0, "!staked");
  }

  // prove the message was included in the given send root
  function _validateMessage(
    bytes32 _sendRoot,
    bytes32[] calldata _proof,
    uint256 _index,
    L2Message calldata _msg
  ) internal {
    // Check that the l2sender is the mirror connector
    require(_msg.l2Sender == mirrorConnector, "!mirrorConnector");

    // Generate the message sent through from L2 (included in sendRoot)
    bytes32 userTx = outbox.calculateItemHash(
      _msg.l2Sender,
      _msg.to,
      _msg.l2Block,
      _msg.l1Block,
      _msg.l2Timestamp,
      _msg.value,
      _msg.callData
    );

    // Prove message is included in the send root
    _recordOutputAsSpent(_proof, _index, userTx, _sendRoot);
  }

  // taken from: https://github.com/OffchainLabs/nitro/blob/208d9d50f250e9b4948f867d3795548256583b17/contracts/src/rollup/RollupLib.sol#L128-L130
  function _confirmHash(bytes32 _blockHash, bytes32 _sendRoot) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked(_blockHash, _sendRoot));
  }

  // modified from: https://github.com/OffchainLabs/nitro/blob/fbaa96d6d6246b427629be176499e1d5c5013d89/contracts/src/bridge/Outbox.sol#L219-L235
  function _recordOutputAsSpent(
    bytes32[] memory _proof,
    uint256 _index,
    bytes32 _item,
    bytes32 _sendRoot
  ) internal {
    require(_proof.length < 256, "proof length");
    require((_index >> _proof.length) == 0, "!minimal proof");

    // NOTE: in the arbitrum contracts, they check that the message index is not yet spent
    // Because the spoke connector calls `processMessage`, which does nothing, it is important
    // to check out own internal mapping to ensure the message is not played twice. this forces
    // all messages from l2 to be processed using the `processMessageFromRoot` fn path.
    require(!processed[_index], "spent");

    // Calculate the root
    bytes32 calcRoot = outbox.calculateMerkleRoot(_proof, _index, _item);

    // Assert the sendRoot is correct
    // NOTE: this send root will *not* yet be stored on the `Outbox`
    // contract (fraud period has not yet elapsed);
    require(calcRoot == _sendRoot, "!proof");

    // Mark as spent
    processed[_index] = true;
  }
}

File 2 of 15 : LibArbitrumL1.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (crosschain/arbitrum/LibArbitrumL1.sol)

pragma solidity ^0.8.4;

import {IBridge as ArbitrumL1_Bridge} from "../../vendor/arbitrum/IBridge.sol";
import {IOutbox as ArbitrumL1_Outbox} from "../../vendor/arbitrum/IOutbox.sol";
import "../errors.sol";

/**
 * @dev Primitives for cross-chain aware contracts for
 * https://arbitrum.io/[Arbitrum].
 *
 * This version should only be used on L1 to process cross-chain messages
 * originating from L2. For the other side, use {LibArbitrumL2}.
 */
library LibArbitrumL1 {
    /**
     * @dev Returns whether the current function call is the result of a
     * cross-chain message relayed by the `bridge`.
     */
    function isCrossChain(address bridge) internal view returns (bool) {
        return msg.sender == bridge;
    }

    /**
     * @dev Returns the address of the sender that triggered the current
     * cross-chain message through the `bridge`.
     *
     * NOTE: {isCrossChain} should be checked before trying to recover the
     * sender, as it will revert with `NotCrossChainCall` if the current
     * function call is not the result of a cross-chain message.
     */
    function crossChainSender(address bridge) internal view returns (address) {
        if (!isCrossChain(bridge)) revert NotCrossChainCall();

        address sender = ArbitrumL1_Outbox(ArbitrumL1_Bridge(bridge).activeOutbox()).l2ToL1Sender();
        require(sender != address(0), "LibArbitrumL1: system messages without sender");

        return sender;
    }
}

File 3 of 15 : errors.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/errors.sol)

pragma solidity ^0.8.4;

error NotCrossChainCall();
error InvalidCrossChainSender(address actual, address expected);

File 4 of 15 : IBridge.sol
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// OpenZeppelin Contracts (last updated v4.8.0) (vendor/arbitrum/IBridge.sol)

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

interface IBridge {
    event MessageDelivered(
        uint256 indexed messageIndex,
        bytes32 indexed beforeInboxAcc,
        address inbox,
        uint8 kind,
        address sender,
        bytes32 messageDataHash,
        uint256 baseFeeL1,
        uint64 timestamp
    );

    event BridgeCallTriggered(address indexed outbox, address indexed to, uint256 value, bytes data);

    event InboxToggle(address indexed inbox, bool enabled);

    event OutboxToggle(address indexed outbox, bool enabled);

    event SequencerInboxUpdated(address newSequencerInbox);

    function allowedDelayedInboxList(uint256) external returns (address);

    function allowedOutboxList(uint256) external returns (address);

    /// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
    function delayedInboxAccs(uint256) external view returns (bytes32);

    /// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
    function sequencerInboxAccs(uint256) external view returns (bytes32);

    // OpenZeppelin: changed return type from IOwnable
    function rollup() external view returns (address);

    function sequencerInbox() external view returns (address);

    function activeOutbox() external view returns (address);

    function allowedDelayedInboxes(address inbox) external view returns (bool);

    function allowedOutboxes(address outbox) external view returns (bool);

    function sequencerReportedSubMessageCount() external view returns (uint256);

    /**
     * @dev Enqueue a message in the delayed inbox accumulator.
     *      These messages are later sequenced in the SequencerInbox, either
     *      by the sequencer as part of a normal batch, or by force inclusion.
     */
    function enqueueDelayedMessage(
        uint8 kind,
        address sender,
        bytes32 messageDataHash
    ) external payable returns (uint256);

    function executeCall(
        address to,
        uint256 value,
        bytes calldata data
    ) external returns (bool success, bytes memory returnData);

    function delayedMessageCount() external view returns (uint256);

    function sequencerMessageCount() external view returns (uint256);

    // ---------- onlySequencerInbox functions ----------

    function enqueueSequencerMessage(
        bytes32 dataHash,
        uint256 afterDelayedMessagesRead,
        uint256 prevMessageCount,
        uint256 newMessageCount
    )
        external
        returns (
            uint256 seqMessageIndex,
            bytes32 beforeAcc,
            bytes32 delayedAcc,
            bytes32 acc
        );

    /**
     * @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type
     *      This is done through a separate function entrypoint instead of allowing the sequencer inbox
     *      to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either
     *      every delayed inbox or every sequencer inbox call.
     */
    function submitBatchSpendingReport(address batchPoster, bytes32 dataHash) external returns (uint256 msgNum);

    // ---------- onlyRollupOrOwner functions ----------

    function setSequencerInbox(address _sequencerInbox) external;

    function setDelayedInbox(address inbox, bool enabled) external;

    function setOutbox(address inbox, bool enabled) external;

    // ---------- initializer ----------

    // OpenZeppelin: changed rollup_ type from IOwnable
    function initialize(address rollup_) external;
}

File 5 of 15 : IOutbox.sol
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// OpenZeppelin Contracts (last updated v4.8.0) (vendor/arbitrum/IOutbox.sol)

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

import "./IBridge.sol";

interface IOutbox {
    event SendRootUpdated(bytes32 indexed blockHash, bytes32 indexed outputRoot);
    event OutBoxTransactionExecuted(
        address indexed to,
        address indexed l2Sender,
        uint256 indexed zero,
        uint256 transactionIndex
    );

    function rollup() external view returns (address); // the rollup contract

    function bridge() external view returns (IBridge); // the bridge contract

    function spent(uint256) external view returns (bytes32); // packed spent bitmap

    function roots(bytes32) external view returns (bytes32); // maps root hashes => L2 block hash

    // solhint-disable-next-line func-name-mixedcase
    function OUTBOX_VERSION() external view returns (uint128); // the outbox version

    function updateSendRoot(bytes32 sendRoot, bytes32 l2BlockHash) external;

    /// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account
    ///         When the return value is zero, that means this is a system message
    /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
    function l2ToL1Sender() external view returns (address);

    /// @return l2Block return L2 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
    function l2ToL1Block() external view returns (uint256);

    /// @return l1Block return L1 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
    function l2ToL1EthBlock() external view returns (uint256);

    /// @return timestamp return L2 timestamp when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
    function l2ToL1Timestamp() external view returns (uint256);

    /// @return outputId returns the unique output identifier of the L2 to L1 tx or 0 if no L2 to L1 transaction is active
    function l2ToL1OutputId() external view returns (bytes32);

    /**
     * @notice Executes a messages in an Outbox entry.
     * @dev Reverts if dispute period hasn't expired, since the outbox entry
     *      is only created once the rollup confirms the respective assertion.
     * @dev it is not possible to execute any L2-to-L1 transaction which contains data
     *      to a contract address without any code (as enforced by the Bridge contract).
     * @param proof Merkle proof of message inclusion in send root
     * @param index Merkle path to message
     * @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
     * @param to destination address for L1 contract call
     * @param l2Block l2 block number at which sendTxToL1 call was made
     * @param l1Block l1 block number at which sendTxToL1 call was made
     * @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made
     * @param value wei in L1 message
     * @param data abi-encoded L1 message data
     */
    function executeTransaction(
        bytes32[] calldata proof,
        uint256 index,
        address l2Sender,
        address to,
        uint256 l2Block,
        uint256 l1Block,
        uint256 l2Timestamp,
        uint256 value,
        bytes calldata data
    ) external;

    /**
     *  @dev function used to simulate the result of a particular function call from the outbox
     *       it is useful for things such as gas estimates. This function includes all costs except for
     *       proof validation (which can be considered offchain as a somewhat of a fixed cost - it's
     *       not really a fixed cost, but can be treated as so with a fixed overhead for gas estimation).
     *       We can't include the cost of proof validation since this is intended to be used to simulate txs
     *       that are included in yet-to-be confirmed merkle roots. The simulation entrypoint could instead pretend
     *       to confirm a pending merkle root, but that would be less practical for integrating with tooling.
     *       It is only possible to trigger it when the msg sender is address zero, which should be impossible
     *       unless under simulation in an eth_call or eth_estimateGas
     */
    function executeTransactionSimulation(
        uint256 index,
        address l2Sender,
        address to,
        uint256 l2Block,
        uint256 l1Block,
        uint256 l2Timestamp,
        uint256 value,
        bytes calldata data
    ) external;

    /**
     * @param index Merkle path to message
     * @return true if the message has been spent
     */
    function isSpent(uint256 index) external view returns (bool);

    function calculateItemHash(
        address l2Sender,
        address to,
        uint256 l2Block,
        uint256 l1Block,
        uint256 l2Timestamp,
        uint256 value,
        bytes calldata data
    ) external pure returns (bytes32);

    function calculateMerkleRoot(
        bytes32[] memory proof,
        uint256 path,
        bytes32 item
    ) external pure returns (bytes32);
}

File 6 of 15 : Connector.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;

import {ProposedOwnable} from "../../shared/ProposedOwnable.sol";
import {IConnector} from "../interfaces/IConnector.sol";

/**
 * @title Connector
 * @author Connext Labs, Inc.
 * @notice This contract has the messaging interface functions used by all connectors.
 *
 * @dev This contract stores information about mirror connectors, but can be used as a
 * base for contracts that do not have a mirror (i.e. the connector handling messaging on
 * mainnet). In this case, the `mirrorConnector` and `MIRROR_DOMAIN`
 * will be empty
 *
 * @dev If ownership is renounced, this contract will be unable to update its `mirrorConnector`
 * or `mirrorGas`
 */
abstract contract Connector is ProposedOwnable, IConnector {
  // ========== Custom Errors ===========

  error Connector__processMessage_notUsed();

  // ============ Events ============

  event NewConnector(
    uint32 indexed domain,
    uint32 indexed mirrorDomain,
    address amb,
    address rootManager,
    address mirrorConnector
  );

  event MirrorConnectorUpdated(address previous, address current);

  // ============ Public Storage ============

  /**
   * @notice The domain of this Messaging (i.e. Connector) contract.
   */
  uint32 public immutable DOMAIN;

  /**
   * @notice Address of the AMB on this domain.
   */
  address public immutable AMB;

  /**
   * @notice RootManager contract address.
   */
  address public immutable ROOT_MANAGER;

  /**
   * @notice The domain of the corresponding messaging (i.e. Connector) contract.
   */
  uint32 public immutable MIRROR_DOMAIN;

  /**
   * @notice Connector on L2 for L1 connectors, and vice versa.
   */
  address public mirrorConnector;

  // ============ Modifiers ============

  /**
   * @notice Errors if the msg.sender is not the registered AMB
   */
  modifier onlyAMB() {
    require(msg.sender == AMB, "!AMB");
    _;
  }

  /**
   * @notice Errors if the msg.sender is not the registered ROOT_MANAGER
   */
  modifier onlyRootManager() {
    // NOTE: RootManager will be zero address for spoke connectors.
    // Only root manager can dispatch a message to spokes/L2s via the hub connector.
    require(msg.sender == ROOT_MANAGER, "!rootManager");
    _;
  }

  // ============ Constructor ============

  /**
   * @notice Creates a new HubConnector instance
   * @dev The connectors are deployed such that there is one on each side of an AMB (i.e.
   * for optimism, there is one connector on optimism and one connector on mainnet)
   * @param _domain The domain this connector lives on
   * @param _mirrorDomain The spoke domain
   * @param _amb The address of the amb on the domain this connector lives on
   * @param _rootManager The address of the RootManager on mainnet
   * @param _mirrorConnector The address of the spoke connector
   */
  constructor(
    uint32 _domain,
    uint32 _mirrorDomain,
    address _amb,
    address _rootManager,
    address _mirrorConnector
  ) ProposedOwnable() {
    // set the owner
    _setOwner(msg.sender);

    // sanity checks on values
    require(_domain != 0, "empty domain");
    require(_rootManager != address(0), "empty rootManager");
    // see note at top of contract on why the mirror values are not sanity checked

    // set immutables
    DOMAIN = _domain;
    AMB = _amb;
    ROOT_MANAGER = _rootManager;
    MIRROR_DOMAIN = _mirrorDomain;
    // set mutables if defined
    if (_mirrorConnector != address(0)) {
      _setMirrorConnector(_mirrorConnector);
    }

    emit NewConnector(_domain, _mirrorDomain, _amb, _rootManager, _mirrorConnector);
  }

  // ============ Receivable ============
  /**
   * @notice Connectors may need to receive native asset to handle fees when sending a
   * message
   */
  receive() external payable {}

  // ============ Admin Functions ============

  /**
   * @notice Sets the address of the l2Connector for this domain
   */
  function setMirrorConnector(address _mirrorConnector) public onlyOwner {
    _setMirrorConnector(_mirrorConnector);
  }

  // ============ Public Functions ============

  /**
   * @notice Processes a message received by an AMB
   * @dev This is called by AMBs to process messages originating from mirror connector
   */
  function processMessage(bytes memory _data) external virtual onlyAMB {
    _processMessage(_data);
    emit MessageProcessed(_data, msg.sender);
  }

  /**
   * @notice Checks the cross domain sender for a given address
   */
  function verifySender(address _expected) external returns (bool) {
    return _verifySender(_expected);
  }

  // ============ Virtual Functions ============

  /**
   * @notice This function is used by the Connext contract on the l2 domain to send a message to the
   * l1 domain (i.e. called by Connext on optimism to send a message to mainnet with roots)
   * @param _data The contents of the message
   * @param _encodedData Data used to send the message; specific to connector
   */
  function _sendMessage(bytes memory _data, bytes memory _encodedData) internal virtual;

  /**
   * @notice This function is used by the AMBs to handle incoming messages. Should store the latest
   * root generated on the l2 domain.
   */
  function _processMessage(
    bytes memory /* _data */
  ) internal virtual {
    // By default, reverts. This is to ensure the call path is not used unless this function is
    // overridden by the inheriting class
    revert Connector__processMessage_notUsed();
  }

  /**
   * @notice Verify that the msg.sender is the correct AMB contract, and that the message's origin sender
   * is the expected address.
   * @dev Should be overridden by the implementing Connector contract.
   */
  function _verifySender(address _expected) internal virtual returns (bool);

  // ============ Private Functions ============

  function _setMirrorConnector(address _mirrorConnector) internal virtual {
    emit MirrorConnectorUpdated(mirrorConnector, _mirrorConnector);
    mirrorConnector = _mirrorConnector;
  }
}

File 7 of 15 : HubConnector.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;

import {Connector} from "./Connector.sol";

/**
 * @title HubConnector
 * @author Connext Labs, Inc.
 * @notice This contract implements the messaging functions needed on the hub-side of a given AMB.
 * The HubConnector has a limited set of functionality compared to the SpokeConnector, namely that
 * it contains no logic to store or prove messages.
 *
 * @dev This contract should be deployed on the hub-side of an AMB (i.e. on L1), and contracts
 * which extend this should implement the virtual functions defined in the BaseConnector class
 */
abstract contract HubConnector is Connector {
  /**
   * @notice Creates a new HubConnector instance
   * @dev The connectors are deployed such that there is one on each side of an AMB (i.e.
   * for optimism, there is one connector on optimism and one connector on mainnet)
   * @param _domain The domain this connector lives on
   * @param _mirrorDomain The spoke domain
   * @param _amb The address of the amb on the domain this connector lives on
   * @param _rootManager The address of the RootManager on mainnet
   * @param _mirrorConnector The address of the spoke connector
   */
  constructor(
    uint32 _domain,
    uint32 _mirrorDomain,
    address _amb,
    address _rootManager,
    address _mirrorConnector
  ) Connector(_domain, _mirrorDomain, _amb, _rootManager, _mirrorConnector) {}

  // ============ Public fns ============
  /**
   * @notice Sends a message over the amb
   * @dev This is called by the root manager *only* on mainnet to propagate the aggregate root
   */
  function sendMessage(bytes memory _data, bytes memory _encodedData) external payable onlyRootManager {
    _sendMessage(_data, _encodedData);
    emit MessageSent(_data, _encodedData, msg.sender);
  }
}

File 8 of 15 : IConnector.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;

import {IProposedOwnable} from "../../shared/interfaces/IProposedOwnable.sol";

/**
 * @notice This interface is what the Connext contract will send and receive messages through.
 * The messaging layer should conform to this interface, and should be interchangeable (i.e.
 * could be Nomad or a generic AMB under the hood).
 *
 * @dev This uses the nomad format to ensure nomad can be added in as it comes back online.
 *
 * Flow from transfer from polygon to optimism:
 * 1. User calls `xcall` with destination specified
 * 2. This will swap in to the bridge assets
 * 3. The swapped assets will get burned
 * 4. The Connext contract will call `dispatch` on the messaging contract to add the transfer
 *    to the root
 * 5. [At some time interval] Relayers call `send` to send the current root from polygon to
 *    mainnet. This is done on all "spoke" domains.
 * 6. [At some time interval] Relayers call `propagate` [better name] on mainnet, this generates a new merkle
 *    root from all of the AMBs
 *    - This function must be able to read root data from all AMBs and aggregate them into a single merkle
 *      tree root
 *    - Will send the mixed root from all chains back through the respective AMBs to all other chains
 * 7. AMB will call `update` to update the latest root on the messaging contract on spoke domains
 * 8. [At any point] Relayers can call `proveAndProcess` to prove inclusion of dispatched message, and call
 *    process on the `Connext` contract
 * 9. Takes minted bridge tokens and credits the LP
 *
 * AMB requirements:
 * - Access `msg.sender` both from mainnet -> spoke and vice versa
 * - Ability to read *our root* from the AMB
 *
 * AMBs:
 * - PoS bridge from polygon
 * - arbitrum bridge
 * - optimism bridge
 * - gnosis chain
 * - bsc (use multichain for messaging)
 */
interface IConnector is IProposedOwnable {
  // ============ Events ============
  /**
   * @notice Emitted whenever a message is successfully sent over an AMB
   * @param data The contents of the message
   * @param encodedData Data used to send the message; specific to connector
   * @param caller Who called the function (sent the message)
   */
  event MessageSent(bytes data, bytes encodedData, address caller);

  /**
   * @notice Emitted whenever a message is successfully received over an AMB
   * @param data The contents of the message
   * @param caller Who called the function
   */
  event MessageProcessed(bytes data, address caller);

  // ============ Public fns ============

  function processMessage(bytes memory _data) external;

  function verifySender(address _expected) external returns (bool);
}

File 9 of 15 : IRootManager.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;

interface IRootManager {
  /**
   * @notice This is called by relayers to generate + send the mixed root from mainnet via AMB to
   * spoke domains.
   * @dev This must read information for the root from the registered AMBs.
   */
  function propagate(
    address[] calldata _connectors,
    uint256[] calldata _fees,
    bytes[] memory _encodedData
  ) external payable;

  /**
   * @notice Called by the connectors for various domains on the hub to aggregate their latest
   * inbound root.
   * @dev This must read information for the root from the registered AMBs
   */
  function aggregate(uint32 _domain, bytes32 _outbound) external;
}

File 10 of 15 : IArbitrumInbox.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;

/**
 * @notice Interface for sending L1 -> L2 messagesto Arbitrum.
 * @dev Arbitrum uses an inbox to aggregate messages going from L1 -> L2, source:
 * https://github.com/OffchainLabs/nitro/blob/master/contracts/src/bridge/Inbox.sol
 *
 */
interface IArbitrumInbox {
  function createRetryableTicket(
    address destAddr,
    uint256 arbTxCallValue,
    uint256 maxSubmissionCost,
    address submissionRefundAddress,
    address valueRefundAddress,
    uint256 maxGas,
    uint256 gasPriceBid,
    bytes calldata data
  ) external payable returns (uint256);
}

File 11 of 15 : IArbitrumOutbox.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;

/**
 * @notice Interface for sending L1 -> L2 messagesto Arbitrum.
 * @dev Arbitrum uses an inbox to aggregate messages going from L1 -> L2, source:
 * https://github.com/OffchainLabs/nitro/blob/master/contracts/src/bridge/Inbox.sol
 *
 */
interface IArbitrumOutbox {
  event SendRootUpdated(bytes32 indexed blockHash, bytes32 indexed outputRoot);
  event OutBoxTransactionExecuted(
    address indexed to,
    address indexed l2Sender,
    uint256 indexed zero,
    uint256 transactionIndex
  );

  function rollup() external view returns (address); // the rollup contract

  // function bridge() external view returns (IBridge); // the bridge contract

  function spent(uint256) external view returns (bytes32); // packed spent bitmap

  function roots(bytes32) external view returns (bytes32); // maps root hashes => L2 block hash

  // solhint-disable-next-line func-name-mixedcase
  function OUTBOX_VERSION() external view returns (uint128); // the outbox version

  function updateSendRoot(bytes32 sendRoot, bytes32 l2BlockHash) external;

  /// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account
  ///         When the return value is zero, that means this is a system message
  /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
  function l2ToL1Sender() external view returns (address);

  /// @return l2Block return L2 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
  function l2ToL1Block() external view returns (uint256);

  /// @return l1Block return L1 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
  function l2ToL1EthBlock() external view returns (uint256);

  /// @return timestamp return L2 timestamp when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
  function l2ToL1Timestamp() external view returns (uint256);

  /// @return outputId returns the unique output identifier of the L2 to L1 tx or 0 if no L2 to L1 transaction is active
  function l2ToL1OutputId() external view returns (bytes32);

  /**
   * @notice Executes a messages in an Outbox entry.
   * @dev Reverts if dispute period hasn't expired, since the outbox entry
   *      is only created once the rollup confirms the respective assertion.
   * @dev it is not possible to execute any L2-to-L1 transaction which contains data
   *      to a contract address without any code (as enforced by the Bridge contract).
   * @param proof Merkle proof of message inclusion in send root
   * @param index Merkle path to message
   * @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
   * @param to destination address for L1 contract call
   * @param l2Block l2 block number at which sendTxToL1 call was made
   * @param l1Block l1 block number at which sendTxToL1 call was made
   * @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made
   * @param value wei in L1 message
   * @param data abi-encoded L1 message data
   */
  function executeTransaction(
    bytes32[] calldata proof,
    uint256 index,
    address l2Sender,
    address to,
    uint256 l2Block,
    uint256 l1Block,
    uint256 l2Timestamp,
    uint256 value,
    bytes calldata data
  ) external;

  /**
   *  @dev function used to simulate the result of a particular function call from the outbox
   *       it is useful for things such as gas estimates. This function includes all costs except for
   *       proof validation (which can be considered offchain as a somewhat of a fixed cost - it's
   *       not really a fixed cost, but can be treated as so with a fixed overhead for gas estimation).
   *       We can't include the cost of proof validation since this is intended to be used to simulate txs
   *       that are included in yet-to-be confirmed merkle roots. The simulation entrypoint could instead pretend
   *       to confirm a pending merkle root, but that would be less pratical for integrating with tooling.
   *       It is only possible to trigger it when the msg sender is address zero, which should be impossible
   *       unless under simulation in an eth_call or eth_estimateGas
   */
  function executeTransactionSimulation(
    uint256 index,
    address l2Sender,
    address to,
    uint256 l2Block,
    uint256 l1Block,
    uint256 l2Timestamp,
    uint256 value,
    bytes calldata data
  ) external;

  /**
   * @param index Merkle path to message
   * @return true if the message has been spent
   */
  function isSpent(uint256 index) external view returns (bool);

  function calculateItemHash(
    address l2Sender,
    address to,
    uint256 l2Block,
    uint256 l1Block,
    uint256 l2Timestamp,
    uint256 value,
    bytes calldata data
  ) external pure returns (bytes32);

  function calculateMerkleRoot(
    bytes32[] memory proof,
    uint256 path,
    bytes32 item
  ) external pure returns (bytes32);
}

File 12 of 15 : IArbitrumRollup.sol
pragma solidity 0.8.17;

// modified from: https://github.com/OffchainLabs/nitro/blob/master/contracts/src/rollup/Node.sol
struct Node {
  // Hash of the state of the chain as of this node
  bytes32 stateHash;
  // Hash of the data that can be challenged
  bytes32 challengeHash;
  // Hash of the data that will be committed if this node is confirmed
  bytes32 confirmData;
  // Index of the node previous to this one
  uint64 prevNum;
  // Deadline at which this node can be confirmed
  uint64 deadlineBlock;
  // Deadline at which a child of this node can be confirmed
  uint64 noChildConfirmedBeforeBlock;
  // Number of stakers staked on this node. This includes real stakers and zombies
  uint64 stakerCount;
  // Number of stakers staked on a child node. This includes real stakers and zombies
  uint64 childStakerCount;
  // This value starts at zero and is set to a value when the first child is created. After that it is constant until the node is destroyed or the owner destroys pending nodes
  uint64 firstChildBlock;
  // The number of the latest child of this node to be created
  uint64 latestChildNumber;
  // The block number when this node was created
  uint64 createdAtBlock;
  // A hash of all the data needed to determine this node's validity, to protect against reorgs
  bytes32 nodeHash;
}

// modified from: https://github.com/OffchainLabs/nitro/blob/master/contracts/src/rollup/IRollupCore.sol
interface IArbitrumRollup {
  /**
   * @notice Get the Node for the given index.
   */
  function getNode(uint64 nodeNum) external view returns (Node memory);
}

File 13 of 15 : ProposedOwnable.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;

import {IProposedOwnable} from "./interfaces/IProposedOwnable.sol";

/**
 * @title ProposedOwnable
 * @notice Contract module which provides a basic access control mechanism,
 * where there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed via a two step process:
 * 1. Call `proposeOwner`
 * 2. Wait out the delay period
 * 3. Call `acceptOwner`
 *
 * @dev This module is used through inheritance. It will make available the
 * modifier `onlyOwner`, which can be applied to your functions to restrict
 * their use to the owner.
 *
 * @dev The majority of this code was taken from the openzeppelin Ownable
 * contract
 *
 */
abstract contract ProposedOwnable is IProposedOwnable {
  // ========== Custom Errors ===========

  error ProposedOwnable__onlyOwner_notOwner();
  error ProposedOwnable__onlyProposed_notProposedOwner();
  error ProposedOwnable__ownershipDelayElapsed_delayNotElapsed();
  error ProposedOwnable__proposeNewOwner_invalidProposal();
  error ProposedOwnable__proposeNewOwner_noOwnershipChange();
  error ProposedOwnable__renounceOwnership_noProposal();
  error ProposedOwnable__renounceOwnership_invalidProposal();

  // ============ Properties ============

  address private _owner;

  address private _proposed;
  uint256 private _proposedOwnershipTimestamp;

  uint256 private constant _delay = 7 days;

  // ======== Getters =========

  /**
   * @notice Returns the address of the current owner.
   */
  function owner() public view virtual returns (address) {
    return _owner;
  }

  /**
   * @notice Returns the address of the proposed owner.
   */
  function proposed() public view virtual returns (address) {
    return _proposed;
  }

  /**
   * @notice Returns the address of the proposed owner.
   */
  function proposedTimestamp() public view virtual returns (uint256) {
    return _proposedOwnershipTimestamp;
  }

  /**
   * @notice Returns the delay period before a new owner can be accepted.
   */
  function delay() public view virtual returns (uint256) {
    return _delay;
  }

  /**
   * @notice Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    if (_owner != msg.sender) revert ProposedOwnable__onlyOwner_notOwner();
    _;
  }

  /**
   * @notice Throws if called by any account other than the proposed owner.
   */
  modifier onlyProposed() {
    if (_proposed != msg.sender) revert ProposedOwnable__onlyProposed_notProposedOwner();
    _;
  }

  /**
   * @notice Throws if the ownership delay has not elapsed
   */
  modifier ownershipDelayElapsed() {
    // Ensure delay has elapsed
    if ((block.timestamp - _proposedOwnershipTimestamp) <= _delay)
      revert ProposedOwnable__ownershipDelayElapsed_delayNotElapsed();
    _;
  }

  /**
   * @notice Indicates if the ownership has been renounced() by
   * checking if current owner is address(0)
   */
  function renounced() public view returns (bool) {
    return _owner == address(0);
  }

  // ======== External =========

  /**
   * @notice Sets the timestamp for an owner to be proposed, and sets the
   * newly proposed owner as step 1 in a 2-step process
   */
  function proposeNewOwner(address newlyProposed) public virtual onlyOwner {
    // Contract as source of truth
    if (_proposed == newlyProposed && _proposedOwnershipTimestamp != 0)
      revert ProposedOwnable__proposeNewOwner_invalidProposal();

    // Sanity check: reasonable proposal
    if (_owner == newlyProposed) revert ProposedOwnable__proposeNewOwner_noOwnershipChange();

    _setProposed(newlyProposed);
  }

  /**
   * @notice Renounces ownership of the contract after a delay
   */
  function renounceOwnership() public virtual onlyOwner ownershipDelayElapsed {
    // Ensure there has been a proposal cycle started
    if (_proposedOwnershipTimestamp == 0) revert ProposedOwnable__renounceOwnership_noProposal();

    // Require proposed is set to 0
    if (_proposed != address(0)) revert ProposedOwnable__renounceOwnership_invalidProposal();

    // Emit event, set new owner, reset timestamp
    _setOwner(address(0));
  }

  /**
   * @notice Transfers ownership of the contract to a new account (`newOwner`).
   * Can only be called by the current owner.
   */
  function acceptProposedOwner() public virtual onlyProposed ownershipDelayElapsed {
    // NOTE: no need to check if _owner == _proposed, because the _proposed
    // is 0-d out and this check is implicitly enforced by modifier

    // NOTE: no need to check if _proposedOwnershipTimestamp > 0 because
    // the only time this would happen is if the _proposed was never
    // set (will fail from modifier) or if the owner == _proposed (checked
    // above)

    // Emit event, set new owner, reset timestamp
    _setOwner(_proposed);
  }

  // ======== Internal =========

  function _setOwner(address newOwner) internal {
    emit OwnershipTransferred(_owner, newOwner);
    _owner = newOwner;
    delete _proposedOwnershipTimestamp;
    delete _proposed;
  }

  function _setProposed(address newlyProposed) private {
    _proposedOwnershipTimestamp = block.timestamp;
    _proposed = newlyProposed;
    emit OwnershipProposed(newlyProposed);
  }
}

File 14 of 15 : IProposedOwnable.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

/**
 * @title IProposedOwnable
 * @notice Defines a minimal interface for ownership with a two step proposal and acceptance
 * process
 */
interface IProposedOwnable {
  /**
   * @dev This emits when change in ownership of a contract is proposed.
   */
  event OwnershipProposed(address indexed proposedOwner);

  /**
   * @dev This emits when ownership of a contract changes.
   */
  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  /**
   * @notice Get the address of the owner
   * @return owner_ The address of the owner.
   */
  function owner() external view returns (address owner_);

  /**
   * @notice Get the address of the proposed owner
   * @return proposed_ The address of the proposed.
   */
  function proposed() external view returns (address proposed_);

  /**
   * @notice Set the address of the proposed owner of the contract
   * @param newlyProposed The proposed new owner of the contract
   */
  function proposeNewOwner(address newlyProposed) external;

  /**
   * @notice Set the address of the proposed owner of the contract
   */
  function acceptProposedOwner() external;
}

File 15 of 15 : TypedMemView.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.17;

library TypedMemView {
  // Why does this exist?
  // the solidity `bytes memory` type has a few weaknesses.
  // 1. You can't index ranges effectively
  // 2. You can't slice without copying
  // 3. The underlying data may represent any type
  // 4. Solidity never deallocates memory, and memory costs grow
  //    superlinearly

  // By using a memory view instead of a `bytes memory` we get the following
  // advantages:
  // 1. Slices are done on the stack, by manipulating the pointer
  // 2. We can index arbitrary ranges and quickly convert them to stack types
  // 3. We can insert type info into the pointer, and typecheck at runtime

  // This makes `TypedMemView` a useful tool for efficient zero-copy
  // algorithms.

  // Why bytes29?
  // We want to avoid confusion between views, digests, and other common
  // types so we chose a large and uncommonly used odd number of bytes
  //
  // Note that while bytes are left-aligned in a word, integers and addresses
  // are right-aligned. This means when working in assembly we have to
  // account for the 3 unused bytes on the righthand side
  //
  // First 5 bytes are a type flag.
  // - ff_ffff_fffe is reserved for unknown type.
  // - ff_ffff_ffff is reserved for invalid types/errors.
  // next 12 are memory address
  // next 12 are len
  // bottom 3 bytes are empty

  // Assumptions:
  // - non-modification of memory.
  // - No Solidity updates
  // - - wrt free mem point
  // - - wrt bytes representation in memory
  // - - wrt memory addressing in general

  // Usage:
  // - create type constants
  // - use `assertType` for runtime type assertions
  // - - unfortunately we can't do this at compile time yet :(
  // - recommended: implement modifiers that perform type checking
  // - - e.g.
  // - - `uint40 constant MY_TYPE = 3;`
  // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }`
  // - instantiate a typed view from a bytearray using `ref`
  // - use `index` to inspect the contents of the view
  // - use `slice` to create smaller views into the same memory
  // - - `slice` can increase the offset
  // - - `slice can decrease the length`
  // - - must specify the output type of `slice`
  // - - `slice` will return a null view if you try to overrun
  // - - make sure to explicitly check for this with `notNull` or `assertType`
  // - use `equal` for typed comparisons.

  // The null view
  bytes29 public constant NULL = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
  uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff;
  uint256 constant TWENTY_SEVEN_BYTES = 8 * 27;
  uint256 private constant _27_BYTES_IN_BITS = 8 * 27; // <--- also used this named constant where ever 216 is used.
  uint256 private constant LOW_27_BYTES_MASK = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffff; // (1 << _27_BYTES_IN_BITS) - 1;

  // ========== Custom Errors ===========

  error TypedMemView__assertType_typeAssertionFailed(uint256 actual, uint256 expected);
  error TypedMemView__index_overrun(uint256 loc, uint256 len, uint256 index, uint256 slice);
  error TypedMemView__index_indexMoreThan32Bytes();
  error TypedMemView__unsafeCopyTo_nullPointer();
  error TypedMemView__unsafeCopyTo_invalidPointer();
  error TypedMemView__unsafeCopyTo_identityOOG();
  error TypedMemView__assertValid_validityAssertionFailed();

  /**
   * @notice          Changes the endianness of a uint256.
   * @dev             https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel
   * @param _b        The unsigned integer to reverse
   * @return          v - The reversed value
   */
  function reverseUint256(uint256 _b) internal pure returns (uint256 v) {
    v = _b;

    // swap bytes
    v =
      ((v >> 8) & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) |
      ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8);
    // swap 2-byte long pairs
    v =
      ((v >> 16) & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) |
      ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16);
    // swap 4-byte long pairs
    v =
      ((v >> 32) & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) |
      ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32);
    // swap 8-byte long pairs
    v =
      ((v >> 64) & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) |
      ((v & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64);
    // swap 16-byte long pairs
    v = (v >> 128) | (v << 128);
  }

  /**
   * @notice      Create a mask with the highest `_len` bits set.
   * @param _len  The length
   * @return      mask - The mask
   */
  function leftMask(uint8 _len) private pure returns (uint256 mask) {
    // ugly. redo without assembly?
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      mask := sar(sub(_len, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)
    }
  }

  /**
   * @notice      Return the null view.
   * @return      bytes29 - The null view
   */
  function nullView() internal pure returns (bytes29) {
    return NULL;
  }

  /**
   * @notice      Check if the view is null.
   * @return      bool - True if the view is null
   */
  function isNull(bytes29 memView) internal pure returns (bool) {
    return memView == NULL;
  }

  /**
   * @notice      Check if the view is not null.
   * @return      bool - True if the view is not null
   */
  function notNull(bytes29 memView) internal pure returns (bool) {
    return !isNull(memView);
  }

  /**
   * @notice          Check if the view is of a invalid type and points to a valid location
   *                  in memory.
   * @dev             We perform this check by examining solidity's unallocated memory
   *                  pointer and ensuring that the view's upper bound is less than that.
   * @param memView   The view
   * @return          ret - True if the view is invalid
   */
  function isNotValid(bytes29 memView) internal pure returns (bool ret) {
    if (typeOf(memView) == 0xffffffffff) {
      return true;
    }
    uint256 _end = end(memView);
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      ret := gt(_end, mload(0x40))
    }
  }

  /**
   * @notice          Require that a typed memory view be valid.
   * @dev             Returns the view for easy chaining.
   * @param memView   The view
   * @return          bytes29 - The validated view
   */
  function assertValid(bytes29 memView) internal pure returns (bytes29) {
    if (isNotValid(memView)) revert TypedMemView__assertValid_validityAssertionFailed();
    return memView;
  }

  /**
   * @notice          Return true if the memview is of the expected type. Otherwise false.
   * @param memView   The view
   * @param _expected The expected type
   * @return          bool - True if the memview is of the expected type
   */
  function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) {
    return typeOf(memView) == _expected;
  }

  /**
   * @notice          Require that a typed memory view has a specific type.
   * @dev             Returns the view for easy chaining.
   * @param memView   The view
   * @param _expected The expected type
   * @return          bytes29 - The view with validated type
   */
  function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) {
    if (!isType(memView, _expected)) {
      revert TypedMemView__assertType_typeAssertionFailed(uint256(typeOf(memView)), uint256(_expected));
    }
    return memView;
  }

  /**
   * @notice          Return an identical view with a different type.
   * @param memView   The view
   * @param _newType  The new type
   * @return          newView - The new view with the specified type
   */
  function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) {
    // then | in the new type
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      // shift off the top 5 bytes
      newView := or(and(memView, LOW_27_BYTES_MASK), shl(_27_BYTES_IN_BITS, _newType))
    }
  }

  /**
   * @notice          Unsafe raw pointer construction. This should generally not be called
   *                  directly. Prefer `ref` wherever possible.
   * @dev             Unsafe raw pointer construction. This should generally not be called
   *                  directly. Prefer `ref` wherever possible.
   * @param _type     The type
   * @param _loc      The memory address
   * @param _len      The length
   * @return          newView - The new view with the specified type, location and length
   */
  function unsafeBuildUnchecked(
    uint256 _type,
    uint256 _loc,
    uint256 _len
  ) private pure returns (bytes29 newView) {
    uint256 _uint96Bits = 96;
    uint256 _emptyBits = 24;

    // Cast params to ensure input is of correct length
    uint96 len_ = uint96(_len);
    uint96 loc_ = uint96(_loc);
    require(len_ == _len && loc_ == _loc, "!truncated");

    assembly {
      // solium-disable-previous-line security/no-inline-assembly
      newView := shl(_uint96Bits, _type) // insert type
      newView := shl(_uint96Bits, or(newView, loc_)) // insert loc
      newView := shl(_emptyBits, or(newView, len_)) // empty bottom 3 bytes
    }
  }

  /**
   * @notice          Instantiate a new memory view. This should generally not be called
   *                  directly. Prefer `ref` wherever possible.
   * @dev             Instantiate a new memory view. This should generally not be called
   *                  directly. Prefer `ref` wherever possible.
   * @param _type     The type
   * @param _loc      The memory address
   * @param _len      The length
   * @return          newView - The new view with the specified type, location and length
   */
  function build(
    uint256 _type,
    uint256 _loc,
    uint256 _len
  ) internal pure returns (bytes29 newView) {
    uint256 _end = _loc + _len;
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      if gt(_end, mload(0x40)) {
        _end := 0
      }
    }
    if (_end == 0) {
      return NULL;
    }
    newView = unsafeBuildUnchecked(_type, _loc, _len);
  }

  /**
   * @notice          Instantiate a memory view from a byte array.
   * @dev             Note that due to Solidity memory representation, it is not possible to
   *                  implement a deref, as the `bytes` type stores its len in memory.
   * @param arr       The byte array
   * @param newType   The type
   * @return          bytes29 - The memory view
   */
  function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) {
    uint256 _len = arr.length;

    uint256 _loc;
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      _loc := add(arr, 0x20) // our view is of the data, not the struct
    }

    return build(newType, _loc, _len);
  }

  /**
   * @notice          Return the associated type information.
   * @param memView   The memory view
   * @return          _type - The type associated with the view
   */
  function typeOf(bytes29 memView) internal pure returns (uint40 _type) {
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      // 216 == 256 - 40
      _type := shr(_27_BYTES_IN_BITS, memView) // shift out lower 24 bytes
    }
  }

  /**
   * @notice          Return the memory address of the underlying bytes.
   * @param memView   The view
   * @return          _loc - The memory address
   */
  function loc(bytes29 memView) internal pure returns (uint96 _loc) {
    uint256 _mask = LOW_12_MASK; // assembly can't use globals
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space)
      _loc := and(shr(120, memView), _mask)
    }
  }

  /**
   * @notice          The number of memory words this memory view occupies, rounded up.
   * @param memView   The view
   * @return          uint256 - The number of memory words
   */
  function words(bytes29 memView) internal pure returns (uint256) {
    return (uint256(len(memView)) + 31) / 32;
  }

  /**
   * @notice          The in-memory footprint of a fresh copy of the view.
   * @param memView   The view
   * @return          uint256 - The in-memory footprint of a fresh copy of the view.
   */
  function footprint(bytes29 memView) internal pure returns (uint256) {
    return words(memView) * 32;
  }

  /**
   * @notice          The number of bytes of the view.
   * @param memView   The view
   * @return          _len - The length of the view
   */
  function len(bytes29 memView) internal pure returns (uint96 _len) {
    uint256 _mask = LOW_12_MASK; // assembly can't use globals
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      _len := and(shr(24, memView), _mask)
    }
  }

  /**
   * @notice          Returns the endpoint of `memView`.
   * @param memView   The view
   * @return          uint256 - The endpoint of `memView`
   */
  function end(bytes29 memView) internal pure returns (uint256) {
    unchecked {
      return loc(memView) + len(memView);
    }
  }

  /**
   * @notice          Safe slicing without memory modification.
   * @param memView   The view
   * @param _index    The start index
   * @param _len      The length
   * @param newType   The new type
   * @return          bytes29 - The new view
   */
  function slice(
    bytes29 memView,
    uint256 _index,
    uint256 _len,
    uint40 newType
  ) internal pure returns (bytes29) {
    uint256 _loc = loc(memView);

    // Ensure it doesn't overrun the view
    if (_loc + _index + _len > end(memView)) {
      return NULL;
    }

    _loc = _loc + _index;
    return build(newType, _loc, _len);
  }

  /**
   * @notice          Shortcut to `slice`. Gets a view representing the first `_len` bytes.
   * @param memView   The view
   * @param _len      The length
   * @param newType   The new type
   * @return          bytes29 - The new view
   */
  function prefix(
    bytes29 memView,
    uint256 _len,
    uint40 newType
  ) internal pure returns (bytes29) {
    return slice(memView, 0, _len, newType);
  }

  /**
   * @notice          Shortcut to `slice`. Gets a view representing the last `_len` byte.
   * @param memView   The view
   * @param _len      The length
   * @param newType   The new type
   * @return          bytes29 - The new view
   */
  function postfix(
    bytes29 memView,
    uint256 _len,
    uint40 newType
  ) internal pure returns (bytes29) {
    return slice(memView, uint256(len(memView)) - _len, _len, newType);
  }

  /**
   * @notice          Load up to 32 bytes from the view onto the stack.
   * @dev             Returns a bytes32 with only the `_bytes` highest bytes set.
   *                  This can be immediately cast to a smaller fixed-length byte array.
   *                  To automatically cast to an integer, use `indexUint`.
   * @param memView   The view
   * @param _index    The index
   * @param _bytes    The bytes
   * @return          result - The 32 byte result
   */
  function index(
    bytes29 memView,
    uint256 _index,
    uint8 _bytes
  ) internal pure returns (bytes32 result) {
    if (_bytes == 0) {
      return bytes32(0);
    }
    if (_index + _bytes > len(memView)) {
      // "TypedMemView/index - Overran the view. Slice is at {loc} with length {len}. Attempted to index at offset {index} with length {slice},
      revert TypedMemView__index_overrun(loc(memView), len(memView), _index, uint256(_bytes));
    }
    if (_bytes > 32) revert TypedMemView__index_indexMoreThan32Bytes();

    uint8 bitLength;
    unchecked {
      bitLength = _bytes * 8;
    }
    uint256 _loc = loc(memView);
    uint256 _mask = leftMask(bitLength);
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      result := and(mload(add(_loc, _index)), _mask)
    }
  }

  /**
   * @notice          Parse an unsigned integer from the view at `_index`.
   * @dev             Requires that the view have >= `_bytes` bytes following that index.
   * @param memView   The view
   * @param _index    The index
   * @param _bytes    The bytes
   * @return          result - The unsigned integer
   */
  function indexUint(
    bytes29 memView,
    uint256 _index,
    uint8 _bytes
  ) internal pure returns (uint256 result) {
    return uint256(index(memView, _index, _bytes)) >> ((32 - _bytes) * 8);
  }

  /**
   * @notice          Parse an unsigned integer from LE bytes.
   * @param memView   The view
   * @param _index    The index
   * @param _bytes    The bytes
   * @return          result - The unsigned integer
   */
  function indexLEUint(
    bytes29 memView,
    uint256 _index,
    uint8 _bytes
  ) internal pure returns (uint256 result) {
    return reverseUint256(uint256(index(memView, _index, _bytes)));
  }

  /**
   * @notice          Parse an address from the view at `_index`. Requires that the view have >= 20 bytes
   *                  following that index.
   * @param memView   The view
   * @param _index    The index
   * @return          address - The address
   */
  function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) {
    return address(uint160(indexUint(memView, _index, 20)));
  }

  /**
   * @notice          Return the keccak256 hash of the underlying memory
   * @param memView   The view
   * @return          digest - The keccak256 hash of the underlying memory
   */
  function keccak(bytes29 memView) internal pure returns (bytes32 digest) {
    uint256 _loc = loc(memView);
    uint256 _len = len(memView);
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      digest := keccak256(_loc, _len)
    }
  }

  /**
   * @notice          Return true if the underlying memory is equal. Else false.
   * @param left      The first view
   * @param right     The second view
   * @return          bool - True if the underlying memory is equal
   */
  function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) {
    return (loc(left) == loc(right) && len(left) == len(right)) || keccak(left) == keccak(right);
  }

  /**
   * @notice          Return false if the underlying memory is equal. Else true.
   * @param left      The first view
   * @param right     The second view
   * @return          bool - False if the underlying memory is equal
   */
  function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) {
    return !untypedEqual(left, right);
  }

  /**
   * @notice          Compares type equality.
   * @dev             Shortcuts if the pointers are identical, otherwise compares type and digest.
   * @param left      The first view
   * @param right     The second view
   * @return          bool - True if the types are the same
   */
  function equal(bytes29 left, bytes29 right) internal pure returns (bool) {
    return left == right || (typeOf(left) == typeOf(right) && keccak(left) == keccak(right));
  }

  /**
   * @notice          Compares type inequality.
   * @dev             Shortcuts if the pointers are identical, otherwise compares type and digest.
   * @param left      The first view
   * @param right     The second view
   * @return          bool - True if the types are not the same
   */
  function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) {
    return !equal(left, right);
  }

  /**
   * @notice          Copy the view to a location, return an unsafe memory reference
   * @dev             Super Dangerous direct memory access.
   *
   *                  This reference can be overwritten if anything else modifies memory (!!!).
   *                  As such it MUST be consumed IMMEDIATELY.
   *                  This function is private to prevent unsafe usage by callers.
   * @param memView   The view
   * @param _newLoc   The new location
   * @return          written - the unsafe memory reference
   */
  function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) {
    if (isNull(memView)) revert TypedMemView__unsafeCopyTo_nullPointer();
    if (isNotValid(memView)) revert TypedMemView__unsafeCopyTo_invalidPointer();

    uint256 _len = len(memView);
    uint256 _oldLoc = loc(memView);

    uint256 ptr;
    bool res;
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      ptr := mload(0x40)
      // revert if we're writing in occupied memory
      if gt(ptr, _newLoc) {
        revert(0x60, 0x20) // empty revert message
      }

      // use the identity precompile to copy
      // guaranteed not to fail, so pop the success
      res := staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len)
    }
    if (!res) revert TypedMemView__unsafeCopyTo_identityOOG();
    written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len);
  }

  /**
   * @notice          Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to
   *                  the new memory
   * @dev             Shortcuts if the pointers are identical, otherwise compares type and digest.
   * @param memView   The view
   * @return          ret - The view pointing to the new memory
   */
  function clone(bytes29 memView) internal view returns (bytes memory ret) {
    uint256 ptr;
    uint256 _len = len(memView);
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      ptr := mload(0x40) // load unused memory pointer
      ret := ptr
    }
    unchecked {
      unsafeCopyTo(memView, ptr + 0x20);
    }
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer
      mstore(ptr, _len) // write len of new array (in bytes)
    }
  }

  /**
   * @notice          Join the views in memory, return an unsafe reference to the memory.
   * @dev             Super Dangerous direct memory access.
   *
   *                  This reference can be overwritten if anything else modifies memory (!!!).
   *                  As such it MUST be consumed IMMEDIATELY.
   *                  This function is private to prevent unsafe usage by callers.
   * @param memViews  The views
   * @return          unsafeView - The conjoined view pointing to the new memory
   */
  function unsafeJoin(bytes29[] memory memViews, uint256 _location) private view returns (bytes29 unsafeView) {
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      let ptr := mload(0x40)
      // revert if we're writing in occupied memory
      if gt(ptr, _location) {
        revert(0x60, 0x20) // empty revert message
      }
    }

    uint256 _offset = 0;
    uint256 _len = memViews.length;
    for (uint256 i = 0; i < _len; ) {
      bytes29 memView = memViews[i];
      unchecked {
        unsafeCopyTo(memView, _location + _offset);
        _offset += len(memView);
        ++i;
      }
    }
    unsafeView = unsafeBuildUnchecked(0, _location, _offset);
  }

  /**
   * @notice          Produce the keccak256 digest of the concatenated contents of multiple views.
   * @param memViews  The views
   * @return          bytes32 - The keccak256 digest
   */
  function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) {
    uint256 ptr;
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      ptr := mload(0x40) // load unused memory pointer
    }
    return keccak(unsafeJoin(memViews, ptr));
  }

  /**
   * @notice          copies all views, joins them into a new bytearray.
   * @param memViews  The views
   * @return          ret - The new byte array
   */
  function join(bytes29[] memory memViews) internal view returns (bytes memory ret) {
    uint256 ptr;
    assembly {
      // solhint-disable-previous-line no-inline-assembly
      ptr := mload(0x40) // load unused memory pointer
    }

    bytes29 _newView;
    unchecked {
      _newView = unsafeJoin(memViews, ptr + 0x20);
    }
    uint256 _written = len(_newView);
    uint256 _footprint = footprint(_newView);

    assembly {
      // solhint-disable-previous-line no-inline-assembly
      // store the legnth
      mstore(ptr, _written)
      // new pointer is old + 0x20 + the footprint of the body
      mstore(0x40, add(add(ptr, _footprint), 0x20))
      ret := ptr
    }
  }
}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"uint32","name":"_mirrorDomain","type":"uint32"},{"internalType":"address","name":"_amb","type":"address"},{"internalType":"address","name":"_rootManager","type":"address"},{"internalType":"address","name":"_mirrorConnector","type":"address"},{"internalType":"address","name":"_outbox","type":"address"},{"internalType":"uint256","name":"_maxSubmissionCostCap","type":"uint256"},{"internalType":"uint256","name":"_maxGasCap","type":"uint256"},{"internalType":"uint256","name":"_gasPriceCap","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Connector__processMessage_notUsed","type":"error"},{"inputs":[],"name":"NotCrossChainCall","type":"error"},{"inputs":[],"name":"ProposedOwnable__onlyOwner_notOwner","type":"error"},{"inputs":[],"name":"ProposedOwnable__onlyProposed_notProposedOwner","type":"error"},{"inputs":[],"name":"ProposedOwnable__ownershipDelayElapsed_delayNotElapsed","type":"error"},{"inputs":[],"name":"ProposedOwnable__proposeNewOwner_invalidProposal","type":"error"},{"inputs":[],"name":"ProposedOwnable__proposeNewOwner_noOwnershipChange","type":"error"},{"inputs":[],"name":"ProposedOwnable__renounceOwnership_invalidProposal","type":"error"},{"inputs":[],"name":"ProposedOwnable__renounceOwnership_noProposal","type":"error"},{"inputs":[],"name":"TypedMemView__index_indexMoreThan32Bytes","type":"error"},{"inputs":[{"internalType":"uint256","name":"loc","type":"uint256"},{"internalType":"uint256","name":"len","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"slice","type":"uint256"}],"name":"TypedMemView__index_overrun","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_updated","type":"uint256"}],"name":"GasPriceCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_updated","type":"uint256"}],"name":"MaxGasCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_updated","type":"uint256"}],"name":"MaxSubmissionCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"MessageProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"encodedData","type":"bytes"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"MessageSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previous","type":"address"},{"indexed":false,"internalType":"address","name":"current","type":"address"}],"name":"MirrorConnectorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"mirrorDomain","type":"uint32"},{"indexed":false,"internalType":"address","name":"amb","type":"address"},{"indexed":false,"internalType":"address","name":"rootManager","type":"address"},{"indexed":false,"internalType":"address","name":"mirrorConnector","type":"address"}],"name":"NewConnector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"proposedOwner","type":"address"}],"name":"OwnershipProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"ticketId","type":"uint256"}],"name":"RetryableTicketCreated","type":"event"},{"inputs":[],"name":"AMB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIRROR_DOMAIN","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROOT_MANAGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptProposedOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"delay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasPriceCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxGasCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSubmissionCostCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mirrorConnector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"outbox","outputs":[{"internalType":"contract IArbitrumOutbox","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"processMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_nodeNum","type":"uint64"},{"internalType":"bytes32","name":"_sendRoot","type":"bytes32"},{"internalType":"bytes32","name":"_blockHash","type":"bytes32"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"uint256","name":"_index","type":"uint256"},{"components":[{"internalType":"address","name":"l2Sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"l2Block","type":"uint256"},{"internalType":"uint256","name":"l1Block","type":"uint256"},{"internalType":"uint256","name":"l2Timestamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct L2Message","name":"_message","type":"tuple"}],"name":"processMessageFromRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"processed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newlyProposed","type":"address"}],"name":"proposeNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proposed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposedTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounced","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rollup","outputs":[{"internalType":"contract IArbitrumRollup","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"bytes","name":"_encodedData","type":"bytes"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_updated","type":"uint256"}],"name":"setGasPriceCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_updated","type":"uint256"}],"name":"setMaxGasCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_updated","type":"uint256"}],"name":"setMaxSubmissionCostCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mirrorConnector","type":"address"}],"name":"setMirrorConnector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_expected","type":"address"}],"name":"verifySender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101006040523480156200001257600080fd5b50604051620021f1380380620021f1833981016040819052620000359162000335565b888888888884848484846200004a3362000235565b8463ffffffff16600003620000955760405162461bcd60e51b815260206004820152600c60248201526b32b6b83a3c903237b6b0b4b760a11b60448201526064015b60405180910390fd5b6001600160a01b038216620000e15760405162461bcd60e51b815260206004820152601160248201527032b6b83a3c903937b7ba26b0b730b3b2b960791b60448201526064016200008c565b63ffffffff8086166080526001600160a01b0380851660a05283811660c05290851660e052811615620001195762000119816200029a565b604080516001600160a01b0385811682528481166020830152831681830152905163ffffffff86811692908816917f4f9c27c2fe3f84576ea469d367d044da53c45e951617e8389f2b5ed8db9d25f09181900360600190a35050600480546001600160a01b0319166001600160a01b038e1690811782556040805163cb23bcb560e01b81529051919a5063cb23bcb599508083019850602097509095508590030192508391508790505afa158015620001d6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001fc9190620003d5565b600580546001600160a01b0319166001600160a01b039290921691909117905560069290925560075560085550620003fa945050505050565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b039092166001600160a01b0319928316178155600255600180549091169055565b600354604080516001600160a01b03928316815291831660208301527fc77bec288fc88f168427f2f7da682eadb26cac89d8d591af6e443da98dff2bbc910160405180910390a1600380546001600160a01b0319166001600160a01b0392909216919091179055565b805163ffffffff811681146200031857600080fd5b919050565b80516001600160a01b03811681146200031857600080fd5b60008060008060008060008060006101208a8c0312156200035557600080fd5b620003608a62000303565b98506200037060208b0162000303565b97506200038060408b016200031d565b96506200039060608b016200031d565b9550620003a060808b016200031d565b9450620003b060a08b016200031d565b935060c08a0151925060e08a015191506101008a015190509295985092959850929598565b600060208284031215620003e857600080fd5b620003f3826200031d565b9392505050565b60805160a05160c05160e051611d936200045e60003960008181610227015261095901526000818161032e015281816105da015261098a0152600081816104eb0152818161068f01528181610cc9015261130b015260006102da0152611d936000f3fe6080604052600436106101a05760003560e01c80639ab0563b116100ec578063ce11e6ab1161008a578063d69f9d6111610064578063d69f9d61146104d9578063db1b76591461050d578063e2ce3c641461052d578063fbd4006b1461054357600080fd5b8063ce11e6ab1461047c578063d1851c921461049c578063d232c220146104ba57600080fd5b8063b64d327e116100c6578063b64d327e14610411578063c5b350df14610427578063cb23bcb51461043c578063cc3942831461045c57600080fd5b80639ab0563b146103b15780639d4373a4146103d1578063b1f8100d146103f157600080fd5b80634ff746f6116101595780635f61e3ec116101335780635f61e3ec1461031c5780636a42b8f814610368578063715018a61461037e5780638da5cb5b1461039357600080fd5b80634ff746f6146102a857806352a9674b146102c85780635bd11efc146102fc57600080fd5b806305a79e06146101ac5780630fca49cd146101f157806314168416146102155780633327998d1461025e5780633cf52ffb1461028057806348e6fa231461029557600080fd5b366101a757005b600080fd5b3480156101b857600080fd5b506101dc6101c736600461170b565b60096020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156101fd57600080fd5b5061020760065481565b6040519081526020016101e8565b34801561022157600080fd5b506102497f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020016101e8565b34801561026a57600080fd5b5061027e61027936600461170b565b610563565b005b34801561028c57600080fd5b50600254610207565b61027e6102a33660046117f1565b6105cf565b3480156102b457600080fd5b5061027e6102c3366004611855565b610684565b3480156102d457600080fd5b506102497f000000000000000000000000000000000000000000000000000000000000000081565b34801561030857600080fd5b5061027e6103173660046118a7565b61072a565b34801561032857600080fd5b506103507f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101e8565b34801561037457600080fd5b5062093a80610207565b34801561038a57600080fd5b5061027e610761565b34801561039f57600080fd5b506000546001600160a01b0316610350565b3480156103bd57600080fd5b5061027e6103cc36600461170b565b610815565b3480156103dd57600080fd5b5061027e6103ec3660046118f2565b610881565b3480156103fd57600080fd5b5061027e61040c3660046118a7565b610a50565b34801561041d57600080fd5b5061020760075481565b34801561043357600080fd5b5061027e610aee565b34801561044857600080fd5b50600554610350906001600160a01b031681565b34801561046857600080fd5b50600354610350906001600160a01b031681565b34801561048857600080fd5b50600454610350906001600160a01b031681565b3480156104a857600080fd5b506001546001600160a01b0316610350565b3480156104c657600080fd5b506000546001600160a01b0316156101dc565b3480156104e557600080fd5b506103507f000000000000000000000000000000000000000000000000000000000000000081565b34801561051957600080fd5b506101dc6105283660046118a7565b610b5e565b34801561053957600080fd5b5061020760085481565b34801561054f57600080fd5b5061027e61055e36600461170b565b610b6f565b6000546001600160a01b0316331461058e576040516311a8a1bb60e31b815260040160405180910390fd5b60065460408051918252602082018390527f8826388bbfa56ae5df40ee5607d9d354fa66549d854624242c77b5af2a5e4c3b910160405180910390a1600655565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461063b5760405162461bcd60e51b815260206004820152600c60248201526b10b937b7ba26b0b730b3b2b960a11b60448201526064015b60405180910390fd5b6106458282610bdb565b7fdcaa37a042a0087de79018c629bbd29cee82ca80bd9be394e1696bf9e935507782823360405161067893929190611a02565b60405180910390a15050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106e55760405162461bcd60e51b81526004016106329060208082526004908201526310a0a6a160e11b604082015260600190565b6106ee81610de4565b7fb3abc57bfeebd2cac918901db582f71972a8e628bccf19f5ae3e3482b98a5ced813360405161071f929190611a40565b60405180910390a150565b6000546001600160a01b03163314610755576040516311a8a1bb60e31b815260040160405180910390fd5b61075e81610dfd565b50565b6000546001600160a01b0316331461078c576040516311a8a1bb60e31b815260040160405180910390fd5b62093a806002544261079e9190611a80565b116107bc576040516324e0285f60e21b815260040160405180910390fd5b6002546000036107df57604051630e4b303f60e21b815260040160405180910390fd5b6001546001600160a01b031615610809576040516323295ef960e01b815260040160405180910390fd5b6108136000610e66565b565b6000546001600160a01b03163314610840576040516311a8a1bb60e31b815260040160405180910390fd5b60075460408051918252602082018390527f57bffb29c4c6b672a2e334fa00ea826dba286d6cb34d61bebc6c667abb579c62910160405180910390a1600755565b61088c878787610ecb565b6108998685858585611020565b6108a660c0820182611a93565b90506064146108e15760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610632565b600061094560446020610938846108fb60c0880188611a93565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506111839050565b62ffffff191691906111a7565b60405163473ec9fd60e11b815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152602481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638e7d93fa90604401600060405180830381600087803b1580156109d657600080fd5b505af11580156109ea573d6000803e3d6000fd5b505050507fb3abc57bfeebd2cac918901db582f71972a8e628bccf19f5ae3e3482b98a5ced81604051602001610a2291815260200190565b60408051601f1981840301815290829052610a3e913390611a40565b60405180910390a15050505050505050565b6000546001600160a01b03163314610a7b576040516311a8a1bb60e31b815260040160405180910390fd5b6001546001600160a01b038281169116148015610a99575060025415155b15610ab7576040516311bc066560e11b815260040160405180910390fd5b6000546001600160a01b03808316911603610ae557604051634a2fb73f60e11b815260040160405180910390fd5b61075e816112b6565b6001546001600160a01b03163314610b19576040516311a7f27160e11b815260040160405180910390fd5b62093a8060025442610b2b9190611a80565b11610b49576040516324e0285f60e21b815260040160405180910390fd5b600154610813906001600160a01b0316610e66565b6000610b6982611304565b92915050565b6000546001600160a01b03163314610b9a576040516311a8a1bb60e31b815260040160405180910390fd5b60065460408051918252602082018390527f7f46895145f361561c5e9bbaf45b71269a4399dc3064511f123ebf4c6f04e357910160405180910390a1600855565b8151602014610c165760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610632565b6000634ff746f660e01b83604051602401610c319190611ae1565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091528251909150606014610ca65760405162461bcd60e51b815260206004820152600c60248201526b042c8c2e8c240d8cadccee8d60a31b6044820152606401610632565b600080600084806020019051810190610cbf9190611af4565b92509250925060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663679b6ded34600360009054906101000a90046001600160a01b03166000610d1b8960065461134a565b6003546007546001600160a01b03909116908190610d3a908c9061134a565b610d468b60085461134a565b8e6040518a63ffffffff1660e01b8152600401610d6a989796959493929190611b22565b60206040518083038185885af1158015610d88573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610dad9190611b7d565b60405190915081907fde92b5b7839f4a2c640f5e3bbb66d415458dadc57a487b0c7fa562ed7c9c896f90600090a250505050505050565b6040516316c2fdb560e21b815260040160405180910390fd5b600354604080516001600160a01b03928316815291831660208301527fc77bec288fc88f168427f2f7da682eadb26cac89d8d591af6e443da98dff2bbc910160405180910390a1600380546001600160a01b0319166001600160a01b0392909216919091179055565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b039092166001600160a01b0319928316178155600255600180549091169055565b604080516020808201849052818301859052825180830384018152606090920190925280519101206000906005546040516324b204d360e21b815267ffffffffffffffff871660048201529192506000916001600160a01b03909116906392c8134c9060240161018060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f739190611ba6565b905081816040015114610fb75760405162461bcd60e51b815260206004820152600c60248201526b21636f6e6669726d4461746160a01b6044820152606401610632565b60008160c0015167ffffffffffffffff16118015610fe3575060008160e0015167ffffffffffffffff16115b6110195760405162461bcd60e51b8152602060048201526007602482015266085cdd185ad95960ca1b6044820152606401610632565b5050505050565b6003546001600160a01b031661103960208301836118a7565b6001600160a01b0316146110825760405162461bcd60e51b815260206004820152601060248201526f10b6b4b93937b921b7b73732b1ba37b960811b6044820152606401610632565b6004546000906001600160a01b0316639f0c04bf6110a360208501856118a7565b6110b360408601602087016118a7565b60408601356060870135608088013560a08901356110d460c08b018b611a93565b6040518963ffffffff1660e01b81526004016110f7989796959493929190611c78565b602060405180830381865afa158015611114573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111389190611b7d565b905061117b8585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508792508591508a9050611360565b505050505050565b81516000906020840161119e64ffffffffff851682846114f9565b95945050505050565b60008160ff166000036111bc575060006112af565b6111cf8460181c6001600160601b031690565b6001600160601b03166111e560ff841685611ce0565b111561124d576111fe8460781c6001600160601b031690565b6112118560181c6001600160601b031690565b6040516378218d2960e01b81526001600160601b039283166004820152911660248201526044810184905260ff83166064820152608401610632565b60208260ff1611156112725760405163045df3f960e01b815260040160405180910390fd5b60088202600061128b8660781c6001600160601b031690565b6001600160601b031690506000600160ff1b60001984011d91860151909116925050505b9392505050565b42600255600180546001600160a01b0319166001600160a01b0383169081179091556040517f6ab4d119f23076e8ad491bc65ce85f017fb0591dce08755ba8591059cc51737a90600090a250565b600061132f7f0000000000000000000000000000000000000000000000000000000000000000611536565b6001600160a01b0316826001600160a01b0316149050919050565b600081831061135957816112af565b5090919050565b6101008451106113a15760405162461bcd60e51b815260206004820152600c60248201526b0e0e4dedecc40d8cadccee8d60a31b6044820152606401610632565b835183901c156113e45760405162461bcd60e51b815260206004820152600e60248201526d10b6b4b734b6b0b610383937b7b360911b6044820152606401610632565b60008381526009602052604090205460ff161561142b5760405162461bcd60e51b81526020600482015260056024820152641cdc195b9d60da1b6044820152606401610632565b60048054604051627436d360e01b81526000926001600160a01b0390921691627436d39161145f9189918991899101611cf3565b602060405180830381865afa15801561147c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a09190611b7d565b90508181146114da5760405162461bcd60e51b815260206004820152600660248201526510b83937b7b360d11b6044820152606401610632565b5050506000908152600960205260409020805460ff1916600117905550565b6000806115068385611ce0565b9050604051811115611516575060005b8060000361152b5762ffffff199150506112af565b61119e858585611694565b60006001600160a01b03821633146115615760405163253a6fc960e11b815260040160405180910390fd5b6000826001600160a01b031663ab5d89436040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c59190611d40565b6001600160a01b03166380648b026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611602573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116269190611d40565b90506001600160a01b038116610b695760405162461bcd60e51b815260206004820152602d60248201527f4c6962417262697472756d4c313a2073797374656d206d65737361676573207760448201526c34ba3437baba1039b2b73232b960991b6064820152608401610632565b60006060601883856001600160601b038216821480156116bc575086816001600160601b0316145b6116f55760405162461bcd60e51b815260206004820152600a602482015269085d1c9d5b98d85d195960b21b6044820152606401610632565b96831b90961790911b90941790931b9392505050565b60006020828403121561171d57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051610180810167ffffffffffffffff8111828210171561175e5761175e611724565b60405290565b600082601f83011261177557600080fd5b813567ffffffffffffffff8082111561179057611790611724565b604051601f8301601f19908116603f011681019082821181831017156117b8576117b8611724565b816040528381528660208588010111156117d157600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561180457600080fd5b823567ffffffffffffffff8082111561181c57600080fd5b61182886838701611764565b9350602085013591508082111561183e57600080fd5b5061184b85828601611764565b9150509250929050565b60006020828403121561186757600080fd5b813567ffffffffffffffff81111561187e57600080fd5b61188a84828501611764565b949350505050565b6001600160a01b038116811461075e57600080fd5b6000602082840312156118b957600080fd5b81356112af81611892565b67ffffffffffffffff8116811461075e57600080fd5b600060e082840312156118ec57600080fd5b50919050565b600080600080600080600060c0888a03121561190d57600080fd5b8735611918816118c4565b96506020880135955060408801359450606088013567ffffffffffffffff8082111561194357600080fd5b818a0191508a601f83011261195757600080fd5b81358181111561196657600080fd5b8b60208260051b850101111561197b57600080fd5b6020830196508095505060808a0135935060a08a01359150808211156119a057600080fd5b506119ad8a828b016118da565b91505092959891949750929550565b6000815180845260005b818110156119e2576020818501810151868301820152016119c6565b506000602082860101526020601f19601f83011685010191505092915050565b606081526000611a1560608301866119bc565b8281036020840152611a2781866119bc565b91505060018060a01b0383166040830152949350505050565b604081526000611a5360408301856119bc565b905060018060a01b03831660208301529392505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610b6957610b69611a6a565b6000808335601e19843603018112611aaa57600080fd5b83018035915067ffffffffffffffff821115611ac557600080fd5b602001915036819003821315611ada57600080fd5b9250929050565b6020815260006112af60208301846119bc565b600080600060608486031215611b0957600080fd5b8351925060208401519150604084015190509250925092565b600061010060018060a01b03808c1684528a602085015289604085015280891660608501528088166080850152508560a08401528460c08401528060e0840152611b6e818401856119bc565b9b9a5050505050505050505050565b600060208284031215611b8f57600080fd5b5051919050565b8051611ba1816118c4565b919050565b60006101808284031215611bb957600080fd5b611bc161173a565b825181526020830151602082015260408301516040820152611be560608401611b96565b6060820152611bf660808401611b96565b6080820152611c0760a08401611b96565b60a0820152611c1860c08401611b96565b60c0820152611c2960e08401611b96565b60e0820152610100611c3c818501611b96565b90820152610120611c4e848201611b96565b90820152610140611c60848201611b96565b90820152610160928301519281019290925250919050565b600060018060a01b03808b168352808a166020840152508760408301528660608301528560808301528460a083015260e060c08301528260e08301526101008385828501376000838501820152601f909301601f191690910190910198975050505050505050565b80820180821115610b6957610b69611a6a565b606080825284519082018190526000906020906080840190828801845b82811015611d2c57815184529284019290840190600101611d10565b505050908301949094525060400152919050565b600060208284031215611d5257600080fd5b81516112af8161189256fea2646970667358221220019042e2fa1ddf40ad2442b13da589ca89a15ac368f145ebe78777a555b27d1b64736f6c634300081100330000000000000000000000000000000000000000000000000000000000657468000000000000000000000000000000000000000000000000000000006172626f0000000000000000000000004dbd4fc535ac27206064b68ffcf827b0a60bab3f000000000000000000000000d5d61e9dfb6680cba8353988ba0337802811c2e100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b9857ae2d4a3dbe74ffe1d7df045bb7f96e48400000000000000000000000000000000000000000000000000000002e90edd00000000000000000000000000000000000000000000000000000000000000cf85000000000000000000000000000000000000000000000000000000004a817c800

Deployed Bytecode

0x6080604052600436106101a05760003560e01c80639ab0563b116100ec578063ce11e6ab1161008a578063d69f9d6111610064578063d69f9d61146104d9578063db1b76591461050d578063e2ce3c641461052d578063fbd4006b1461054357600080fd5b8063ce11e6ab1461047c578063d1851c921461049c578063d232c220146104ba57600080fd5b8063b64d327e116100c6578063b64d327e14610411578063c5b350df14610427578063cb23bcb51461043c578063cc3942831461045c57600080fd5b80639ab0563b146103b15780639d4373a4146103d1578063b1f8100d146103f157600080fd5b80634ff746f6116101595780635f61e3ec116101335780635f61e3ec1461031c5780636a42b8f814610368578063715018a61461037e5780638da5cb5b1461039357600080fd5b80634ff746f6146102a857806352a9674b146102c85780635bd11efc146102fc57600080fd5b806305a79e06146101ac5780630fca49cd146101f157806314168416146102155780633327998d1461025e5780633cf52ffb1461028057806348e6fa231461029557600080fd5b366101a757005b600080fd5b3480156101b857600080fd5b506101dc6101c736600461170b565b60096020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156101fd57600080fd5b5061020760065481565b6040519081526020016101e8565b34801561022157600080fd5b506102497f000000000000000000000000000000000000000000000000000000006172626f81565b60405163ffffffff90911681526020016101e8565b34801561026a57600080fd5b5061027e61027936600461170b565b610563565b005b34801561028c57600080fd5b50600254610207565b61027e6102a33660046117f1565b6105cf565b3480156102b457600080fd5b5061027e6102c3366004611855565b610684565b3480156102d457600080fd5b506102497f000000000000000000000000000000000000000000000000000000000065746881565b34801561030857600080fd5b5061027e6103173660046118a7565b61072a565b34801561032857600080fd5b506103507f000000000000000000000000d5d61e9dfb6680cba8353988ba0337802811c2e181565b6040516001600160a01b0390911681526020016101e8565b34801561037457600080fd5b5062093a80610207565b34801561038a57600080fd5b5061027e610761565b34801561039f57600080fd5b506000546001600160a01b0316610350565b3480156103bd57600080fd5b5061027e6103cc36600461170b565b610815565b3480156103dd57600080fd5b5061027e6103ec3660046118f2565b610881565b3480156103fd57600080fd5b5061027e61040c3660046118a7565b610a50565b34801561041d57600080fd5b5061020760075481565b34801561043357600080fd5b5061027e610aee565b34801561044857600080fd5b50600554610350906001600160a01b031681565b34801561046857600080fd5b50600354610350906001600160a01b031681565b34801561048857600080fd5b50600454610350906001600160a01b031681565b3480156104a857600080fd5b506001546001600160a01b0316610350565b3480156104c657600080fd5b506000546001600160a01b0316156101dc565b3480156104e557600080fd5b506103507f0000000000000000000000004dbd4fc535ac27206064b68ffcf827b0a60bab3f81565b34801561051957600080fd5b506101dc6105283660046118a7565b610b5e565b34801561053957600080fd5b5061020760085481565b34801561054f57600080fd5b5061027e61055e36600461170b565b610b6f565b6000546001600160a01b0316331461058e576040516311a8a1bb60e31b815260040160405180910390fd5b60065460408051918252602082018390527f8826388bbfa56ae5df40ee5607d9d354fa66549d854624242c77b5af2a5e4c3b910160405180910390a1600655565b336001600160a01b037f000000000000000000000000d5d61e9dfb6680cba8353988ba0337802811c2e1161461063b5760405162461bcd60e51b815260206004820152600c60248201526b10b937b7ba26b0b730b3b2b960a11b60448201526064015b60405180910390fd5b6106458282610bdb565b7fdcaa37a042a0087de79018c629bbd29cee82ca80bd9be394e1696bf9e935507782823360405161067893929190611a02565b60405180910390a15050565b336001600160a01b037f0000000000000000000000004dbd4fc535ac27206064b68ffcf827b0a60bab3f16146106e55760405162461bcd60e51b81526004016106329060208082526004908201526310a0a6a160e11b604082015260600190565b6106ee81610de4565b7fb3abc57bfeebd2cac918901db582f71972a8e628bccf19f5ae3e3482b98a5ced813360405161071f929190611a40565b60405180910390a150565b6000546001600160a01b03163314610755576040516311a8a1bb60e31b815260040160405180910390fd5b61075e81610dfd565b50565b6000546001600160a01b0316331461078c576040516311a8a1bb60e31b815260040160405180910390fd5b62093a806002544261079e9190611a80565b116107bc576040516324e0285f60e21b815260040160405180910390fd5b6002546000036107df57604051630e4b303f60e21b815260040160405180910390fd5b6001546001600160a01b031615610809576040516323295ef960e01b815260040160405180910390fd5b6108136000610e66565b565b6000546001600160a01b03163314610840576040516311a8a1bb60e31b815260040160405180910390fd5b60075460408051918252602082018390527f57bffb29c4c6b672a2e334fa00ea826dba286d6cb34d61bebc6c667abb579c62910160405180910390a1600755565b61088c878787610ecb565b6108998685858585611020565b6108a660c0820182611a93565b90506064146108e15760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610632565b600061094560446020610938846108fb60c0880188611a93565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506111839050565b62ffffff191691906111a7565b60405163473ec9fd60e11b815263ffffffff7f000000000000000000000000000000000000000000000000000000006172626f166004820152602481018290529091507f000000000000000000000000d5d61e9dfb6680cba8353988ba0337802811c2e16001600160a01b031690638e7d93fa90604401600060405180830381600087803b1580156109d657600080fd5b505af11580156109ea573d6000803e3d6000fd5b505050507fb3abc57bfeebd2cac918901db582f71972a8e628bccf19f5ae3e3482b98a5ced81604051602001610a2291815260200190565b60408051601f1981840301815290829052610a3e913390611a40565b60405180910390a15050505050505050565b6000546001600160a01b03163314610a7b576040516311a8a1bb60e31b815260040160405180910390fd5b6001546001600160a01b038281169116148015610a99575060025415155b15610ab7576040516311bc066560e11b815260040160405180910390fd5b6000546001600160a01b03808316911603610ae557604051634a2fb73f60e11b815260040160405180910390fd5b61075e816112b6565b6001546001600160a01b03163314610b19576040516311a7f27160e11b815260040160405180910390fd5b62093a8060025442610b2b9190611a80565b11610b49576040516324e0285f60e21b815260040160405180910390fd5b600154610813906001600160a01b0316610e66565b6000610b6982611304565b92915050565b6000546001600160a01b03163314610b9a576040516311a8a1bb60e31b815260040160405180910390fd5b60065460408051918252602082018390527f7f46895145f361561c5e9bbaf45b71269a4399dc3064511f123ebf4c6f04e357910160405180910390a1600855565b8151602014610c165760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610632565b6000634ff746f660e01b83604051602401610c319190611ae1565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091528251909150606014610ca65760405162461bcd60e51b815260206004820152600c60248201526b042c8c2e8c240d8cadccee8d60a31b6044820152606401610632565b600080600084806020019051810190610cbf9190611af4565b92509250925060007f0000000000000000000000004dbd4fc535ac27206064b68ffcf827b0a60bab3f6001600160a01b031663679b6ded34600360009054906101000a90046001600160a01b03166000610d1b8960065461134a565b6003546007546001600160a01b03909116908190610d3a908c9061134a565b610d468b60085461134a565b8e6040518a63ffffffff1660e01b8152600401610d6a989796959493929190611b22565b60206040518083038185885af1158015610d88573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610dad9190611b7d565b60405190915081907fde92b5b7839f4a2c640f5e3bbb66d415458dadc57a487b0c7fa562ed7c9c896f90600090a250505050505050565b6040516316c2fdb560e21b815260040160405180910390fd5b600354604080516001600160a01b03928316815291831660208301527fc77bec288fc88f168427f2f7da682eadb26cac89d8d591af6e443da98dff2bbc910160405180910390a1600380546001600160a01b0319166001600160a01b0392909216919091179055565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b039092166001600160a01b0319928316178155600255600180549091169055565b604080516020808201849052818301859052825180830384018152606090920190925280519101206000906005546040516324b204d360e21b815267ffffffffffffffff871660048201529192506000916001600160a01b03909116906392c8134c9060240161018060405180830381865afa158015610f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f739190611ba6565b905081816040015114610fb75760405162461bcd60e51b815260206004820152600c60248201526b21636f6e6669726d4461746160a01b6044820152606401610632565b60008160c0015167ffffffffffffffff16118015610fe3575060008160e0015167ffffffffffffffff16115b6110195760405162461bcd60e51b8152602060048201526007602482015266085cdd185ad95960ca1b6044820152606401610632565b5050505050565b6003546001600160a01b031661103960208301836118a7565b6001600160a01b0316146110825760405162461bcd60e51b815260206004820152601060248201526f10b6b4b93937b921b7b73732b1ba37b960811b6044820152606401610632565b6004546000906001600160a01b0316639f0c04bf6110a360208501856118a7565b6110b360408601602087016118a7565b60408601356060870135608088013560a08901356110d460c08b018b611a93565b6040518963ffffffff1660e01b81526004016110f7989796959493929190611c78565b602060405180830381865afa158015611114573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111389190611b7d565b905061117b8585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508792508591508a9050611360565b505050505050565b81516000906020840161119e64ffffffffff851682846114f9565b95945050505050565b60008160ff166000036111bc575060006112af565b6111cf8460181c6001600160601b031690565b6001600160601b03166111e560ff841685611ce0565b111561124d576111fe8460781c6001600160601b031690565b6112118560181c6001600160601b031690565b6040516378218d2960e01b81526001600160601b039283166004820152911660248201526044810184905260ff83166064820152608401610632565b60208260ff1611156112725760405163045df3f960e01b815260040160405180910390fd5b60088202600061128b8660781c6001600160601b031690565b6001600160601b031690506000600160ff1b60001984011d91860151909116925050505b9392505050565b42600255600180546001600160a01b0319166001600160a01b0383169081179091556040517f6ab4d119f23076e8ad491bc65ce85f017fb0591dce08755ba8591059cc51737a90600090a250565b600061132f7f0000000000000000000000004dbd4fc535ac27206064b68ffcf827b0a60bab3f611536565b6001600160a01b0316826001600160a01b0316149050919050565b600081831061135957816112af565b5090919050565b6101008451106113a15760405162461bcd60e51b815260206004820152600c60248201526b0e0e4dedecc40d8cadccee8d60a31b6044820152606401610632565b835183901c156113e45760405162461bcd60e51b815260206004820152600e60248201526d10b6b4b734b6b0b610383937b7b360911b6044820152606401610632565b60008381526009602052604090205460ff161561142b5760405162461bcd60e51b81526020600482015260056024820152641cdc195b9d60da1b6044820152606401610632565b60048054604051627436d360e01b81526000926001600160a01b0390921691627436d39161145f9189918991899101611cf3565b602060405180830381865afa15801561147c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a09190611b7d565b90508181146114da5760405162461bcd60e51b815260206004820152600660248201526510b83937b7b360d11b6044820152606401610632565b5050506000908152600960205260409020805460ff1916600117905550565b6000806115068385611ce0565b9050604051811115611516575060005b8060000361152b5762ffffff199150506112af565b61119e858585611694565b60006001600160a01b03821633146115615760405163253a6fc960e11b815260040160405180910390fd5b6000826001600160a01b031663ab5d89436040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c59190611d40565b6001600160a01b03166380648b026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611602573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116269190611d40565b90506001600160a01b038116610b695760405162461bcd60e51b815260206004820152602d60248201527f4c6962417262697472756d4c313a2073797374656d206d65737361676573207760448201526c34ba3437baba1039b2b73232b960991b6064820152608401610632565b60006060601883856001600160601b038216821480156116bc575086816001600160601b0316145b6116f55760405162461bcd60e51b815260206004820152600a602482015269085d1c9d5b98d85d195960b21b6044820152606401610632565b96831b90961790911b90941790931b9392505050565b60006020828403121561171d57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051610180810167ffffffffffffffff8111828210171561175e5761175e611724565b60405290565b600082601f83011261177557600080fd5b813567ffffffffffffffff8082111561179057611790611724565b604051601f8301601f19908116603f011681019082821181831017156117b8576117b8611724565b816040528381528660208588010111156117d157600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561180457600080fd5b823567ffffffffffffffff8082111561181c57600080fd5b61182886838701611764565b9350602085013591508082111561183e57600080fd5b5061184b85828601611764565b9150509250929050565b60006020828403121561186757600080fd5b813567ffffffffffffffff81111561187e57600080fd5b61188a84828501611764565b949350505050565b6001600160a01b038116811461075e57600080fd5b6000602082840312156118b957600080fd5b81356112af81611892565b67ffffffffffffffff8116811461075e57600080fd5b600060e082840312156118ec57600080fd5b50919050565b600080600080600080600060c0888a03121561190d57600080fd5b8735611918816118c4565b96506020880135955060408801359450606088013567ffffffffffffffff8082111561194357600080fd5b818a0191508a601f83011261195757600080fd5b81358181111561196657600080fd5b8b60208260051b850101111561197b57600080fd5b6020830196508095505060808a0135935060a08a01359150808211156119a057600080fd5b506119ad8a828b016118da565b91505092959891949750929550565b6000815180845260005b818110156119e2576020818501810151868301820152016119c6565b506000602082860101526020601f19601f83011685010191505092915050565b606081526000611a1560608301866119bc565b8281036020840152611a2781866119bc565b91505060018060a01b0383166040830152949350505050565b604081526000611a5360408301856119bc565b905060018060a01b03831660208301529392505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610b6957610b69611a6a565b6000808335601e19843603018112611aaa57600080fd5b83018035915067ffffffffffffffff821115611ac557600080fd5b602001915036819003821315611ada57600080fd5b9250929050565b6020815260006112af60208301846119bc565b600080600060608486031215611b0957600080fd5b8351925060208401519150604084015190509250925092565b600061010060018060a01b03808c1684528a602085015289604085015280891660608501528088166080850152508560a08401528460c08401528060e0840152611b6e818401856119bc565b9b9a5050505050505050505050565b600060208284031215611b8f57600080fd5b5051919050565b8051611ba1816118c4565b919050565b60006101808284031215611bb957600080fd5b611bc161173a565b825181526020830151602082015260408301516040820152611be560608401611b96565b6060820152611bf660808401611b96565b6080820152611c0760a08401611b96565b60a0820152611c1860c08401611b96565b60c0820152611c2960e08401611b96565b60e0820152610100611c3c818501611b96565b90820152610120611c4e848201611b96565b90820152610140611c60848201611b96565b90820152610160928301519281019290925250919050565b600060018060a01b03808b168352808a166020840152508760408301528660608301528560808301528460a083015260e060c08301528260e08301526101008385828501376000838501820152601f909301601f191690910190910198975050505050505050565b80820180821115610b6957610b69611a6a565b606080825284519082018190526000906020906080840190828801845b82811015611d2c57815184529284019290840190600101611d10565b505050908301949094525060400152919050565b600060208284031215611d5257600080fd5b81516112af8161189256fea2646970667358221220019042e2fa1ddf40ad2442b13da589ca89a15ac368f145ebe78777a555b27d1b64736f6c63430008110033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000000000000000000000000000000000000657468000000000000000000000000000000000000000000000000000000006172626f0000000000000000000000004dbd4fc535ac27206064b68ffcf827b0a60bab3f000000000000000000000000d5d61e9dfb6680cba8353988ba0337802811c2e100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b9857ae2d4a3dbe74ffe1d7df045bb7f96e48400000000000000000000000000000000000000000000000000000002e90edd00000000000000000000000000000000000000000000000000000000000000cf85000000000000000000000000000000000000000000000000000000004a817c800

-----Decoded View---------------
Arg [0] : _domain (uint32): 6648936
Arg [1] : _mirrorDomain (uint32): 1634886255
Arg [2] : _amb (address): 0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f
Arg [3] : _rootManager (address): 0xd5d61E9dfb6680Cba8353988Ba0337802811C2e1
Arg [4] : _mirrorConnector (address): 0x0000000000000000000000000000000000000000
Arg [5] : _outbox (address): 0x0B9857ae2D4A3DBe74ffE1d7DF045bb7F96E4840
Arg [6] : _maxSubmissionCostCap (uint256): 200000000000
Arg [7] : _maxGasCap (uint256): 850000
Arg [8] : _gasPriceCap (uint256): 20000000000

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000657468
Arg [1] : 000000000000000000000000000000000000000000000000000000006172626f
Arg [2] : 0000000000000000000000004dbd4fc535ac27206064b68ffcf827b0a60bab3f
Arg [3] : 000000000000000000000000d5d61e9dfb6680cba8353988ba0337802811c2e1
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000b9857ae2d4a3dbe74ffe1d7df045bb7f96e4840
Arg [6] : 0000000000000000000000000000000000000000000000000000002e90edd000
Arg [7] : 00000000000000000000000000000000000000000000000000000000000cf850
Arg [8] : 00000000000000000000000000000000000000000000000000000004a817c800


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.