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