Skip to content

Commit 090d795

Browse files
greged93Thegaram
andauthored
fix: feynman transition function (#285)
* fix: feynman transition function Signed-off-by: Gregory Edison <[email protected]> * add unit test --------- Signed-off-by: Gregory Edison <[email protected]> Co-authored-by: Péter Garamvölgyi <[email protected]>
1 parent 95b2762 commit 090d795

File tree

1 file changed

+70
-4
lines changed

1 file changed

+70
-4
lines changed

crates/scroll/alloy/evm/src/block/feynman.rs

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,17 @@ const FEYNMAN_L1_GAS_PRICE_ORACLE_STORAGE: [(U256, U256); 3] = [
4242
pub(super) fn apply_feynman_hard_fork<DB: Database>(
4343
state: &mut State<DB>,
4444
) -> Result<(), DB::Error> {
45-
let oracle = state.load_cache_account(L1_GAS_PRICE_ORACLE_ADDRESS)?;
46-
4745
// No-op if already applied.
4846
// Note: This requires a storage read for every Feynman block, and it means this
4947
// read needs to be included in the execution witness. Unfortunately, there is no
5048
// other reliable way to apply the change only at the transition block, since
5149
// `ScrollBlockExecutor` does not have access to the parent timestamp.
52-
if matches!(oracle.storage_slot(IS_FEYNMAN_SLOT), Some(val) if val == IS_FEYNMAN) {
50+
if state.storage(L1_GAS_PRICE_ORACLE_ADDRESS, IS_FEYNMAN_SLOT)? == IS_FEYNMAN {
5351
return Ok(())
5452
}
5553

54+
let oracle = state.load_cache_account(L1_GAS_PRICE_ORACLE_ADDRESS)?;
55+
5656
// compute the code hash
5757
let bytecode = Bytecode::new_raw(FEYNMAN_L1_GAS_PRICE_ORACLE_BYTECODE);
5858
let code_hash = bytecode.hash_slow();
@@ -94,7 +94,7 @@ mod tests {
9494
use revm::{
9595
database::{
9696
states::{bundle_state::BundleRetention, plain_account::PlainStorage, StorageSlot},
97-
EmptyDB, State,
97+
CacheDB, EmptyDB, State,
9898
},
9999
primitives::{keccak256, U256},
100100
state::{AccountInfo, Bytecode},
@@ -195,4 +195,70 @@ mod tests {
195195

196196
Ok(())
197197
}
198+
199+
#[test]
200+
fn test_apply_feynman_fork_only_once() -> eyre::Result<()> {
201+
let bytecode = Bytecode::new_raw(FEYNMAN_L1_GAS_PRICE_ORACLE_BYTECODE);
202+
203+
let oracle_account = AccountInfo {
204+
code_hash: bytecode.hash_slow(),
205+
code: Some(bytecode),
206+
..Default::default()
207+
};
208+
209+
let oracle_storage = PlainStorage::from_iter([
210+
// owner
211+
(U256::ZERO, U256::from_str("0x13d24a7ff6f5ec5ff0e9c40fc3b8c9c01c65437b")?),
212+
// l1BaseFee
213+
(U256::from(1), U256::from(0x15f50e5e)),
214+
// overhead
215+
(U256::from(2), U256::from(0x38)),
216+
// scalar
217+
(U256::from(3), U256::from(0x3e95ba80)),
218+
// whitelist
219+
(U256::from(4), U256::from_str("0x5300000000000000000000000000000000000003")?),
220+
// l1BlobBaseFee
221+
(U256::from(5), U256::from(0x15f50e5e)),
222+
// commitScalar
223+
(U256::from(6), U256::from(0x3e95ba80)),
224+
// blobScalar
225+
(U256::from(7), U256::from(0x3e95ba80)),
226+
// isCurie
227+
(U256::from(8), U256::from(1)),
228+
// penaltyThreshold
229+
(U256::from(9), U256::from(1_100_000_000u64)),
230+
// penaltyFactor
231+
(U256::from(10), U256::from(3_000_000_000u64)),
232+
// isFeynman
233+
(U256::from(11), U256::from(1)),
234+
]);
235+
236+
// init state,
237+
// we write to db directly to make sure we do not have account storage in cache
238+
let mut db = CacheDB::new(EmptyDB::default());
239+
240+
db.insert_account_info(L1_GAS_PRICE_ORACLE_ADDRESS, oracle_account);
241+
242+
for (slot, value) in oracle_storage {
243+
db.insert_account_storage(L1_GAS_PRICE_ORACLE_ADDRESS, slot, value).unwrap();
244+
}
245+
246+
let mut state =
247+
State::builder().with_database(db).with_bundle_update().without_state_clear().build();
248+
249+
// make sure account is in cache
250+
state.load_cache_account(L1_GAS_PRICE_ORACLE_ADDRESS)?;
251+
252+
// apply feynman fork
253+
apply_feynman_hard_fork(&mut state)?;
254+
255+
// merge transitions
256+
state.merge_transitions(BundleRetention::Reverts);
257+
let bundle = state.take_bundle();
258+
259+
// isFeynman is already set, apply_feynman_hard_fork should be a no-op
260+
assert_eq!(bundle.state.get(&L1_GAS_PRICE_ORACLE_ADDRESS), None);
261+
262+
Ok(())
263+
}
198264
}

0 commit comments

Comments
 (0)