Commit 2d1f41c4 authored by tre's avatar tre Committed by GitHub

feat(L2toL2CrossDomainMessenger): update `sendMessage` to return relay message hash (#12089)

* feat(L2toL2CrossDomainMessenger): return message hash from sendMessage

* fix

* fix build

* revert

* fix build

* bump version

* nit

* address comments

* update tests

* nit

* revert

* update snapshot

* update semver devdoc

* update semver-lock

* bump token versions

* bump semver lock

* fix semver and update output

* update semver-lock

* delete clones-with-immutable-args

* bump versions:

* update semver-lock
parent 2a25c62c
...@@ -112,12 +112,12 @@ ...@@ -112,12 +112,12 @@
"sourceCodeHash": "0xd08a2e6514dbd44e16aa312a1b27b2841a9eab5622cbd05a39c30f543fad673c" "sourceCodeHash": "0xd08a2e6514dbd44e16aa312a1b27b2841a9eab5622cbd05a39c30f543fad673c"
}, },
"src/L2/L2ToL2CrossDomainMessenger.sol": { "src/L2/L2ToL2CrossDomainMessenger.sol": {
"initCodeHash": "0x2ec4cdf62baf9dfb2c4c211d8b914f3dd1e0c0133c15c739ff81c5a2504d4359", "initCodeHash": "0x652e07372d45f0f861aa65b4a73db55871291b875ced02df893a405419de723a",
"sourceCodeHash": "0x54dfffed789dafe11b7f7bb16dfb29988713a19da5209452119c5d6539e48c48" "sourceCodeHash": "0xc3e73c2d9abf3c7853d2505a83e475d58e96ab5fc5ad7770d04dea5feb9e5717"
}, },
"src/L2/OptimismSuperchainERC20.sol": { "src/L2/OptimismSuperchainERC20.sol": {
"initCodeHash": "0x192bb3abd2a103832172d913f548e36bcf6f2c0220cd224a83f8420e2e86b4ec", "initCodeHash": "0xe3dbb0851669708901a4c6bb7ad7d55f9896deeec02cbe53ac58d689ff95b88b",
"sourceCodeHash": "0x09d3367612dee674e3708da1c70eebbd0c6835fbcbba339780e678338bdfd3ca" "sourceCodeHash": "0xe853817da47d32b4ec5bb5392405278c82a1e9620aef377491dcb371fbbe682f"
}, },
"src/L2/OptimismSuperchainERC20Beacon.sol": { "src/L2/OptimismSuperchainERC20Beacon.sol": {
"initCodeHash": "0x99ce8095b23c124850d866cbc144fee6cee05dbc6bb5d83acadfe00b90cf42c7", "initCodeHash": "0x99ce8095b23c124850d866cbc144fee6cee05dbc6bb5d83acadfe00b90cf42c7",
...@@ -132,8 +132,8 @@ ...@@ -132,8 +132,8 @@
"sourceCodeHash": "0xd56922cb04597dea469c65e5a49d4b3c50c171e603601e6f41da9517cae0b11a" "sourceCodeHash": "0xd56922cb04597dea469c65e5a49d4b3c50c171e603601e6f41da9517cae0b11a"
}, },
"src/L2/SuperchainWETH.sol": { "src/L2/SuperchainWETH.sol": {
"initCodeHash": "0xd8766c7ab41d34d935febf5b48289f947804634bde38f8e346075b9f2d867275", "initCodeHash": "0x4ccd25f37a816205bc26f8532afa66e02f2b36ca7b7404d0fa48a4313ed16f0c",
"sourceCodeHash": "0x6c1691c0fb5c86f1fd67e23495725c2cd86567556602e8cc0f28104ad6114bf4" "sourceCodeHash": "0xd186614f1515fa3ba2f43e401e639bfa3159603954e39a51769e9b57ad19a3fd"
}, },
"src/L2/WETH.sol": { "src/L2/WETH.sol": {
"initCodeHash": "0xfb253765520690623f177941c2cd9eba23e4c6d15063bccdd5e98081329d8956", "initCodeHash": "0xfb253765520690623f177941c2cd9eba23e4c6d15063bccdd5e98081329d8956",
......
...@@ -108,7 +108,13 @@ ...@@ -108,7 +108,13 @@
} }
], ],
"name": "sendMessage", "name": "sendMessage",
"outputs": [], "outputs": [
{
"internalType": "bytes32",
"name": "msgHash_",
"type": "bytes32"
}
],
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
pragma solidity 0.8.25; pragma solidity 0.8.25;
import { Encoding } from "src/libraries/Encoding.sol"; import { Encoding } from "src/libraries/Encoding.sol";
import { Hashing } from "src/libraries/Hashing.sol";
import { Predeploys } from "src/libraries/Predeploys.sol"; import { Predeploys } from "src/libraries/Predeploys.sol";
import { CrossL2Inbox } from "src/L2/CrossL2Inbox.sol"; import { CrossL2Inbox } from "src/L2/CrossL2Inbox.sol";
import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol";
...@@ -57,8 +58,8 @@ contract L2ToL2CrossDomainMessenger is IL2ToL2CrossDomainMessenger, ISemver, Tra ...@@ -57,8 +58,8 @@ contract L2ToL2CrossDomainMessenger is IL2ToL2CrossDomainMessenger, ISemver, Tra
uint16 public constant messageVersion = uint16(0); uint16 public constant messageVersion = uint16(0);
/// @notice Semantic version. /// @notice Semantic version.
/// @custom:semver 1.0.0-beta.5 /// @custom:semver 1.0.0-beta.6
string public constant version = "1.0.0-beta.5"; string public constant version = "1.0.0-beta.6";
/// @notice Mapping of message hashes to boolean receipt values. Note that a message will only be present in this /// @notice Mapping of message hashes to boolean receipt values. Note that a message will only be present in this
/// mapping if it has successfully been relayed on this chain, and can therefore not be relayed again. /// mapping if it has successfully been relayed on this chain, and can therefore not be relayed again.
...@@ -99,15 +100,32 @@ contract L2ToL2CrossDomainMessenger is IL2ToL2CrossDomainMessenger, ISemver, Tra ...@@ -99,15 +100,32 @@ contract L2ToL2CrossDomainMessenger is IL2ToL2CrossDomainMessenger, ISemver, Tra
/// @param _destination Chain ID of the destination chain. /// @param _destination Chain ID of the destination chain.
/// @param _target Target contract or wallet address. /// @param _target Target contract or wallet address.
/// @param _message Message payload to call target with. /// @param _message Message payload to call target with.
function sendMessage(uint256 _destination, address _target, bytes calldata _message) external { /// @return msgHash_ The hash of the message being sent, which can be used for tracking whether
/// the message has successfully been relayed.
function sendMessage(
uint256 _destination,
address _target,
bytes calldata _message
)
external
returns (bytes32 msgHash_)
{
if (_destination == block.chainid) revert MessageDestinationSameChain(); if (_destination == block.chainid) revert MessageDestinationSameChain();
if (_target == Predeploys.CROSS_L2_INBOX) revert MessageTargetCrossL2Inbox(); if (_target == Predeploys.CROSS_L2_INBOX) revert MessageTargetCrossL2Inbox();
if (_target == Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER) revert MessageTargetL2ToL2CrossDomainMessenger(); if (_target == Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER) revert MessageTargetL2ToL2CrossDomainMessenger();
(uint256 source, uint256 nonce, address sender) = (block.chainid, messageNonce(), msg.sender);
bytes memory data = abi.encodeCall( bytes memory data = abi.encodeCall(
L2ToL2CrossDomainMessenger.relayMessage, L2ToL2CrossDomainMessenger.relayMessage, (_destination, source, nonce, sender, _target, _message)
(_destination, block.chainid, messageNonce(), msg.sender, _target, _message)
); );
msgHash_ = Hashing.hashL2toL2CrossDomainMessengerRelayMessage({
_destination: _destination,
_source: source,
_nonce: nonce,
_sender: sender,
_target: _target,
_message: _message
});
assembly { assembly {
log0(add(data, 0x20), mload(data)) log0(add(data, 0x20), mload(data))
} }
...@@ -145,7 +163,14 @@ contract L2ToL2CrossDomainMessenger is IL2ToL2CrossDomainMessenger, ISemver, Tra ...@@ -145,7 +163,14 @@ contract L2ToL2CrossDomainMessenger is IL2ToL2CrossDomainMessenger, ISemver, Tra
revert MessageTargetL2ToL2CrossDomainMessenger(); revert MessageTargetL2ToL2CrossDomainMessenger();
} }
bytes32 messageHash = keccak256(abi.encode(_destination, _source, _nonce, _sender, _target, _message)); bytes32 messageHash = Hashing.hashL2toL2CrossDomainMessengerRelayMessage({
_destination: _destination,
_source: _source,
_nonce: _nonce,
_sender: _sender,
_target: _target,
_message: _message
});
if (successfulMessages[messageHash]) { if (successfulMessages[messageHash]) {
revert MessageAlreadyRelayed(); revert MessageAlreadyRelayed();
} }
......
...@@ -63,8 +63,8 @@ contract OptimismSuperchainERC20 is ...@@ -63,8 +63,8 @@ contract OptimismSuperchainERC20 is
} }
/// @notice Semantic version. /// @notice Semantic version.
/// @custom:semver 1.0.0-beta.3 /// @custom:semver 1.0.0-beta.4
string public constant version = "1.0.0-beta.3"; string public constant version = "1.0.0-beta.4";
/// @notice Constructs the OptimismSuperchainERC20 contract. /// @notice Constructs the OptimismSuperchainERC20 contract.
constructor() { constructor() {
......
...@@ -21,8 +21,8 @@ import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol"; ...@@ -21,8 +21,8 @@ import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol";
/// do not use a custom gas token. /// do not use a custom gas token.
contract SuperchainWETH is WETH98, ISuperchainERC20Extensions, ISemver { contract SuperchainWETH is WETH98, ISuperchainERC20Extensions, ISemver {
/// @notice Semantic version. /// @notice Semantic version.
/// @custom:semver 1.0.0-beta.4 /// @custom:semver 1.0.0-beta.5
string public constant version = "1.0.0-beta.4"; string public constant version = "1.0.0-beta.5";
/// @inheritdoc WETH98 /// @inheritdoc WETH98
function deposit() public payable override { function deposit() public payable override {
......
...@@ -32,7 +32,15 @@ interface IL2ToL2CrossDomainMessenger { ...@@ -32,7 +32,15 @@ interface IL2ToL2CrossDomainMessenger {
/// @param _destination Chain ID of the destination chain. /// @param _destination Chain ID of the destination chain.
/// @param _target Target contract or wallet address. /// @param _target Target contract or wallet address.
/// @param _message Message to trigger the target address with. /// @param _message Message to trigger the target address with.
function sendMessage(uint256 _destination, address _target, bytes calldata _message) external; /// @return msgHash_ The hash of the message being sent, which can be used for tracking whether
/// the message has successfully been relayed.
function sendMessage(
uint256 _destination,
address _target,
bytes calldata _message
)
external
returns (bytes32 msgHash_);
/// @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only /// @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only
/// be executed via cross-chain call from the other messenger OR if the message was /// be executed via cross-chain call from the other messenger OR if the message was
......
...@@ -121,4 +121,28 @@ library Hashing { ...@@ -121,4 +121,28 @@ library Hashing {
) )
); );
} }
/// @notice Generates a unique hash for a message to be relayed across chains. This hash is
/// used to identify the message and ensure it is not relayed more than once.
/// @param _destination Chain ID of the destination chain.
/// @param _source Chain ID of the source chain.
/// @param _nonce Unique nonce associated with the message to prevent replay attacks.
/// @param _sender Address of the user who originally sent the message.
/// @param _target Address of the contract or wallet that the message is targeting on the destination chain.
/// @param _message The message payload to be relayed to the target on the destination chain.
/// @return Hash of the encoded message parameters, used to uniquely identify the message.
function hashL2toL2CrossDomainMessengerRelayMessage(
uint256 _destination,
uint256 _source,
uint256 _nonce,
address _sender,
address _target,
bytes memory _message
)
internal
pure
returns (bytes32)
{
return keccak256(abi.encode(_destination, _source, _nonce, _sender, _target, _message));
}
} }
...@@ -7,6 +7,7 @@ import { Vm } from "forge-std/Vm.sol"; ...@@ -7,6 +7,7 @@ import { Vm } from "forge-std/Vm.sol";
// Libraries // Libraries
import { Predeploys } from "src/libraries/Predeploys.sol"; import { Predeploys } from "src/libraries/Predeploys.sol";
import { Hashing } from "src/libraries/Hashing.sol";
// Target contract // Target contract
import { import {
...@@ -90,7 +91,14 @@ contract L2ToL2CrossDomainMessengerTest is Test { ...@@ -90,7 +91,14 @@ contract L2ToL2CrossDomainMessengerTest is Test {
vm.recordLogs(); vm.recordLogs();
// Call the sendMessage function // Call the sendMessage function
l2ToL2CrossDomainMessenger.sendMessage({ _destination: _destination, _target: _target, _message: _message }); bytes32 msgHash =
l2ToL2CrossDomainMessenger.sendMessage({ _destination: _destination, _target: _target, _message: _message });
assertEq(
msgHash,
Hashing.hashL2toL2CrossDomainMessengerRelayMessage(
_destination, block.chainid, messageNonce, address(this), _target, _message
)
);
// Check that the event was emitted with the correct parameters // Check that the event was emitted with the correct parameters
Vm.Log[] memory logs = vm.getRecordedLogs(); Vm.Log[] memory logs = vm.getRecordedLogs();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment