Skip to content

Commit 839408d

Browse files
tomip01lima-limon-inc
authored andcommitted
fix(levm): increase support for stZeroCallsTest test suite (#1975)
**Motivation** This pull request includes several changes to improve handling of account state transitions and gas cost calculations, particularly in relation to Ethereum's EIP-161. **Description** * `cmd/ef_tests/state/runner/levm_runner.rs`: Implemented logic to remove accounts that remain empty after the Spurious Dragon fork, in compliance with EIP-161. * `crates/vm/levm/src/gas_cost.rs`: Added a new parameter `address_exists` to the `call` function and updated the logic for handling empty accounts based on EIP-161. * `crates/vm/levm/src/opcode_handlers/system.rs`: Updated the `call` and `selfdestruct` function to check if an account exists and adjusted the logic for determining if an account is empty based on the fork configuration. --------- Co-authored-by: Tomas Fabrizio Orsi <[email protected]>
1 parent 2a6519d commit 839408d

File tree

5 files changed

+32
-6
lines changed

5 files changed

+32
-6
lines changed

cmd/ef_tests/state/runner/levm_runner.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{
44
types::{EFTest, TransactionExpectedException},
55
utils::{self, effective_gas_price},
66
};
7+
use bytes::Bytes;
78
use ethrex_common::{
89
types::{code_hash, tx_fields::*, AccountInfo, Fork},
910
H256, U256,
@@ -313,7 +314,7 @@ pub fn ensure_post_state(
313314
None => {
314315
let (initial_state, block_hash) = utils::load_initial_state(test);
315316
let levm_account_updates =
316-
get_state_transitions(&initial_state, block_hash, execution_report);
317+
get_state_transitions(&initial_state, block_hash, execution_report, fork);
317318
let pos_state_root = post_state_root(&levm_account_updates, test);
318319
let expected_post_state_root_hash =
319320
test.post.vector_post_value(vector, *fork).hash;
@@ -372,6 +373,7 @@ pub fn get_state_transitions(
372373
initial_state: &EvmState,
373374
block_hash: H256,
374375
execution_report: &ExecutionReport,
376+
fork: &Fork,
375377
) -> Vec<AccountUpdate> {
376378
let current_db = match initial_state {
377379
EvmState::Store(state) => state.database.store.clone(),
@@ -441,8 +443,25 @@ pub fn get_state_transitions(
441443
added_storage,
442444
};
443445

446+
if let Some(old_info) = current_db
447+
.get_account_info_by_hash(block_hash, account_update.address)
448+
.unwrap()
449+
{
450+
// https://eips.ethereum.org/EIPS/eip-161
451+
// if an account was empty and is now empty, after spurious dragon, it should be removed
452+
if account_update.removed
453+
&& old_info.balance.is_zero()
454+
&& old_info.nonce == 0
455+
&& old_info.code_hash == code_hash(&Bytes::new())
456+
&& *fork < Fork::SpuriousDragon
457+
{
458+
continue;
459+
}
460+
}
461+
444462
account_updates.push(account_update);
445463
}
464+
446465
account_updates
447466
}
448467

cmd/ef_tests/state/runner/revm_runner.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ pub fn ensure_post_state(
329329
&initial_state,
330330
block_hash,
331331
levm_execution_report,
332+
fork,
332333
);
333334
let revm_account_updates = ethrex_vm::get_state_transitions(revm_state);
334335
let account_updates_report = compare_levm_revm_account_updates(

crates/vm/levm/src/gas_cost.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,7 @@ pub fn call(
829829
current_memory_size: usize,
830830
address_was_cold: bool,
831831
address_is_empty: bool,
832+
address_exists: bool,
832833
value_to_transfer: U256,
833834
gas_from_stack: U256,
834835
gas_left: u64,
@@ -854,9 +855,8 @@ pub fn call(
854855
} else {
855856
0
856857
};
857-
858-
// https://eips.ethereum.org/EIPS/eip-161
859-
let value_to_empty_account = if (address_is_empty && fork < Fork::SpuriousDragon)
858+
// https://eips.ethereum.org/EIPS/eip-161 change the definition of empty address
859+
let value_to_empty_account = if (!address_exists && fork < Fork::SpuriousDragon)
860860
|| address_is_empty && !value_to_transfer.is_zero() && fork >= Fork::SpuriousDragon
861861
{
862862
CALL_TO_EMPTY_ACCOUNT

crates/vm/levm/src/opcode_handlers/system.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ impl VM {
7272
current_memory_size,
7373
address_was_cold,
7474
account_info.is_empty(),
75+
self.db.account_exists(callee),
7576
value_to_transfer,
7677
gas,
7778
gas_left,
@@ -542,9 +543,14 @@ impl VM {
542543
);
543544
let balance_to_transfer = current_account_info.balance;
544545

546+
let account_is_empty = if self.env.config.fork >= Fork::SpuriousDragon {
547+
target_account_info.is_empty()
548+
} else {
549+
!self.db.account_exists(target_address)
550+
};
545551
current_call_frame.increase_consumed_gas(gas_cost::selfdestruct(
546552
target_account_is_cold,
547-
target_account_info.is_empty(),
553+
account_is_empty,
548554
balance_to_transfer,
549555
self.env.config.fork,
550556
)?)?;

crates/vm/levm/src/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ pub fn eip7702_get_code(
712712
address: Address,
713713
) -> Result<(bool, u64, Address, Bytes), VMError> {
714714
// Address is the delgated address
715-
let account = get_account(cache, db.clone(), address);
715+
let account = get_account_no_push_cache(cache, db.clone(), address);
716716
let bytecode = account.info.bytecode.clone();
717717

718718
// If the Address doesn't have a delegation code

0 commit comments

Comments
 (0)