Outbox
The Outbox is a contract deployed on L1 that handles message passing from L2 to L1. Portal contracts call consume() to receive and process messages that were sent from L2 contracts. The Rollup contract inserts message roots via insert() when checkpoints are proven.
Links: Interface, Implementation.
insert()
Inserts the root of a merkle tree containing all of the L2 to L1 messages in a checkpoint. This function is only callable by the Rollup contract.
/**
* @notice Inserts the root of a merkle tree containing all of the L2 to L1 messages in
* a checkpoint specified by _checkpointNumber.
* @dev Only callable by the rollup contract
* @dev Emits `RootAdded` upon inserting the root successfully
* @param _checkpointNumber - The checkpoint number in which the L2 to L1 messages reside
* @param _root - The merkle root of the tree where all the L2 to L1 messages are leaves
*/
function insert(uint256 _checkpointNumber, bytes32 _root) external;
Source code: l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol#L19-L29
| Name | Type | Description |
|---|---|---|
_checkpointNumber | uint256 | The checkpoint number in which the L2 to L1 messages reside |
_root | bytes32 | The merkle root of the tree where all the L2 to L1 messages are leaves |
Edge cases
- Will revert with
Outbox__Unauthorized()ifmsg.sender != ROLLUP_CONTRACT. - Will revert with
Outbox__CheckpointAlreadyProven(uint256 checkpointNumber)if the checkpoint has already been proven.
consume()
Allows a recipient to consume a message from the Outbox.
/**
* @notice Consumes an entry from the Outbox
* @dev Only useable by portals / recipients of messages
* @dev Emits `MessageConsumed` when consuming messages
* @param _message - The L2 to L1 message
* @param _checkpointNumber - The checkpoint number specifying the checkpoint that contains the message we want to
* consume
* @param _leafIndex - The index inside the merkle tree where the message is located
* @param _path - The sibling path used to prove inclusion of the message, the _path length directly depends
* on the total amount of L2 to L1 messages in the checkpoint. i.e. the length of _path is equal to the depth of the
* L1 to L2 message tree.
*/
function consume(
DataStructures.L2ToL1Msg calldata _message,
uint256 _checkpointNumber,
uint256 _leafIndex,
bytes32[] calldata _path
) external;
Source code: l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol#L31-L50
| Name | Type | Description |
|---|---|---|
_message | L2ToL1Msg | The L2 to L1 message to consume |
_checkpointNumber | uint256 | The checkpoint number specifying the checkpoint that contains the message to consume |
_leafIndex | uint256 | The index inside the merkle tree where the message is located |
_path | bytes32[] | The sibling path used to prove inclusion of the message |
Edge cases
- Will revert with
Outbox__PathTooLong()if the path length is >= 256. - Will revert with
Outbox__LeafIndexOutOfBounds(uint256 leafIndex, uint256 pathLength)if the leaf index exceeds the tree capacity for the given path length. - Will revert with
Outbox__CheckpointNotProven(uint256 checkpointNumber)if the checkpoint has not been proven yet. - Will revert with
Outbox__VersionMismatch(uint256 expected, uint256 actual)if the message version does not match the Outbox version. - Will revert with
Outbox__InvalidRecipient(address expected, address actual)ifmsg.sender != _message.recipient.actor. - Will revert with
Outbox__InvalidChainId()ifblock.chainid != _message.recipient.chainId. - Will revert with
Outbox__NothingToConsumeAtCheckpoint(uint256 checkpointNumber)if the root for the checkpoint has not been set. - Will revert with
Outbox__AlreadyNullified(uint256 checkpointNumber, uint256 leafIndex)if the message has already been consumed. - Will revert with
MerkleLib__InvalidIndexForPathLength()if the leaf index has bits set beyond the tree height. - Will revert with
MerkleLib__InvalidRoot(bytes32 expected, bytes32 actual, bytes32 leaf, uint256 leafIndex)if the merkle proof verification fails.
hasMessageBeenConsumedAtCheckpoint()
Checks if an L2 to L1 message in a specific checkpoint has been consumed.
/**
* @notice Checks to see if an L2 to L1 message in a specific checkpoint has been consumed
* @dev - This function does not throw. Out-of-bounds access is considered valid, but will always return false
* @param _checkpointNumber - The checkpoint number specifying the checkpoint that contains the message we want to
* check
* @param _leafId - The unique id of the message leaf
*/
function hasMessageBeenConsumedAtCheckpoint(uint256 _checkpointNumber, uint256 _leafId) external view returns (bool);
Source code: l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol#L52-L61
| Name | Type | Description |
|---|---|---|
_checkpointNumber | uint256 | The checkpoint number specifying the checkpoint that contains the message to check |
_leafId | uint256 | The unique id of the message leaf |
Edge cases
- This function does not throw. Out-of-bounds access is considered valid, but will always return false.
getRootData()
Returns the merkle root for a given checkpoint number. Returns bytes32(0) if the checkpoint has not been proven.
function getRootData(uint256 _checkpointNumber) external view returns (bytes32);
| Name | Type | Description |
|---|---|---|
_checkpointNumber | uint256 | The checkpoint number to fetch the root data for |
Returns: The merkle root of the L2 to L1 message tree for the checkpoint, or bytes32(0) if not proven.
Related pages
- Inbox - L1 to L2 message passing
- Data Structures - Message struct definitions
- L1-L2 Communication (Portals) - Overview of cross-chain messaging