Commit b6af4279 authored by Kelvin Fichter's avatar Kelvin Fichter

feat(ctb): add message versioning to MessagePasser

Adds message versioning to the L2ToL1MessagePasser, using the same
scheme as in the CrossDomainMessenger. Also renames the "nonce" variable
to "messageNonce" in line with the naming within the
CrossDomainMessenger contracts.
parent f6cdc1d9
This diff is collapsed.
......@@ -4,7 +4,6 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"math/big"
"os"
"path/filepath"
......@@ -327,11 +326,8 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
return storage, errors.New("block base fee not set")
}
// Set the initial L2ToL1MessagePasser nonce to
// `type(uint32).max` to prevent nonce collisions
// with historical withdrawals.
storage["L2ToL1MessagePasser"] = state.StorageValues{
"nonce": math.MaxUint32,
"msgNonce": 0,
}
storage["L2CrossDomainMessenger"] = state.StorageValues{
"_initialized": 1,
......
......@@ -81,8 +81,8 @@ L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 53204)
L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 36172)
L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageV0Fails() (gas: 18870)
L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41596)
L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 122423)
L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 134632)
L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 122533)
L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 134716)
L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10568)
L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 52615)
L2OutputOracleTest:testCannot_ProposeWithUnmatchedBlockhash() (gas: 29434)
......@@ -118,13 +118,13 @@ L2StandardBridge_Test:test_finalizeBridgeETH_sendToMessengerReverts() (gas: 2396
L2StandardBridge_Test:test_finalizeBridgeETH_sendToSelfReverts() (gas: 23793)
L2StandardBridge_Test:test_finalizeDeposit() (gas: 89363)
L2StandardBridge_Test:test_initialize() (gas: 10536)
L2StandardBridge_Test:test_receive() (gas: 131820)
L2StandardBridge_Test:test_withdraw() (gas: 343951)
L2StandardBridge_Test:test_withdrawTo() (gas: 344680)
L2StandardBridge_Test:test_receive() (gas: 131862)
L2StandardBridge_Test:test_withdraw() (gas: 343984)
L2StandardBridge_Test:test_withdrawTo() (gas: 344713)
L2StandardBridge_Test:test_withdraw_onlyEOA() (gas: 251816)
L2ToL1MessagePasserTest:test_burn() (gas: 112530)
L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 70246)
L2ToL1MessagePasserTest:test_initiateWithdrawal_fromEOA() (gas: 75764)
L2ToL1MessagePasserTest:test_burn() (gas: 112594)
L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 70356)
L2ToL1MessagePasserTest:test_initiateWithdrawal_fromEOA() (gas: 75874)
LegacyERC20ETH_Test:test_approve() (gas: 10723)
LegacyERC20ETH_Test:test_burn() (gas: 10615)
LegacyERC20ETH_Test:test_crossDomain() (gas: 6339)
......@@ -293,4 +293,4 @@ SequencerFeeVault_Test:test_constructor() (gas: 5459)
SequencerFeeVault_Test:test_minWithdrawalAmount() (gas: 5418)
SequencerFeeVault_Test:test_receive() (gas: 17316)
SequencerFeeVault_Test:test_revertWithdraw() (gas: 9343)
SequencerFeeVault_Test:test_withdraw() (gas: 135837)
SequencerFeeVault_Test:test_withdraw() (gas: 135879)
......@@ -256,7 +256,7 @@
+============================================================================================================================+
| sentMessages | mapping(bytes32 => bool) | 0 | 0 | 32 | contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser |
|--------------+--------------------------+------+--------+-------+----------------------------------------------------------|
| nonce | uint256 | 1 | 0 | 32 | contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser |
| msgNonce | uint240 | 1 | 0 | 30 | contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser |
+--------------+--------------------------+------+--------+-------+----------------------------------------------------------+
=======================
......
......@@ -3,6 +3,7 @@ pragma solidity 0.8.15;
import { Types } from "../libraries/Types.sol";
import { Hashing } from "../libraries/Hashing.sol";
import { Encoding } from "../libraries/Encoding.sol";
import { Burn } from "../libraries/Burn.sol";
import { Semver } from "../universal/Semver.sol";
......@@ -20,6 +21,11 @@ contract L2ToL1MessagePasser is Semver {
*/
uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;
/**
* @notice Current message version identifier.
*/
uint16 public constant MESSAGE_VERSION = 1;
/**
* @notice Includes the message hashes for all withdrawals
*/
......@@ -28,7 +34,7 @@ contract L2ToL1MessagePasser is Semver {
/**
* @notice A unique value hashed with each withdrawal.
*/
uint256 public nonce;
uint240 internal msgNonce;
/**
* @notice Emitted any time a withdrawal is initiated.
......@@ -37,7 +43,7 @@ contract L2ToL1MessagePasser is Semver {
* @param sender The L2 account address which initiated the withdrawal.
* @param target The L1 account address the call will be send to.
* @param value The ETH value submitted for withdrawal, to be forwarded to the target.
* @param gasLimit The minimum amount of gas that must be provided when withdrawing on L1.
* @param gasLimit The minimum amount of gas that must be provided when withdrawing.
* @param data The data to be forwarded to the target on L1.
* @param withdrawalHash The hash of the withdrawal.
*/
......@@ -96,7 +102,7 @@ contract L2ToL1MessagePasser is Semver {
) public payable {
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
nonce: nonce,
nonce: messageNonce(),
sender: msg.sender,
target: _target,
value: msg.value,
......@@ -107,9 +113,29 @@ contract L2ToL1MessagePasser is Semver {
sentMessages[withdrawalHash] = true;
emit MessagePassed(nonce, msg.sender, _target, msg.value, _gasLimit, _data, withdrawalHash);
emit MessagePassed(
messageNonce(),
msg.sender,
_target,
msg.value,
_gasLimit,
_data,
withdrawalHash
);
unchecked {
++nonce;
++msgNonce;
}
}
/**
* @notice Retrieves the next message nonce. Message version will be added to the upper two
* bytes of the message nonce. Message version allows us to treat messages as having
* different structures.
*
* @return Nonce of the next message to be sent, with added message version.
*/
function messageNonce() public view returns (uint256) {
return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);
}
}
......@@ -58,7 +58,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
// MessagePassed event
vm.expectEmit(true, true, true, true);
emit MessagePassed(
messagePasser.nonce(),
messagePasser.messageNonce(),
address(L2Messenger),
address(L1Messenger),
0,
......@@ -66,7 +66,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
xDomainCallData,
Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
nonce: messagePasser.nonce(),
nonce: messagePasser.messageNonce(),
sender: address(L2Messenger),
target: address(L1Messenger),
value: 0,
......
......@@ -32,7 +32,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
uint256 _gasLimit,
bytes memory _data
) external {
uint256 nonce = messagePasser.nonce();
uint256 nonce = messagePasser.messageNonce();
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
......@@ -63,7 +63,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
function test_initiateWithdrawal_fromContract() external {
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction(
messagePasser.nonce(),
messagePasser.messageNonce(),
address(this),
address(4),
100,
......@@ -74,7 +74,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
vm.expectEmit(true, true, true, true);
emit MessagePassed(
messagePasser.nonce(),
messagePasser.messageNonce(),
address(this),
address(4),
100,
......@@ -93,7 +93,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
address target = address(4);
uint256 value = 100;
bytes memory data = hex"ff";
uint256 nonce = messagePasser.nonce();
uint256 nonce = messagePasser.messageNonce();
// EOA emulation
vm.prank(alice, alice);
......@@ -110,7 +110,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
// the sent messages mapping is filled
assertEq(messagePasser.sentMessages(withdrawalHash), true);
// the nonce increments
assertEq(nonce + 1, messagePasser.nonce());
assertEq(nonce + 1, messagePasser.messageNonce());
}
// Test: burn should destroy the ETH held in the contract
......
......@@ -814,7 +814,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// Total ETH supply is currently about 120M ETH.
uint256 value = bound(_value, 0, 200_000_000 ether);
uint256 gasLimit = bound(_gasLimit, 0, 50_000_000);
uint256 nonce = messagePasser.nonce();
uint256 nonce = messagePasser.messageNonce();
Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({
nonce: nonce,
sender: _sender,
......
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