diff --git a/crates/evm/core/src/era_revm/db.rs b/crates/evm/core/src/era_revm/db.rs index 02a7ac6ed..1e1f52c3c 100644 --- a/crates/evm/core/src/era_revm/db.rs +++ b/crates/evm/core/src/era_revm/db.rs @@ -33,7 +33,7 @@ use zksync_utils::{address_to_h256, h256_to_u256, u256_to_h256}; #[derive(Default)] pub struct RevmDatabaseForEra { pub db: Arc>>, - pub current_block: u64, + current_block: u64, } impl Clone for RevmDatabaseForEra { @@ -55,9 +55,26 @@ impl RevmDatabaseForEra where ::Error: Debug, { - /// Returns the current block number and timestamp from the database. + /// Create a new instance of [RevmDatabaseForEra] caching the current l2 block. + pub fn new(db: Arc>>) -> Self { + let db_inner = db.clone(); + let current_block = { + let mut db = db_inner.lock().unwrap(); + let result = db + .storage(h160_to_address(SYSTEM_CONTEXT_ADDRESS), u256_to_revm_u256(U256::from(9))) + .unwrap(); + let num_and_ts = revm_u256_to_h256(result); + let num_and_ts_bytes = num_and_ts.as_fixed_bytes(); + let num: [u8; 8] = num_and_ts_bytes[24..32].try_into().unwrap(); + u64::from_be_bytes(num) + }; + + Self { db, current_block } + } + + /// Returns the current L1 block number and timestamp from the database. /// Reads it directly from the SYSTEM_CONTEXT storage. - pub fn block_number_and_timestamp(&self) -> (u64, u64) { + pub fn get_l1_block_number_and_timestamp(&self) -> (u64, u64) { let num_and_ts = self.read_storage_internal(SYSTEM_CONTEXT_ADDRESS, U256::from(7)); let num_and_ts_bytes = num_and_ts.as_fixed_bytes(); let num: [u8; 8] = num_and_ts_bytes[24..32].try_into().unwrap(); @@ -66,6 +83,17 @@ where (u64::from_be_bytes(num), u64::from_be_bytes(ts)) } + /// Returns the current L2 block number and timestamp from the database. + /// Reads it directly from the SYSTEM_CONTEXT storage. + pub fn get_l2_block_number_and_timestamp(&self) -> (u64, u64) { + let num_and_ts = self.read_storage_internal(SYSTEM_CONTEXT_ADDRESS, U256::from(9)); + let num_and_ts_bytes = num_and_ts.as_fixed_bytes(); + let num: [u8; 8] = num_and_ts_bytes[24..32].try_into().unwrap(); + let ts: [u8; 8] = num_and_ts_bytes[8..16].try_into().unwrap(); + + (u64::from_be_bytes(num), u64::from_be_bytes(ts)) + } + /// Returns the nonce for a given account from NonceHolder storage. pub fn get_nonce_for_address(&self, address: H160) -> u64 { // Nonce is stored in the first mapping of the Nonce contract. @@ -155,14 +183,13 @@ where idx: U256, block: Option, ) -> eyre::Result { - // We cannot support historical lookups. Only the most recent block is supported. - let current_block = self.current_block; + // We cannot support historical lookups. Only the most recent L2 block is supported. if let Some(block) = &block { match block { BlockIdVariant::BlockNumber(zksync_types::api::BlockNumber::Number(num)) => { - let current_block_number_l2 = current_block * 2; - if num.as_u64() != current_block_number_l2 { - eyre::bail!("Only fetching of the most recent L2 block {} is supported - but queried for {}", current_block_number_l2, num) + // let current_block_number_l2 = current_l1_block * 2; + if num.as_u64() != self.current_block { + eyre::bail!("Only fetching of the most recent L2 block {} is supported - but queried for {}", self.current_block, num) } } _ => eyre::bail!("Only fetching most recent block is implemented"), diff --git a/crates/evm/core/src/era_revm/transactions.rs b/crates/evm/core/src/era_revm/transactions.rs index 7563cb373..6252749d6 100644 --- a/crates/evm/core/src/era_revm/transactions.rs +++ b/crates/evm/core/src/era_revm/transactions.rs @@ -135,10 +135,9 @@ where ::Error: Debug, INSP: ToTracerPointer>>, HistoryDisabled>, { - let (num, ts) = (env.block.number.to::(), env.block.timestamp.to::()); - let era_db = RevmDatabaseForEra { db: Arc::new(Mutex::new(Box::new(db))), current_block: num }; - + let era_db = RevmDatabaseForEra::new(Arc::new(Mutex::new(Box::new(db)))); let nonces = era_db.get_nonce_for_address(address_to_h160(env.tx.caller)); + let (num, ts) = era_db.get_l2_block_number_and_timestamp(); debug!( "*** Starting ERA transaction: block: {:?} timestamp: {:?} - but using {:?} and {:?} instead with nonce {:?}", @@ -161,14 +160,14 @@ where 31337 }; - let (l2_num, l2_ts) = (num * 2, ts * 2); + let l1_num = num / 2; let fork_details = ForkDetails { fork_source: era_db.clone(), - l1_block: L1BatchNumber(num as u32), + l1_block: L1BatchNumber(l1_num as u32), l2_block: Block::default(), - l2_miniblock: l2_num, + l2_miniblock: num, l2_miniblock_hash: Default::default(), - block_timestamp: l2_ts, + block_timestamp: ts, overwrite_chain_id: Some(L2ChainId::from(chain_id_u32)), // Make sure that l1 gas price is set to reasonable values. l1_gas_price: u64::max(env.block.basefee.to::(), 1000), diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index 5f58cc53f..f29cf7917 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -147,15 +147,6 @@ impl Executor { self } - // Record any changes made to the block's environment during setup, - // and also the chainid, which can be set manually. - pub fn record_env_changes(&mut self, env: &Env) { - // record any changes made to the block's environment during setup - self.env.block = env.block.clone(); - // and also the chainid, which can be set manually - self.env.cfg.chain_id = env.cfg.chain_id; - } - /// Calls the `setUp()` function on a contract. /// /// This will commit any state changes to the underlying database. @@ -169,7 +160,10 @@ impl Executor { self.backend.set_test_contract(to).set_caller(from); let res = self.call_committing::<_, _>(from, to, "setUp()", vec![], U256::ZERO, None)?; - self.record_env_changes(&res.env); + // record any changes made to the block's environment during setup + self.env.block = env.block.clone(); + // and also the chainid, which can be set manually + self.env.cfg.chain_id = env.cfg.chain_id; match res.state_changeset.as_ref() { Some(changeset) => { @@ -249,7 +243,6 @@ impl Executor { // execute the call let env = self.build_test_env(from, TransactTo::Call(test_contract), calldata, value); let call_result = self.call_raw_with_env(env)?; - self.record_env_changes(&call_result.env); convert_call_result(abi, &func, call_result) } @@ -432,12 +425,7 @@ impl Executor { abi: Option<&Abi>, ) -> Result { let env = self.build_test_env(from, TransactTo::Create(CreateScheme::Create), code, value); - let res = self.deploy_with_env(env, abi); - if let Ok(DeployResult { env, .. }) = &res { - self.record_env_changes(env); - } - - res + self.deploy_with_env(env, abi) } /// Check if a call to a test contract was successful.