diff --git a/specs/interop/predeploys.md b/specs/interop/predeploys.md index be232b3fd..b19390d71 100644 --- a/specs/interop/predeploys.md +++ b/specs/interop/predeploys.md @@ -279,6 +279,8 @@ as well as domain binding, ie the executing transaction can only be valid on a s - The `Identifier.origin` MUST be `address(L2ToL2CrossDomainMessenger)` - The `_destination` chain id MUST be equal to the local chain id - Messages MUST NOT be relayed more than once +- The `msg.sender` MUST be equal to the `entrypoint` address, if set +- If `entrypoint` is not set, anyone MUST be able to relay the message ### `sendMessage` Invariants @@ -310,23 +312,33 @@ chain is included instead. #### Sending Messages -The following function is used for sending messages between domains: +The following functions are used for sending messages between domains: + +**Permissionless:** Can be relayed on the destination chain by any address. ```solidity function sendMessage(uint256 _destination, address _target, bytes calldata _message) external returns (bytes32); ``` -It returns the hash of the message being sent, -used to track whether the message has successfully been relayed. -It emits a `SentMessage` event with the necessary metadata to execute when relayed on the destination chain. +**Using Entrypoint:** Can be relayed on the destination chain only by the `_entrypoint` address. ```solidity -event SentMessage(uint256 indexed destination, address indexed target, uint256 indexed messageNonce, address sender, bytes message); +function sendMessage(uint256 _destination, address _target, address _entrypoint, bytes calldata _message) external returns (bytes32); +``` + +Both functions return the hash of the message being sent, +which is used to track whether the message has successfully been relayed. +They emit a `SentMessage` event with the necessary metadata to execute when relayed on the destination chain. + +```solidity +event SentMessage(uint256 indexed destination, address indexed target, uint256 indexed messageNonce, address sender, address entrypoint, bytes message); ``` An explicit `_destination` chain and `nonce` are used to ensure that the message can only be played on a single remote chain a single time. The `_destination` is enforced to not be the local chain to avoid edge cases. +Note that when sending the message with the **permisionless** variant of `sendMessage`, `entrypoint` will default to `address(0)`. + There is no need for address aliasing as the aliased address would need to commit to the source chain's chain id to create a unique alias that commits to a particular sender on a particular domain and it is far more simple to assert on both the address and the source chain's chain id rather than assert on an unaliased address. @@ -392,7 +404,8 @@ function relayMessage(ICrossL2Inbox.Identifier calldata _id, bytes calldata _sen require(_destination == block.chainid); // log data - (address _sender, bytes memory _message) = abi.decode(_sentMessage[128:], (address,bytes)); + (address _sender, address _entrypoint, bytes memory _message) = + abi.decode(_sentMessage[128:], (address,address,bytes)); bool success = SafeCall.call(_target, msg.value, _message); require(success); @@ -403,6 +416,8 @@ function relayMessage(ICrossL2Inbox.Identifier calldata _id, bytes calldata _sen Note that the `relayMessage` function is `payable` to enable relayers to earn in the gas paying asset. +Additionally, if the `_entrypoint` is not `address(0)` and the caller is not `_entrypoint`, the transaction MUST revert. + To enable cross chain authorization patterns, both the `_sender` and the `_source` MUST be exposed via `public` getters.