@@ -8,9 +8,9 @@ use foundry_cheatcodes::{
88 CheatcodeInspectorStrategyContext , CheatcodeInspectorStrategyRunner , CheatsConfig , CheatsCtxt ,
99 CommonCreateInput , Ecx , EvmCheatcodeInspectorStrategyRunner , Result ,
1010 Vm :: {
11- chainIdCall, coinbaseCall, dealCall, etchCall, getNonce_0Call, loadCall, pvmCall ,
12- resetNonceCall, revertToStateAndDeleteCall, revertToStateCall, rollCall, setNonceCall ,
13- setNonceUnsafeCall, snapshotStateCall, storeCall, warpCall,
11+ chainIdCall, coinbaseCall, dealCall, etchCall, getNonce_0Call, loadCall, polkadotSkipCall ,
12+ pvmCall , resetNonceCall, revertToStateAndDeleteCall, revertToStateCall, rollCall,
13+ setNonceCall , setNonceUnsafeCall, snapshotStateCall, storeCall, warpCall,
1414 } ,
1515 journaled_account, precompile_error,
1616} ;
@@ -42,6 +42,7 @@ use crate::{
4242 tracing:: { Tracer , storage_tracer:: AccountAccess } ,
4343} ;
4444use foundry_cheatcodes:: Vm :: { AccountAccess as FAccountAccess , ChainInfo } ;
45+ use polkadot_sdk:: pallet_revive:: tracing:: Tracing ;
4546
4647use revm:: {
4748 bytecode:: opcode as op,
@@ -113,6 +114,14 @@ impl PvmStartupMigration {
113114pub struct PvmCheatcodeInspectorStrategyContext {
114115 /// Whether we're currently using pallet-revive (migrated from REVM)
115116 pub using_pvm : bool ,
117+ /// When in PVM context, execute the next CALL or CREATE in the EVM instead.
118+ pub skip_pvm : bool ,
119+ /// Any contracts that were deployed in `skip_pvm` step.
120+ /// This makes it easier to dispatch calls to any of these addresses in PVM context, directly
121+ /// to EVM. Alternatively, we'd need to add `vm.polkadotSkip()` to these calls manually.
122+ pub skip_pvm_addresses : std:: collections:: HashSet < Address > ,
123+ /// Records the next create address for `skip_pvm_addresses`.
124+ pub record_next_create_address : bool ,
116125 /// Controls automatic migration to pallet-revive
117126 pub pvm_startup_migration : PvmStartupMigration ,
118127 pub dual_compiled_contracts : DualCompiledContracts ,
@@ -131,6 +140,9 @@ impl PvmCheatcodeInspectorStrategyContext {
131140 Self {
132141 // Start in REVM mode by default
133142 using_pvm : false ,
143+ skip_pvm : false ,
144+ skip_pvm_addresses : Default :: default ( ) ,
145+ record_next_create_address : Default :: default ( ) ,
134146 // Will be set to Allow when test contract deploys
135147 pvm_startup_migration : PvmStartupMigration :: Defer ,
136148 dual_compiled_contracts,
@@ -275,6 +287,12 @@ impl CheatcodeInspectorStrategyRunner for PvmCheatcodeInspectorStrategyRunner {
275287 }
276288 Ok ( Default :: default ( ) )
277289 }
290+ t if is :: < polkadotSkipCall > ( t) => {
291+ let polkadotSkipCall { .. } = cheatcode. as_any ( ) . downcast_ref ( ) . unwrap ( ) ;
292+ let ctx = get_context_ref_mut ( ccx. state . strategy . context . as_mut ( ) ) ;
293+ ctx. skip_pvm = true ;
294+ Ok ( Default :: default ( ) )
295+ }
278296 t if using_pvm && is :: < dealCall > ( t) => {
279297 tracing:: info!( cheatcode = ?cheatcode. as_debug( ) , using_pvm = ?using_pvm) ;
280298 let dealCall { account, newBalance } = cheatcode. as_any ( ) . downcast_ref ( ) . unwrap ( ) ;
@@ -783,6 +801,13 @@ impl foundry_cheatcodes::CheatcodeInspectorStrategyExt for PvmCheatcodeInspector
783801 return None ;
784802 }
785803
804+ if ctx. skip_pvm {
805+ ctx. skip_pvm = false ; // handled the skip, reset flag
806+ ctx. record_next_create_address = true ;
807+ tracing:: info!( "running create in EVM, instead of pallet-revive (skipped)" ) ;
808+ return None ;
809+ }
810+
786811 if let Some ( CreateScheme :: Create ) = input. scheme ( ) {
787812 let caller = input. caller ( ) ;
788813 let nonce = ecx
@@ -832,9 +857,12 @@ impl foundry_cheatcodes::CheatcodeInspectorStrategyExt for PvmCheatcodeInspector
832857 let gas_price_pvm =
833858 sp_core:: U256 :: from_little_endian ( & U256 :: from ( ecx. tx . gas_price ) . as_le_bytes ( ) ) ;
834859 let mut tracer = Tracer :: new ( true ) ;
860+ let caller_h160 = H160 :: from_slice ( input. caller ( ) . as_slice ( ) ) ;
861+
835862 let res = ctx. externalities . execute_with ( || {
863+ tracer. watch_address ( & caller_h160) ;
864+
836865 tracer. trace ( || {
837- let caller_h160 = H160 :: from_slice ( input. caller ( ) . as_slice ( ) ) ;
838866 let origin_account_id = AccountId :: to_fallback_account_id ( & caller_h160) ;
839867 let origin = OriginFor :: < Runtime > :: signed ( origin_account_id. clone ( ) ) ;
840868 let evm_value = sp_core:: U256 :: from_little_endian ( & input. value ( ) . as_le_bytes ( ) ) ;
@@ -956,6 +984,12 @@ impl foundry_cheatcodes::CheatcodeInspectorStrategyExt for PvmCheatcodeInspector
956984 return None ;
957985 }
958986
987+ if ctx. skip_pvm || ctx. skip_pvm_addresses . contains ( & call. target_address ) {
988+ ctx. skip_pvm = false ; // handled the skip, reset flag
989+ tracing:: info!( "running call in EVM, instead of pallet-revive (skipped)" ) ;
990+ return None ;
991+ }
992+
959993 if ecx
960994 . journaled_state
961995 . database
@@ -991,6 +1025,9 @@ impl foundry_cheatcodes::CheatcodeInspectorStrategyExt for PvmCheatcodeInspector
9911025
9921026 let mut tracer = Tracer :: new ( true ) ;
9931027 let res = ctx. externalities . execute_with ( || {
1028+ // Watch the caller's address so its nonce changes get tracked in prestate trace
1029+ tracer. watch_address ( & caller_h160) ;
1030+
9941031 tracer. trace ( || {
9951032 let origin =
9961033 OriginFor :: < Runtime > :: signed ( AccountId :: to_fallback_account_id ( & caller_h160) ) ;
@@ -1121,6 +1158,25 @@ impl foundry_cheatcodes::CheatcodeInspectorStrategyExt for PvmCheatcodeInspector
11211158
11221159 apply_revm_storage_diff ( ctx, ecx, call. target_address ) ;
11231160 }
1161+
1162+ fn revive_record_create_address (
1163+ & self ,
1164+ state : & mut foundry_cheatcodes:: Cheatcodes ,
1165+ outcome : & CreateOutcome ,
1166+ ) {
1167+ let ctx = get_context_ref_mut ( state. strategy . context . as_mut ( ) ) ;
1168+
1169+ if ctx. record_next_create_address {
1170+ ctx. record_next_create_address = false ;
1171+ if let Some ( address) = outcome. address {
1172+ ctx. skip_pvm_addresses . insert ( address) ;
1173+ tracing:: info!(
1174+ "recorded address {:?} for skip execution in the pallet-revive" ,
1175+ address
1176+ ) ;
1177+ }
1178+ }
1179+ }
11241180}
11251181
11261182fn post_exec (
0 commit comments