@@ -10,8 +10,11 @@ use alloy_provider::Provider;
1010use alloy_rpc_types:: Filter ;
1111use alloy_sol_types:: SolValue ;
1212use foundry_common:: provider:: ProviderBuilder ;
13- use foundry_evm_core:: { backend:: FoundryJournalExt , fork:: CreateFork } ;
14- use revm:: context:: ContextTr ;
13+ use foundry_evm_core:: {
14+ backend:: { FoundryJournalExt , JournaledState } ,
15+ fork:: CreateFork ,
16+ } ;
17+ use revm:: context:: { ContextTr , TxEnv } ;
1518
1619impl Cheatcode for activeForkCall {
1720 fn apply_stateful < CTX : ContextTr < Db : DatabaseExt > > (
@@ -73,55 +76,39 @@ impl Cheatcode for rollFork_0Call {
7376 fn apply_stateful < CTX : EthCheatCtx > ( & self , ccx : & mut CheatsCtxt < ' _ , CTX > ) -> Result {
7477 let Self { blockNumber } = self ;
7578 persist_caller ( ccx) ;
76- let mut evm_env = ccx. ecx . evm_clone ( ) ;
77- let mut tx_env = ccx. ecx . tx_clone ( ) ;
78- let ( db, inner) = ccx. ecx . journal_mut ( ) . as_db_and_inner ( ) ;
79- db. roll_fork ( None , ( * blockNumber) . to ( ) , & mut evm_env, & mut tx_env, inner) ?;
80- ccx. ecx . set_evm ( evm_env) ;
81- ccx. ecx . set_tx ( tx_env) ;
82- Ok ( Default :: default ( ) )
79+ fork_env_op ( ccx, |db, evm_env, tx_env, inner| {
80+ db. roll_fork ( None , ( * blockNumber) . to ( ) , evm_env, tx_env, inner)
81+ } )
8382 }
8483}
8584
8685impl Cheatcode for rollFork_1Call {
8786 fn apply_stateful < CTX : EthCheatCtx > ( & self , ccx : & mut CheatsCtxt < ' _ , CTX > ) -> Result {
8887 let Self { txHash } = self ;
8988 persist_caller ( ccx) ;
90- let mut evm_env = ccx. ecx . evm_clone ( ) ;
91- let mut tx_env = ccx. ecx . tx_clone ( ) ;
92- let ( db, inner) = ccx. ecx . journal_mut ( ) . as_db_and_inner ( ) ;
93- db. roll_fork_to_transaction ( None , * txHash, & mut evm_env, & mut tx_env, inner) ?;
94- ccx. ecx . set_evm ( evm_env) ;
95- ccx. ecx . set_tx ( tx_env) ;
96- Ok ( Default :: default ( ) )
89+ fork_env_op ( ccx, |db, evm_env, tx_env, inner| {
90+ db. roll_fork_to_transaction ( None , * txHash, evm_env, tx_env, inner)
91+ } )
9792 }
9893}
9994
10095impl Cheatcode for rollFork_2Call {
10196 fn apply_stateful < CTX : EthCheatCtx > ( & self , ccx : & mut CheatsCtxt < ' _ , CTX > ) -> Result {
10297 let Self { forkId, blockNumber } = self ;
10398 persist_caller ( ccx) ;
104- let mut evm_env = ccx. ecx . evm_clone ( ) ;
105- let mut tx_env = ccx. ecx . tx_clone ( ) ;
106- let ( db, inner) = ccx. ecx . journal_mut ( ) . as_db_and_inner ( ) ;
107- db. roll_fork ( Some ( * forkId) , ( * blockNumber) . to ( ) , & mut evm_env, & mut tx_env, inner) ?;
108- ccx. ecx . set_evm ( evm_env) ;
109- ccx. ecx . set_tx ( tx_env) ;
110- Ok ( Default :: default ( ) )
99+ fork_env_op ( ccx, |db, evm_env, tx_env, inner| {
100+ db. roll_fork ( Some ( * forkId) , ( * blockNumber) . to ( ) , evm_env, tx_env, inner)
101+ } )
111102 }
112103}
113104
114105impl Cheatcode for rollFork_3Call {
115106 fn apply_stateful < CTX : EthCheatCtx > ( & self , ccx : & mut CheatsCtxt < ' _ , CTX > ) -> Result {
116107 let Self { forkId, txHash } = self ;
117108 persist_caller ( ccx) ;
118- let mut evm_env = ccx. ecx . evm_clone ( ) ;
119- let mut tx_env = ccx. ecx . tx_clone ( ) ;
120- let ( db, inner) = ccx. ecx . journal_mut ( ) . as_db_and_inner ( ) ;
121- db. roll_fork_to_transaction ( Some ( * forkId) , * txHash, & mut evm_env, & mut tx_env, inner) ?;
122- ccx. ecx . set_evm ( evm_env) ;
123- ccx. ecx . set_tx ( tx_env) ;
124- Ok ( Default :: default ( ) )
109+ fork_env_op ( ccx, |db, evm_env, tx_env, inner| {
110+ db. roll_fork_to_transaction ( Some ( * forkId) , * txHash, evm_env, tx_env, inner)
111+ } )
125112 }
126113}
127114
@@ -130,13 +117,9 @@ impl Cheatcode for selectForkCall {
130117 let Self { forkId } = self ;
131118 persist_caller ( ccx) ;
132119 check_broadcast ( ccx. state ) ?;
133- let mut evm_env = ccx. ecx . evm_clone ( ) ;
134- let mut tx_env = ccx. ecx . tx_clone ( ) ;
135- let ( db, inner) = ccx. ecx . journal_mut ( ) . as_db_and_inner ( ) ;
136- db. select_fork ( * forkId, & mut evm_env, & mut tx_env, inner) ?;
137- ccx. ecx . set_evm ( evm_env) ;
138- ccx. ecx . set_tx ( tx_env) ;
139- Ok ( Default :: default ( ) )
120+ fork_env_op ( ccx, |db, evm_env, tx_env, inner| {
121+ db. select_fork ( * forkId, evm_env, tx_env, inner)
122+ } )
140123 }
141124}
142125
@@ -355,13 +338,9 @@ fn create_select_fork<CTX: EthCheatCtx>(
355338 check_broadcast ( ccx. state ) ?;
356339
357340 let fork = create_fork_request ( ccx, url_or_alias, block) ?;
358- let mut evm_env = ccx. ecx . evm_clone ( ) ;
359- let mut tx_env = ccx. ecx . tx_clone ( ) ;
360- let ( db, inner) = ccx. ecx . journal_mut ( ) . as_db_and_inner ( ) ;
361- let id = db. create_select_fork ( fork, & mut evm_env, & mut tx_env, inner) ?;
362- ccx. ecx . set_evm ( evm_env) ;
363- ccx. ecx . set_tx ( tx_env) ;
364- Ok ( id. abi_encode ( ) )
341+ fork_env_op ( ccx, |db, evm_env, tx_env, inner| {
342+ db. create_select_fork ( fork, evm_env, tx_env, inner)
343+ } )
365344}
366345
367346/// Creates a new fork
@@ -384,14 +363,9 @@ fn create_select_fork_at_transaction<CTX: EthCheatCtx>(
384363 check_broadcast ( ccx. state ) ?;
385364
386365 let fork = create_fork_request ( ccx, url_or_alias, None ) ?;
387- let mut evm_env = ccx. ecx . evm_clone ( ) ;
388- let mut tx_env = ccx. ecx . tx_clone ( ) ;
389- let ( db, inner) = ccx. ecx . journal_mut ( ) . as_db_and_inner ( ) ;
390- let id =
391- db. create_select_fork_at_transaction ( fork, & mut evm_env, & mut tx_env, inner, * transaction) ?;
392- ccx. ecx . set_evm ( evm_env) ;
393- ccx. ecx . set_tx ( tx_env) ;
394- Ok ( id. abi_encode ( ) )
366+ fork_env_op ( ccx, |db, evm_env, tx_env, inner| {
367+ db. create_select_fork_at_transaction ( fork, evm_env, tx_env, inner, * transaction)
368+ } )
395369}
396370
397371/// Creates a new fork at the given transaction
@@ -435,6 +409,27 @@ fn create_fork_request<CTX: EthCheatCtx>(
435409 Ok ( fork)
436410}
437411
412+ /// Clones the EVM and tx environments, runs a fork operation that may modify them, then writes
413+ /// them back. This is the common pattern for all fork-switching cheatcodes (rollFork, selectFork,
414+ /// createSelectFork).
415+ fn fork_env_op < CTX : EthCheatCtx , T : SolValue > (
416+ ccx : & mut CheatsCtxt < ' _ , CTX > ,
417+ f : impl FnOnce (
418+ & mut dyn DatabaseExt ,
419+ & mut EvmEnv ,
420+ & mut TxEnv ,
421+ & mut JournaledState ,
422+ ) -> eyre:: Result < T > ,
423+ ) -> Result {
424+ let mut evm_env = ccx. ecx . evm_clone ( ) ;
425+ let mut tx_env = ccx. ecx . tx_clone ( ) ;
426+ let ( db, inner) = ccx. ecx . journal_mut ( ) . as_db_and_inner ( ) ;
427+ let result = f ( db, & mut evm_env, & mut tx_env, inner) ?;
428+ ccx. ecx . set_evm ( evm_env) ;
429+ ccx. ecx . set_tx ( tx_env) ;
430+ Ok ( result. abi_encode ( ) )
431+ }
432+
438433fn check_broadcast ( state : & Cheatcodes ) -> Result < ( ) > {
439434 if state. broadcast . is_none ( ) {
440435 Ok ( ( ) )
0 commit comments