Skip to content
Merged
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 81 additions & 1 deletion specs/interop/predeploys.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@
- [`Identifier` Getters](#identifier-getters)
- [L2ToL2CrossDomainMessenger](#l2tol2crossdomainmessenger)
- [`relayMessage` Invariants](#relaymessage-invariants)
- [`sendMessageHashBack` Invariants](#sendhashtorollbackinbox-invariants)
- [`receiveMessageHash` Invariants](#receivemessagehash-invariants)
- [Message Versioning](#message-versioning)
- [No Native Support for Cross Chain Ether Sends](#no-native-support-for-cross-chain-ether-sends)
- [Interfaces](#interfaces)
- [Sending Messages](#sending-messages)
- [Relaying Messages](#relaying-messages)
- [Sending Back Messages](#sending-back-messages)
- [Storing Sent-back Messages](#storing-sent-back-messages)
- [L1Block](#l1block)
- [Static Configuration](#static-configuration)
- [Dependency Set](#dependency-set)
Expand Down Expand Up @@ -159,6 +163,23 @@ as well as domain binding, ie the executing transaction can only be valid on a s
- The `_destination` chain id MUST be equal to the local chain id
- The `CrossL2Inbox` cannot call itself

### `sendMessageHashBack` Invariants

- The Source chain id MUST not be `block.chainid`
- The `_destination` chain id MUST be equal to the local chain id
- The message MUST have not been successfully relayed
- The `RETURN_DELAY` MUST have elapsed since the message first failed to be relayed
- The sent-back message MUST not have been previously relayed
- The sent-back message MUST not be relayable after being sent back

### `receiveMessageHash` Invariants

- Only callable by the `CrossL2Inbox`
- The message source MUST be `block.chainid`
- The sender MUST be `address(L2ToL2CrossDomainMessenger)`
- The `Identifier.origin` MUST be `address(L2ToL2CrossDomainMessenger)`
- The `Identifier.chainId` MUST be `_destination`

Comment thread
tynes marked this conversation as resolved.
### Message Versioning

Versioning is handled in the most significant bits of the nonce, similarly to how it is handled by
Expand Down Expand Up @@ -245,7 +266,11 @@ function relayMessage(uint256 _destination, uint256 _source, uint256 _nonce, add
_calldata: _message
});

Comment thread
tynes marked this conversation as resolved.
require(success);
if (!success) {
if (failedMessages[messageHash] == 0) {
Comment thread
skeletor-spaceman marked this conversation as resolved.
Outdated
Comment thread
skeletor-spaceman marked this conversation as resolved.
Outdated
failedMessages[messageHash] = block.timestamp;
}
};
}
```

Expand All @@ -254,6 +279,61 @@ Note that the `relayMessage` function is `payable` to enable relayers to earn in
To enable cross chain authorization patterns, both the `_sender` and the `_source` MUST be exposed via `public`
getters.

#### Sending Back Messages Hashes

When sending back a message that failed to be relayed on the destination chain
to the source chain, it's crucial to ensure the message can only be sent back
to the `L2ToL2CrossDomainMessenger` contract in its source chain.

```solidity
function sendMessageHashBack(uint256 _messageSource, uint256 _nonce, address _sender, address _target, bytes calldata _message) external nonReentrant {
Comment thread
tynes marked this conversation as resolved.
Outdated
if (_source == block.chainid) revert MessageSourceSameChain();

bytes32 messageHash = keccak256(abi.encode(block.chainid, _messageSource, _nonce, _sender, _target, _message));

if (successfulMessages[messageHash]) revert MessageAlreadyRelayed();
if (block.timestamp < failedMessages[messageHash] + RETURN_DELAY) revert DelayHasNotEnsued();
Comment thread
tynes marked this conversation as resolved.
Outdated

successfulMessages[messageHash] = true;

bytes memory data = abi.encodeCall(
L2ToL2CrossDomainMessenger.receiveMessageHash,
(_messageSource, Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, messageHash)
);
emit SentMessage(data);
}
```

#### Storing Sent-back Message Hashes

When receiving a sent-back message only message hashes
of actual failed messages should be stored, for this we must ensure the origin,
sender and caller are all the expected contracts.

It's also important to ensure only the hashes of messages that were initiated
in this chain are accepted and that they come from the correct destination
chain id.

```solidity
function receiveMessageHash(uint256 _messageSource, uint256 _messageDestination, address _sender, bytes32 _messageHash) external {
Comment thread
tynes marked this conversation as resolved.
Outdated
Comment thread
tynes marked this conversation as resolved.
Outdated
if (_messageSource != block.chainid) revert IncorrectMessageSource();
Comment thread
tynes marked this conversation as resolved.
if (_sender != Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER) revert SenderIsNotCrossDomainMesenger();
if (msg.sender != Predeploys.CROSS_L2_INBOX) revert ReceiveMessageHashCallerNotCrossL2Inbox();

if (CrossL2Inbox(Predeploys.CROSS_L2_INBOX).origin() != Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER) {
revert CrossL2InboxOriginNotL2ToL2CrossDomainMessenger();
}

Comment thread
tynes marked this conversation as resolved.
if (CrossL2Inbox(Predeploys.CROSS_L2_INBOX).chainid() != _messageDestination) {
revert CrossL2InboxDestinationDoesntMatch();
}

returnedMessages[_messageHash] = block.timestamp;
Comment thread
tynes marked this conversation as resolved.
Outdated

emit MessageHashReceived(_messageHash);
Comment thread
tynes marked this conversation as resolved.
Outdated
}
```

## L1Block

| Constant | Value |
Expand Down