diff --git a/op-node/rollup/derive/deposit_log.go b/op-node/rollup/derive/deposit_log.go index 74fde28c59882..ea4b39f1ff885 100644 --- a/op-node/rollup/derive/deposit_log.go +++ b/op-node/rollup/derive/deposit_log.go @@ -17,7 +17,8 @@ import ( var ( DepositEventABI = "TransactionDeposited(address,address,uint256,bytes)" DepositEventABIHash = crypto.Keccak256Hash([]byte(DepositEventABI)) - DepositEventVersion0 = common.Hash{} + DepositEventVersion0 = uint64(0) + DepositEventVersion1 = uint64(1) ) // UnmarshalDepositLogEvent decodes an EVM log entry emitted by the deposit contract into typed deposit data. @@ -27,7 +28,7 @@ var ( // event TransactionDeposited( // address indexed from, // address indexed to, -// uint256 indexed version, +// uint256 indexed nonceAndVersion, // bytes opaqueData // ); // @@ -51,7 +52,7 @@ func UnmarshalDepositLogEvent(ev *types.Log) (*types.DepositTx, error) { // indexed 1 to := common.BytesToAddress(ev.Topics[2][12:]) // indexed 2 - version := ev.Topics[3] + nonceAndVersion := ev.Topics[3] // unindexed data // Solidity serializes the event's Data field as follows: // abi.encode(abi.encodPacked(uint256 mint, uint256 value, uint64 gasLimit, uint8 isCreation, bytes data)) @@ -83,19 +84,38 @@ func UnmarshalDepositLogEvent(ev *types.Log) (*types.DepositTx, error) { dep.From = from dep.IsSystemTransaction = false + _, version := unpackNonceAndVersion(nonceAndVersion) + var err error switch version { case DepositEventVersion0: err = unmarshalDepositVersion0(&dep, to, opaqueData) + case DepositEventVersion1: + err = unmarshalDepositVersion1(&dep, to, opaqueData) default: - return nil, fmt.Errorf("invalid deposit version, got %s", version) + return nil, fmt.Errorf("invalid deposit version, got %d", version) } if err != nil { - return nil, fmt.Errorf("failed to decode deposit (version %s): %w", version, err) + return nil, fmt.Errorf("failed to decode deposit (version %d): %w", version, err) } return &dep, nil } +func unpackNonceAndVersion(nonceAndVersion common.Hash) (nonce uint64, version uint64) { + i := new(big.Int).SetBytes(nonceAndVersion[:]) + mask64 := new(big.Int).SetBytes(common.Hex2Bytes("ffffffffffffffff")) + version = mask64.And(mask64, i).Uint64() + nonce = i.Lsh(i, 128).Uint64() + return +} + +func packNonceAndVersion(nonce uint64, version uint64) common.Hash { + i := new(big.Int).SetUint64(nonce) + i.Rsh(i, 128) + i.Or(i, new(big.Int).SetUint64(version)) + return common.BytesToHash(i.Bytes()) +} + func unmarshalDepositVersion0(dep *types.DepositTx, to common.Address, opaqueData []byte) error { if len(opaqueData) < 32+32+8+1 { return fmt.Errorf("unexpected opaqueData length: %d", len(opaqueData)) @@ -140,6 +160,11 @@ func unmarshalDepositVersion0(dep *types.DepositTx, to common.Address, opaqueDat return nil } +func unmarshalDepositVersion1(dep *types.DepositTx, to common.Address, opaqueData []byte) error { + // version 1 simply adds a nonce; the rest is the same + return unmarshalDepositVersion0(dep, to, opaqueData) +} + // MarshalDepositLogEvent returns an EVM log entry that encodes a TransactionDeposited event from the deposit contract. // This is the reverse of the deposit transaction derivation. func MarshalDepositLogEvent(depositContractAddr common.Address, deposit *types.DepositTx) (*types.Log, error) { @@ -151,7 +176,7 @@ func MarshalDepositLogEvent(depositContractAddr common.Address, deposit *types.D DepositEventABIHash, eth.AddressAsLeftPaddedHash(deposit.From), toBytes, - DepositEventVersion0, + packNonceAndVersion(0, DepositEventVersion0), } data := make([]byte, 64, 64+3*32) diff --git a/op-node/rollup/derive/deposit_log_tob_test.go b/op-node/rollup/derive/deposit_log_tob_test.go index 49721104b0867..4dc04beaf28c3 100644 --- a/op-node/rollup/derive/deposit_log_tob_test.go +++ b/op-node/rollup/derive/deposit_log_tob_test.go @@ -188,13 +188,13 @@ func FuzzDeriveDepositsBadVersion(f *testing.F) { // Generate any topic but the deposit event versions we support. // TODO: As opposed to keeping this hardcoded, a method such as IsValidVersion(v) should be // used here. - badTopic := DepositEventVersion0 - for badTopic == DepositEventVersion0 { - typeProvider.Fuzz(&badTopic) + badVersion := DepositEventVersion0 + for badVersion == DepositEventVersion0 { + typeProvider.Fuzz(&badVersion) } // Set our bad topic and update our state - log.Topics[3] = badTopic + log.Topics[3] = packNonceAndVersion(0, badVersion) hasBadDepositVersion = true } } diff --git a/op-node/rollup/derive/system_config.go b/op-node/rollup/derive/system_config.go index 72c4e713c30e9..6c41b39d0b86e 100644 --- a/op-node/rollup/derive/system_config.go +++ b/op-node/rollup/derive/system_config.go @@ -27,7 +27,8 @@ var ( var ( ConfigUpdateEventABI = "ConfigUpdate(uint256,uint8,bytes)" ConfigUpdateEventABIHash = crypto.Keccak256Hash([]byte(ConfigUpdateEventABI)) - ConfigUpdateEventVersion0 = common.Hash{} + ConfigUpdateEventVersion0 = uint64(0) + ConfigUpdateEventVersion1 = uint64(1) ) // UpdateSystemConfigWithL1Receipts filters all L1 receipts to find config updates and applies the config updates to the given sysCfg @@ -53,7 +54,7 @@ func UpdateSystemConfigWithL1Receipts(sysCfg *eth.SystemConfig, receipts []*type // parse log data for: // // event ConfigUpdate( -// uint256 indexed version, +// uint256 indexed nonceAndVersion, // UpdateType indexed updateType, // bytes data // ); @@ -66,10 +67,14 @@ func ProcessSystemConfigUpdateLogEvent(destSysCfg *eth.SystemConfig, ev *types.L } // indexed 0 - version := ev.Topics[1] - if version != ConfigUpdateEventVersion0 { - return fmt.Errorf("unrecognized SystemConfig update event version: %s", version) + _, version := unpackNonceAndVersion(ev.Topics[1]) + switch version { + case ConfigUpdateEventVersion0: + case ConfigUpdateEventVersion1: + default: + return fmt.Errorf("unrecognized SystemConfig update event version: %d", version) } + // indexed 1 updateType := ev.Topics[2] diff --git a/op-node/rollup/derive/system_config_test.go b/op-node/rollup/derive/system_config_test.go index add1790938796..600b5df76ccbf 100644 --- a/op-node/rollup/derive/system_config_test.go +++ b/op-node/rollup/derive/system_config_test.go @@ -57,7 +57,7 @@ func TestProcessSystemConfigUpdateLogEvent(t *testing.T) { log: &types.Log{ Topics: []common.Hash{ ConfigUpdateEventABIHash, - ConfigUpdateEventVersion0, + packNonceAndVersion(0, ConfigUpdateEventVersion0), SystemConfigUpdateUnsafeBlockSigner, }, }, @@ -77,7 +77,7 @@ func TestProcessSystemConfigUpdateLogEvent(t *testing.T) { log: &types.Log{ Topics: []common.Hash{ ConfigUpdateEventABIHash, - ConfigUpdateEventVersion0, + packNonceAndVersion(0, ConfigUpdateEventVersion0), SystemConfigUpdateBatcher, }, }, @@ -101,7 +101,7 @@ func TestProcessSystemConfigUpdateLogEvent(t *testing.T) { log: &types.Log{ Topics: []common.Hash{ ConfigUpdateEventABIHash, - ConfigUpdateEventVersion0, + packNonceAndVersion(0, ConfigUpdateEventVersion0), SystemConfigUpdateFeeScalars, }, }, @@ -127,7 +127,7 @@ func TestProcessSystemConfigUpdateLogEvent(t *testing.T) { log: &types.Log{ Topics: []common.Hash{ ConfigUpdateEventABIHash, - ConfigUpdateEventVersion0, + packNonceAndVersion(0, ConfigUpdateEventVersion0), SystemConfigUpdateGasLimit, }, }, @@ -151,7 +151,7 @@ func TestProcessSystemConfigUpdateLogEvent(t *testing.T) { log: &types.Log{ Topics: []common.Hash{ ConfigUpdateEventABIHash, - ConfigUpdateEventVersion0, + packNonceAndVersion(0, ConfigUpdateEventVersion0), SystemConfigUpdateFeeScalars, }, }, @@ -191,7 +191,7 @@ func TestProcessSystemConfigUpdateLogEvent(t *testing.T) { log: &types.Log{ Topics: []common.Hash{ ConfigUpdateEventABIHash, - ConfigUpdateEventVersion0, + packNonceAndVersion(0, ConfigUpdateEventVersion0), SystemConfigUpdateEIP1559Params, }, }, diff --git a/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol b/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol index 74ba7b4790e95..580180c8aa385 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol @@ -38,7 +38,7 @@ interface IOptimismPortal2 { event DisputeGameBlacklisted(IDisputeGame indexed disputeGame); event Initialized(uint8 version); event RespectedGameTypeSet(GameType indexed newGameType, Timestamp indexed updatedAt); - event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); + event TransactionDeposited(address indexed from, address indexed to, uint256 indexed nonceAndVersion, bytes opaqueData); event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); event WithdrawalProvenExtension1(bytes32 indexed withdrawalHash, address indexed proofSubmitter); @@ -92,6 +92,7 @@ interface IOptimismPortal2 { function paused() external view returns (bool); function proofMaturityDelaySeconds() external view returns (uint256); function proofSubmitters(bytes32, uint256) external view returns (address); + function transactionDepositedNonce() external view returns (uint256); function proveWithdrawalTransaction( Types.WithdrawalTransaction memory _tx, uint256 _disputeGameIndex, diff --git a/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol b/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol index 58fe5eff5dcab..c24827cef2863 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol @@ -39,7 +39,7 @@ interface IOptimismPortalInterop { event DisputeGameBlacklisted(IDisputeGame indexed disputeGame); event Initialized(uint8 version); event RespectedGameTypeSet(GameType indexed newGameType, Timestamp indexed updatedAt); - event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); + event TransactionDeposited(address indexed from, address indexed to, uint256 indexed nonceAndVersion, bytes opaqueData); event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); event WithdrawalProvenExtension1(bytes32 indexed withdrawalHash, address indexed proofSubmitter); @@ -93,6 +93,7 @@ interface IOptimismPortalInterop { function paused() external view returns (bool); function proofMaturityDelaySeconds() external view returns (uint256); function proofSubmitters(bytes32, uint256) external view returns (address); + function transactionDepositedNonce() external view returns (uint256); function proveWithdrawalTransaction( Types.WithdrawalTransaction memory _tx, uint256 _disputeGameIndex, diff --git a/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol b/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol index 904375167f48d..3751b2c9a1d8d 100644 --- a/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol +++ b/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol @@ -23,7 +23,7 @@ interface ISystemConfig { address gasPayingToken; } - event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); + event ConfigUpdate(uint256 indexed nonceAndVersion, UpdateType indexed updateType, bytes data); event Initialized(uint8 version); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); @@ -45,6 +45,7 @@ interface ISystemConfig { function gasLimit() external view returns (uint64); function eip1559Denominator() external view returns (uint32); function eip1559Elasticity() external view returns (uint32); + function configUpdateNonce() external view returns (uint256); function gasPayingToken() external view returns (address addr_, uint8 decimals_); function gasPayingTokenName() external view returns (string memory name_); function gasPayingTokenSymbol() external view returns (string memory symbol_); diff --git a/packages/contracts-bedrock/interfaces/L1/ISystemConfigInterop.sol b/packages/contracts-bedrock/interfaces/L1/ISystemConfigInterop.sol index 4cf4a06f943fe..75a1329c5c09f 100644 --- a/packages/contracts-bedrock/interfaces/L1/ISystemConfigInterop.sol +++ b/packages/contracts-bedrock/interfaces/L1/ISystemConfigInterop.sol @@ -5,7 +5,7 @@ import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; interface ISystemConfigInterop { - event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data); + event ConfigUpdate(uint256 indexed nonceAndVersion, ISystemConfig.UpdateType indexed updateType, bytes data); event Initialized(uint8 version); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); @@ -27,6 +27,7 @@ interface ISystemConfigInterop { function gasLimit() external view returns (uint64); function eip1559Denominator() external view returns (uint32); function eip1559Elasticity() external view returns (uint32); + function configUpdateNonce() external view returns (uint256); function gasPayingToken() external view returns (address addr_, uint8 decimals_); function gasPayingTokenName() external view returns (string memory name_); function gasPayingTokenSymbol() external view returns (string memory symbol_); diff --git a/packages/contracts-bedrock/snapshots/.gas-snapshot b/packages/contracts-bedrock/snapshots/.gas-snapshot index f22930eef9226..1020bc65250c8 100644 --- a/packages/contracts-bedrock/snapshots/.gas-snapshot +++ b/packages/contracts-bedrock/snapshots/.gas-snapshot @@ -4,10 +4,10 @@ GasBenchMark_L1BlockInterop_SetValuesInterop:test_setL1BlockValuesInterop_benchm GasBenchMark_L1BlockInterop_SetValuesInterop_Warm:test_setL1BlockValuesInterop_benchmark() (gas: 5144) GasBenchMark_L1Block_SetValuesEcotone:test_setL1BlockValuesEcotone_benchmark() (gas: 158531) GasBenchMark_L1Block_SetValuesEcotone_Warm:test_setL1BlockValuesEcotone_benchmark() (gas: 7597) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369235) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967442) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 564429) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4076577) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 467041) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512790) -GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72667) \ No newline at end of file +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369292) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967499) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 564486) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4076634) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 466926) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512847) +GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72667) diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json index 2f52ed573d37c..7f148032b7ec0 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json @@ -669,6 +669,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "transactionDepositedNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "version", @@ -745,7 +758,7 @@ { "indexed": true, "internalType": "uint256", - "name": "version", + "name": "nonceAndVersion", "type": "uint256" }, { diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json index 5b9f72b9446c8..b6c958870f018 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json @@ -687,6 +687,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "transactionDepositedNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "version", @@ -763,7 +776,7 @@ { "indexed": true, "internalType": "uint256", - "name": "version", + "name": "nonceAndVersion", "type": "uint256" }, { diff --git a/packages/contracts-bedrock/snapshots/abi/SystemConfig.json b/packages/contracts-bedrock/snapshots/abi/SystemConfig.json index b7e18556fa2cb..0a6971f48a8de 100644 --- a/packages/contracts-bedrock/snapshots/abi/SystemConfig.json +++ b/packages/contracts-bedrock/snapshots/abi/SystemConfig.json @@ -186,6 +186,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "configUpdateNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "disputeGameFactory", @@ -750,7 +763,7 @@ { "indexed": true, "internalType": "uint256", - "name": "version", + "name": "nonceAndVersion", "type": "uint256" }, { diff --git a/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json b/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json index a459af15801b5..dc05995e7f816 100644 --- a/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json @@ -194,6 +194,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "configUpdateNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "dependencyManager", @@ -911,7 +924,7 @@ { "indexed": true, "internalType": "uint256", - "name": "version", + "name": "nonceAndVersion", "type": "uint256" }, { diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 42019379ded7d..2b6a8598c3e45 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -20,11 +20,11 @@ "sourceCodeHash": "0x05ed7ad68e4e9bca7334314e794a1f66e5899532bb01cfa3a7716cb2688df9d5" }, "src/L1/OptimismPortal2.sol": { - "initCodeHash": "0xfd14fd690752519064d6de6c3e15d69ec9146bc8714e56ac286305773dbb1533", - "sourceCodeHash": "0x3dbd4601c67a43c42f403f6b28e6e2d8bf4f3d2cf2f2d8f7460026e0c6c66def" + "initCodeHash": "0x27e3a366a587527da8711dcb4d9db7823957162bb6a5e440e312e2671ea69ff1", + "sourceCodeHash": "0xbf2942e32831d9cfeebd05b027061bddbc42a15d797a3c83da2104e8309f3da0" }, "src/L1/OptimismPortalInterop.sol": { - "initCodeHash": "0xc7a9282ef32425b65a647039908ea2b8d6ef231ba1b87c345c7b9f3f73acc240", + "initCodeHash": "0x22e59084c8fbac4a2bfce514223d7f4063f47d8fba2df2d2328eb315b070e0eb", "sourceCodeHash": "0x85e9f10ba1884b1a45737fd35ae4c2f9a9054f81a6aba08941ab7a95e74543da" }, "src/L1/ProtocolVersions.sol": { @@ -36,11 +36,11 @@ "sourceCodeHash": "0xafa784ea78818a382ff3a61e2d84be58c7978110c06b9273db68c0213ead02d3" }, "src/L1/SystemConfig.sol": { - "initCodeHash": "0xe1baf5d3415baf65a45031c37e4bd794ecb7f779b227f6cbed06d945aa2097fc", - "sourceCodeHash": "0x52b7d8825b4962e720513906ac993d36964cf03c45364c9f03d88507a0caac57" + "initCodeHash": "0x93d918bc4cb5a3046f0fd7a77b86d8e442b0498a5712acf920236c9db745203d", + "sourceCodeHash": "0xfd2e112013acd94aa426df3a0bea114f1294ef04368cee046aa039832c61ea69" }, "src/L1/SystemConfigInterop.sol": { - "initCodeHash": "0x91ed371ee2f6d4a9ed1483971df8a6888cc8b5aca5212b180e395476f21cb268", + "initCodeHash": "0xc84e909a540a9f48c5be831a87592e9518b3201105d89f6b095d3300a82366e3", "sourceCodeHash": "0x6a51dc1b2bfadd9781c729f8db70972926f364b0e605536fb075bfddd0d4c433" }, "src/L2/BaseFeeVault.sol": { diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json index 0fdd65b3e88fb..8a37c572a9049 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json @@ -124,5 +124,12 @@ "offset": 0, "slot": "61", "type": "uint256" + }, + { + "bytes": "32", + "label": "transactionDepositedNonce", + "offset": 0, + "slot": "62", + "type": "uint256" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json index 0fdd65b3e88fb..8a37c572a9049 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json @@ -124,5 +124,12 @@ "offset": 0, "slot": "61", "type": "uint256" + }, + { + "bytes": "32", + "label": "transactionDepositedNonce", + "offset": 0, + "slot": "62", + "type": "uint256" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/SystemConfig.json b/packages/contracts-bedrock/snapshots/storageLayout/SystemConfig.json index a6184a1f10dd5..366d1ebff85ad 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/SystemConfig.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/SystemConfig.json @@ -96,5 +96,12 @@ "offset": 4, "slot": "106", "type": "uint32" + }, + { + "bytes": "32", + "label": "configUpdateNonce", + "offset": 0, + "slot": "107", + "type": "uint256" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/SystemConfigInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/SystemConfigInterop.json index a6184a1f10dd5..366d1ebff85ad 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/SystemConfigInterop.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/SystemConfigInterop.json @@ -96,5 +96,12 @@ "offset": 4, "slot": "106", "type": "uint32" + }, + { + "bytes": "32", + "label": "configUpdateNonce", + "offset": 0, + "slot": "107", + "type": "uint256" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol index 10448f0b7fb65..c0758d7178493 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -71,7 +71,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { uint256 internal immutable DISPUTE_GAME_FINALITY_DELAY_SECONDS; /// @notice Version of the deposit event. - uint256 internal constant DEPOSIT_VERSION = 0; + uint256 internal constant DEPOSIT_VERSION = 1; /// @notice The L2 gas limit set when eth is deposited using the receive() function. uint64 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000; @@ -141,14 +141,19 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { /// It is not safe to trust `ERC20.balanceOf` as it may lie. uint256 internal _balance; + /// @notice Nonce incremented for each TransactionDeposited event + uint256 public transactionDepositedNonce; + /// @notice Emitted when a transaction is deposited from L1 to L2. /// The parameters of this event are read by the rollup node and used to derive deposit /// transactions on L2. - /// @param from Address that triggered the deposit transaction. - /// @param to Address that the deposit transaction is directed to. - /// @param version Version of this deposit transaction event. - /// @param opaqueData ABI encoded deposit data to be parsed off-chain. - event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); + /// @param from Address that triggered the deposit transaction. + /// @param to Address that the deposit transaction is directed to. + /// @param nonceAndVersion Nonce (first 128-bits) and version (second 128-bits). + /// @param opaqueData ABI encoded deposit data to be parsed off-chain. + event TransactionDeposited( + address indexed from, address indexed to, uint256 indexed nonceAndVersion, bytes opaqueData + ); /// @notice Emitted when a withdrawal transaction is proven. /// @param withdrawalHash Hash of the withdrawal transaction. @@ -183,9 +188,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { } /// @notice Semantic version. - /// @custom:semver 3.11.0-beta.9 + /// @custom:semver 3.11.0-beta.10 function version() public pure virtual returns (string memory) { - return "3.11.0-beta.9"; + return "3.11.0-beta.10"; } /// @notice Constructs the OptimismPortal contract. @@ -597,7 +602,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { // Emit a TransactionDeposited event so that the rollup node can derive a deposit // transaction for this deposit. - emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData); + _emitTransactionDeposited(from, _to, opaqueData); } /// @notice Sets the gas paying token for the L2 system. This token is used as the @@ -611,10 +616,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { // Emit the special deposit transaction directly that sets the gas paying // token in the L1Block predeploy contract. - emit TransactionDeposited( + _emitTransactionDeposited( Constants.DEPOSITOR_ACCOUNT, Predeploys.L1_BLOCK_ATTRIBUTES, - DEPOSIT_VERSION, abi.encodePacked( uint256(0), // mint uint256(0), // value @@ -625,6 +629,13 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ); } + /// @notice Emit a TransactionDeposited event and increment the nonce. + function _emitTransactionDeposited(address _from, address _to, bytes memory _opaqueData) internal { + uint256 _version = transactionDepositedNonce << 128 | DEPOSIT_VERSION; + transactionDepositedNonce++; + emit TransactionDeposited(_from, _to, _version, _opaqueData); + } + /// @notice Blacklists a dispute game. Should only be used in the event that a dispute game resolves incorrectly. /// @param _disputeGame Dispute game to blacklist. function blacklistDisputeGame(IDisputeGame _disputeGame) external { diff --git a/packages/contracts-bedrock/src/L1/SystemConfig.sol b/packages/contracts-bedrock/src/L1/SystemConfig.sol index 0b4562543d925..df5fcc80a96ad 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfig.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfig.sol @@ -49,7 +49,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { } /// @notice Version identifier, used for upgrades. - uint256 public constant VERSION = 0; + uint256 public constant VERSION = 1; /// @notice Storage slot that the unsafe block signer is stored at. /// Storing it at this deterministic storage slot allows for decoupling the storage @@ -130,16 +130,19 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { /// @notice The EIP-1559 elasticity multiplier. uint32 public eip1559Elasticity; + /// @notice Nonce incremented for each ConfigUpdate event + uint256 public configUpdateNonce; + /// @notice Emitted when configuration is updated. - /// @param version SystemConfig version. - /// @param updateType Type of update. - /// @param data Encoded update data. - event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); + /// @param nonceAndVersion Nonce (first 128-bits) and version (second 128-bits). + /// @param updateType Type of update. + /// @param data Encoded update data. + event ConfigUpdate(uint256 indexed nonceAndVersion, UpdateType indexed updateType, bytes data); /// @notice Semantic version. - /// @custom:semver 2.3.0-beta.9 + /// @custom:semver 2.3.0-beta.10 function version() public pure virtual returns (string memory) { - return "2.3.0-beta.9"; + return "2.3.0-beta.10"; } /// @notice Constructs the SystemConfig contract. @@ -323,7 +326,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { Storage.setAddress(UNSAFE_BLOCK_SIGNER_SLOT, _unsafeBlockSigner); bytes memory data = abi.encode(_unsafeBlockSigner); - emit ConfigUpdate(VERSION, UpdateType.UNSAFE_BLOCK_SIGNER, data); + _emitConfigUpdate(UpdateType.UNSAFE_BLOCK_SIGNER, data); } /// @notice Updates the batcher hash. Can only be called by the owner. @@ -338,7 +341,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { batcherHash = _batcherHash; bytes memory data = abi.encode(_batcherHash); - emit ConfigUpdate(VERSION, UpdateType.BATCHER, data); + _emitConfigUpdate(UpdateType.BATCHER, data); } /// @notice Updates gas config. Can only be called by the owner. @@ -359,7 +362,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { scalar = _scalar; bytes memory data = abi.encode(_overhead, _scalar); - emit ConfigUpdate(VERSION, UpdateType.FEE_SCALARS, data); + _emitConfigUpdate(UpdateType.FEE_SCALARS, data); } /// @notice Updates gas config as of the Ecotone upgrade. Can only be called by the owner. @@ -379,7 +382,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { scalar = (uint256(0x01) << 248) | (uint256(_blobbasefeeScalar) << 32) | _basefeeScalar; bytes memory data = abi.encode(overhead, scalar); - emit ConfigUpdate(VERSION, UpdateType.FEE_SCALARS, data); + _emitConfigUpdate(UpdateType.FEE_SCALARS, data); } /// @notice Updates the L2 gas limit. Can only be called by the owner. @@ -396,7 +399,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { gasLimit = _gasLimit; bytes memory data = abi.encode(_gasLimit); - emit ConfigUpdate(VERSION, UpdateType.GAS_LIMIT, data); + _emitConfigUpdate(UpdateType.GAS_LIMIT, data); } /// @notice Updates the EIP-1559 parameters of the chain. Can only be called by the owner. @@ -415,7 +418,14 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { eip1559Elasticity = _elasticity; bytes memory data = abi.encode(uint256(_denominator) << 32 | uint64(_elasticity)); - emit ConfigUpdate(VERSION, UpdateType.EIP_1559_PARAMS, data); + _emitConfigUpdate(UpdateType.EIP_1559_PARAMS, data); + } + + /// @notice Emit a ConfigUpdate event and increment the nonce. + function _emitConfigUpdate(UpdateType _updateType, bytes memory _data) internal { + uint256 _version = configUpdateNonce << 128 | VERSION; + configUpdateNonce++; + emit ConfigUpdate(_version, _updateType, _data); } /// @notice Sets the start block in a backwards compatible way. Proxies diff --git a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol index c3e80183c6eb6..ede3e08e25043 100644 --- a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol @@ -225,7 +225,7 @@ contract PreBridgeETH is CommonTest { assertEq(address(optimismPortal2).balance, 0); } uint256 nonce = l1CrossDomainMessenger.messageNonce(); - uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION + uint256 version = 1; // Internal constant in the OptimismPortal: DEPOSIT_VERSION address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); bytes memory message = abi.encodeCall(StandardBridge.finalizeBridgeETH, (alice, alice, value, hex"dead")); @@ -356,7 +356,7 @@ contract PreBridgeETHTo is CommonTest { /// address depending on whether the bridge call is legacy or not. function _preBridgeETHTo(bool isLegacy, uint256 value) internal { uint256 nonce = l1CrossDomainMessenger.messageNonce(); - uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION + uint256 version = 1; // Internal constant in the OptimismPortal: DEPOSIT_VERSION address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); if (isLegacy) { @@ -506,7 +506,7 @@ contract L1StandardBridge_DepositERC20_Test is CommonTest { /// Only EOA can call depositERC20. function test_depositERC20_succeeds() external { uint256 nonce = l1CrossDomainMessenger.messageNonce(); - uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION + uint256 version = 1; // Internal constant in the OptimismPortal: DEPOSIT_VERSION address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); // Deal Alice's ERC20 State @@ -589,7 +589,7 @@ contract L1StandardBridge_DepositERC20To_Test is CommonTest { /// Contracts can call depositERC20. function test_depositERC20To_succeeds() external { uint256 nonce = l1CrossDomainMessenger.messageNonce(); - uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION + uint256 version = 1; // Internal constant in the OptimismPortal: DEPOSIT_VERSION address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); bytes memory message = abi.encodeCall( diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol index 19ff94552fc17..ce9e1b282e315 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -325,7 +325,7 @@ contract OptimismPortal2_Test is CommonTest { emit TransactionDeposited( 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001, Predeploys.L1_BLOCK_ATTRIBUTES, - 0, + 1, abi.encodePacked( uint256(0), // mint uint256(0), // value @@ -383,12 +383,15 @@ contract OptimismPortal2_Test is CommonTest { VmSafe.Log memory systemPath = logs[0]; VmSafe.Log memory userPath = logs[1]; + // nonce is incremented, copy it + bytes32 systemPathVersion = bytes32(uint256(systemPath.topics[3]) | 1 << 128); + assertEq(systemPath.topics.length, 4); assertEq(systemPath.topics.length, userPath.topics.length); - assertEq(systemPath.topics[0], userPath.topics[0]); - assertEq(systemPath.topics[1], userPath.topics[1]); - assertEq(systemPath.topics[2], userPath.topics[2]); - assertEq(systemPath.topics[3], userPath.topics[3]); + assertEq(systemPath.topics[0], userPath.topics[0]); // address + assertEq(systemPath.topics[1], userPath.topics[1]); // from + assertEq(systemPath.topics[2], userPath.topics[2]); // to + assertEq(systemPathVersion, userPath.topics[3]); // nonceAndVersion assertEq(systemPath.data, userPath.data); } @@ -1821,7 +1824,7 @@ contract OptimismPortal2WithMockERC20_Test is OptimismPortal2_FinalizeWithdrawal emit TransactionDeposited( _from, // from _to, - uint256(0), // DEPOSIT_VERSION + uint256(1), // DEPOSIT_VERSION opaqueData ); @@ -2056,7 +2059,7 @@ contract OptimismPortal2WithMockERC20_Test is OptimismPortal2_FinalizeWithdrawal emit TransactionDeposited( _from, // from _to, - uint256(0), // DEPOSIT_VERSION + uint256(1), // DEPOSIT_VERSION opaqueData ); diff --git a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol index af96c0cce9017..a0afd600ff405 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol @@ -18,7 +18,7 @@ import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { IL1Block } from "interfaces/L2/IL1Block.sol"; contract SystemConfig_Init is CommonTest { - event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data); + event ConfigUpdate(uint256 indexed nonceAndVersion, ISystemConfig.UpdateType indexed updateType, bytes data); } contract SystemConfig_Initialize_Test is SystemConfig_Init { @@ -485,7 +485,7 @@ contract SystemConfig_Init_CustomGasToken is SystemConfig_Init { emit TransactionDeposited( 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001, Predeploys.L1_BLOCK_ATTRIBUTES, - 0, // deposit version + 1 << 128 | 1, // deposit version abi.encodePacked( uint256(0), // mint uint256(0), // value @@ -588,7 +588,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { /// @dev Tests that `setBatcherHash` updates the batcher hash successfully. function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external { vm.expectEmit(address(systemConfig)); - emit ConfigUpdate(0, ISystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash)); + emit ConfigUpdate(3 << 128 | 1, ISystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash)); vm.prank(systemConfig.owner()); systemConfig.setBatcherHash(newBatcherHash); @@ -600,7 +600,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { // always zero out most significant byte newScalar = (newScalar << 16) >> 16; vm.expectEmit(address(systemConfig)); - emit ConfigUpdate(0, ISystemConfig.UpdateType.FEE_SCALARS, abi.encode(newOverhead, newScalar)); + emit ConfigUpdate(3 << 128 | 1, ISystemConfig.UpdateType.FEE_SCALARS, abi.encode(newOverhead, newScalar)); vm.prank(systemConfig.owner()); systemConfig.setGasConfig(newOverhead, newScalar); @@ -615,7 +615,9 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { ffi.encodeScalarEcotone({ _basefeeScalar: _basefeeScalar, _blobbasefeeScalar: _blobbasefeeScalar }); vm.expectEmit(address(systemConfig)); - emit ConfigUpdate(0, ISystemConfig.UpdateType.FEE_SCALARS, abi.encode(systemConfig.overhead(), encoded)); + emit ConfigUpdate( + 3 << 128 | 1, ISystemConfig.UpdateType.FEE_SCALARS, abi.encode(systemConfig.overhead(), encoded) + ); vm.prank(systemConfig.owner()); systemConfig.setGasConfigEcotone({ _basefeeScalar: _basefeeScalar, _blobbasefeeScalar: _blobbasefeeScalar }); @@ -635,7 +637,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { newGasLimit = uint64(bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(maximumGasLimit))); vm.expectEmit(address(systemConfig)); - emit ConfigUpdate(0, ISystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit)); + emit ConfigUpdate(3 << 128 | 1, ISystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit)); vm.prank(systemConfig.owner()); systemConfig.setGasLimit(newGasLimit); @@ -645,7 +647,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { /// @dev Tests that `setUnsafeBlockSigner` updates the block signer successfully. function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external { vm.expectEmit(address(systemConfig)); - emit ConfigUpdate(0, ISystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER, abi.encode(newUnsafeSigner)); + emit ConfigUpdate(3 << 128 | 1, ISystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER, abi.encode(newUnsafeSigner)); vm.prank(systemConfig.owner()); systemConfig.setUnsafeBlockSigner(newUnsafeSigner); @@ -661,7 +663,9 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { vm.expectEmit(address(systemConfig)); emit ConfigUpdate( - 0, ISystemConfig.UpdateType.EIP_1559_PARAMS, abi.encode(uint256(_denominator) << 32 | uint64(_elasticity)) + 3 << 128 | 1, + ISystemConfig.UpdateType.EIP_1559_PARAMS, + abi.encode(uint256(_denominator) << 32 | uint64(_elasticity)) ); vm.prank(systemConfig.owner()); diff --git a/packages/contracts-bedrock/test/setup/CommonTest.sol b/packages/contracts-bedrock/test/setup/CommonTest.sol index d04b3f1ac0220..5d3d56427d1eb 100644 --- a/packages/contracts-bedrock/test/setup/CommonTest.sol +++ b/packages/contracts-bedrock/test/setup/CommonTest.sol @@ -168,7 +168,7 @@ contract CommonTest is Test, Setup, Events { ) internal { - emit TransactionDeposited(_from, _to, 0, abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data)); + emit TransactionDeposited(_from, _to, 1, abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data)); } function enableLegacyContracts() public { diff --git a/packages/contracts-bedrock/test/setup/Events.sol b/packages/contracts-bedrock/test/setup/Events.sol index 7056f0cbdd6b0..d79e3cdba1363 100644 --- a/packages/contracts-bedrock/test/setup/Events.sol +++ b/packages/contracts-bedrock/test/setup/Events.sol @@ -13,7 +13,9 @@ import { Types } from "src/libraries/Types.sol"; contract Events { /// @dev OpenZeppelin Ownable.sol transferOwnership event event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); + event TransactionDeposited( + address indexed from, address indexed to, uint256 indexed nonceAndVersion, bytes opaqueData + ); event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); diff --git a/packages/contracts-bedrock/test/universal/Specs.t.sol b/packages/contracts-bedrock/test/universal/Specs.t.sol index 14dcbc9bc884d..8022028c94e03 100644 --- a/packages/contracts-bedrock/test/universal/Specs.t.sol +++ b/packages/contracts-bedrock/test/universal/Specs.t.sol @@ -261,6 +261,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("respectedGameTypeUpdatedAt()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("proofSubmitters(bytes32,uint256)") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("numProofSubmitters(bytes32)") }); + _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("transactionDepositedNonce()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("balance()") }); _addSpec({ _name: "OptimismPortalInterop", @@ -313,6 +314,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OptimismPortal2", _sel: _getSel("respectedGameTypeUpdatedAt()") }); _addSpec({ _name: "OptimismPortal2", _sel: _getSel("proofSubmitters(bytes32,uint256)") }); _addSpec({ _name: "OptimismPortal2", _sel: _getSel("numProofSubmitters(bytes32)") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("transactionDepositedNonce()") }); _addSpec({ _name: "OptimismPortal2", _sel: _getSel("balance()") }); _addSpec({ _name: "OptimismPortal2", @@ -363,6 +365,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "SystemConfig", _sel: _getSel("gasLimit()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("eip1559Denominator()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("eip1559Elasticity()") }); + _addSpec({ _name: "SystemConfig", _sel: _getSel("configUpdateNonce()") }); _addSpec({ _name: "SystemConfig", _sel: ISystemConfig.initialize.selector }); _addSpec({ _name: "SystemConfig", _sel: ISystemConfig.minimumGasLimit.selector }); _addSpec({ _name: "SystemConfig", _sel: _getSel("overhead()") }); @@ -418,6 +421,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("gasLimit()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("eip1559Denominator()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("eip1559Elasticity()") }); + _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("configUpdateNonce()") }); _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.initialize.selector }); _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.initialize.selector }); _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.minimumGasLimit.selector });