Skip to content

Latest commit

 

History

History
112 lines (86 loc) · 3.69 KB

messengers.md

File metadata and controls

112 lines (86 loc) · 3.69 KB

Cross Domain Messengers

Table of Contents

The cross domain messengers are responsible for providing a higher level API for developers who are interested in sending cross domain messages. They allow for the ability to replay cross domain messages and sit directly on top of the lower level system contracts responsible for cross domain messaging on L1 and L2.

The CrossDomainMessenger is extended to create both an L1CrossDomainMessenger and well as a L2CrossDomainMessenger.

The L2CrossDomainMessenger is a predeploy contract located at 0x4200000000000000000000000000000000000004.

interface CrossDomainMessenger {
    event FailedRelayedMessage(bytes32 indexed msgHash);

    event RelayedMessage(bytes32 indexed msgHash);

    event SentMessage(
      address indexed target,
      address indexed sender,
      uint256 value,
      bytes message,
      uint256 messageNonce,
      uint256 gasLimit
    );

    function MESSAGE_VERSION() view external returns (uint16);

    function OTHER_MESSENGER() view external returns (address);

    function messageNonce() view external returns (uint256);

    function failedMessages(bytes32) view external returns (bool);

    function relayMessage(
      uint256 _nonce,
      address _sender,
      address _target,
      uint256 _value,
      uint256 _minGasLimit,
      bytes calldata _message
    ) payable external;

    function sendMessage(
      address _target,
      bytes calldata _message,
      uint32 _minGasLimit
    ) payable external;

    function successfulMessages(bytes32) view external returns (bool);

    function xDomainMessageSender() view external returns (address);
}

Message Passing

The sendMessage function is used to send a cross domain message. To trigger the execution on the other side, the relayMessage function is called. Successful messages have their hash stored in the successfulMessages mapping while unsuccessful messages have their hash stored in the failedMessages mapping.

The user experience when sending from L1 to L2 is a bit different than when sending a transaction from L2 to L1. When going into L2 from L1, the user does not need to call relayMessage on L2 themselves. The user pays for L2 gas on L1 and the transaction is automatically pulled into L2 where it is executed on L2. When going from L2 into L1, the user proves their withdrawal on KromaPortal, then waits for the finalization window to pass, and then finalizes the withdrawal on the KromaPortal, which calls relayMessage on the L1CrossDomainMessenger to finalize the withdrawal.

Upgradeability

The L1 and L2 cross domain messengers should be deployed behind upgradable proxies. This will allow for updating the message version.

Message Versioning

Messages are versioned based on the first 2 bytes of their nonce. Depending on the version, messages can have a different serialization and hashing scheme. The first two bytes of the nonce are reserved for version metadata because a version field was not originally included in the messages themselves, but a uint256 nonce is so large that we can very easily pack additional data into that field.

Message Version 0

abi.encodeWithSignature(
    "relayMessage(uint256,address,address,uint256,uint256,bytes)",
    _nonce,
    _sender,
    _target,
    _value,
    _gasLimit,
    _data
);