or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdl1-messaging-bridging.mdl1-rollup-management.mdl2-messaging-bridging.mdl2-system-contracts.mdstandards-interfaces.mdtypescript-utilities.mdutility-libraries.md
tile.json

l1-messaging-bridging.mddocs/

Layer 1 Messaging & Bridging

L1 contracts deployed on Ethereum mainnet that handle cross-domain messaging and asset bridging between Ethereum and Optimism L2. These contracts enable secure communication and token transfers with cryptographic proof verification.

L1CrossDomainMessenger

Contract Path: L1/messaging/L1CrossDomainMessenger.sol

The core L1 contract for cross-domain messaging that sends messages from L1 to L2 and relays messages from L2 to L1 with fraud proof verification.

Key Functions

contract L1CrossDomainMessenger {
  function initialize(address _libAddressManager) external;
  
  function sendMessage(
    address _target,
    bytes calldata _message,
    uint32 _gasLimit
  ) external;
  
  function relayMessage(
    address _target,
    address _sender,
    bytes memory _message,
    uint256 _messageNonce,
    L2MessageInclusionProof memory _proof
  ) external;
  
  function replayMessage(
    address _target,
    address _sender,
    bytes memory _message,
    uint256 _queueIndex,
    uint32 _oldGasLimit,
    uint32 _newGasLimit
  ) external;
  
  function pause() external;
  function unpause() external;
  
  function blockMessage(bytes32 _xDomainCalldataHash) external;
  function allowMessage(bytes32 _xDomainCalldataHash) external;
  
  function xDomainMessageSender() external view returns (address);
}

initialize

Initializes the messenger contract with the address manager.

Parameters:

  • _libAddressManager (address): Address of the Lib_AddressManager contract

Usage:

messenger.initialize(addressManagerAddress);

sendMessage

Sends a message from L1 to L2.

Parameters:

  • _target (address): Target contract address on L2
  • _message (bytes): Encoded message data to send
  • _gasLimit (uint32): Gas limit for L2 execution

Events Emitted:

  • SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit)

Usage:

// Send a simple message
messenger.sendMessage(
  l2ContractAddress,
  abi.encodeWithSignature("handleL1Message(uint256)", 12345),
  200000
);

relayMessage

Relays a message from L2 to L1 with cryptographic proof verification.

Parameters:

  • _target (address): Target contract address on L1
  • _sender (address): Original sender address on L2
  • _message (bytes): Message data to relay
  • _messageNonce (uint256): Message nonce from L2
  • _proof (L2MessageInclusionProof): Merkle proof of message inclusion

Events Emitted:

  • RelayedMessage(bytes32 indexed msgHash) (on success)
  • FailedRelayedMessage(bytes32 indexed msgHash) (on failure)

Usage:

L2MessageInclusionProof memory proof = L2MessageInclusionProof({
  stateRoot: stateRoot,
  stateRootBatchHeader: batchHeader,
  stateRootProof: inclusionProof,
  stateTrieWitness: stateWitness,
  storageTrieWitness: storageWitness
});

messenger.relayMessage(
  targetAddress,
  senderAddress,
  messageData,
  messageNonce,
  proof
);

replayMessage

Replays a failed message with a new gas limit.

Parameters:

  • _target (address): Target contract address
  • _sender (address): Original sender address
  • _message (bytes): Message data to replay
  • _queueIndex (uint256): Queue index of the original message
  • _oldGasLimit (uint32): Previous gas limit that failed
  • _newGasLimit (uint32): New gas limit for retry

Administrative Functions

pause / unpause

Pauses or unpauses message relaying (owner only).

blockMessage / allowMessage

Blocks or unblocks specific message hashes (owner only).

Parameters:

  • _xDomainCalldataHash (bytes32): Hash of the cross-domain message to block/allow

State Variables

mapping(bytes32 => bool) public blockedMessages;
mapping(bytes32 => bool) public relayedMessages;
mapping(bytes32 => bool) public successfulMessages;
uint256 public messageNonce;

Events

event MessageBlocked(bytes32 indexed _xDomainCalldataHash);
event MessageAllowed(bytes32 indexed _xDomainCalldataHash);
event SentMessage(
  address indexed target,
  address sender,
  bytes message,
  uint256 messageNonce,
  uint256 gasLimit
);
event RelayedMessage(bytes32 indexed msgHash);
event FailedRelayedMessage(bytes32 indexed msgHash);

L1StandardBridge

Contract Path: L1/messaging/L1StandardBridge.sol

The standard bridge contract for ETH and ERC20 token transfers between L1 and L2.

Key Functions

contract L1StandardBridge {
  function initialize(
    address _l1messenger,
    address _l2TokenBridge
  ) external;
  
  function depositETH(
    uint32 _l2Gas,
    bytes calldata _data
  ) external payable;
  
  function depositETHTo(
    address _to,
    uint32 _l2Gas,
    bytes calldata _data
  ) external payable;
  
  function depositERC20(
    address _l1Token,
    address _l2Token,
    uint256 _amount,
    uint32 _l2Gas,
    bytes calldata _data
  ) external;
  
  function depositERC20To(
    address _l1Token,
    address _l2Token,
    address _to,
    uint256 _amount,
    uint32 _l2Gas,
    bytes calldata _data
  ) external;
  
  function finalizeETHWithdrawal(
    address _from,
    address _to,
    uint256 _amount,
    bytes calldata _data
  ) external;
  
  function finalizeERC20Withdrawal(
    address _l1Token,
    address _l2Token,
    address _from,
    address _to,
    uint256 _amount,
    bytes calldata _data
  ) external;
}

