From 7c14012ff5bcf98c2d14361ed5983723f7313a30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Nov 2025 12:58:46 +0100 Subject: [PATCH 1/7] feat: upgrade L1GasOracle predeploy in GalileoV2 upgrade --- .../scroll/alloy/evm/src/block/galileo_v2.rs | 249 ++++++++++++++++++ crates/scroll/alloy/evm/src/block/mod.rs | 16 ++ crates/scroll/alloy/evm/src/lib.rs | 4 +- crates/scroll/alloy/evm/src/tx/compression.rs | 8 + crates/scroll/alloy/hardforks/src/hardfork.rs | 10 +- crates/scroll/alloy/hardforks/src/lib.rs | 6 + crates/scroll/chainspec/src/genesis.rs | 8 +- crates/scroll/chainspec/src/lib.rs | 14 + crates/scroll/evm/src/execute.rs | 33 ++- crates/scroll/evm/src/lib.rs | 5 + 10 files changed, 346 insertions(+), 7 deletions(-) create mode 100644 crates/scroll/alloy/evm/src/block/galileo_v2.rs diff --git a/crates/scroll/alloy/evm/src/block/galileo_v2.rs b/crates/scroll/alloy/evm/src/block/galileo_v2.rs new file mode 100644 index 00000000000..95138c4cc47 --- /dev/null +++ b/crates/scroll/alloy/evm/src/block/galileo_v2.rs @@ -0,0 +1,249 @@ +//! GalileoV2 fork transition for Scroll. + +use alloc::vec; +use revm::{ + bytecode::Bytecode, + database::{states::StorageSlot, State}, + primitives::{bytes, Bytes, U256}, + state::AccountInfo, + Database, +}; + +use super::curie::L1_GAS_PRICE_ORACLE_ADDRESS; + +/// Bytecode of L1GasPriceOracle at GalileoV2 transition. +/// Run these commands in the scroll-contracts repo to verify this bytecode: +/// +/// git checkout dfffa0f04bbd1de31ef342e1642a2f9ad9a620fe +/// yarn +/// forge build +/// cat artifacts/src/L1GasPriceOracle.sol/L1GasPriceOracle.json | jq -r .deployedBytecode.object +const GALILEO_V2_L1_GAS_PRICE_ORACLE_BYTECODE: Bytes = bytes!("608060405234801561000f575f80fd5b50600436106101c6575f3560e01c8063715018a6116100fe578063bede39b51161009e578063e88a60ad1161006e578063e88a60ad1461035d578063f2fde38b14610370578063f45e65d814610383578063fe5b04151461038c575f80fd5b8063bede39b51461031c578063c63b9e2d1461032f578063c91e514914610342578063de26c4a11461034a575f80fd5b80638da5cb5b116100d95780638da5cb5b146102c457806393e59dc1146102ee578063944b247f14610301578063a911d77f14610314575f80fd5b8063715018a6146102ab5780637f977cbf146102b357806384189161146102bb575f80fd5b80633d0f963e116101695780635471db39116101445780635471db391461027d5780636112d6db146102865780636a5e67e51461028f5780637046559714610298575f80fd5b80633d0f963e1461024e57806349948e0e14610261578063519b4bd314610274575f80fd5b806323e524ac116101a457806323e524ac146102105780633577afc51461021957806339455d3a1461022e5780633b7656bb14610241575f80fd5b80630c18c162146101ca5780630f337f6d146101e657806313dad5be14610203575b5f80fd5b6101d360025481565b6040519081526020015b60405180910390f35b600c546101f39060ff1681565b60405190151581526020016101dd565b6008546101f39060ff1681565b6101d360065481565b61022c610227366004610ccf565b610394565b005b61022c61023c366004610ce6565b610426565b600b546101f39060ff1681565b61022c61025c366004610d06565b610523565b6101d361026f366004610d47565b6105a6565b6101d360015481565b6101d360095481565b6101d3600a5481565b6101d360075481565b61022c6102a6366004610ccf565b6105f3565b61022c610681565b61022c6106b5565b6101d360055481565b5f546102d6906001600160a01b031681565b6040516001600160a01b0390911681526020016101dd565b6004546102d6906001600160a01b031681565b61022c61030f366004610ccf565b610711565b61022c61079d565b61022c61032a366004610ccf565b6107f9565b61022c61033d366004610ccf565b6108b6565b6009546101d3565b6101d3610358366004610d47565b610933565b61022c61036b366004610ccf565b61096a565b61022c61037e366004610d06565b6109f6565b6101d360035481565b61022c610a81565b5f546001600160a01b031633146103c65760405162461bcd60e51b81526004016103bd90610df2565b60405180910390fd5b621c9c388111156103ea57604051635742c80560e11b815260040160405180910390fd5b60028190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa15801561046d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104919190610e29565b6104ae576040516326b3506d60e11b815260040160405180910390fd5b600182905560058190556040518281527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200160405180910390a16040518181527f9a14bfb5d18c4c3cf14cae19c23d7cf1bcede357ea40ca1f75cd49542c71c214906020015b60405180910390a15050565b5f546001600160a01b0316331461054c5760405162461bcd60e51b81526004016103bd90610df2565b600480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f22d1c35fe072d2e42c3c8f9bd4a0d34aa84a0101d020a62517b33fdb3174e5f79101610517565b600c545f9060ff16156105c2576105bc82610add565b92915050565b600b5460ff16156105d6576105bc82610b55565b60085460ff16156105ea576105bc82610bb3565b6105bc82610bef565b5f546001600160a01b0316331461061c5760405162461bcd60e51b81526004016103bd90610df2565b61062c633b9aca006103e8610e5c565b81111561064c57604051631e44fdeb60e11b815260040160405180910390fd5b60038190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a9060200161041b565b5f546001600160a01b031633146106aa5760405162461bcd60e51b81526004016103bd90610df2565b6106b35f610c20565b565b5f546001600160a01b031633146106de5760405162461bcd60e51b81526004016103bd90610df2565b600c5460ff16156107025760405163182389a760e01b815260040160405180910390fd5b600c805460ff19166001179055565b5f546001600160a01b0316331461073a5760405162461bcd60e51b81526004016103bd90610df2565b610748633b9aca0080610e5c565b8111156107685760405163874f603160e01b815260040160405180910390fd5b60068190556040518181527f2ab3f5a4ebbcbf3c24f62f5454f52f10e1a8c9dcc5acac8f19199ce881a6a1089060200161041b565b5f546001600160a01b031633146107c65760405162461bcd60e51b81526004016103bd90610df2565b60085460ff16156107ea576040516379f9c57560e01b815260040160405180910390fd5b6008805460ff19166001179055565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa158015610840573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108649190610e29565b610881576040516326b3506d60e11b815260040160405180910390fd5b60018190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200161041b565b5f546001600160a01b031633146108df5760405162461bcd60e51b81526004016103bd90610df2565b805f036108fe5760405162ae184360e01b815260040160405180910390fd5b600a8190556040518181527f8647cebb7e57360673a28415c0bed2f68c42a86c5035f1c9b2eda2b09509288a9060200161041b565b600c545f9060ff16806109485750600b5460ff165b80610955575060085460ff165b1561096157505f919050565b6105bc82610c6f565b5f546001600160a01b031633146109935760405162461bcd60e51b81526004016103bd90610df2565b6109a1633b9aca0080610e5c565b8111156109c15760405163f37ec21560e01b815260040160405180910390fd5b60078190556040518181527f6b332a036d8c3ead57dcb06c87243bd7a2aed015ddf2d0528c2501dae56331aa9060200161041b565b5f546001600160a01b03163314610a1f5760405162461bcd60e51b81526004016103bd90610df2565b6001600160a01b038116610a755760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f206164647265737300000060448201526064016103bd565b610a7e81610c20565b50565b5f546001600160a01b03163314610aaa5760405162461bcd60e51b81526004016103bd90610df2565b600b5460ff1615610ace57604051631a7c228b60e21b815260040160405180910390fd5b600b805460ff19166001179055565b5f808251600554600754610af19190610e5c565b600154600654610b019190610e5c565b610b0b9190610e73565b610b159190610e5c565b90505f600a54845183610b289190610e5c565b610b329190610e86565b9050633b9aca00610b438284610e73565b610b4d9190610e86565b949350505050565b5f633b9aca0080600a548451600554600754610b719190610e5c565b600154600654610b819190610e5c565b610b8b9190610e73565b610b959190610e5c565b610b9f9190610e5c565b610ba99190610e86565b6105bc9190610e86565b5f633b9aca006005548351600754610bcb9190610e5c565b610bd59190610e5c565b600154600654610be59190610e5c565b610ba99190610e73565b5f80610bfa83610c6f565b90505f60015482610c0b9190610e5c565b9050633b9aca0060035482610b439190610e5c565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80515f908190815b81811015610cc057848181518110610c9157610c91610ea5565b01602001516001600160f81b0319165f03610cb157600483019250610cb8565b6010830192505b600101610c77565b50506002540160400192915050565b5f60208284031215610cdf575f80fd5b5035919050565b5f8060408385031215610cf7575f80fd5b50508035926020909101359150565b5f60208284031215610d16575f80fd5b81356001600160a01b0381168114610d2c575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610d57575f80fd5b813567ffffffffffffffff80821115610d6e575f80fd5b818401915084601f830112610d81575f80fd5b813581811115610d9357610d93610d33565b604051601f8201601f19908116603f01168101908382118183101715610dbb57610dbb610d33565b81604052828152876020848701011115610dd3575f80fd5b826020860160208301375f928101602001929092525095945050505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b5f60208284031215610e39575f80fd5b81518015158114610d2c575f80fd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176105bc576105bc610e48565b808201808211156105bc576105bc610e48565b5f82610ea057634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffdfea164736f6c6343000818000a"); + +/// L1 gas price oracle "is Galileo" slot. Added in the GalileoV2 fork. +pub const IS_GALILEO_SLOT: U256 = U256::from_limbs([12, 0, 0, 0]); + +/// Galileo slot is set to 1 (true) after the GalileoV2 block fork. +const IS_GALILEO: U256 = U256::from_limbs([1, 0, 0, 0]); + +/// Storage update of L1 gas price oracle at Feynman transition. +const GALILEO_V2_L1_GAS_PRICE_ORACLE_STORAGE: [(U256, U256); 1] = [(IS_GALILEO_SLOT, IS_GALILEO)]; + +/// Applies the Scroll GalileoV2 hard fork to the state: +/// - Updates the L1 oracle contract bytecode. +/// - Sets the `isGalileo` slot to 1 (true). +pub(super) fn apply_galileo_v2_hard_fork( + state: &mut State, +) -> Result<(), DB::Error> { + // No-op if already applied. + // Note: This requires a storage read for every Feynman block, and it means this + // read needs to be included in the execution witness. Unfortunately, there is no + // other reliable way to apply the change only at the transition block, since + // `ScrollBlockExecutor` does not have access to the parent timestamp. + if state.storage(L1_GAS_PRICE_ORACLE_ADDRESS, IS_GALILEO_SLOT)? == IS_GALILEO { + return Ok(()) + } + + let oracle = state.load_cache_account(L1_GAS_PRICE_ORACLE_ADDRESS)?; + + // compute the code hash + let bytecode = Bytecode::new_raw(GALILEO_V2_L1_GAS_PRICE_ORACLE_BYTECODE); + let code_hash = bytecode.hash_slow(); + + // get the old oracle account info + let old_oracle_info = oracle.account_info().unwrap_or_default(); + + // init new oracle account information + let new_oracle_info = AccountInfo { code_hash, code: Some(bytecode), ..old_oracle_info }; + + // init new storage + let new_storage = GALILEO_V2_L1_GAS_PRICE_ORACLE_STORAGE + .into_iter() + .map(|(slot, present_value)| { + ( + slot, + StorageSlot { + present_value, + previous_or_original_value: oracle.storage_slot(slot).unwrap_or_default(), + }, + ) + }) + .collect(); + + // create transition for oracle new account info and storage + let transition = oracle.change(new_oracle_info, new_storage); + + // add transition + if let Some(s) = state.transition_state.as_mut() { + s.add_transitions(vec![(L1_GAS_PRICE_ORACLE_ADDRESS, transition)]) + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use revm::{ + database::{ + states::{bundle_state::BundleRetention, plain_account::PlainStorage, StorageSlot}, + CacheDB, EmptyDB, State, + }, + primitives::{keccak256, U256}, + state::{AccountInfo, Bytecode}, + Database, + }; + use std::str::FromStr; + + use super::super::curie::CURIE_L1_GAS_PRICE_ORACLE_BYTECODE; + + #[test] + fn test_apply_galileo_v2_fork() -> eyre::Result<()> { + // init state + let db = EmptyDB::new(); + let mut state = + State::builder().with_database(db).with_bundle_update().without_state_clear().build(); + + // oracle pre fork state + let bytecode_pre_fork = Bytecode::new_raw(CURIE_L1_GAS_PRICE_ORACLE_BYTECODE); + let oracle_pre_fork = AccountInfo { + code_hash: bytecode_pre_fork.hash_slow(), + code: Some(bytecode_pre_fork), + ..Default::default() + }; + let oracle_storage_pre_fork = PlainStorage::from_iter([ + // owner + (U256::ZERO, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), + // l1BaseFee + (U256::from(1), U256::from(0x15f50e5e)), + // overhead + (U256::from(2), U256::from(0x38)), + // scalar + (U256::from(3), U256::from(0x3e95ba80)), + // whitelist + (U256::from(4), U256::from_str("0x5300000000000000000000000000000000000003")?), + // l1BlobBaseFee + (U256::from(5), U256::from(0x15f50e5e)), + // commitScalar + (U256::from(6), U256::from(0x3e95ba80)), + // blobScalar + (U256::from(7), U256::from(0x3e95ba80)), + // isCurie + (U256::from(8), U256::from(1)), + // penaltyThreshold + (U256::from(9), U256::from(1_000_000_000)), + // penaltyFactor + (U256::from(10), U256::from(1_000_000_000)), + // isFeynman + (U256::from(11), U256::from(1)), + ]); + state.insert_account_with_storage( + L1_GAS_PRICE_ORACLE_ADDRESS, + oracle_pre_fork.clone(), + oracle_storage_pre_fork.clone(), + ); + + // apply GalileoV2 fork + apply_galileo_v2_hard_fork(&mut state)?; + + // merge transitions + state.merge_transitions(BundleRetention::Reverts); + let bundle = state.take_bundle(); + + // check oracle account info + let oracle = bundle.state.get(&L1_GAS_PRICE_ORACLE_ADDRESS).unwrap().clone(); + let code_hash = keccak256(&GALILEO_V2_L1_GAS_PRICE_ORACLE_BYTECODE); + let bytecode = Bytecode::new_raw(GALILEO_V2_L1_GAS_PRICE_ORACLE_BYTECODE); + let expected_oracle_info = + AccountInfo { code_hash, code: Some(bytecode.clone()), ..Default::default() }; + + assert_eq!(oracle.original_info.unwrap(), oracle_pre_fork); + assert_eq!(oracle.info.unwrap(), expected_oracle_info); + + // check oracle storage changeset + let mut storage = oracle.storage.into_iter().collect::>(); + storage.sort_by(|(a, _), (b, _)| a.cmp(b)); + for (got, expected) in storage.into_iter().zip(GALILEO_V2_L1_GAS_PRICE_ORACLE_STORAGE) { + assert_eq!(got.0, expected.0); + assert_eq!(got.1, StorageSlot { present_value: expected.1, ..Default::default() }); + } + + // check oracle original storage + for (slot, value) in oracle_storage_pre_fork { + assert_eq!(state.storage(L1_GAS_PRICE_ORACLE_ADDRESS, slot)?, value) + } + + // check deployed contract + assert_eq!(bundle.contracts.get(&code_hash).unwrap(), &bytecode); + + Ok(()) + } + + #[test] + fn test_apply_galileo_v2_fork_only_once() -> eyre::Result<()> { + let bytecode = Bytecode::new_raw(GALILEO_V2_L1_GAS_PRICE_ORACLE_BYTECODE); + + let oracle_account = AccountInfo { + code_hash: bytecode.hash_slow(), + code: Some(bytecode), + ..Default::default() + }; + + let oracle_storage = PlainStorage::from_iter([ + // owner + (U256::ZERO, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), + // l1BaseFee + (U256::from(1), U256::from(0x15f50e5e)), + // overhead + (U256::from(2), U256::from(0x38)), + // scalar + (U256::from(3), U256::from(0x3e95ba80)), + // whitelist + (U256::from(4), U256::from_str("0x5300000000000000000000000000000000000003")?), + // l1BlobBaseFee + (U256::from(5), U256::from(0x15f50e5e)), + // commitScalar + (U256::from(6), U256::from(0x3e95ba80)), + // blobScalar + (U256::from(7), U256::from(0x3e95ba80)), + // isCurie + (U256::from(8), U256::from(1)), + // penaltyThreshold + (U256::from(9), U256::from(1_100_000_000u64)), + // penaltyFactor + (U256::from(10), U256::from(3_000_000_000u64)), + // isFeynman + (U256::from(11), U256::from(1)), + // isGalileo + (U256::from(12), U256::from(1)), + ]); + + // init state, + // we write to db directly to make sure we do not have account storage in cache + let mut db = CacheDB::new(EmptyDB::default()); + + db.insert_account_info(L1_GAS_PRICE_ORACLE_ADDRESS, oracle_account); + + for (slot, value) in oracle_storage { + db.insert_account_storage(L1_GAS_PRICE_ORACLE_ADDRESS, slot, value).unwrap(); + } + + let mut state = + State::builder().with_database(db).with_bundle_update().without_state_clear().build(); + + // make sure account is in cache + state.load_cache_account(L1_GAS_PRICE_ORACLE_ADDRESS)?; + + // apply GalileoV2 fork + apply_galileo_v2_hard_fork(&mut state)?; + + // merge transitions + state.merge_transitions(BundleRetention::Reverts); + let bundle = state.take_bundle(); + + // isGalileo is already set, apply_galileo_v2_hard_fork should be a no-op + assert_eq!(bundle.state.get(&L1_GAS_PRICE_ORACLE_ADDRESS), None); + + Ok(()) + } +} diff --git a/crates/scroll/alloy/evm/src/block/mod.rs b/crates/scroll/alloy/evm/src/block/mod.rs index 610f67122ea..f4edfa525ea 100644 --- a/crates/scroll/alloy/evm/src/block/mod.rs +++ b/crates/scroll/alloy/evm/src/block/mod.rs @@ -1,5 +1,6 @@ pub mod curie; pub mod feynman; +pub mod galileo_v2; pub use receipt_builder::{ReceiptBuilderCtx, ScrollReceiptBuilder}; mod receipt_builder; @@ -8,6 +9,7 @@ use crate::{ block::{ curie::{apply_curie_hard_fork, L1_GAS_PRICE_ORACLE_ADDRESS}, feynman::apply_feynman_hard_fork, + galileo_v2::apply_galileo_v2_hard_fork, }, system_caller::ScrollSystemCaller, FromTxWithCompressionInfo, ScrollDefaultPrecompilesFactory, ScrollEvm, ScrollEvmFactory, @@ -192,6 +194,20 @@ where }; } + // apply gas oracle predeploy upgrade at GalileoV2 transition block. + #[allow(clippy::collapsible_if)] + if self + .spec + .scroll_fork_activation(ScrollHardfork::GalileoV2) + .active_at_timestamp(self.evm.block().timestamp().to()) + { + if let Err(err) = apply_galileo_v2_hard_fork(self.evm.db_mut()) { + return Err(BlockExecutionError::msg(format!( + "error occurred at GalileoV2 fork: {err:?}" + ))); + }; + } + // apply eip-2935. self.system_caller.apply_blockhashes_contract_call(self.ctx.parent_hash, &mut self.evm)?; diff --git a/crates/scroll/alloy/evm/src/lib.rs b/crates/scroll/alloy/evm/src/lib.rs index cf0c3f8837b..d7c7013d42f 100644 --- a/crates/scroll/alloy/evm/src/lib.rs +++ b/crates/scroll/alloy/evm/src/lib.rs @@ -6,8 +6,8 @@ mod block; pub use block::{ - curie, feynman, EvmExt, ReceiptBuilderCtx, ScrollBlockExecutionCtx, ScrollBlockExecutor, - ScrollBlockExecutorFactory, ScrollReceiptBuilder, ScrollTxCompressionInfo, + curie, feynman, galileo_v2, EvmExt, ReceiptBuilderCtx, ScrollBlockExecutionCtx, + ScrollBlockExecutor, ScrollBlockExecutorFactory, ScrollReceiptBuilder, ScrollTxCompressionInfo, ScrollTxCompressionInfos, }; diff --git a/crates/scroll/alloy/evm/src/tx/compression.rs b/crates/scroll/alloy/evm/src/tx/compression.rs index cb6492e4ca6..5bedb26e783 100644 --- a/crates/scroll/alloy/evm/src/tx/compression.rs +++ b/crates/scroll/alloy/evm/src/tx/compression.rs @@ -329,6 +329,14 @@ mod tests { assert_eq!(ratio, U256::from(1_298_578_199u64)); // 1.3x assert_eq!(size, 422); + // galileo-mismatch + // https://scrollscan.com/tx/0x773daae3ac1d31cf0ac76dc25504fe76ad5458c7df9578161898b73bd8039c90 + let bytes = bytes!("0xf901ae8265f68301d52c8307040d94c9c35e593842c3d5e71304b2291e204583226e2a80b90144412658e5000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000fe0000000000000000000000000000000000000000020027004f00a500d100d500d900dd00ed00fd530000000000000000000000000000000000000406efdbff2a14a7c8e15944d1f4a48f9f95f663a4005300903c813df550a32d4a9d42010d057386429ad2328ed906efdbff2a14a7c8e15944d1f4a48f9f95f663a4530000000000000000000000000000000000000414ffa10b2019d6eb63140ef4b5026c7e049936bfeb00a900bdfeec4e40c170ef3736dc9a29389fb8cd7ed12409ae7bb52a3614ac5b66389d8873a8cb9f45f817c500a900bd000500010000000000000000000000000000187abb94380e0000000000000000000000092f2a085c00000083104ec3a0e3c466f58aa6edab61bd5f2bab117804d6f3cf125a815e53c161c02df8209d09a0267df663ab1cb9a5c85441df5051a7a03623b946a87ff42af694fc21e40f34fb"); + let ratio = compute_compression_ratio(&bytes); + let size = compute_compressed_size(&bytes); + assert_eq!(ratio, U256::from(1_438_538_205u64)); // 1.4x + assert_eq!(size, 301); + Ok(()) } } diff --git a/crates/scroll/alloy/hardforks/src/hardfork.rs b/crates/scroll/alloy/hardforks/src/hardfork.rs index 77edb9fa072..b8bca4dea75 100644 --- a/crates/scroll/alloy/hardforks/src/hardfork.rs +++ b/crates/scroll/alloy/hardforks/src/hardfork.rs @@ -24,12 +24,14 @@ hardfork!( Feynman, /// Galileo Galileo, + /// GalileoV2 + GalileoV2, } ); impl ScrollHardfork { /// Scroll mainnet list of hardforks. - pub const fn scroll_mainnet() -> [(Self, ForkCondition); 9] { + pub const fn scroll_mainnet() -> [(Self, ForkCondition); 10] { [ (Self::Archimedes, ForkCondition::Block(0)), (Self::Bernoulli, ForkCondition::Block(5220340)), @@ -40,11 +42,12 @@ impl ScrollHardfork { (Self::EuclidV2, ForkCondition::Timestamp(1745305200)), (Self::Feynman, ForkCondition::Timestamp(1755576000)), (Self::Galileo, ForkCondition::Timestamp(u64::MAX)), + (Self::GalileoV2, ForkCondition::Timestamp(u64::MAX)), ] } /// Scroll sepolia list of hardforks. - pub const fn scroll_sepolia() -> [(Self, ForkCondition); 9] { + pub const fn scroll_sepolia() -> [(Self, ForkCondition); 10] { [ (Self::Archimedes, ForkCondition::Block(0)), (Self::Bernoulli, ForkCondition::Block(3747132)), @@ -55,6 +58,7 @@ impl ScrollHardfork { (Self::EuclidV2, ForkCondition::Timestamp(1741852800)), (Self::Feynman, ForkCondition::Timestamp(1753167600)), (Self::Galileo, ForkCondition::Timestamp(1764054000)), + (Self::GalileoV2, ForkCondition::Timestamp(u64::MAX)), ] } } @@ -75,6 +79,7 @@ mod tests { "eUClidv2", "FEYnmaN", "gaLiLEo", + "gaLiLEov2", ]; let expected_hardforks = [ ScrollHardfork::Bernoulli, @@ -85,6 +90,7 @@ mod tests { ScrollHardfork::EuclidV2, ScrollHardfork::Feynman, ScrollHardfork::Galileo, + ScrollHardfork::GalileoV2, ]; let hardforks: Vec = diff --git a/crates/scroll/alloy/hardforks/src/lib.rs b/crates/scroll/alloy/hardforks/src/lib.rs index 7dba7693601..be76ecfcfa2 100644 --- a/crates/scroll/alloy/hardforks/src/lib.rs +++ b/crates/scroll/alloy/hardforks/src/lib.rs @@ -57,6 +57,12 @@ pub trait ScrollHardforks: EthereumHardforks { fn is_galileo_active_at_timestamp(&self, timestamp: u64) -> bool { self.scroll_fork_activation(ScrollHardfork::Galileo).active_at_timestamp(timestamp) } + + /// Returns `true` if [`GalileoV2`](ScrollHardfork::GalileoV2) is active at given block + /// timestamp. + fn is_galileo_v2_active_at_timestamp(&self, timestamp: u64) -> bool { + self.scroll_fork_activation(ScrollHardfork::GalileoV2).active_at_timestamp(timestamp) + } } /// A type allowing to configure activation [`ForkCondition`]s for a given list of diff --git a/crates/scroll/chainspec/src/genesis.rs b/crates/scroll/chainspec/src/genesis.rs index 56a8c1ab885..747e2ddd1b3 100644 --- a/crates/scroll/chainspec/src/genesis.rs +++ b/crates/scroll/chainspec/src/genesis.rs @@ -71,6 +71,8 @@ pub struct ScrollHardforkInfo { pub feynman_time: Option, /// galileo hardfork timestamp pub galileo_time: Option, + /// galileoV2 hardfork timestamp + pub galileo_v2_time: Option, } impl ScrollHardforkInfo { @@ -190,7 +192,8 @@ mod tests { "darwinTime": 0, "euclidTime": 11, "feynmanTime": 100, - "galileoTime": 110 + "galileoTime": 110, + "galileoV2Time": 120 } "#; @@ -209,6 +212,7 @@ mod tests { euclid_v2_time: None, feynman_time: Some(100), galileo_time: Some(110), + galileo_v2_time: Some(120), } ); } @@ -224,6 +228,7 @@ mod tests { "euclidTime": 11, "feynmanTime": 100, "galileoTime": 110, + "galileoV2Time": 120, "scroll": { "feeVaultAddress": "0x5300000000000000000000000000000000000005", "maxTxPayloadBytesPerBlock": 122880, @@ -253,6 +258,7 @@ mod tests { euclid_v2_time: None, feynman_time: Some(100), galileo_time: Some(110), + galileo_v2_time: Some(120), }), scroll_chain_config: ScrollChainConfig { fee_vault_address: Some(address!("5300000000000000000000000000000000000005")), diff --git a/crates/scroll/chainspec/src/lib.rs b/crates/scroll/chainspec/src/lib.rs index 6030643eabf..e2c7ac1b66a 100644 --- a/crates/scroll/chainspec/src/lib.rs +++ b/crates/scroll/chainspec/src/lib.rs @@ -188,6 +188,13 @@ impl ScrollChainSpecBuilder { self } + /// Enable `GalileoV2` at genesis + pub fn galileo_v2_activated(mut self) -> Self { + self = self.feynman_activated(); + self.inner = self.inner.with_fork(ScrollHardfork::GalileoV2, ForkCondition::Timestamp(0)); + self + } + /// Build the resulting [`ScrollChainSpec`]. /// /// # Panics @@ -446,6 +453,7 @@ impl From for ScrollChainSpec { (ScrollHardfork::EuclidV2.boxed(), hard_fork_info.euclid_v2_time), (ScrollHardfork::Feynman.boxed(), hard_fork_info.feynman_time), (ScrollHardfork::Galileo.boxed(), hard_fork_info.galileo_time), + (ScrollHardfork::GalileoV2.boxed(), hard_fork_info.galileo_v2_time), ]; let mut time_hardforks = time_hardfork_opts @@ -765,6 +773,8 @@ mod tests { assert_eq!(actual_feynman_timestamp, Some(serde_json::Value::from(34)).as_ref()); let actual_galileo_timestamp = genesis.config.extra_fields.get("galileoTime"); assert_eq!(actual_galileo_timestamp, Some(serde_json::Value::from(35)).as_ref()); + let actual_galileo_v2_timestamp = genesis.config.extra_fields.get("galileoV2Time"); + assert_eq!(actual_galileo_v2_timestamp, Some(serde_json::Value::from(36)).as_ref()); let scroll_object = genesis.config.extra_fields.get("scroll").unwrap(); assert_eq!( @@ -793,6 +803,7 @@ mod tests { assert!(!chain_spec.is_fork_active_at_timestamp(ScrollHardfork::EuclidV2, 0)); assert!(!chain_spec.is_fork_active_at_timestamp(ScrollHardfork::Feynman, 0)); assert!(!chain_spec.is_fork_active_at_timestamp(ScrollHardfork::Galileo, 0)); + assert!(!chain_spec.is_fork_active_at_timestamp(ScrollHardfork::GalileoV2, 0)); assert!(chain_spec.is_fork_active_at_block(ScrollHardfork::Bernoulli, 10)); assert!(chain_spec.is_fork_active_at_block(ScrollHardfork::Curie, 20)); @@ -802,6 +813,7 @@ mod tests { assert!(chain_spec.is_fork_active_at_timestamp(ScrollHardfork::EuclidV2, 33)); assert!(chain_spec.is_fork_active_at_timestamp(ScrollHardfork::Feynman, 34)); assert!(chain_spec.is_fork_active_at_timestamp(ScrollHardfork::Galileo, 35)); + assert!(chain_spec.is_fork_active_at_timestamp(ScrollHardfork::GalileoV2, 36)); } #[test] @@ -830,6 +842,7 @@ mod tests { (String::from("darwinV2Time"), 0.into()), (String::from("feynmanTime"), 0.into()), (String::from("galileoTime"), 0.into()), + (String::from("galileoV2Time"), 0.into()), ( String::from("scroll"), serde_json::json!({ @@ -874,6 +887,7 @@ mod tests { ScrollHardfork::DarwinV2.boxed(), ScrollHardfork::Feynman.boxed(), ScrollHardfork::Galileo.boxed(), + ScrollHardfork::GalileoV2.boxed(), ]; assert!(expected_hardforks diff --git a/crates/scroll/evm/src/execute.rs b/crates/scroll/evm/src/execute.rs index 384d848fd32..f3d40c6f30b 100644 --- a/crates/scroll/evm/src/execute.rs +++ b/crates/scroll/evm/src/execute.rs @@ -84,6 +84,7 @@ mod tests { L1_GAS_PRICE_ORACLE_ADDRESS, }, feynman::{IS_FEYNMAN_SLOT, PENALTY_FACTOR_SLOT, PENALTY_THRESHOLD_SLOT}, + galileo_v2::IS_GALILEO_SLOT, ScrollBlockExecutionCtx, ScrollBlockExecutor, ScrollEvm, ScrollTxCompressionInfos, }; use scroll_alloy_hardforks::ScrollHardforks; @@ -231,7 +232,21 @@ mod tests { // determine l1 gas oracle storage let l1_gas_oracle_storage = - if strategy.spec().is_feynman_active_at_timestamp(block_timestamp) { + if strategy.spec().is_galileo_v2_active_at_timestamp(block_timestamp) { + vec![ + (L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), + (OVER_HEAD_SLOT, U256::from(1000)), + (SCALAR_SLOT, U256::from(1000)), + (L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), + (COMMIT_SCALAR_SLOT, U256::from(1000)), + (BLOB_SCALAR_SLOT, U256::from(10000)), + (IS_CURIE_SLOT, U256::from(1)), + (PENALTY_THRESHOLD_SLOT, U256::from(1_000_000_000u64)), + (PENALTY_FACTOR_SLOT, U256::from(1_000_000_000u64)), + (IS_FEYNMAN_SLOT, U256::from(1)), + (IS_GALILEO_SLOT, U256::from(1)), + ] + } else if strategy.spec().is_feynman_active_at_timestamp(block_timestamp) { vec![ (L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), (OVER_HEAD_SLOT, U256::from(1000)), @@ -304,7 +319,21 @@ mod tests { // determine l1 gas oracle storage let l1_gas_oracle_storage = - if strategy.spec().is_feynman_active_at_timestamp(block_timestamp) { + if strategy.spec().is_galileo_v2_active_at_timestamp(block_timestamp) { + vec![ + (L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), + (OVER_HEAD_SLOT, U256::from(1000)), + (SCALAR_SLOT, U256::from(1000)), + (L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), + (COMMIT_SCALAR_SLOT, U256::from(1000)), + (BLOB_SCALAR_SLOT, U256::from(10000)), + (IS_CURIE_SLOT, U256::from(1)), + (PENALTY_THRESHOLD_SLOT, U256::from(2_000_000_000u64)), // penalty if <2x + (PENALTY_FACTOR_SLOT, U256::from(10_000_000_000u64)), // 10x penalty + (IS_FEYNMAN_SLOT, U256::from(1)), + (IS_GALILEO_SLOT, U256::from(1)), + ] + } else if strategy.spec().is_feynman_active_at_timestamp(block_timestamp) { vec![ (L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), (OVER_HEAD_SLOT, U256::from(1000)), diff --git a/crates/scroll/evm/src/lib.rs b/crates/scroll/evm/src/lib.rs index 217fa845a50..10c8f572018 100644 --- a/crates/scroll/evm/src/lib.rs +++ b/crates/scroll/evm/src/lib.rs @@ -114,6 +114,11 @@ pub fn spec_id_at_timestamp_and_number( chain_spec: impl ScrollHardforks, ) -> ScrollSpecId { if chain_spec + .scroll_fork_activation(ScrollHardfork::GalileoV2) + .active_at_timestamp_or_number(timestamp, number) + { + ScrollSpecId::GALILEO + } else if chain_spec .scroll_fork_activation(ScrollHardfork::Galileo) .active_at_timestamp_or_number(timestamp, number) { From d7b03a442d4fb875d6ee4837471b934ba8382b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Nov 2025 14:11:05 +0100 Subject: [PATCH 2/7] fix comments --- crates/scroll/alloy/evm/src/block/galileo_v2.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/scroll/alloy/evm/src/block/galileo_v2.rs b/crates/scroll/alloy/evm/src/block/galileo_v2.rs index 95138c4cc47..648a30bc8b7 100644 --- a/crates/scroll/alloy/evm/src/block/galileo_v2.rs +++ b/crates/scroll/alloy/evm/src/block/galileo_v2.rs @@ -26,7 +26,7 @@ pub const IS_GALILEO_SLOT: U256 = U256::from_limbs([12, 0, 0, 0]); /// Galileo slot is set to 1 (true) after the GalileoV2 block fork. const IS_GALILEO: U256 = U256::from_limbs([1, 0, 0, 0]); -/// Storage update of L1 gas price oracle at Feynman transition. +/// Storage update of L1 gas price oracle at GalileoV2 transition. const GALILEO_V2_L1_GAS_PRICE_ORACLE_STORAGE: [(U256, U256); 1] = [(IS_GALILEO_SLOT, IS_GALILEO)]; /// Applies the Scroll GalileoV2 hard fork to the state: @@ -36,7 +36,7 @@ pub(super) fn apply_galileo_v2_hard_fork( state: &mut State, ) -> Result<(), DB::Error> { // No-op if already applied. - // Note: This requires a storage read for every Feynman block, and it means this + // Note: This requires a storage read for every block after GalileoV2, and it means this // read needs to be included in the execution witness. Unfortunately, there is no // other reliable way to apply the change only at the transition block, since // `ScrollBlockExecutor` does not have access to the parent timestamp. From 55a34403206deefd90c30f66cb43091e9eaff7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Nov 2025 14:59:53 +0100 Subject: [PATCH 3/7] refactor gpo configs --- crates/scroll/alloy/evm/src/block/curie.rs | 37 ++--- crates/scroll/alloy/evm/src/block/feynman.rs | 85 ++++------- .../scroll/alloy/evm/src/block/galileo_v2.rs | 103 +++++-------- crates/scroll/alloy/evm/src/block/mod.rs | 4 +- .../scroll/alloy/evm/src/gas_price_oracle.rs | 88 +++++++++++ crates/scroll/alloy/evm/src/lib.rs | 2 + crates/scroll/alloy/evm/src/system_caller.rs | 2 +- crates/scroll/chainspec/src/lib.rs | 1 + crates/scroll/evm/src/base_fee.rs | 9 +- crates/scroll/evm/src/execute.rs | 137 ++++++++---------- crates/scroll/evm/src/lib.rs | 12 +- crates/scroll/node/src/builder/pool.rs | 2 +- 12 files changed, 248 insertions(+), 234 deletions(-) create mode 100644 crates/scroll/alloy/evm/src/gas_price_oracle.rs diff --git a/crates/scroll/alloy/evm/src/block/curie.rs b/crates/scroll/alloy/evm/src/block/curie.rs index 3c65e9cc04d..4678d42c409 100644 --- a/crates/scroll/alloy/evm/src/block/curie.rs +++ b/crates/scroll/alloy/evm/src/block/curie.rs @@ -21,34 +21,25 @@ use alloc::vec; use revm::{ bytecode::Bytecode, database::{states::StorageSlot, State}, - primitives::{address, bytes, Address, Bytes, U256}, + primitives::{bytes, Bytes, U256}, state::AccountInfo, Database, }; -/// L1 gas price oracle address. -/// -pub const L1_GAS_PRICE_ORACLE_ADDRESS: Address = - address!("5300000000000000000000000000000000000002"); +// Import L1GasPriceOracle address and slots. +use crate::gas_price_oracle::*; + /// Bytecode of L1 gas price oracle at Curie transition. pub const CURIE_L1_GAS_PRICE_ORACLE_BYTECODE: Bytes = bytes!("608060405234801561000f575f80fd5b5060043610610132575f3560e01c8063715018a6116100b4578063a911d77f11610079578063a911d77f1461024c578063bede39b514610254578063de26c4a114610267578063e88a60ad1461027a578063f2fde38b1461028d578063f45e65d8146102a0575f80fd5b8063715018a6146101eb57806384189161146101f35780638da5cb5b146101fc57806393e59dc114610226578063944b247f14610239575f80fd5b80633d0f963e116100fa5780633d0f963e146101a057806349948e0e146101b3578063519b4bd3146101c65780636a5e67e5146101cf57806370465597146101d8575f80fd5b80630c18c1621461013657806313dad5be1461015257806323e524ac1461016f5780633577afc51461017857806339455d3a1461018d575b5f80fd5b61013f60025481565b6040519081526020015b60405180910390f35b60085461015f9060ff1681565b6040519015158152602001610149565b61013f60065481565b61018b6101863660046109b3565b6102a9565b005b61018b61019b3660046109ca565b61033b565b61018b6101ae3660046109ea565b610438565b61013f6101c1366004610a2b565b6104bb565b61013f60015481565b61013f60075481565b61018b6101e63660046109b3565b6104e0565b61018b61056e565b61013f60055481565b5f5461020e906001600160a01b031681565b6040516001600160a01b039091168152602001610149565b60045461020e906001600160a01b031681565b61018b6102473660046109b3565b6105a2565b61018b61062e565b61018b6102623660046109b3565b61068a565b61013f610275366004610a2b565b610747565b61018b6102883660046109b3565b610764565b61018b61029b3660046109ea565b6107f0565b61013f60035481565b5f546001600160a01b031633146102db5760405162461bcd60e51b81526004016102d290610ad6565b60405180910390fd5b621c9c388111156102ff57604051635742c80560e11b815260040160405180910390fd5b60028190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa158015610382573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a69190610b0d565b6103c3576040516326b3506d60e11b815260040160405180910390fd5b600182905560058190556040518281527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200160405180910390a16040518181527f9a14bfb5d18c4c3cf14cae19c23d7cf1bcede357ea40ca1f75cd49542c71c214906020015b60405180910390a15050565b5f546001600160a01b031633146104615760405162461bcd60e51b81526004016102d290610ad6565b600480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f22d1c35fe072d2e42c3c8f9bd4a0d34aa84a0101d020a62517b33fdb3174e5f7910161042c565b6008545f9060ff16156104d7576104d18261087b565b92915050565b6104d1826108c1565b5f546001600160a01b031633146105095760405162461bcd60e51b81526004016102d290610ad6565b610519633b9aca006103e8610b40565b81111561053957604051631e44fdeb60e11b815260040160405180910390fd5b60038190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a90602001610330565b5f546001600160a01b031633146105975760405162461bcd60e51b81526004016102d290610ad6565b6105a05f610904565b565b5f546001600160a01b031633146105cb5760405162461bcd60e51b81526004016102d290610ad6565b6105d9633b9aca0080610b40565b8111156105f95760405163874f603160e01b815260040160405180910390fd5b60068190556040518181527f2ab3f5a4ebbcbf3c24f62f5454f52f10e1a8c9dcc5acac8f19199ce881a6a10890602001610330565b5f546001600160a01b031633146106575760405162461bcd60e51b81526004016102d290610ad6565b60085460ff161561067b576040516379f9c57560e01b815260040160405180910390fd5b6008805460ff19166001179055565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa1580156106d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f59190610b0d565b610712576040516326b3506d60e11b815260040160405180910390fd5b60018190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c4490602001610330565b6008545f9060ff161561075b57505f919050565b6104d182610953565b5f546001600160a01b0316331461078d5760405162461bcd60e51b81526004016102d290610ad6565b61079b633b9aca0080610b40565b8111156107bb5760405163f37ec21560e01b815260040160405180910390fd5b60078190556040518181527f6b332a036d8c3ead57dcb06c87243bd7a2aed015ddf2d0528c2501dae56331aa90602001610330565b5f546001600160a01b031633146108195760405162461bcd60e51b81526004016102d290610ad6565b6001600160a01b03811661086f5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f206164647265737300000060448201526064016102d2565b61087881610904565b50565b5f633b9aca0060055483516007546108939190610b40565b61089d9190610b40565b6001546006546108ad9190610b40565b6108b79190610b57565b6104d19190610b6a565b5f806108cc83610953565b90505f600154826108dd9190610b40565b9050633b9aca00600354826108f29190610b40565b6108fc9190610b6a565b949350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80515f908190815b818110156109a45784818151811061097557610975610b89565b01602001516001600160f81b0319165f036109955760048301925061099c565b6010830192505b60010161095b565b50506002540160400192915050565b5f602082840312156109c3575f80fd5b5035919050565b5f80604083850312156109db575f80fd5b50508035926020909101359150565b5f602082840312156109fa575f80fd5b81356001600160a01b0381168114610a10575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610a3b575f80fd5b813567ffffffffffffffff80821115610a52575f80fd5b818401915084601f830112610a65575f80fd5b813581811115610a7757610a77610a17565b604051601f8201601f19908116603f01168101908382118183101715610a9f57610a9f610a17565b81604052828152876020848701011115610ab7575f80fd5b826020860160208301375f928101602001929092525095945050505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b5f60208284031215610b1d575f80fd5b81518015158114610a10575f80fd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176104d1576104d1610b2c565b808201808211156104d1576104d1610b2c565b5f82610b8457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffdfea26469706673582212200c2ac583f18be4f94ab169ae6f2ea3a708a7c0d4424746b120b177adb39e626064736f6c63430008180033"); + /// Storage update of L1 gas price oracle at Curie transition. pub const CURIE_L1_GAS_PRICE_ORACLE_STORAGE: [(U256, U256); 4] = [ - (L1_BLOB_BASE_FEE_SLOT, INITIAL_L1_BLOB_BASE_FEE), - (COMMIT_SCALAR_SLOT, INITIAL_COMMIT_SCALAR), - (BLOB_SCALAR_SLOT, INITIAL_BLOB_SCALAR), - (IS_CURIE_SLOT, IS_CURIE), + (GPO_L1_BLOB_BASE_FEE_SLOT, INITIAL_L1_BLOB_BASE_FEE), + (GPO_COMMIT_SCALAR_SLOT, INITIAL_COMMIT_SCALAR), + (GPO_BLOB_SCALAR_SLOT, INITIAL_BLOB_SCALAR), + (GPO_IS_CURIE_SLOT, IS_CURIE), ]; -/// L1 gas price oracle blob base fee slot. Added in the Curie fork. -pub const L1_BLOB_BASE_FEE_SLOT: U256 = U256::from_limbs([5, 0, 0, 0]); -/// L1 gas price oracle commit scalar slot. Added in the Curie fork. -pub const COMMIT_SCALAR_SLOT: U256 = U256::from_limbs([6, 0, 0, 0]); -/// L1 gas price oracle blob scalar slot. Added in the Curie fork. -pub const BLOB_SCALAR_SLOT: U256 = U256::from_limbs([7, 0, 0, 0]); -/// L1 gas price oracle "is Curie" slot. Added in the Curie fork. -pub const IS_CURIE_SLOT: U256 = U256::from_limbs([8, 0, 0, 0]); - /// The initial blob base fee used by the oracle contract. pub const INITIAL_L1_BLOB_BASE_FEE: U256 = U256::from_limbs([1, 0, 0, 0]); /// The initial commit scalar used by the oracle contract. @@ -129,11 +120,11 @@ mod tests { ..Default::default() }; let oracle_storage_pre_fork = PlainStorage::from_iter([ - (U256::ZERO, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), - (U256::from(1), U256::from(0x15f50e5e)), - (U256::from(2), U256::from(0x38)), - (U256::from(3), U256::from(0x3e95ba80)), - (U256::from(4), U256::from_str("0x5300000000000000000000000000000000000003")?), + (GPO_OWNER_SLOT, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), + (GPO_L1_BASE_FEE_SLOT, U256::from(0x15f50e5e)), + (GPO_OVERHEAD_SLOT, U256::from(0x38)), + (GPO_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_WHITELIST_SLOT, U256::from_str("0x5300000000000000000000000000000000000003")?), ]); state.insert_account_with_storage( L1_GAS_PRICE_ORACLE_ADDRESS, diff --git a/crates/scroll/alloy/evm/src/block/feynman.rs b/crates/scroll/alloy/evm/src/block/feynman.rs index c739d4a3abd..555338e3cb6 100644 --- a/crates/scroll/alloy/evm/src/block/feynman.rs +++ b/crates/scroll/alloy/evm/src/block/feynman.rs @@ -9,17 +9,11 @@ use revm::{ Database, }; -use super::curie::L1_GAS_PRICE_ORACLE_ADDRESS; +// Import L1GasPriceOracle address and slots. +use crate::gas_price_oracle::*; /// Bytecode of L1 gas price oracle at Feynman transition. -const FEYNMAN_L1_GAS_PRICE_ORACLE_BYTECODE: Bytes = bytes!("608060405234801561000f575f80fd5b50600436106101a1575f3560e01c806384189161116100f3578063c63b9e2d11610093578063e88a60ad1161006e578063e88a60ad1461032e578063f2fde38b14610341578063f45e65d814610354578063fe5b04151461035d575f80fd5b8063c63b9e2d146102ff578063c91e514914610312578063de26c4a11461031b575f80fd5b8063944b247f116100ce578063944b247f146102be578063a911d77f146102d1578063aa5e9334146102d9578063bede39b5146102ec575f80fd5b806384189161146102785780638da5cb5b1461028157806393e59dc1146102ab575f80fd5b80633d0f963e1161015e5780636112d6db116101395780636112d6db1461024b5780636a5e67e514610254578063704655971461025d578063715018a614610270575f80fd5b80633d0f963e1461021c57806349948e0e1461022f578063519b4bd314610242575f80fd5b80630c18c162146101a557806313dad5be146101c157806323e524ac146101de5780633577afc5146101e757806339455d3a146101fc5780633b7656bb1461020f575b5f80fd5b6101ae60025481565b6040519081526020015b60405180910390f35b6008546101ce9060ff1681565b60405190151581526020016101b8565b6101ae60065481565b6101fa6101f5366004610c73565b610365565b005b6101fa61020a366004610c8a565b6103f7565b600b546101ce9060ff1681565b6101fa61022a366004610caa565b6104f4565b6101ae61023d366004610ceb565b610577565b6101ae60015481565b6101ae600a5481565b6101ae60075481565b6101fa61026b366004610c73565b6105b0565b6101fa61063e565b6101ae60055481565b5f54610293906001600160a01b031681565b6040516001600160a01b0390911681526020016101b8565b600454610293906001600160a01b031681565b6101fa6102cc366004610c73565b610672565b6101fa6106fe565b6101fa6102e7366004610c73565b61075a565b6101fa6102fa366004610c73565b6107f4565b6101fa61030d366004610c73565b6108b1565b6101ae60095481565b6101ae610329366004610ceb565b61094a565b6101fa61033c366004610c73565b610974565b6101fa61034f366004610caa565b610a00565b6101ae60035481565b6101fa610a8b565b5f546001600160a01b031633146103975760405162461bcd60e51b815260040161038e90610d96565b60405180910390fd5b621c9c388111156103bb57604051635742c80560e11b815260040160405180910390fd5b60028190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa15801561043e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104629190610dcd565b61047f576040516326b3506d60e11b815260040160405180910390fd5b600182905560058190556040518281527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200160405180910390a16040518181527f9a14bfb5d18c4c3cf14cae19c23d7cf1bcede357ea40ca1f75cd49542c71c214906020015b60405180910390a15050565b5f546001600160a01b0316331461051d5760405162461bcd60e51b815260040161038e90610d96565b600480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f22d1c35fe072d2e42c3c8f9bd4a0d34aa84a0101d020a62517b33fdb3174e5f791016104e8565b600b545f9060ff16156105935761058d82610ae7565b92915050565b60085460ff16156105a75761058d82610b45565b61058d82610b81565b5f546001600160a01b031633146105d95760405162461bcd60e51b815260040161038e90610d96565b6105e9633b9aca006103e8610e00565b81111561060957604051631e44fdeb60e11b815260040160405180910390fd5b60038190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a906020016103ec565b5f546001600160a01b031633146106675760405162461bcd60e51b815260040161038e90610d96565b6106705f610bc4565b565b5f546001600160a01b0316331461069b5760405162461bcd60e51b815260040161038e90610d96565b6106a9633b9aca0080610e00565b8111156106c95760405163874f603160e01b815260040160405180910390fd5b60068190556040518181527f2ab3f5a4ebbcbf3c24f62f5454f52f10e1a8c9dcc5acac8f19199ce881a6a108906020016103ec565b5f546001600160a01b031633146107275760405162461bcd60e51b815260040161038e90610d96565b60085460ff161561074b576040516379f9c57560e01b815260040160405180910390fd5b6008805460ff19166001179055565b5f546001600160a01b031633146107835760405162461bcd60e51b815260040161038e90610d96565b633b9aca008110806107a1575061079e633b9aca0080610e00565b81115b156107bf5760405163d9b5dcdf60e01b815260040160405180910390fd5b60098190556040518181527fd50d3079c77df569cd58d55d4e5614bfe7066449009425d22bde8e75242f50bb906020016103ec565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa15801561083b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061085f9190610dcd565b61087c576040516326b3506d60e11b815260040160405180910390fd5b60018190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c44906020016103ec565b5f546001600160a01b031633146108da5760405162461bcd60e51b815260040161038e90610d96565b633b9aca008110806108f857506108f5633b9aca0080610e00565b81115b156109155760405162ae184360e01b815260040160405180910390fd5b600a8190556040518181527f8647cebb7e57360673a28415c0bed2f68c42a86c5035f1c9b2eda2b09509288a906020016103ec565b600b545f9060ff168061095f575060085460ff165b1561096b57505f919050565b61058d82610c13565b5f546001600160a01b0316331461099d5760405162461bcd60e51b815260040161038e90610d96565b6109ab633b9aca0080610e00565b8111156109cb5760405163f37ec21560e01b815260040160405180910390fd5b60078190556040518181527f6b332a036d8c3ead57dcb06c87243bd7a2aed015ddf2d0528c2501dae56331aa906020016103ec565b5f546001600160a01b03163314610a295760405162461bcd60e51b815260040161038e90610d96565b6001600160a01b038116610a7f5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f2061646472657373000000604482015260640161038e565b610a8881610bc4565b50565b5f546001600160a01b03163314610ab45760405162461bcd60e51b815260040161038e90610d96565b600b5460ff1615610ad857604051631a7c228b60e21b815260040160405180910390fd5b600b805460ff19166001179055565b5f633b9aca0080600a548451600554600754610b039190610e00565b600154600654610b139190610e00565b610b1d9190610e17565b610b279190610e00565b610b319190610e00565b610b3b9190610e2a565b61058d9190610e2a565b5f633b9aca006005548351600754610b5d9190610e00565b610b679190610e00565b600154600654610b779190610e00565b610b3b9190610e17565b5f80610b8c83610c13565b90505f60015482610b9d9190610e00565b9050633b9aca0060035482610bb29190610e00565b610bbc9190610e2a565b949350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80515f908190815b81811015610c6457848181518110610c3557610c35610e49565b01602001516001600160f81b0319165f03610c5557600483019250610c5c565b6010830192505b600101610c1b565b50506002540160400192915050565b5f60208284031215610c83575f80fd5b5035919050565b5f8060408385031215610c9b575f80fd5b50508035926020909101359150565b5f60208284031215610cba575f80fd5b81356001600160a01b0381168114610cd0575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610cfb575f80fd5b813567ffffffffffffffff80821115610d12575f80fd5b818401915084601f830112610d25575f80fd5b813581811115610d3757610d37610cd7565b604051601f8201601f19908116603f01168101908382118183101715610d5f57610d5f610cd7565b81604052828152876020848701011115610d77575f80fd5b826020860160208301375f928101602001929092525095945050505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b5f60208284031215610ddd575f80fd5b81518015158114610cd0575f80fd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761058d5761058d610dec565b8082018082111561058d5761058d610dec565b5f82610e4457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffdfea164736f6c6343000818000a"); - -/// L1 gas price oracle compression penalty threshold slot. Added in the Feynman fork. -pub const PENALTY_THRESHOLD_SLOT: U256 = U256::from_limbs([9, 0, 0, 0]); -/// L1 gas price oracle compression penalty factor slot. Added in the Feynman fork. -pub const PENALTY_FACTOR_SLOT: U256 = U256::from_limbs([10, 0, 0, 0]); -/// L1 gas price oracle "is Feynman" slot. Added in the Feynman fork. -pub const IS_FEYNMAN_SLOT: U256 = U256::from_limbs([11, 0, 0, 0]); +pub const FEYNMAN_L1_GAS_PRICE_ORACLE_BYTECODE: Bytes = bytes!("608060405234801561000f575f80fd5b50600436106101a1575f3560e01c806384189161116100f3578063c63b9e2d11610093578063e88a60ad1161006e578063e88a60ad1461032e578063f2fde38b14610341578063f45e65d814610354578063fe5b04151461035d575f80fd5b8063c63b9e2d146102ff578063c91e514914610312578063de26c4a11461031b575f80fd5b8063944b247f116100ce578063944b247f146102be578063a911d77f146102d1578063aa5e9334146102d9578063bede39b5146102ec575f80fd5b806384189161146102785780638da5cb5b1461028157806393e59dc1146102ab575f80fd5b80633d0f963e1161015e5780636112d6db116101395780636112d6db1461024b5780636a5e67e514610254578063704655971461025d578063715018a614610270575f80fd5b80633d0f963e1461021c57806349948e0e1461022f578063519b4bd314610242575f80fd5b80630c18c162146101a557806313dad5be146101c157806323e524ac146101de5780633577afc5146101e757806339455d3a146101fc5780633b7656bb1461020f575b5f80fd5b6101ae60025481565b6040519081526020015b60405180910390f35b6008546101ce9060ff1681565b60405190151581526020016101b8565b6101ae60065481565b6101fa6101f5366004610c73565b610365565b005b6101fa61020a366004610c8a565b6103f7565b600b546101ce9060ff1681565b6101fa61022a366004610caa565b6104f4565b6101ae61023d366004610ceb565b610577565b6101ae60015481565b6101ae600a5481565b6101ae60075481565b6101fa61026b366004610c73565b6105b0565b6101fa61063e565b6101ae60055481565b5f54610293906001600160a01b031681565b6040516001600160a01b0390911681526020016101b8565b600454610293906001600160a01b031681565b6101fa6102cc366004610c73565b610672565b6101fa6106fe565b6101fa6102e7366004610c73565b61075a565b6101fa6102fa366004610c73565b6107f4565b6101fa61030d366004610c73565b6108b1565b6101ae60095481565b6101ae610329366004610ceb565b61094a565b6101fa61033c366004610c73565b610974565b6101fa61034f366004610caa565b610a00565b6101ae60035481565b6101fa610a8b565b5f546001600160a01b031633146103975760405162461bcd60e51b815260040161038e90610d96565b60405180910390fd5b621c9c388111156103bb57604051635742c80560e11b815260040160405180910390fd5b60028190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa15801561043e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104629190610dcd565b61047f576040516326b3506d60e11b815260040160405180910390fd5b600182905560058190556040518281527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200160405180910390a16040518181527f9a14bfb5d18c4c3cf14cae19c23d7cf1bcede357ea40ca1f75cd49542c71c214906020015b60405180910390a15050565b5f546001600160a01b0316331461051d5760405162461bcd60e51b815260040161038e90610d96565b600480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f22d1c35fe072d2e42c3c8f9bd4a0d34aa84a0101d020a62517b33fdb3174e5f791016104e8565b600b545f9060ff16156105935761058d82610ae7565b92915050565b60085460ff16156105a75761058d82610b45565b61058d82610b81565b5f546001600160a01b031633146105d95760405162461bcd60e51b815260040161038e90610d96565b6105e9633b9aca006103e8610e00565b81111561060957604051631e44fdeb60e11b815260040160405180910390fd5b60038190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a906020016103ec565b5f546001600160a01b031633146106675760405162461bcd60e51b815260040161038e90610d96565b6106705f610bc4565b565b5f546001600160a01b0316331461069b5760405162461bcd60e51b815260040161038e90610d96565b6106a9633b9aca0080610e00565b8111156106c95760405163874f603160e01b815260040160405180910390fd5b60068190556040518181527f2ab3f5a4ebbcbf3c24f62f5454f52f10e1a8c9dcc5acac8f19199ce881a6a108906020016103ec565b5f546001600160a01b031633146107275760405162461bcd60e51b815260040161038e90610d96565b60085460ff161561074b576040516379f9c57560e01b815260040160405180910390fd5b6008805460ff19166001179055565b5f546001600160a01b031633146107835760405162461bcd60e51b815260040161038e90610d96565b633b9aca008110806107a1575061079e633b9aca0080610e00565b81115b156107bf5760405163d9b5dcdf60e01b815260040160405180910390fd5b60098190556040518181527fd50d3079c77df569cd58d55d4e5614bfe7066449009425d22bde8e75242f50bb906020016103ec565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa15801561083b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061085f9190610dcd565b61087c576040516326b3506d60e11b815260040160405180910390fd5b60018190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c44906020016103ec565b5f546001600160a01b031633146108da5760405162461bcd60e51b815260040161038e90610d96565b633b9aca008110806108f857506108f5633b9aca0080610e00565b81115b156109155760405162ae184360e01b815260040160405180910390fd5b600a8190556040518181527f8647cebb7e57360673a28415c0bed2f68c42a86c5035f1c9b2eda2b09509288a906020016103ec565b600b545f9060ff168061095f575060085460ff165b1561096b57505f919050565b61058d82610c13565b5f546001600160a01b0316331461099d5760405162461bcd60e51b815260040161038e90610d96565b6109ab633b9aca0080610e00565b8111156109cb5760405163f37ec21560e01b815260040160405180910390fd5b60078190556040518181527f6b332a036d8c3ead57dcb06c87243bd7a2aed015ddf2d0528c2501dae56331aa906020016103ec565b5f546001600160a01b03163314610a295760405162461bcd60e51b815260040161038e90610d96565b6001600160a01b038116610a7f5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f2061646472657373000000604482015260640161038e565b610a8881610bc4565b50565b5f546001600160a01b03163314610ab45760405162461bcd60e51b815260040161038e90610d96565b600b5460ff1615610ad857604051631a7c228b60e21b815260040160405180910390fd5b600b805460ff19166001179055565b5f633b9aca0080600a548451600554600754610b039190610e00565b600154600654610b139190610e00565b610b1d9190610e17565b610b279190610e00565b610b319190610e00565b610b3b9190610e2a565b61058d9190610e2a565b5f633b9aca006005548351600754610b5d9190610e00565b610b679190610e00565b600154600654610b779190610e00565b610b3b9190610e17565b5f80610b8c83610c13565b90505f60015482610b9d9190610e00565b9050633b9aca0060035482610bb29190610e00565b610bbc9190610e2a565b949350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80515f908190815b81811015610c6457848181518110610c3557610c35610e49565b01602001516001600160f81b0319165f03610c5557600483019250610c5c565b6010830192505b600101610c1b565b50506002540160400192915050565b5f60208284031215610c83575f80fd5b5035919050565b5f8060408385031215610c9b575f80fd5b50508035926020909101359150565b5f60208284031215610cba575f80fd5b81356001600160a01b0381168114610cd0575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610cfb575f80fd5b813567ffffffffffffffff80821115610d12575f80fd5b818401915084601f830112610d25575f80fd5b813581811115610d3757610d37610cd7565b604051601f8201601f19908116603f01168101908382118183101715610d5f57610d5f610cd7565b81604052828152876020848701011115610d77575f80fd5b826020860160208301375f928101602001929092525095945050505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b5f60208284031215610ddd575f80fd5b81518015158114610cd0575f80fd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761058d5761058d610dec565b8082018082111561058d5761058d610dec565b5f82610e4457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffdfea164736f6c6343000818000a"); /// The initial compression penalty threshold used by the oracle contract. const INITIAL_PENALTY_THRESHOLD: U256 = U256::from_limbs([1_000_000_000, 0, 0, 0]); @@ -30,9 +24,9 @@ const IS_FEYNMAN: U256 = U256::from_limbs([1, 0, 0, 0]); /// Storage update of L1 gas price oracle at Feynman transition. const FEYNMAN_L1_GAS_PRICE_ORACLE_STORAGE: [(U256, U256); 3] = [ - (PENALTY_THRESHOLD_SLOT, INITIAL_PENALTY_THRESHOLD), - (PENALTY_FACTOR_SLOT, INITIAL_PENALTY_FACTOR), - (IS_FEYNMAN_SLOT, IS_FEYNMAN), + (GPO_PENALTY_THRESHOLD_SLOT, INITIAL_PENALTY_THRESHOLD), + (GPO_PENALTY_FACTOR_SLOT, INITIAL_PENALTY_FACTOR), + (GPO_IS_FEYNMAN_SLOT, IS_FEYNMAN), ]; /// Applies the Scroll Feynman hard fork to the state: @@ -47,7 +41,7 @@ pub(super) fn apply_feynman_hard_fork( // read needs to be included in the execution witness. Unfortunately, there is no // other reliable way to apply the change only at the transition block, since // `ScrollBlockExecutor` does not have access to the parent timestamp. - if state.storage(L1_GAS_PRICE_ORACLE_ADDRESS, IS_FEYNMAN_SLOT)? == IS_FEYNMAN { + if state.storage(L1_GAS_PRICE_ORACLE_ADDRESS, GPO_IS_FEYNMAN_SLOT)? == IS_FEYNMAN { return Ok(()) } @@ -91,6 +85,7 @@ pub(super) fn apply_feynman_hard_fork( #[cfg(test)] mod tests { use super::*; + use crate::curie::CURIE_L1_GAS_PRICE_ORACLE_BYTECODE; use revm::{ database::{ states::{bundle_state::BundleRetention, plain_account::PlainStorage, StorageSlot}, @@ -102,8 +97,6 @@ mod tests { }; use std::str::FromStr; - use super::super::curie::CURIE_L1_GAS_PRICE_ORACLE_BYTECODE; - #[test] fn test_apply_feynman_fork() -> eyre::Result<()> { // init state @@ -120,23 +113,15 @@ mod tests { }; let oracle_storage_pre_fork = PlainStorage::from_iter([ // owner - (U256::ZERO, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), - // l1BaseFee - (U256::from(1), U256::from(0x15f50e5e)), - // overhead - (U256::from(2), U256::from(0x38)), - // scalar - (U256::from(3), U256::from(0x3e95ba80)), - // whitelist - (U256::from(4), U256::from_str("0x5300000000000000000000000000000000000003")?), - // l1BlobBaseFee - (U256::from(5), U256::from(0x15f50e5e)), - // commitScalar - (U256::from(6), U256::from(0x3e95ba80)), - // blobScalar - (U256::from(7), U256::from(0x3e95ba80)), - // isCurie - (U256::from(8), U256::from(1)), + (GPO_OWNER_SLOT, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), + (GPO_L1_BASE_FEE_SLOT, U256::from(0x15f50e5e)), + (GPO_OVERHEAD_SLOT, U256::from(0x38)), + (GPO_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_WHITELIST_SLOT, U256::from_str("0x5300000000000000000000000000000000000003")?), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(0x15f50e5e)), + (GPO_COMMIT_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_BLOB_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_IS_CURIE_SLOT, U256::from(1)), ]); state.insert_account_with_storage( L1_GAS_PRICE_ORACLE_ADDRESS, @@ -191,30 +176,18 @@ mod tests { }; let oracle_storage = PlainStorage::from_iter([ - // owner - (U256::ZERO, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), - // l1BaseFee - (U256::from(1), U256::from(0x15f50e5e)), - // overhead - (U256::from(2), U256::from(0x38)), - // scalar - (U256::from(3), U256::from(0x3e95ba80)), - // whitelist - (U256::from(4), U256::from_str("0x5300000000000000000000000000000000000003")?), - // l1BlobBaseFee - (U256::from(5), U256::from(0x15f50e5e)), - // commitScalar - (U256::from(6), U256::from(0x3e95ba80)), - // blobScalar - (U256::from(7), U256::from(0x3e95ba80)), - // isCurie - (U256::from(8), U256::from(1)), - // penaltyThreshold - (U256::from(9), U256::from(1_100_000_000u64)), - // penaltyFactor - (U256::from(10), U256::from(3_000_000_000u64)), - // isFeynman - (U256::from(11), U256::from(1)), + (GPO_OWNER_SLOT, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), + (GPO_L1_BASE_FEE_SLOT, U256::from(0x15f50e5e)), + (GPO_OVERHEAD_SLOT, U256::from(0x38)), + (GPO_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_WHITELIST_SLOT, U256::from_str("0x5300000000000000000000000000000000000003")?), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(0x15f50e5e)), + (GPO_COMMIT_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_BLOB_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_IS_CURIE_SLOT, U256::from(1)), + (GPO_PENALTY_THRESHOLD_SLOT, U256::from(1_100_000_000u64)), + (GPO_PENALTY_FACTOR_SLOT, U256::from(3_000_000_000u64)), + (GPO_IS_FEYNMAN_SLOT, U256::from(1)), ]); // init state, diff --git a/crates/scroll/alloy/evm/src/block/galileo_v2.rs b/crates/scroll/alloy/evm/src/block/galileo_v2.rs index 648a30bc8b7..b48dce60ac9 100644 --- a/crates/scroll/alloy/evm/src/block/galileo_v2.rs +++ b/crates/scroll/alloy/evm/src/block/galileo_v2.rs @@ -1,4 +1,4 @@ -//! GalileoV2 fork transition for Scroll. +//! `GalileoV2` fork transition for Scroll. use alloc::vec; use revm::{ @@ -9,9 +9,10 @@ use revm::{ Database, }; -use super::curie::L1_GAS_PRICE_ORACLE_ADDRESS; +// Import L1GasPriceOracle address and slots. +use crate::gas_price_oracle::*; -/// Bytecode of L1GasPriceOracle at GalileoV2 transition. +/// Bytecode of `L1GasPriceOracle` at `GalileoV2` transition. /// Run these commands in the scroll-contracts repo to verify this bytecode: /// /// git checkout dfffa0f04bbd1de31ef342e1642a2f9ad9a620fe @@ -20,27 +21,25 @@ use super::curie::L1_GAS_PRICE_ORACLE_ADDRESS; /// cat artifacts/src/L1GasPriceOracle.sol/L1GasPriceOracle.json | jq -r .deployedBytecode.object const GALILEO_V2_L1_GAS_PRICE_ORACLE_BYTECODE: Bytes = bytes!("608060405234801561000f575f80fd5b50600436106101c6575f3560e01c8063715018a6116100fe578063bede39b51161009e578063e88a60ad1161006e578063e88a60ad1461035d578063f2fde38b14610370578063f45e65d814610383578063fe5b04151461038c575f80fd5b8063bede39b51461031c578063c63b9e2d1461032f578063c91e514914610342578063de26c4a11461034a575f80fd5b80638da5cb5b116100d95780638da5cb5b146102c457806393e59dc1146102ee578063944b247f14610301578063a911d77f14610314575f80fd5b8063715018a6146102ab5780637f977cbf146102b357806384189161146102bb575f80fd5b80633d0f963e116101695780635471db39116101445780635471db391461027d5780636112d6db146102865780636a5e67e51461028f5780637046559714610298575f80fd5b80633d0f963e1461024e57806349948e0e14610261578063519b4bd314610274575f80fd5b806323e524ac116101a457806323e524ac146102105780633577afc51461021957806339455d3a1461022e5780633b7656bb14610241575f80fd5b80630c18c162146101ca5780630f337f6d146101e657806313dad5be14610203575b5f80fd5b6101d360025481565b6040519081526020015b60405180910390f35b600c546101f39060ff1681565b60405190151581526020016101dd565b6008546101f39060ff1681565b6101d360065481565b61022c610227366004610ccf565b610394565b005b61022c61023c366004610ce6565b610426565b600b546101f39060ff1681565b61022c61025c366004610d06565b610523565b6101d361026f366004610d47565b6105a6565b6101d360015481565b6101d360095481565b6101d3600a5481565b6101d360075481565b61022c6102a6366004610ccf565b6105f3565b61022c610681565b61022c6106b5565b6101d360055481565b5f546102d6906001600160a01b031681565b6040516001600160a01b0390911681526020016101dd565b6004546102d6906001600160a01b031681565b61022c61030f366004610ccf565b610711565b61022c61079d565b61022c61032a366004610ccf565b6107f9565b61022c61033d366004610ccf565b6108b6565b6009546101d3565b6101d3610358366004610d47565b610933565b61022c61036b366004610ccf565b61096a565b61022c61037e366004610d06565b6109f6565b6101d360035481565b61022c610a81565b5f546001600160a01b031633146103c65760405162461bcd60e51b81526004016103bd90610df2565b60405180910390fd5b621c9c388111156103ea57604051635742c80560e11b815260040160405180910390fd5b60028190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa15801561046d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104919190610e29565b6104ae576040516326b3506d60e11b815260040160405180910390fd5b600182905560058190556040518281527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200160405180910390a16040518181527f9a14bfb5d18c4c3cf14cae19c23d7cf1bcede357ea40ca1f75cd49542c71c214906020015b60405180910390a15050565b5f546001600160a01b0316331461054c5760405162461bcd60e51b81526004016103bd90610df2565b600480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f22d1c35fe072d2e42c3c8f9bd4a0d34aa84a0101d020a62517b33fdb3174e5f79101610517565b600c545f9060ff16156105c2576105bc82610add565b92915050565b600b5460ff16156105d6576105bc82610b55565b60085460ff16156105ea576105bc82610bb3565b6105bc82610bef565b5f546001600160a01b0316331461061c5760405162461bcd60e51b81526004016103bd90610df2565b61062c633b9aca006103e8610e5c565b81111561064c57604051631e44fdeb60e11b815260040160405180910390fd5b60038190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a9060200161041b565b5f546001600160a01b031633146106aa5760405162461bcd60e51b81526004016103bd90610df2565b6106b35f610c20565b565b5f546001600160a01b031633146106de5760405162461bcd60e51b81526004016103bd90610df2565b600c5460ff16156107025760405163182389a760e01b815260040160405180910390fd5b600c805460ff19166001179055565b5f546001600160a01b0316331461073a5760405162461bcd60e51b81526004016103bd90610df2565b610748633b9aca0080610e5c565b8111156107685760405163874f603160e01b815260040160405180910390fd5b60068190556040518181527f2ab3f5a4ebbcbf3c24f62f5454f52f10e1a8c9dcc5acac8f19199ce881a6a1089060200161041b565b5f546001600160a01b031633146107c65760405162461bcd60e51b81526004016103bd90610df2565b60085460ff16156107ea576040516379f9c57560e01b815260040160405180910390fd5b6008805460ff19166001179055565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa158015610840573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108649190610e29565b610881576040516326b3506d60e11b815260040160405180910390fd5b60018190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200161041b565b5f546001600160a01b031633146108df5760405162461bcd60e51b81526004016103bd90610df2565b805f036108fe5760405162ae184360e01b815260040160405180910390fd5b600a8190556040518181527f8647cebb7e57360673a28415c0bed2f68c42a86c5035f1c9b2eda2b09509288a9060200161041b565b600c545f9060ff16806109485750600b5460ff165b80610955575060085460ff165b1561096157505f919050565b6105bc82610c6f565b5f546001600160a01b031633146109935760405162461bcd60e51b81526004016103bd90610df2565b6109a1633b9aca0080610e5c565b8111156109c15760405163f37ec21560e01b815260040160405180910390fd5b60078190556040518181527f6b332a036d8c3ead57dcb06c87243bd7a2aed015ddf2d0528c2501dae56331aa9060200161041b565b5f546001600160a01b03163314610a1f5760405162461bcd60e51b81526004016103bd90610df2565b6001600160a01b038116610a755760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f206164647265737300000060448201526064016103bd565b610a7e81610c20565b50565b5f546001600160a01b03163314610aaa5760405162461bcd60e51b81526004016103bd90610df2565b600b5460ff1615610ace57604051631a7c228b60e21b815260040160405180910390fd5b600b805460ff19166001179055565b5f808251600554600754610af19190610e5c565b600154600654610b019190610e5c565b610b0b9190610e73565b610b159190610e5c565b90505f600a54845183610b289190610e5c565b610b329190610e86565b9050633b9aca00610b438284610e73565b610b4d9190610e86565b949350505050565b5f633b9aca0080600a548451600554600754610b719190610e5c565b600154600654610b819190610e5c565b610b8b9190610e73565b610b959190610e5c565b610b9f9190610e5c565b610ba99190610e86565b6105bc9190610e86565b5f633b9aca006005548351600754610bcb9190610e5c565b610bd59190610e5c565b600154600654610be59190610e5c565b610ba99190610e73565b5f80610bfa83610c6f565b90505f60015482610c0b9190610e5c565b9050633b9aca0060035482610b439190610e5c565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80515f908190815b81811015610cc057848181518110610c9157610c91610ea5565b01602001516001600160f81b0319165f03610cb157600483019250610cb8565b6010830192505b600101610c77565b50506002540160400192915050565b5f60208284031215610cdf575f80fd5b5035919050565b5f8060408385031215610cf7575f80fd5b50508035926020909101359150565b5f60208284031215610d16575f80fd5b81356001600160a01b0381168114610d2c575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610d57575f80fd5b813567ffffffffffffffff80821115610d6e575f80fd5b818401915084601f830112610d81575f80fd5b813581811115610d9357610d93610d33565b604051601f8201601f19908116603f01168101908382118183101715610dbb57610dbb610d33565b81604052828152876020848701011115610dd3575f80fd5b826020860160208301375f928101602001929092525095945050505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b5f60208284031215610e39575f80fd5b81518015158114610d2c575f80fd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176105bc576105bc610e48565b808201808211156105bc576105bc610e48565b5f82610ea057634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffdfea164736f6c6343000818000a"); -/// L1 gas price oracle "is Galileo" slot. Added in the GalileoV2 fork. -pub const IS_GALILEO_SLOT: U256 = U256::from_limbs([12, 0, 0, 0]); - -/// Galileo slot is set to 1 (true) after the GalileoV2 block fork. +/// Galileo slot is set to 1 (true) after the `GalileoV2` block fork. const IS_GALILEO: U256 = U256::from_limbs([1, 0, 0, 0]); -/// Storage update of L1 gas price oracle at GalileoV2 transition. -const GALILEO_V2_L1_GAS_PRICE_ORACLE_STORAGE: [(U256, U256); 1] = [(IS_GALILEO_SLOT, IS_GALILEO)]; +/// Storage update of L1 gas price oracle at `GalileoV2` transition. +const GALILEO_V2_L1_GAS_PRICE_ORACLE_STORAGE: [(U256, U256); 1] = + [(GPO_IS_GALILEO_SLOT, IS_GALILEO)]; -/// Applies the Scroll GalileoV2 hard fork to the state: +/// Applies the Scroll `GalileoV2` hard fork to the state: /// - Updates the L1 oracle contract bytecode. /// - Sets the `isGalileo` slot to 1 (true). pub(super) fn apply_galileo_v2_hard_fork( state: &mut State, ) -> Result<(), DB::Error> { // No-op if already applied. - // Note: This requires a storage read for every block after GalileoV2, and it means this + // Note: This requires a storage read for every block after `GalileoV2`, and it means this // read needs to be included in the execution witness. Unfortunately, there is no // other reliable way to apply the change only at the transition block, since // `ScrollBlockExecutor` does not have access to the parent timestamp. - if state.storage(L1_GAS_PRICE_ORACLE_ADDRESS, IS_GALILEO_SLOT)? == IS_GALILEO { + if state.storage(L1_GAS_PRICE_ORACLE_ADDRESS, GPO_IS_GALILEO_SLOT)? == IS_GALILEO { return Ok(()) } @@ -84,6 +83,7 @@ pub(super) fn apply_galileo_v2_hard_fork( #[cfg(test)] mod tests { use super::*; + use crate::feynman::FEYNMAN_L1_GAS_PRICE_ORACLE_BYTECODE; use revm::{ database::{ states::{bundle_state::BundleRetention, plain_account::PlainStorage, StorageSlot}, @@ -95,8 +95,6 @@ mod tests { }; use std::str::FromStr; - use super::super::curie::CURIE_L1_GAS_PRICE_ORACLE_BYTECODE; - #[test] fn test_apply_galileo_v2_fork() -> eyre::Result<()> { // init state @@ -105,37 +103,25 @@ mod tests { State::builder().with_database(db).with_bundle_update().without_state_clear().build(); // oracle pre fork state - let bytecode_pre_fork = Bytecode::new_raw(CURIE_L1_GAS_PRICE_ORACLE_BYTECODE); + let bytecode_pre_fork = Bytecode::new_raw(FEYNMAN_L1_GAS_PRICE_ORACLE_BYTECODE); let oracle_pre_fork = AccountInfo { code_hash: bytecode_pre_fork.hash_slow(), code: Some(bytecode_pre_fork), ..Default::default() }; let oracle_storage_pre_fork = PlainStorage::from_iter([ - // owner - (U256::ZERO, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), - // l1BaseFee - (U256::from(1), U256::from(0x15f50e5e)), - // overhead - (U256::from(2), U256::from(0x38)), - // scalar - (U256::from(3), U256::from(0x3e95ba80)), - // whitelist - (U256::from(4), U256::from_str("0x5300000000000000000000000000000000000003")?), - // l1BlobBaseFee - (U256::from(5), U256::from(0x15f50e5e)), - // commitScalar - (U256::from(6), U256::from(0x3e95ba80)), - // blobScalar - (U256::from(7), U256::from(0x3e95ba80)), - // isCurie - (U256::from(8), U256::from(1)), - // penaltyThreshold - (U256::from(9), U256::from(1_000_000_000)), - // penaltyFactor - (U256::from(10), U256::from(1_000_000_000)), - // isFeynman - (U256::from(11), U256::from(1)), + (GPO_OWNER_SLOT, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), + (GPO_L1_BASE_FEE_SLOT, U256::from(0x15f50e5e)), + (GPO_OVERHEAD_SLOT, U256::from(0x38)), + (GPO_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_WHITELIST_SLOT, U256::from_str("0x5300000000000000000000000000000000000003")?), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(0x15f50e5e)), + (GPO_COMMIT_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_BLOB_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_IS_CURIE_SLOT, U256::from(1)), + (GPO_PENALTY_THRESHOLD_SLOT, U256::from(1_000_000_000)), + (GPO_PENALTY_FACTOR_SLOT, U256::from(1_000_000_000)), + (GPO_IS_FEYNMAN_SLOT, U256::from(1)), ]); state.insert_account_with_storage( L1_GAS_PRICE_ORACLE_ADDRESS, @@ -190,32 +176,19 @@ mod tests { }; let oracle_storage = PlainStorage::from_iter([ - // owner - (U256::ZERO, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), - // l1BaseFee - (U256::from(1), U256::from(0x15f50e5e)), - // overhead - (U256::from(2), U256::from(0x38)), - // scalar - (U256::from(3), U256::from(0x3e95ba80)), - // whitelist - (U256::from(4), U256::from_str("0x5300000000000000000000000000000000000003")?), - // l1BlobBaseFee - (U256::from(5), U256::from(0x15f50e5e)), - // commitScalar - (U256::from(6), U256::from(0x3e95ba80)), - // blobScalar - (U256::from(7), U256::from(0x3e95ba80)), - // isCurie - (U256::from(8), U256::from(1)), - // penaltyThreshold - (U256::from(9), U256::from(1_100_000_000u64)), - // penaltyFactor - (U256::from(10), U256::from(3_000_000_000u64)), - // isFeynman - (U256::from(11), U256::from(1)), - // isGalileo - (U256::from(12), U256::from(1)), + (GPO_OWNER_SLOT, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?), + (GPO_L1_BASE_FEE_SLOT, U256::from(0x15f50e5e)), + (GPO_OVERHEAD_SLOT, U256::from(0x38)), + (GPO_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_WHITELIST_SLOT, U256::from_str("0x5300000000000000000000000000000000000003")?), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(0x15f50e5e)), + (GPO_COMMIT_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_BLOB_SCALAR_SLOT, U256::from(0x3e95ba80)), + (GPO_IS_CURIE_SLOT, U256::from(1)), + (GPO_PENALTY_THRESHOLD_SLOT, U256::from(1_100_000_000u64)), + (GPO_PENALTY_FACTOR_SLOT, U256::from(3_000_000_000u64)), + (GPO_IS_FEYNMAN_SLOT, U256::from(1)), + (GPO_IS_GALILEO_SLOT, U256::from(1)), ]); // init state, diff --git a/crates/scroll/alloy/evm/src/block/mod.rs b/crates/scroll/alloy/evm/src/block/mod.rs index f4edfa525ea..0c7315c9a97 100644 --- a/crates/scroll/alloy/evm/src/block/mod.rs +++ b/crates/scroll/alloy/evm/src/block/mod.rs @@ -7,10 +7,10 @@ mod receipt_builder; use crate::{ block::{ - curie::{apply_curie_hard_fork, L1_GAS_PRICE_ORACLE_ADDRESS}, - feynman::apply_feynman_hard_fork, + curie::apply_curie_hard_fork, feynman::apply_feynman_hard_fork, galileo_v2::apply_galileo_v2_hard_fork, }, + gas_price_oracle::L1_GAS_PRICE_ORACLE_ADDRESS, system_caller::ScrollSystemCaller, FromTxWithCompressionInfo, ScrollDefaultPrecompilesFactory, ScrollEvm, ScrollEvmFactory, ScrollPrecompilesFactory, ScrollTransactionIntoTxEnv, ToTxWithCompressionInfo, diff --git a/crates/scroll/alloy/evm/src/gas_price_oracle.rs b/crates/scroll/alloy/evm/src/gas_price_oracle.rs new file mode 100644 index 00000000000..12ba98a3d69 --- /dev/null +++ b/crates/scroll/alloy/evm/src/gas_price_oracle.rs @@ -0,0 +1,88 @@ +//! L1 Gas Price Oracle constants. + +use revm::primitives::{address, Address, U256}; + +/// L1 gas price oracle address. +/// +pub const L1_GAS_PRICE_ORACLE_ADDRESS: Address = + address!("5300000000000000000000000000000000000002"); + +// forge inspect src/L2/predeploys/L1GasPriceOracle.sol:L1GasPriceOracle storageLayout +// ╭------------------+---------------------+------+--------+-------╮ +// | Name | Type | Slot | Offset | Bytes | +// +================================================================+ +// | owner | address | 0 | 0 | 20 | +// |------------------+---------------------+------+--------+-------+ +// | l1BaseFee | uint256 | 1 | 0 | 32 | +// |------------------+---------------------+------+--------+-------+ +// | overhead | uint256 | 2 | 0 | 32 | +// |------------------+---------------------+------+--------+-------+ +// | scalar | uint256 | 3 | 0 | 32 | +// |------------------+---------------------+------+--------+-------+ +// | whitelist | contract IWhitelist | 4 | 0 | 20 | +// |------------------+---------------------+------+--------+-------+ +// | l1BlobBaseFee | uint256 | 5 | 0 | 32 | +// |------------------+---------------------+------+--------+-------+ +// | commitScalar | uint256 | 6 | 0 | 32 | +// |------------------+---------------------+------+--------+-------+ +// | blobScalar | uint256 | 7 | 0 | 32 | +// |------------------+---------------------+------+--------+-------+ +// | isCurie | bool | 8 | 0 | 1 | +// |------------------+---------------------+------+--------+-------+ +// | penaltyThreshold | uint256 | 9 | 0 | 32 | +// |------------------+---------------------+------+--------+-------+ +// | penaltyFactor | uint256 | 10 | 0 | 32 | +// |------------------+---------------------+------+--------+-------+ +// | isFeynman | bool | 11 | 0 | 1 | +// |------------------+---------------------+------+--------+-------+ +// | __gap | uint248 | 11 | 1 | 31 | +// |------------------+---------------------+------+--------+-------+ +// | isGalileo | bool | 12 | 0 | 1 | +// ╰------------------+---------------------+------+--------+-------╯ + +/// Storage slot for `owner` in the `L1GasPriceOracle` contract. +pub const GPO_OWNER_SLOT: U256 = U256::from_limbs([0, 0, 0, 0]); + +/// Storage slot for `l1BaseFee` in the `L1GasPriceOracle` contract. +pub const GPO_L1_BASE_FEE_SLOT: U256 = U256::from_limbs([1, 0, 0, 0]); + +/// Storage slot for `overhead` in the `L1GasPriceOracle` contract. +pub const GPO_OVERHEAD_SLOT: U256 = U256::from_limbs([2, 0, 0, 0]); + +/// Storage slot for `scalar` in the `L1GasPriceOracle` contract. +pub const GPO_SCALAR_SLOT: U256 = U256::from_limbs([3, 0, 0, 0]); + +/// Storage slot for `whitelist` in the `L1GasPriceOracle` contract. +pub const GPO_WHITELIST_SLOT: U256 = U256::from_limbs([4, 0, 0, 0]); + +/// Storage slot for `blobBaseFee` in the `L1GasPriceOracle` contract. +/// Added in the Curie fork. +pub const GPO_L1_BLOB_BASE_FEE_SLOT: U256 = U256::from_limbs([5, 0, 0, 0]); + +/// Storage slot for `commitScalar` in the `L1GasPriceOracle` contract. +/// Added in the Curie fork. +pub const GPO_COMMIT_SCALAR_SLOT: U256 = U256::from_limbs([6, 0, 0, 0]); + +/// Storage slot for `blobSclar` in the `L1GasPriceOracle` contract. +/// Added in the Curie fork. +pub const GPO_BLOB_SCALAR_SLOT: U256 = U256::from_limbs([7, 0, 0, 0]); + +/// Storage slot for `isCurie` in the `L1GasPriceOracle` contract. +/// Added in the Curie fork. +pub const GPO_IS_CURIE_SLOT: U256 = U256::from_limbs([8, 0, 0, 0]); + +/// Storage slot for `penaltyThreshold` in the `L1GasPriceOracle` contract. +/// Added in the Feynman fork. +pub const GPO_PENALTY_THRESHOLD_SLOT: U256 = U256::from_limbs([9, 0, 0, 0]); + +/// Storage slot for `penaltyFactor` in the `L1GasPriceOracle` contract. +/// Added in the Feynman fork. +pub const GPO_PENALTY_FACTOR_SLOT: U256 = U256::from_limbs([10, 0, 0, 0]); + +/// Storage slot for `isFeynman` in the `L1GasPriceOracle` contract. +/// Added in the Feynman fork. +pub const GPO_IS_FEYNMAN_SLOT: U256 = U256::from_limbs([11, 0, 0, 0]); + +/// Storage slot for `isGalileo` in the `L1GasPriceOracle` contract. +/// Added in the Galileo fork. +pub const GPO_IS_GALILEO_SLOT: U256 = U256::from_limbs([12, 0, 0, 0]); diff --git a/crates/scroll/alloy/evm/src/lib.rs b/crates/scroll/alloy/evm/src/lib.rs index d7c7013d42f..7f1a9238e87 100644 --- a/crates/scroll/alloy/evm/src/lib.rs +++ b/crates/scroll/alloy/evm/src/lib.rs @@ -11,6 +11,8 @@ pub use block::{ ScrollTxCompressionInfos, }; +pub mod gas_price_oracle; + mod tx; pub use tx::{ compute_compressed_size, compute_compression_ratio, FromTxWithCompressionInfo, diff --git a/crates/scroll/alloy/evm/src/system_caller.rs b/crates/scroll/alloy/evm/src/system_caller.rs index 12f87c4d4a0..67d17bdbc34 100644 --- a/crates/scroll/alloy/evm/src/system_caller.rs +++ b/crates/scroll/alloy/evm/src/system_caller.rs @@ -94,7 +94,7 @@ mod tests { use super::*; use std::{convert::Infallible, sync::Arc}; - use crate::curie::L1_GAS_PRICE_ORACLE_ADDRESS; + use crate::gas_price_oracle::L1_GAS_PRICE_ORACLE_ADDRESS; use alloy_consensus::{Block, BlockBody, Header}; use alloy_eips::eip2935::HISTORY_STORAGE_CODE; use alloy_hardforks::ForkCondition; diff --git a/crates/scroll/chainspec/src/lib.rs b/crates/scroll/chainspec/src/lib.rs index e2c7ac1b66a..bd715b54368 100644 --- a/crates/scroll/chainspec/src/lib.rs +++ b/crates/scroll/chainspec/src/lib.rs @@ -741,6 +741,7 @@ mod tests { "euclidV2Time": 33, "feynmanTime": 34, "galileoTime": 35, + "galileoV2Time": 36, "scroll": { "feeVaultAddress": "0x5300000000000000000000000000000000000005", "maxTxPayloadBytesPerBlock": 122880, diff --git a/crates/scroll/evm/src/base_fee.rs b/crates/scroll/evm/src/base_fee.rs index 61d67b5bd45..411ac75bbab 100644 --- a/crates/scroll/evm/src/base_fee.rs +++ b/crates/scroll/evm/src/base_fee.rs @@ -4,12 +4,9 @@ use alloy_primitives::U256; use reth_chainspec::EthChainSpec; use reth_scroll_chainspec::{ChainConfig, ScrollChainConfig}; use reth_storage_api::{BaseFeeProvider, StorageProvider}; -use scroll_alloy_evm::curie::L1_GAS_PRICE_ORACLE_ADDRESS; +use scroll_alloy_evm::gas_price_oracle::{GPO_L1_BASE_FEE_SLOT, L1_GAS_PRICE_ORACLE_ADDRESS}; use scroll_alloy_hardforks::ScrollHardforks; -/// L1 gas price oracle base fee slot. -pub const L1_BASE_FEE_SLOT: U256 = U256::from_limbs([1, 0, 0, 0]); - /// Protocol-enforced maximum L2 base fee. pub const MAX_L2_BASE_FEE: u64 = 10_000_000_000; @@ -82,7 +79,7 @@ where feynman_base_fee(chain_spec, parent_header, ts, overhead.saturating_to()) } else { let parent_l1_base_fee = - provider.storage(L1_GAS_PRICE_ORACLE_ADDRESS, L1_BASE_FEE_SLOT)?; + provider.storage(L1_GAS_PRICE_ORACLE_ADDRESS, GPO_L1_BASE_FEE_SLOT)?; pre_feynman_base_fee(parent_l1_base_fee, scalar, overhead).saturating_to() }; @@ -190,7 +187,7 @@ mod tests { // helper closure to insert the l1 base fee in state. let insert_l1_base_fee = |state: &mut State, l1_base_fee: u64| { let oracle_storage_pre_fork = - PlainStorage::from_iter([(L1_BASE_FEE_SLOT, U256::from(l1_base_fee))]); + PlainStorage::from_iter([(GPO_L1_BASE_FEE_SLOT, U256::from(l1_base_fee))]); state.insert_account_with_storage( L1_GAS_PRICE_ORACLE_ADDRESS, Default::default(), diff --git a/crates/scroll/evm/src/execute.rs b/crates/scroll/evm/src/execute.rs index f3d40c6f30b..df76d8cee3d 100644 --- a/crates/scroll/evm/src/execute.rs +++ b/crates/scroll/evm/src/execute.rs @@ -78,13 +78,8 @@ mod tests { use scroll_alloy_consensus::{ScrollTransactionReceipt, ScrollTxEnvelope, ScrollTxType}; use scroll_alloy_evm::{ compute_compressed_size, compute_compression_ratio, - curie::{ - BLOB_SCALAR_SLOT, COMMIT_SCALAR_SLOT, CURIE_L1_GAS_PRICE_ORACLE_BYTECODE, - CURIE_L1_GAS_PRICE_ORACLE_STORAGE, IS_CURIE_SLOT, L1_BLOB_BASE_FEE_SLOT, - L1_GAS_PRICE_ORACLE_ADDRESS, - }, - feynman::{IS_FEYNMAN_SLOT, PENALTY_FACTOR_SLOT, PENALTY_THRESHOLD_SLOT}, - galileo_v2::IS_GALILEO_SLOT, + curie::{CURIE_L1_GAS_PRICE_ORACLE_BYTECODE, CURIE_L1_GAS_PRICE_ORACLE_STORAGE}, + gas_price_oracle::*, ScrollBlockExecutionCtx, ScrollBlockExecutor, ScrollEvm, ScrollTxCompressionInfos, }; use scroll_alloy_hardforks::ScrollHardforks; @@ -97,10 +92,6 @@ mod tests { const EUCLID_V2_BLOCK_TIMESTAMP: u64 = 1745305200; const FEYNMAN_BLOCK_TIMESTAMP: u64 = 1755576000; - const L1_BASE_FEE_SLOT: U256 = U256::from_limbs([1, 0, 0, 0]); - const OVER_HEAD_SLOT: U256 = U256::from_limbs([2, 0, 0, 0]); - const SCALAR_SLOT: U256 = U256::from_limbs([3, 0, 0, 0]); - fn state() -> State> { let db = EmptyDBTyped::::new(); State::builder().with_database(db).with_bundle_update().without_state_clear().build() @@ -234,46 +225,46 @@ mod tests { let l1_gas_oracle_storage = if strategy.spec().is_galileo_v2_active_at_timestamp(block_timestamp) { vec![ - (L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), - (OVER_HEAD_SLOT, U256::from(1000)), - (SCALAR_SLOT, U256::from(1000)), - (L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), - (COMMIT_SCALAR_SLOT, U256::from(1000)), - (BLOB_SCALAR_SLOT, U256::from(10000)), - (IS_CURIE_SLOT, U256::from(1)), - (PENALTY_THRESHOLD_SLOT, U256::from(1_000_000_000u64)), - (PENALTY_FACTOR_SLOT, U256::from(1_000_000_000u64)), - (IS_FEYNMAN_SLOT, U256::from(1)), - (IS_GALILEO_SLOT, U256::from(1)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), + (GPO_OVERHEAD_SLOT, U256::from(1000)), + (GPO_SCALAR_SLOT, U256::from(1000)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), + (GPO_COMMIT_SCALAR_SLOT, U256::from(1000)), + (GPO_BLOB_SCALAR_SLOT, U256::from(10000)), + (GPO_IS_CURIE_SLOT, U256::from(1)), + (GPO_PENALTY_THRESHOLD_SLOT, U256::from(1_000_000_000u64)), + (GPO_PENALTY_FACTOR_SLOT, U256::from(1_000_000_000u64)), + (GPO_IS_FEYNMAN_SLOT, U256::from(1)), + (GPO_IS_GALILEO_SLOT, U256::from(1)), ] } else if strategy.spec().is_feynman_active_at_timestamp(block_timestamp) { vec![ - (L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), - (OVER_HEAD_SLOT, U256::from(1000)), - (SCALAR_SLOT, U256::from(1000)), - (L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), - (COMMIT_SCALAR_SLOT, U256::from(1000)), - (BLOB_SCALAR_SLOT, U256::from(10000)), - (IS_CURIE_SLOT, U256::from(1)), - (PENALTY_THRESHOLD_SLOT, U256::from(1_000_000_000u64)), - (PENALTY_FACTOR_SLOT, U256::from(1_000_000_000u64)), - (IS_FEYNMAN_SLOT, U256::from(1)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), + (GPO_OVERHEAD_SLOT, U256::from(1000)), + (GPO_SCALAR_SLOT, U256::from(1000)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), + (GPO_COMMIT_SCALAR_SLOT, U256::from(1000)), + (GPO_BLOB_SCALAR_SLOT, U256::from(10000)), + (GPO_IS_CURIE_SLOT, U256::from(1)), + (GPO_PENALTY_THRESHOLD_SLOT, U256::from(1_000_000_000u64)), + (GPO_PENALTY_FACTOR_SLOT, U256::from(1_000_000_000u64)), + (GPO_IS_FEYNMAN_SLOT, U256::from(1)), ] } else if strategy.spec().is_curie_active_at_block(block_number) { vec![ - (L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), - (OVER_HEAD_SLOT, U256::from(1000)), - (SCALAR_SLOT, U256::from(1000)), - (L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), - (COMMIT_SCALAR_SLOT, U256::from(1000)), - (BLOB_SCALAR_SLOT, U256::from(10000)), - (IS_CURIE_SLOT, U256::from(1)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), + (GPO_OVERHEAD_SLOT, U256::from(1000)), + (GPO_SCALAR_SLOT, U256::from(1000)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), + (GPO_COMMIT_SCALAR_SLOT, U256::from(1000)), + (GPO_BLOB_SCALAR_SLOT, U256::from(10000)), + (GPO_IS_CURIE_SLOT, U256::from(1)), ] } else { vec![ - (L1_BASE_FEE_SLOT, U256::from(1000)), - (OVER_HEAD_SLOT, U256::from(1000)), - (SCALAR_SLOT, U256::from(1000)), + (GPO_L1_BASE_FEE_SLOT, U256::from(1000)), + (GPO_OVERHEAD_SLOT, U256::from(1000)), + (GPO_SCALAR_SLOT, U256::from(1000)), ] } .into_iter() @@ -321,46 +312,46 @@ mod tests { let l1_gas_oracle_storage = if strategy.spec().is_galileo_v2_active_at_timestamp(block_timestamp) { vec![ - (L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), - (OVER_HEAD_SLOT, U256::from(1000)), - (SCALAR_SLOT, U256::from(1000)), - (L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), - (COMMIT_SCALAR_SLOT, U256::from(1000)), - (BLOB_SCALAR_SLOT, U256::from(10000)), - (IS_CURIE_SLOT, U256::from(1)), - (PENALTY_THRESHOLD_SLOT, U256::from(2_000_000_000u64)), // penalty if <2x - (PENALTY_FACTOR_SLOT, U256::from(10_000_000_000u64)), // 10x penalty - (IS_FEYNMAN_SLOT, U256::from(1)), - (IS_GALILEO_SLOT, U256::from(1)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), + (GPO_OVERHEAD_SLOT, U256::from(1000)), + (GPO_SCALAR_SLOT, U256::from(1000)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), + (GPO_COMMIT_SCALAR_SLOT, U256::from(1000)), + (GPO_BLOB_SCALAR_SLOT, U256::from(10000)), + (GPO_IS_CURIE_SLOT, U256::from(1)), + (GPO_PENALTY_THRESHOLD_SLOT, U256::from(2_000_000_000u64)), // penalty if <2x + (GPO_PENALTY_FACTOR_SLOT, U256::from(10_000_000_000u64)), // 10x penalty + (GPO_IS_FEYNMAN_SLOT, U256::from(1)), + (GPO_IS_GALILEO_SLOT, U256::from(1)), ] } else if strategy.spec().is_feynman_active_at_timestamp(block_timestamp) { vec![ - (L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), - (OVER_HEAD_SLOT, U256::from(1000)), - (SCALAR_SLOT, U256::from(1000)), - (L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), - (COMMIT_SCALAR_SLOT, U256::from(1000)), - (BLOB_SCALAR_SLOT, U256::from(10000)), - (IS_CURIE_SLOT, U256::from(1)), - (PENALTY_THRESHOLD_SLOT, U256::from(2_000_000_000u64)), // penalty if <2x - (PENALTY_FACTOR_SLOT, U256::from(10_000_000_000u64)), // 10x penalty - (IS_FEYNMAN_SLOT, U256::from(1)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), + (GPO_OVERHEAD_SLOT, U256::from(1000)), + (GPO_SCALAR_SLOT, U256::from(1000)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), + (GPO_COMMIT_SCALAR_SLOT, U256::from(1000)), + (GPO_BLOB_SCALAR_SLOT, U256::from(10000)), + (GPO_IS_CURIE_SLOT, U256::from(1)), + (GPO_PENALTY_THRESHOLD_SLOT, U256::from(2_000_000_000u64)), // penalty if <2x + (GPO_PENALTY_FACTOR_SLOT, U256::from(10_000_000_000u64)), // 10x penalty + (GPO_IS_FEYNMAN_SLOT, U256::from(1)), ] } else if strategy.spec().is_curie_active_at_block(block_number) { vec![ - (L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), - (OVER_HEAD_SLOT, U256::from(1000)), - (SCALAR_SLOT, U256::from(1000)), - (L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), - (COMMIT_SCALAR_SLOT, U256::from(1000)), - (BLOB_SCALAR_SLOT, U256::from(10000)), - (IS_CURIE_SLOT, U256::from(1)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), + (GPO_OVERHEAD_SLOT, U256::from(1000)), + (GPO_SCALAR_SLOT, U256::from(1000)), + (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(10000)), + (GPO_COMMIT_SCALAR_SLOT, U256::from(1000)), + (GPO_BLOB_SCALAR_SLOT, U256::from(10000)), + (GPO_IS_CURIE_SLOT, U256::from(1)), ] } else { vec![ - (L1_BASE_FEE_SLOT, U256::from(1000)), - (OVER_HEAD_SLOT, U256::from(1000)), - (SCALAR_SLOT, U256::from(1000)), + (GPO_L1_BASE_FEE_SLOT, U256::from(1000)), + (GPO_OVERHEAD_SLOT, U256::from(1000)), + (GPO_SCALAR_SLOT, U256::from(1000)), ] } .into_iter() diff --git a/crates/scroll/evm/src/lib.rs b/crates/scroll/evm/src/lib.rs index 10c8f572018..745b31c9016 100644 --- a/crates/scroll/evm/src/lib.rs +++ b/crates/scroll/evm/src/lib.rs @@ -17,7 +17,7 @@ pub use l1::RethL1BlockInfo; mod base_fee; pub use base_fee::{ ScrollBaseFeeProvider, DEFAULT_BASE_FEE_OVERHEAD, DEFAULT_BASE_FEE_SCALAR, - L1_BASE_FEE_PRECISION, L1_BASE_FEE_SLOT, MAX_L2_BASE_FEE, + L1_BASE_FEE_PRECISION, MAX_L2_BASE_FEE, }; mod receipt; @@ -115,12 +115,10 @@ pub fn spec_id_at_timestamp_and_number( ) -> ScrollSpecId { if chain_spec .scroll_fork_activation(ScrollHardfork::GalileoV2) - .active_at_timestamp_or_number(timestamp, number) - { - ScrollSpecId::GALILEO - } else if chain_spec - .scroll_fork_activation(ScrollHardfork::Galileo) - .active_at_timestamp_or_number(timestamp, number) + .active_at_timestamp_or_number(timestamp, number) || + chain_spec + .scroll_fork_activation(ScrollHardfork::Galileo) + .active_at_timestamp_or_number(timestamp, number) { ScrollSpecId::GALILEO } else if chain_spec diff --git a/crates/scroll/node/src/builder/pool.rs b/crates/scroll/node/src/builder/pool.rs index 2f7c2b65a8a..27079e78d14 100644 --- a/crates/scroll/node/src/builder/pool.rs +++ b/crates/scroll/node/src/builder/pool.rs @@ -162,7 +162,7 @@ mod tests { PoolConfig, TransactionOrigin, TransactionPool, }; use scroll_alloy_consensus::{ScrollTxEnvelope, TxL1Message}; - use scroll_alloy_evm::curie::L1_GAS_PRICE_ORACLE_ADDRESS; + use scroll_alloy_evm::gas_price_oracle::L1_GAS_PRICE_ORACLE_ADDRESS; async fn pool() -> ( ScrollTransactionPool, DiskFileBlobStore>, From 16b8b5c93844532eaab27901bcdba7aa22d58241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Nov 2025 15:10:31 +0100 Subject: [PATCH 4/7] fix --- crates/scroll/chainspec/src/dev.rs | 1 + crates/scroll/chainspec/src/lib.rs | 2 +- crates/scroll/hardforks/src/lib.rs | 3 +++ crates/scroll/node/src/test_utils.rs | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/scroll/chainspec/src/dev.rs b/crates/scroll/chainspec/src/dev.rs index 61bc0e52d62..a16a6792cfd 100644 --- a/crates/scroll/chainspec/src/dev.rs +++ b/crates/scroll/chainspec/src/dev.rs @@ -20,6 +20,7 @@ use scroll_alloy_hardforks::ScrollHardfork; pub static SCROLL_DEV: LazyLock> = LazyLock::new(|| { // In order to have Feynman activated at block 0, we set the `baseFeePerGas` field of the devnet // genesis to 0. + // TODO(thegaram): Update L1GasPriceOracle genesis account bytecode and storage. let genesis = serde_json::from_str(include_str!("../res/genesis/dev.json")) .expect("Can't deserialize Dev testnet genesis json"); diff --git a/crates/scroll/chainspec/src/lib.rs b/crates/scroll/chainspec/src/lib.rs index bd715b54368..1b67205476e 100644 --- a/crates/scroll/chainspec/src/lib.rs +++ b/crates/scroll/chainspec/src/lib.rs @@ -190,7 +190,7 @@ impl ScrollChainSpecBuilder { /// Enable `GalileoV2` at genesis pub fn galileo_v2_activated(mut self) -> Self { - self = self.feynman_activated(); + self = self.galileo_activated(); self.inner = self.inner.with_fork(ScrollHardfork::GalileoV2, ForkCondition::Timestamp(0)); self } diff --git a/crates/scroll/hardforks/src/lib.rs b/crates/scroll/hardforks/src/lib.rs index 99a23458473..d9ce3e95256 100644 --- a/crates/scroll/hardforks/src/lib.rs +++ b/crates/scroll/hardforks/src/lib.rs @@ -41,6 +41,7 @@ pub static SCROLL_MAINNET_HARDFORKS: LazyLock = LazyLock::new(|| (ScrollHardfork::EuclidV2.boxed(), ForkCondition::Timestamp(1745305200)), (ScrollHardfork::Feynman.boxed(), ForkCondition::Timestamp(1755576000)), (ScrollHardfork::Galileo.boxed(), ForkCondition::Timestamp(u64::MAX)), + (ScrollHardfork::GalileoV2.boxed(), ForkCondition::Timestamp(u64::MAX)), ]) }); @@ -66,6 +67,7 @@ pub static SCROLL_SEPOLIA_HARDFORKS: LazyLock = LazyLock::new(|| (ScrollHardfork::EuclidV2.boxed(), ForkCondition::Timestamp(1741852800)), (ScrollHardfork::Feynman.boxed(), ForkCondition::Timestamp(1753167600)), (ScrollHardfork::Galileo.boxed(), ForkCondition::Timestamp(1764054000)), + (ScrollHardfork::GalileoV2.boxed(), ForkCondition::Timestamp(u64::MAX)), ]) }); @@ -91,5 +93,6 @@ pub static DEV_HARDFORKS: LazyLock = LazyLock::new(|| { (ScrollHardfork::EuclidV2.boxed(), ForkCondition::Timestamp(0)), (ScrollHardfork::Feynman.boxed(), ForkCondition::Timestamp(0)), (ScrollHardfork::Galileo.boxed(), ForkCondition::Timestamp(0)), + (ScrollHardfork::GalileoV2.boxed(), ForkCondition::Timestamp(0)), ]) }); diff --git a/crates/scroll/node/src/test_utils.rs b/crates/scroll/node/src/test_utils.rs index 822f62c34b0..2530441b9be 100644 --- a/crates/scroll/node/src/test_utils.rs +++ b/crates/scroll/node/src/test_utils.rs @@ -31,7 +31,7 @@ pub async fn setup( reth_e2e_test_utils::setup_engine( num_nodes, Arc::new( - ScrollChainSpecBuilder::scroll_mainnet().genesis(genesis).galileo_activated().build( + ScrollChainSpecBuilder::scroll_mainnet().genesis(genesis).galileo_v2_activated().build( ScrollChainConfig { max_tx_payload_bytes_per_block: 120 * 1024, ..Default::default() From 3e8428b3d3a60d4e0b7e9962d56c346167ce65f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Nov 2025 15:13:21 +0100 Subject: [PATCH 5/7] typo --- crates/scroll/alloy/evm/src/gas_price_oracle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/scroll/alloy/evm/src/gas_price_oracle.rs b/crates/scroll/alloy/evm/src/gas_price_oracle.rs index 12ba98a3d69..6a8ec82b42d 100644 --- a/crates/scroll/alloy/evm/src/gas_price_oracle.rs +++ b/crates/scroll/alloy/evm/src/gas_price_oracle.rs @@ -63,7 +63,7 @@ pub const GPO_L1_BLOB_BASE_FEE_SLOT: U256 = U256::from_limbs([5, 0, 0, 0]); /// Added in the Curie fork. pub const GPO_COMMIT_SCALAR_SLOT: U256 = U256::from_limbs([6, 0, 0, 0]); -/// Storage slot for `blobSclar` in the `L1GasPriceOracle` contract. +/// Storage slot for `blobScalar` in the `L1GasPriceOracle` contract. /// Added in the Curie fork. pub const GPO_BLOB_SCALAR_SLOT: U256 = U256::from_limbs([7, 0, 0, 0]); From 97cb53e6e29e3b89ea8efc28e0a30430ede1ddc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Nov 2025 15:23:45 +0100 Subject: [PATCH 6/7] fix forkid test --- crates/scroll/chainspec/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/scroll/chainspec/src/lib.rs b/crates/scroll/chainspec/src/lib.rs index 1b67205476e..01a1ad772b8 100644 --- a/crates/scroll/chainspec/src/lib.rs +++ b/crates/scroll/chainspec/src/lib.rs @@ -715,7 +715,7 @@ mod tests { // Galileo ( Head { number: 4740239, timestamp: 1764054000, ..Default::default() }, - ForkId { hash: ForkHash([0xe8, 0xc2, 0x20, 0x80]), next: 0 }, + ForkId { hash: ForkHash([0xe8, 0xc2, 0x20, 0x80]), next: u64::MAX }, ), ], ); From 871daf2943df348ca51e9d6cbf73e68a4bbcbbfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Nov 2025 16:34:36 +0100 Subject: [PATCH 7/7] add galileo fee test --- crates/scroll/alloy/hardforks/src/lib.rs | 3 +- crates/scroll/evm/src/execute.rs | 50 +++++++++++++++++++----- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/crates/scroll/alloy/hardforks/src/lib.rs b/crates/scroll/alloy/hardforks/src/lib.rs index be76ecfcfa2..6a19b2d6af8 100644 --- a/crates/scroll/alloy/hardforks/src/lib.rs +++ b/crates/scroll/alloy/hardforks/src/lib.rs @@ -4,7 +4,8 @@ #[cfg(not(feature = "std"))] extern crate alloc as std; -use alloy_hardforks::{EthereumHardfork, EthereumHardforks, ForkCondition}; +pub use alloy_hardforks::ForkCondition; +use alloy_hardforks::{EthereumHardfork, EthereumHardforks}; use std::vec::Vec; pub use hardfork::ScrollHardfork; diff --git a/crates/scroll/evm/src/execute.rs b/crates/scroll/evm/src/execute.rs index df76d8cee3d..02da4109559 100644 --- a/crates/scroll/evm/src/execute.rs +++ b/crates/scroll/evm/src/execute.rs @@ -82,7 +82,7 @@ mod tests { gas_price_oracle::*, ScrollBlockExecutionCtx, ScrollBlockExecutor, ScrollEvm, ScrollTxCompressionInfos, }; - use scroll_alloy_hardforks::ScrollHardforks; + use scroll_alloy_hardforks::{ForkCondition, ScrollHardfork, ScrollHardforks}; const BLOCK_GAS_LIMIT: u64 = 10_000_000; const SCROLL_CHAIN_ID: u64 = 534352; @@ -91,6 +91,7 @@ mod tests { const EUCLID_V2_BLOCK_NUMBER: u64 = 14907015; const EUCLID_V2_BLOCK_TIMESTAMP: u64 = 1745305200; const FEYNMAN_BLOCK_TIMESTAMP: u64 = 1755576000; + const GALILEO_BLOCK_TIMESTAMP: u64 = 1755576001; // TODO(thegaram): update to actual timestamp fn state() -> State> { let db = EmptyDBTyped::::new(); @@ -106,8 +107,10 @@ mod tests { ScrollRethReceiptBuilder, Arc, > { - let chain_spec = - Arc::new(ScrollChainSpecBuilder::scroll_mainnet().build(ScrollChainConfig::mainnet())); + // build chain spec based on mainnet config, with some fork overrides + let spec_builder = ScrollChainSpecBuilder::scroll_mainnet() + .with_fork(ScrollHardfork::Galileo, ForkCondition::Timestamp(GALILEO_BLOCK_TIMESTAMP)); + let chain_spec = Arc::new(spec_builder.build(ScrollChainConfig::mainnet())); let evm_config = ScrollEvmConfig::scroll(chain_spec.clone()); let evm = @@ -223,7 +226,7 @@ mod tests { // determine l1 gas oracle storage let l1_gas_oracle_storage = - if strategy.spec().is_galileo_v2_active_at_timestamp(block_timestamp) { + if strategy.spec().is_galileo_active_at_timestamp(block_timestamp) { vec![ (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), (GPO_OVERHEAD_SLOT, U256::from(1000)), @@ -233,9 +236,9 @@ mod tests { (GPO_BLOB_SCALAR_SLOT, U256::from(10000)), (GPO_IS_CURIE_SLOT, U256::from(1)), (GPO_PENALTY_THRESHOLD_SLOT, U256::from(1_000_000_000u64)), - (GPO_PENALTY_FACTOR_SLOT, U256::from(1_000_000_000u64)), + (GPO_PENALTY_FACTOR_SLOT, U256::from(5u64)), // apply high penalty (GPO_IS_FEYNMAN_SLOT, U256::from(1)), - (GPO_IS_GALILEO_SLOT, U256::from(1)), + (GPO_IS_GALILEO_SLOT, U256::from(0)), // only activated in `GalileoV2` ] } else if strategy.spec().is_feynman_active_at_timestamp(block_timestamp) { vec![ @@ -310,7 +313,7 @@ mod tests { // determine l1 gas oracle storage let l1_gas_oracle_storage = - if strategy.spec().is_galileo_v2_active_at_timestamp(block_timestamp) { + if strategy.spec().is_galileo_active_at_timestamp(block_timestamp) { vec![ (GPO_L1_BLOB_BASE_FEE_SLOT, U256::from(1000)), (GPO_OVERHEAD_SLOT, U256::from(1000)), @@ -320,9 +323,10 @@ mod tests { (GPO_BLOB_SCALAR_SLOT, U256::from(10000)), (GPO_IS_CURIE_SLOT, U256::from(1)), (GPO_PENALTY_THRESHOLD_SLOT, U256::from(2_000_000_000u64)), // penalty if <2x - (GPO_PENALTY_FACTOR_SLOT, U256::from(10_000_000_000u64)), // 10x penalty + (GPO_PENALTY_FACTOR_SLOT, U256::from(5u64)), /* apply high + * penalty */ (GPO_IS_FEYNMAN_SLOT, U256::from(1)), - (GPO_IS_GALILEO_SLOT, U256::from(1)), + (GPO_IS_GALILEO_SLOT, U256::from(0)), // only activated in `GalileoV2` ] } else if strategy.spec().is_feynman_active_at_timestamp(block_timestamp) { vec![ @@ -519,6 +523,20 @@ mod tests { Ok(()) } + #[test] + fn test_execute_transaction_l1_message_galileo_fork() -> eyre::Result<()> { + // Execute L1 message on galileo block + let expected_l1_fee = U256::ZERO; + execute_transaction( + ScrollTxType::L1Message, + CURIE_BLOCK_NUMBER + 1, + GALILEO_BLOCK_TIMESTAMP, + expected_l1_fee, + None, + )?; + Ok(()) + } + #[test] fn test_execute_transactions_legacy_curie_fork() -> eyre::Result<()> { // Execute legacy transaction on curie block @@ -555,6 +573,20 @@ mod tests { Ok(()) } + #[test] + fn test_execute_transactions_legacy_galileo_fork() -> eyre::Result<()> { + // Execute legacy transaction on galileo block + let expected_l1_fee = U256::from(182); + execute_transaction( + ScrollTxType::Legacy, + CURIE_BLOCK_NUMBER + 1, + GALILEO_BLOCK_TIMESTAMP, + expected_l1_fee, + None, + )?; + Ok(()) + } + #[test] fn test_execute_transactions_eip2930_curie_fork() -> eyre::Result<()> { // Execute eip2930 transaction on curie block