@@ -7,7 +7,7 @@ use crate::{
77} ;
88use alloy_consensus:: TxEnvelope ;
99use alloy_genesis:: { Genesis , GenesisAccount } ;
10- use alloy_primitives:: { Address , B256 , U256 } ;
10+ use alloy_primitives:: { Address , Bytes , B256 , U256 } ;
1111use alloy_rlp:: Decodable ;
1212use alloy_sol_types:: SolValue ;
1313use foundry_common:: fs:: { read_json_file, write_json_file} ;
@@ -18,7 +18,7 @@ use foundry_evm_core::{
1818} ;
1919use foundry_evm_traces:: StackSnapshotType ;
2020use rand:: Rng ;
21- use revm:: primitives:: { Account , SpecId } ;
21+ use revm:: primitives:: { Account , Bytecode , SpecId , KECCAK_EMPTY } ;
2222use std:: { collections:: BTreeMap , path:: Path } ;
2323mod record_debug_step;
2424use record_debug_step:: { convert_call_trace_to_debug_step, flatten_call_trace} ;
@@ -63,8 +63,7 @@ impl Cheatcode for addrCall {
6363impl Cheatcode for getNonce_0Call {
6464 fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
6565 let Self { account } = self ;
66-
67- ccx. state . strategy . runner . clone ( ) . cheatcode_get_nonce ( ccx, * account)
66+ get_nonce ( ccx, account)
6867 }
6968}
7069
@@ -350,7 +349,8 @@ impl Cheatcode for getBlobhashesCall {
350349impl Cheatcode for rollCall {
351350 fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
352351 let Self { newHeight } = self ;
353- ccx. state . strategy . runner . clone ( ) . cheatcode_roll ( ccx, * newHeight)
352+ ccx. ecx . env . block . number = * newHeight;
353+ Ok ( Default :: default ( ) )
354354 }
355355}
356356
@@ -372,7 +372,8 @@ impl Cheatcode for txGasPriceCall {
372372impl Cheatcode for warpCall {
373373 fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
374374 let Self { newTimestamp } = self ;
375- ccx. state . strategy . runner . clone ( ) . cheatcode_warp ( ccx, * newTimestamp)
375+ ccx. ecx . env . block . timestamp = * newTimestamp;
376+ Ok ( Default :: default ( ) )
376377 }
377378}
378379
@@ -407,38 +408,65 @@ impl Cheatcode for dealCall {
407408 fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
408409 let Self { account : address, newBalance : new_balance } = * self ;
409410
410- ccx. state . strategy . runner . clone ( ) . cheatcode_deal ( ccx, address, new_balance)
411+ let account = journaled_account ( ccx. ecx , address) ?;
412+ let old_balance = std:: mem:: replace ( & mut account. info . balance , new_balance) ;
413+ let record = DealRecord { address, old_balance, new_balance } ;
414+ ccx. state . eth_deals . push ( record) ;
415+ Ok ( Default :: default ( ) )
411416 }
412417}
413418
414419impl Cheatcode for etchCall {
415420 fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
416421 let Self { target, newRuntimeBytecode } = self ;
417422
418- ccx. state . strategy . runner . clone ( ) . cheatcode_etch ( ccx, * target, newRuntimeBytecode)
423+ ensure_not_precompile ! ( & target, ccx) ;
424+ ccx. ecx . load_account ( * target) ?;
425+ let bytecode = Bytecode :: new_raw ( Bytes :: copy_from_slice ( newRuntimeBytecode) ) ;
426+ ccx. ecx . journaled_state . set_code ( * target, bytecode) ;
427+ Ok ( Default :: default ( ) )
419428 }
420429}
421430
422431impl Cheatcode for resetNonceCall {
423432 fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
424433 let Self { account } = self ;
425- ccx. state . strategy . runner . clone ( ) . cheatcode_reset_nonce ( ccx, * account)
434+ let account = journaled_account ( ccx. ecx , * account) ?;
435+ // Per EIP-161, EOA nonces start at 0, but contract nonces
436+ // start at 1. Comparing by code_hash instead of code
437+ // to avoid hitting the case where account's code is None.
438+ let empty = account. info . code_hash == KECCAK_EMPTY ;
439+ let nonce = if empty { 0 } else { 1 } ;
440+ account. info . nonce = nonce;
441+ debug ! ( target: "cheatcodes" , nonce, "reset" ) ;
442+ Ok ( Default :: default ( ) )
426443 }
427444}
428445
429446impl Cheatcode for setNonceCall {
430447 fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
431448 let Self { account, newNonce } = * self ;
432449
433- ccx. state . strategy . runner . clone ( ) . cheatcode_set_nonce ( ccx, account, newNonce)
450+ let account = journaled_account ( ccx. ecx , account) ?;
451+ // nonce must increment only
452+ let current = account. info . nonce ;
453+ ensure ! (
454+ newNonce >= current,
455+ "new nonce ({newNonce}) must be strictly equal to or higher than the \
456+ account's current nonce ({current})"
457+ ) ;
458+ account. info . nonce = newNonce;
459+ Ok ( Default :: default ( ) )
434460 }
435461}
436462
437463impl Cheatcode for setNonceUnsafeCall {
438464 fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
439465 let Self { account, newNonce } = * self ;
440466
441- ccx. state . strategy . runner . clone ( ) . cheatcode_set_nonce_unsafe ( ccx, account, newNonce)
467+ let account = journaled_account ( ccx. ecx , account) ?;
468+ account. info . nonce = newNonce;
469+ Ok ( Default :: default ( ) )
442470 }
443471}
444472
0 commit comments