initialize

Initializes the bridge with the L1 messenger and L2 bridge address.

Parameters:

  • _l1messenger (address): L1CrossDomainMessenger contract address
  • _l2TokenBridge (address): L2StandardBridge contract address

depositETH

Deposits ETH to L2 for the sender.

Parameters:

  • _l2Gas (uint32): Gas limit for L2 execution
  • _data (bytes): Optional data to pass to L2

Usage:

// Deposit 1 ETH to L2
bridge.depositETH{value: 1 ether}(200000, "");

depositETHTo

Deposits ETH to L2 for a specific recipient.

Parameters:

  • _to (address): Recipient address on L2
  • _l2Gas (uint32): Gas limit for L2 execution
  • _data (bytes): Optional data to pass to L2

depositERC20

Deposits ERC20 tokens to L2.

Parameters:

  • _l1Token (address): L1 token contract address
  • _l2Token (address): Corresponding L2 token contract address
  • _amount (uint256): Amount of tokens to deposit
  • _l2Gas (uint32): Gas limit for L2 execution
  • _data (bytes): Optional data to pass to L2

Usage:

// Approve bridge to spend tokens
IERC20(l1TokenAddress).approve(bridgeAddress, amount);

// Deposit tokens
bridge.depositERC20(
  l1TokenAddress,
  l2TokenAddress,
  amount,
  200000,
  ""
);

depositERC20To

Deposits ERC20 tokens to L2 for a specific recipient.

Parameters:

  • _l1Token (address): L1 token contract address
  • _l2Token (address): L2 token contract address
  • _to (address): Recipient address on L2
  • _amount (uint256): Amount of tokens to deposit
  • _l2Gas (uint32): Gas limit for L2 execution
  • _data (bytes): Optional data to pass to L2

finalizeETHWithdrawal

Finalizes an ETH withdrawal from L2 (called by the messenger).

Parameters:

  • _from (address): Sender address on L2
  • _to (address): Recipient address on L1
  • _amount (uint256): Amount of ETH to withdraw
  • _data (bytes): Optional data from L2

finalizeERC20Withdrawal

Finalizes an ERC20 token withdrawal from L2 (called by the messenger).

Parameters:

  • _l1Token (address): L1 token contract address
  • _l2Token (address): L2 token contract address
  • _from (address): Sender address on L2
  • _to (address): Recipient address on L1
  • _amount (uint256): Amount of tokens to withdraw
  • _data (bytes): Optional data from L2

Events

event ETHDepositInitiated(
  address indexed _from,
  address indexed _to,
  uint256 _amount,
  bytes _data
);

event ETHWithdrawalFinalized(
  address indexed _from,
  address indexed _to,
  uint256 _amount,
  bytes _data
);

event ERC20DepositInitiated(
  address indexed _l1Token,
  address indexed _l2Token,
  address indexed _from,
  address _to,
  uint256 _amount,
  bytes _data
);

event ERC20WithdrawalFinalized(
  address indexed _l1Token,
  address indexed _l2Token,
  address indexed _from,
  address _to,
  uint256 _amount,
  bytes _data
);

Common Types

L2MessageInclusionProof

struct L2MessageInclusionProof {
  bytes32 stateRoot;
  ChainBatchHeader stateRootBatchHeader;
  ChainInclusionProof stateRootProof;
  bytes stateTrieWitness;
  bytes storageTrieWitness;
}

Proof structure for verifying L2 message inclusion in L1.

ChainBatchHeader

struct ChainBatchHeader {
  uint256 batchIndex;
  bytes32 batchRoot;
  uint256 batchSize;
  uint256 prevTotalElements;
  bytes extraData;
}

Header structure for state batch proofs.

ChainInclusionProof

struct ChainInclusionProof {
  uint256 index;
  bytes32[] siblings;
}

Merkle proof structure for chain inclusion verification.

Usage Examples

Cross-Domain Message Passing

// L1 Contract sending message to L2
contract L1Contract {
  IL1CrossDomainMessenger public messenger;
  
  function sendToL2(address l2Target, bytes calldata data) external {
    messenger.sendMessage(l2Target, data, 200000);
  }
  
  function handleFromL2(uint256 value) external {
    require(
      msg.sender == address(messenger) &&
      messenger.xDomainMessageSender() == trustedL2Address,
      "Invalid sender"
    );
    
    // Handle message from L2
    processValue(value);
  }
}

ETH and Token Bridging

// Bridge ETH and tokens
contract BridgeUser {
  IL1StandardBridge public bridge;
  
  function bridgeETH(uint256 amount) external {
    bridge.depositETH{value: amount}(200000, "");
  }
  
  function bridgeTokens(
    address l1Token,
    address l2Token,
    uint256 amount
  ) external {
    IERC20(l1Token).transferFrom(msg.sender, address(this), amount);
    IERC20(l1Token).approve(address(bridge), amount);
    
    bridge.depositERC20(l1Token, l2Token, amount, 200000, "");
  }
}