Commit 3659a097 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge pull request #4135 from ethereum-optimism/sc/ctb-mp-versioned-nonce

feat(ctb): add message versioning to MessagePasser
parents df47e202 b6af4279
This diff is collapsed.
......@@ -4,7 +4,6 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"math/big"
"os"
"path/filepath"
......@@ -339,11 +338,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