Skip to content

Commit 7074d20

Browse files
authored
chore(evm): make Executor fields private (foundry-rs#8233)
1 parent e3267bd commit 7074d20

File tree

11 files changed

+108
-73
lines changed

11 files changed

+108
-73
lines changed

crates/chisel/src/runner.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -125,19 +125,20 @@ impl ChiselRunner {
125125
value: U256,
126126
commit: bool,
127127
) -> eyre::Result<ChiselResult> {
128-
let fs_commit_changed = if let Some(cheatcodes) = &mut self.executor.inspector.cheatcodes {
129-
let original_fs_commit = cheatcodes.fs_commit;
130-
cheatcodes.fs_commit = false;
131-
original_fs_commit != cheatcodes.fs_commit
132-
} else {
133-
false
134-
};
128+
let fs_commit_changed =
129+
if let Some(cheatcodes) = &mut self.executor.inspector_mut().cheatcodes {
130+
let original_fs_commit = cheatcodes.fs_commit;
131+
cheatcodes.fs_commit = false;
132+
original_fs_commit != cheatcodes.fs_commit
133+
} else {
134+
false
135+
};
135136

136137
let mut res = self.executor.call_raw(from, to, calldata.clone(), value)?;
137138
let mut gas_used = res.gas_used;
138139
if matches!(res.exit_reason, return_ok!()) {
139140
// store the current gas limit and reset it later
140-
let init_gas_limit = self.executor.env.tx.gas_limit;
141+
let init_gas_limit = self.executor.env().tx.gas_limit;
141142

142143
// the executor will return the _exact_ gas value this transaction consumed, setting
143144
// this value as gas limit will result in `OutOfGas` so to come up with a
@@ -148,7 +149,7 @@ impl ChiselRunner {
148149
let mut last_highest_gas_limit = highest_gas_limit;
149150
while (highest_gas_limit - lowest_gas_limit) > 1 {
150151
let mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2;
151-
self.executor.env.tx.gas_limit = mid_gas_limit;
152+
self.executor.env_mut().tx.gas_limit = mid_gas_limit;
152153
let res = self.executor.call_raw(from, to, calldata.clone(), value)?;
153154
match res.exit_reason {
154155
InstructionResult::Revert |
@@ -174,13 +175,13 @@ impl ChiselRunner {
174175
}
175176
}
176177
// reset gas limit in the
177-
self.executor.env.tx.gas_limit = init_gas_limit;
178+
self.executor.env_mut().tx.gas_limit = init_gas_limit;
178179
}
179180

180181
// if we changed `fs_commit` during gas limit search, re-execute the call with original
181182
// value
182183
if fs_commit_changed {
183-
if let Some(cheatcodes) = &mut self.executor.inspector.cheatcodes {
184+
if let Some(cheatcodes) = &mut self.executor.inspector_mut().cheatcodes {
184185
cheatcodes.fs_commit = !cheatcodes.fs_commit;
185186
}
186187

crates/evm/core/src/backend/cow.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub struct CowBackend<'a> {
5151

5252
impl<'a> CowBackend<'a> {
5353
/// Creates a new `CowBackend` with the given `Backend`.
54-
pub fn new(backend: &'a Backend) -> Self {
54+
pub fn new_borrowed(backend: &'a Backend) -> Self {
5555
Self { backend: Cow::Borrowed(backend), is_initialized: false, spec_id: SpecId::LATEST }
5656
}
5757

crates/evm/evm/src/executors/fuzz/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,10 @@ impl FuzzedExecutor {
234234

235235
/// Stores fuzz state for use with [fuzz_calldata_from_state]
236236
pub fn build_fuzz_state(&self) -> EvmFuzzState {
237-
if let Some(fork_db) = self.executor.backend.active_fork_db() {
237+
if let Some(fork_db) = self.executor.backend().active_fork_db() {
238238
EvmFuzzState::new(fork_db, self.config.dictionary)
239239
} else {
240-
EvmFuzzState::new(self.executor.backend.mem_db(), self.config.dictionary)
240+
EvmFuzzState::new(self.executor.backend().mem_db(), self.config.dictionary)
241241
}
242242
}
243243
}

crates/evm/evm/src/executors/invariant/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,8 @@ impl<'a> InvariantExecutor<'a> {
364364
self.select_contracts_and_senders(invariant_contract.address)?;
365365

366366
// Stores fuzz state for use with [fuzz_calldata_from_state].
367-
let fuzz_state = EvmFuzzState::new(self.executor.backend.mem_db(), self.config.dictionary);
367+
let fuzz_state =
368+
EvmFuzzState::new(self.executor.backend().mem_db(), self.config.dictionary);
368369

369370
// Creates the invariant strategy.
370371
let strat = invariant_strat(
@@ -395,7 +396,7 @@ impl<'a> InvariantExecutor<'a> {
395396
));
396397
}
397398

398-
self.executor.inspector.fuzzer =
399+
self.executor.inspector_mut().fuzzer =
399400
Some(Fuzzer { call_generator, fuzz_state: fuzz_state.clone(), collect: true });
400401

401402
Ok((fuzz_state, targeted_contracts, strat))

crates/evm/evm/src/executors/invariant/replay.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ pub fn replay_error(
138138

139139
/// Sets up the calls generated by the internal fuzzer, if they exist.
140140
fn set_up_inner_replay(executor: &mut Executor, inner_sequence: &[Option<BasicTxDetails>]) {
141-
if let Some(fuzzer) = &mut executor.inspector.fuzzer {
141+
if let Some(fuzzer) = &mut executor.inspector_mut().fuzzer {
142142
if let Some(call_generator) = &mut fuzzer.call_generator {
143143
call_generator.last_sequence = Arc::new(RwLock::new(inner_sequence.to_owned()));
144144
call_generator.set_replay(true);

crates/evm/evm/src/executors/invariant/result.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub(crate) fn assert_invariants(
5656
) -> Result<Option<RawCallResult>> {
5757
let mut inner_sequence = vec![];
5858

59-
if let Some(fuzzer) = &executor.inspector.fuzzer {
59+
if let Some(fuzzer) = &executor.inspector().fuzzer {
6060
if let Some(call_generator) = &fuzzer.call_generator {
6161
inner_sequence.extend(call_generator.last_sequence.read().iter().cloned());
6262
}

crates/evm/evm/src/executors/mod.rs

+76-43
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ pub struct Executor {
7272
// only interested in the database. REVM's `EVM` is a thin
7373
// wrapper around spawning a new EVM on every call anyway,
7474
// so the performance difference should be negligible.
75-
pub backend: Backend,
75+
backend: Backend,
7676
/// The EVM environment.
77-
pub env: EnvWithHandlerCfg,
77+
env: EnvWithHandlerCfg,
7878
/// The Revm inspector stack.
79-
pub inspector: InspectorStack,
79+
inspector: InspectorStack,
8080
/// The gas limit for calls and deployments. This is different from the gas limit imposed by
8181
/// the passed in environment, as those limits are used by the EVM for certain opcodes like
8282
/// `gaslimit`.
@@ -99,7 +99,7 @@ impl Executor {
9999
gas_limit: u64,
100100
) -> Self {
101101
// Need to create a non-empty contract on the cheatcodes address so `extcodesize` checks
102-
// does not fail
102+
// do not fail.
103103
backend.insert_account_info(
104104
CHEATCODE_ADDRESS,
105105
revm::primitives::AccountInfo {
@@ -114,16 +114,51 @@ impl Executor {
114114
Self { backend, env, inspector, gas_limit }
115115
}
116116

117-
/// Returns the spec ID of the executor.
117+
fn clone_with_backend(&self, backend: Backend) -> Self {
118+
let env = EnvWithHandlerCfg::new_with_spec_id(Box::new(self.env().clone()), self.spec_id());
119+
Self::new(backend, env, self.inspector().clone(), self.gas_limit)
120+
}
121+
122+
/// Returns a reference to the EVM backend.
123+
pub fn backend(&self) -> &Backend {
124+
&self.backend
125+
}
126+
127+
/// Returns a mutable reference to the EVM backend.
128+
pub fn backend_mut(&mut self) -> &mut Backend {
129+
&mut self.backend
130+
}
131+
132+
/// Returns a reference to the EVM environment.
133+
pub fn env(&self) -> &Env {
134+
&self.env.env
135+
}
136+
137+
/// Returns a mutable reference to the EVM environment.
138+
pub fn env_mut(&mut self) -> &mut Env {
139+
&mut self.env.env
140+
}
141+
142+
/// Returns a reference to the EVM inspector.
143+
pub fn inspector(&self) -> &InspectorStack {
144+
&self.inspector
145+
}
146+
147+
/// Returns a mutable reference to the EVM inspector.
148+
pub fn inspector_mut(&mut self) -> &mut InspectorStack {
149+
&mut self.inspector
150+
}
151+
152+
/// Returns the EVM spec ID.
118153
pub fn spec_id(&self) -> SpecId {
119-
self.env.handler_cfg.spec_id
154+
self.env.spec_id()
120155
}
121156

122157
/// Creates the default CREATE2 Contract Deployer for local tests and scripts.
123158
pub fn deploy_create2_deployer(&mut self) -> eyre::Result<()> {
124159
trace!("deploying local create2 deployer");
125160
let create2_deployer_account = self
126-
.backend
161+
.backend()
127162
.basic_ref(DEFAULT_CREATE2_DEPLOYER)?
128163
.ok_or_else(|| DatabaseError::MissingAccount(DEFAULT_CREATE2_DEPLOYER))?;
129164

@@ -145,53 +180,52 @@ impl Executor {
145180
}
146181

147182
/// Set the balance of an account.
148-
pub fn set_balance(&mut self, address: Address, amount: U256) -> DatabaseResult<&mut Self> {
183+
pub fn set_balance(&mut self, address: Address, amount: U256) -> DatabaseResult<()> {
149184
trace!(?address, ?amount, "setting account balance");
150-
let mut account = self.backend.basic_ref(address)?.unwrap_or_default();
185+
let mut account = self.backend().basic_ref(address)?.unwrap_or_default();
151186
account.balance = amount;
152-
153-
self.backend.insert_account_info(address, account);
154-
Ok(self)
187+
self.backend_mut().insert_account_info(address, account);
188+
Ok(())
155189
}
156190

157191
/// Gets the balance of an account
158192
pub fn get_balance(&self, address: Address) -> DatabaseResult<U256> {
159-
Ok(self.backend.basic_ref(address)?.map(|acc| acc.balance).unwrap_or_default())
193+
Ok(self.backend().basic_ref(address)?.map(|acc| acc.balance).unwrap_or_default())
160194
}
161195

162196
/// Set the nonce of an account.
163-
pub fn set_nonce(&mut self, address: Address, nonce: u64) -> DatabaseResult<&mut Self> {
164-
let mut account = self.backend.basic_ref(address)?.unwrap_or_default();
197+
pub fn set_nonce(&mut self, address: Address, nonce: u64) -> DatabaseResult<()> {
198+
let mut account = self.backend().basic_ref(address)?.unwrap_or_default();
165199
account.nonce = nonce;
166-
self.backend.insert_account_info(address, account);
167-
Ok(self)
200+
self.backend_mut().insert_account_info(address, account);
201+
Ok(())
168202
}
169203

170204
/// Returns the nonce of an account.
171205
pub fn get_nonce(&self, address: Address) -> DatabaseResult<u64> {
172-
Ok(self.backend.basic_ref(address)?.map(|acc| acc.nonce).unwrap_or_default())
206+
Ok(self.backend().basic_ref(address)?.map(|acc| acc.nonce).unwrap_or_default())
173207
}
174208

175209
/// Returns `true` if the account has no code.
176210
pub fn is_empty_code(&self, address: Address) -> DatabaseResult<bool> {
177-
Ok(self.backend.basic_ref(address)?.map(|acc| acc.is_empty_code_hash()).unwrap_or(true))
211+
Ok(self.backend().basic_ref(address)?.map(|acc| acc.is_empty_code_hash()).unwrap_or(true))
178212
}
179213

180214
#[inline]
181215
pub fn set_tracing(&mut self, tracing: bool) -> &mut Self {
182-
self.inspector.tracing(tracing);
216+
self.inspector_mut().tracing(tracing);
183217
self
184218
}
185219

186220
#[inline]
187221
pub fn set_debugger(&mut self, debugger: bool) -> &mut Self {
188-
self.inspector.enable_debugger(debugger);
222+
self.inspector_mut().enable_debugger(debugger);
189223
self
190224
}
191225

192226
#[inline]
193227
pub fn set_trace_printer(&mut self, trace_printer: bool) -> &mut Self {
194-
self.inspector.print(trace_printer);
228+
self.inspector_mut().print(trace_printer);
195229
self
196230
}
197231

@@ -242,7 +276,7 @@ impl Executor {
242276

243277
// also mark this library as persistent, this will ensure that the state of the library is
244278
// persistent across fork swaps in forking mode
245-
self.backend.add_persistent_account(address);
279+
self.backend_mut().add_persistent_account(address);
246280

247281
debug!(%address, "deployed contract");
248282

@@ -264,15 +298,15 @@ impl Executor {
264298
trace!(?from, ?to, "setting up contract");
265299

266300
let from = from.unwrap_or(CALLER);
267-
self.backend.set_test_contract(to).set_caller(from);
301+
self.backend_mut().set_test_contract(to).set_caller(from);
268302
let calldata = Bytes::from_static(&ITest::setUpCall::SELECTOR);
269303
let mut res = self.transact_raw(from, to, calldata, U256::ZERO)?;
270304
res = res.into_result(rd)?;
271305

272306
// record any changes made to the block's environment during setup
273-
self.env.block = res.env.block.clone();
307+
self.env_mut().block = res.env.block.clone();
274308
// and also the chainid, which can be set manually
275-
self.env.cfg.chain_id = res.env.cfg.chain_id;
309+
self.env_mut().cfg.chain_id = res.env.cfg.chain_id;
276310

277311
let success =
278312
self.is_raw_call_success(to, Cow::Borrowed(&res.state_changeset), &res, false);
@@ -356,16 +390,16 @@ impl Executor {
356390
///
357391
/// The state after the call is **not** persisted.
358392
pub fn call_with_env(&self, mut env: EnvWithHandlerCfg) -> eyre::Result<RawCallResult> {
359-
let mut inspector = self.inspector.clone();
360-
let mut backend = CowBackend::new(&self.backend);
393+
let mut inspector = self.inspector().clone();
394+
let mut backend = CowBackend::new_borrowed(self.backend());
361395
let result = backend.inspect(&mut env, &mut inspector)?;
362396
convert_executed_result(env, inspector, result, backend.has_snapshot_failure())
363397
}
364398

365399
/// Execute the transaction configured in `env.tx`.
366400
pub fn transact_with_env(&mut self, mut env: EnvWithHandlerCfg) -> eyre::Result<RawCallResult> {
367-
let mut inspector = self.inspector.clone();
368-
let backend = &mut self.backend;
401+
let mut inspector = self.inspector().clone();
402+
let backend = self.backend_mut();
369403
let result = backend.inspect(&mut env, &mut inspector)?;
370404
let mut result =
371405
convert_executed_result(env, inspector, result, backend.has_snapshot_failure())?;
@@ -379,11 +413,11 @@ impl Executor {
379413
/// This should not be exposed to the user, as it should be called only by `transact*`.
380414
fn commit(&mut self, result: &mut RawCallResult) {
381415
// Persist changes to db.
382-
self.backend.commit(result.state_changeset.clone());
416+
self.backend_mut().commit(result.state_changeset.clone());
383417

384418
// Persist cheatcode state.
385-
self.inspector.cheatcodes = result.cheatcodes.take();
386-
if let Some(cheats) = self.inspector.cheatcodes.as_mut() {
419+
self.inspector_mut().cheatcodes = result.cheatcodes.take();
420+
if let Some(cheats) = self.inspector_mut().cheatcodes.as_mut() {
387421
// Clear broadcastable transactions
388422
cheats.broadcastable_transactions.clear();
389423
debug!(target: "evm::executors", "cleared broadcastable transactions");
@@ -393,7 +427,7 @@ impl Executor {
393427
}
394428

395429
// Persist the changed environment.
396-
self.inspector.set_env(&result.env);
430+
self.inspector_mut().set_env(&result.env);
397431
}
398432

399433
/// Checks if a call to a test contract was successful.
@@ -474,20 +508,20 @@ impl Executor {
474508
reverted: bool,
475509
state_changeset: Cow<'_, StateChangeset>,
476510
) -> bool {
477-
if self.backend.has_snapshot_failure() {
511+
if self.backend().has_snapshot_failure() {
478512
// a failure occurred in a reverted snapshot, which is considered a failed test
479513
return false;
480514
}
481515

482516
let mut success = !reverted;
483517
if success {
484518
// Construct a new bare-bones backend to evaluate success.
485-
let mut backend = self.backend.clone_empty();
519+
let mut backend = self.backend().clone_empty();
486520

487521
// We only clone the test contract and cheatcode accounts,
488522
// that's all we need to evaluate success.
489523
for address in [address, CHEATCODE_ADDRESS] {
490-
let Ok(acc) = self.backend.basic_ref(address) else { return false };
524+
let Ok(acc) = self.backend().basic_ref(address) else { return false };
491525
backend.insert_account_info(address, acc.unwrap_or_default());
492526
}
493527

@@ -498,8 +532,7 @@ impl Executor {
498532
backend.commit(state_changeset.into_owned());
499533

500534
// Check if a DSTest assertion failed
501-
let executor =
502-
Self::new(backend, self.env.clone(), self.inspector.clone(), self.gas_limit);
535+
let executor = self.clone_with_backend(backend);
503536
let call = executor.call_sol(CALLER, address, &ITest::failedCall {}, U256::ZERO, None);
504537
match call {
505538
Ok(CallResult { raw: _, decoded_result: ITest::failedReturn { failed } }) => {
@@ -526,14 +559,14 @@ impl Executor {
526559
value: U256,
527560
) -> EnvWithHandlerCfg {
528561
let env = Env {
529-
cfg: self.env.cfg.clone(),
562+
cfg: self.env().cfg.clone(),
530563
// We always set the gas price to 0 so we can execute the transaction regardless of
531564
// network conditions - the actual gas price is kept in `self.block` and is applied by
532565
// the cheatcode handler if it is enabled
533566
block: BlockEnv {
534567
basefee: U256::ZERO,
535568
gas_limit: U256::from(self.gas_limit),
536-
..self.env.block.clone()
569+
..self.env().block.clone()
537570
},
538571
tx: TxEnv {
539572
caller,
@@ -544,11 +577,11 @@ impl Executor {
544577
gas_price: U256::ZERO,
545578
gas_priority_fee: None,
546579
gas_limit: self.gas_limit,
547-
..self.env.tx.clone()
580+
..self.env().tx.clone()
548581
},
549582
};
550583

551-
EnvWithHandlerCfg::new_with_spec_id(Box::new(env), self.env.handler_cfg.spec_id)
584+
EnvWithHandlerCfg::new_with_spec_id(Box::new(env), self.spec_id())
552585
}
553586
}
554587

0 commit comments

Comments
 (0)