revive_strategy/executor/
runner.rs1use alloy_primitives::{Address, U256};
2use foundry_cheatcodes::CheatcodeInspectorStrategy;
3use foundry_compilers::{
4 ProjectCompileOutput, compilers::resolc::dual_compiled_contracts::DualCompiledContracts,
5};
6use foundry_evm::{
7 Env,
8 backend::BackendStrategy,
9 executors::{
10 EvmExecutorStrategyRunner, ExecutorStrategyContext, ExecutorStrategyRunner,
11 strategy::ExecutorStrategyExt,
12 },
13};
14use polkadot_sdk::sp_externalities::Externalities;
15use revm::context::result::ResultAndState;
16
17use crate::{
18 backend::ReviveBackendStrategyBuilder, cheatcodes::PvmCheatcodeInspectorStrategyBuilder,
19 executor::context::ReviveExecutorStrategyContext,
20};
21
22#[derive(Debug, Default, Clone)]
24pub struct ReviveExecutorStrategyRunner;
25
26impl ReviveExecutorStrategyRunner {
27 pub fn new() -> Self {
28 Self
29 }
30}
31
32impl ExecutorStrategyRunner for ReviveExecutorStrategyRunner {
33 fn new_backend_strategy(&self, _ctx: &dyn ExecutorStrategyContext) -> BackendStrategy {
34 BackendStrategy::new_revive()
35 }
36
37 fn new_cheatcodes_strategy(
38 &self,
39 ctx: &dyn ExecutorStrategyContext,
40 ) -> foundry_cheatcodes::CheatcodesStrategy {
41 let ctx = get_context_ref(ctx);
42 CheatcodeInspectorStrategy::new_pvm(
43 ctx.dual_compiled_contracts.clone(),
44 ctx.runtime_mode,
45 ctx.externalties.shallow_clone(),
46 )
47 }
48
49 fn set_balance(
54 &self,
55 executor: &mut foundry_evm::executors::Executor,
56 address: Address,
57 amount: U256,
58 ) -> foundry_evm::backend::BackendResult<()> {
59 EvmExecutorStrategyRunner.set_balance(executor, address, amount)?;
60
61 let ctx = get_context_ref_mut(executor.strategy.context.as_mut());
62
63 ctx.externalties.set_balance(address, amount);
64 Ok(())
65 }
66
67 fn get_balance(
68 &self,
69 executor: &mut foundry_evm::executors::Executor,
70 address: Address,
71 ) -> foundry_evm::backend::BackendResult<U256> {
72 let evm_balance = EvmExecutorStrategyRunner.get_balance(executor, address)?;
73 let ctx = get_context_ref_mut(executor.strategy.context.as_mut());
74
75 let revive_balance = ctx.externalties.get_balance(address);
76 assert_eq!(evm_balance, revive_balance);
77 Ok(evm_balance)
78 }
79
80 fn set_nonce(
81 &self,
82 executor: &mut foundry_evm::executors::Executor,
83 address: Address,
84 nonce: u64,
85 ) -> foundry_evm::backend::BackendResult<()> {
86 EvmExecutorStrategyRunner.set_nonce(executor, address, nonce)?;
87 let ctx = get_context_ref_mut(executor.strategy.context.as_mut());
88 ctx.externalties.set_nonce(address, nonce);
89 Ok(())
90 }
91
92 fn get_nonce(
93 &self,
94 executor: &mut foundry_evm::executors::Executor,
95 address: Address,
96 ) -> foundry_evm::backend::BackendResult<u64> {
97 let evm_nonce = EvmExecutorStrategyRunner.get_nonce(executor, address)?;
98 let ctx = get_context_ref_mut(executor.strategy.context.as_mut());
99
100 let revive_nonce = ctx.externalties.get_nonce(address);
101
102 assert_eq!(evm_nonce, revive_nonce as u64);
103 Ok(evm_nonce)
104 }
105
106 fn call(
107 &self,
108 ctx: &dyn ExecutorStrategyContext,
109 backend: &mut foundry_evm::backend::CowBackend<'_>,
110 env: &mut Env,
111 executor_env: &Env,
112 inspector: &mut foundry_evm::inspectors::InspectorStack,
113 ) -> eyre::Result<ResultAndState> {
114 EvmExecutorStrategyRunner.call(ctx, backend, env, executor_env, inspector)
115 }
116
117 fn transact(
118 &self,
119 ctx: &mut dyn ExecutorStrategyContext,
120 backend: &mut foundry_evm::backend::Backend,
121 env: &mut Env,
122 executor_env: &Env,
123 inspector: &mut foundry_evm::inspectors::InspectorStack,
124 ) -> eyre::Result<ResultAndState> {
125 EvmExecutorStrategyRunner.transact(ctx, backend, env, executor_env, inspector)
126 }
127}
128
129fn get_context_ref(ctx: &dyn ExecutorStrategyContext) -> &ReviveExecutorStrategyContext {
130 ctx.as_any_ref().downcast_ref().expect("expected ReviveExecutorStrategyContext")
131}
132
133fn get_context_ref_mut(
134 ctx: &mut dyn ExecutorStrategyContext,
135) -> &mut ReviveExecutorStrategyContext {
136 ctx.as_any_mut().downcast_mut().expect("expected ReviveExecutorStrategyContext")
137}
138
139impl ExecutorStrategyExt for ReviveExecutorStrategyRunner {
140 fn revive_set_dual_compiled_contracts(
141 &self,
142 ctx: &mut dyn ExecutorStrategyContext,
143 dual_compiled_contracts: DualCompiledContracts,
144 ) {
145 let ctx = get_context_ref_mut(ctx);
146 ctx.dual_compiled_contracts = dual_compiled_contracts;
147 }
148
149 fn revive_set_compilation_output(
150 &self,
151 ctx: &mut dyn ExecutorStrategyContext,
152 output: ProjectCompileOutput,
153 ) {
154 let ctx = get_context_ref_mut(ctx);
155 ctx.compilation_output.replace(output);
156 }
157 fn start_transaction(&self, ctx: &dyn ExecutorStrategyContext) {
158 let ctx = get_context_ref(ctx);
159 let mut externalities = ctx.externalties.0.lock().unwrap();
160 externalities.externalities.ext().storage_start_transaction();
161 }
162
163 fn rollback_transaction(&self, ctx: &dyn ExecutorStrategyContext) {
164 let ctx = get_context_ref(ctx);
165 let mut state = ctx.externalties.0.lock().unwrap();
166 let _ = state.externalities.ext().storage_rollback_transaction();
167 }
168}