Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions crates/anvil/src/eth/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ use revm::{
primitives::eip7702::PER_EMPTY_ACCOUNT_COST,
};
use std::{sync::Arc, time::Duration};
use tokio::sync::mpsc::{UnboundedReceiver, unbounded_channel};
use tokio::{
sync::mpsc::{UnboundedReceiver, unbounded_channel},
try_join,
};

/// The client version: `anvil/v{major}.{minor}.{patch}`
pub const CLIENT_VERSION: &str = concat!("anvil/v", env!("CARGO_PKG_VERSION"));
Expand Down Expand Up @@ -762,12 +765,9 @@ impl EthApi {
block_number: Option<BlockId>,
) -> Result<alloy_rpc_types::eth::AccountInfo> {
node_info!("eth_getAccountInfo");
let account = self
.backend
.get_account_at_block(address, Some(self.block_request(block_number).await?))
.await?;
let code =
self.backend.get_code(address, Some(self.block_request(block_number).await?)).await?;
let account = self.get_account(address, block_number);
let code = self.get_code(address, block_number);
let (account, code) = try_join!(account, code)?;
Ok(alloy_rpc_types::eth::AccountInfo {
balance: account.balance,
nonce: account.nonce,
Expand Down
5 changes: 2 additions & 3 deletions crates/anvil/src/eth/backend/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1722,11 +1722,10 @@ impl Backend {
cache_db.commit(state);
gas_used += result.gas_used();

// TODO: this is likely incomplete
// create the transaction from a request
let from = request.from.unwrap_or_default();
let request =
transaction_request_to_typed(WithOtherFields::new(request)).unwrap();
let request = transaction_request_to_typed(WithOtherFields::new(request))
.ok_or(BlockchainError::MissingRequiredFields)?;
let tx = build_typed_transaction(
request,
Signature::new(Default::default(), Default::default(), false),
Expand Down
5 changes: 5 additions & 0 deletions crates/anvil/src/eth/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ pub enum BlockchainError {
/// Duration that was waited before timing out
duration: Duration,
},
#[error("Failed to parse transaction request: missing required fields")]
MissingRequiredFields,
}

impl From<eyre::Report> for BlockchainError {
Expand Down Expand Up @@ -563,6 +565,9 @@ impl<T: Serialize> ToRpcResponseResult for Result<T> {
err @ BlockchainError::UnknownTransactionType => {
RpcError::invalid_params(err.to_string())
}
err @ BlockchainError::MissingRequiredFields => {
RpcError::invalid_params(err.to_string())
}
}
.into(),
}
Expand Down
2 changes: 1 addition & 1 deletion crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ pub trait CheatcodesExecutor {
}

/// Returns a mutable reference to the tracing inspector if it is available.
fn tracing_inspector(&mut self) -> Option<&mut Option<TracingInspector>> {
fn tracing_inspector(&mut self) -> Option<&mut Option<Box<TracingInspector>>> {
None
}
}
Expand Down
7 changes: 5 additions & 2 deletions crates/evm/evm/src/executors/invariant/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,8 +609,11 @@ impl<'a> InvariantExecutor<'a> {
));
}

self.executor.inspector_mut().fuzzer =
Some(Fuzzer { call_generator, fuzz_state: fuzz_state.clone(), collect: true });
self.executor.inspector_mut().set_fuzzer(Fuzzer {
call_generator,
fuzz_state: fuzz_state.clone(),
collect: true,
});

// Let's make sure the invariant is sound before actually starting the run:
// We'll assert the invariant in its initial state, and if it fails, we'll
Expand Down
2 changes: 1 addition & 1 deletion crates/evm/evm/src/executors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ pub struct RawCallResult {
/// The `revm::Env` after the call
pub env: Env,
/// The cheatcode states after execution
pub cheatcodes: Option<Cheatcodes>,
pub cheatcodes: Option<Box<Cheatcodes>>,
/// The raw output of the execution
pub out: Option<Output>,
/// The chisel state
Expand Down
72 changes: 38 additions & 34 deletions crates/evm/evm/src/inspectors/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ pub struct InspectorData {
pub traces: Option<SparsedTraceArena>,
pub line_coverage: Option<HitMaps>,
pub edge_coverage: Option<Vec<u8>>,
pub cheatcodes: Option<Cheatcodes>,
pub cheatcodes: Option<Box<Cheatcodes>>,
pub chisel_state: Option<(Vec<U256>, Vec<u8>, Option<InstructionResult>)>,
pub reverter: Option<Address>,
}
Expand Down Expand Up @@ -290,7 +290,7 @@ pub struct InnerContextData {
/// collection, etc.
#[derive(Clone, Debug, Default)]
pub struct InspectorStack {
pub cheatcodes: Option<Cheatcodes>,
pub cheatcodes: Option<Box<Cheatcodes>>,
pub inner: InspectorStackInner,
}

Expand All @@ -300,15 +300,17 @@ pub struct InspectorStack {
#[derive(Default, Clone, Debug)]
pub struct InspectorStackInner {
// Inspectors.
pub chisel_state: Option<ChiselState>,
pub edge_coverage: Option<EdgeCovInspector>,
pub fuzzer: Option<Fuzzer>,
pub line_coverage: Option<LineCoverageCollector>,
pub log_collector: Option<LogCollector>,
pub printer: Option<CustomPrintTracer>,
pub revert_diag: Option<RevertDiagnostic>,
pub script_execution_inspector: Option<ScriptExecutionInspector>,
pub tracer: Option<TracingInspector>,
// These are boxed to reduce the size of the struct and slightly improve performance of the
// `if let Some` checks.
pub chisel_state: Option<Box<ChiselState>>,
pub edge_coverage: Option<Box<EdgeCovInspector>>,
pub fuzzer: Option<Box<Fuzzer>>,
pub line_coverage: Option<Box<LineCoverageCollector>>,
pub log_collector: Option<Box<LogCollector>>,
pub printer: Option<Box<CustomPrintTracer>>,
pub revert_diag: Option<Box<RevertDiagnostic>>,
pub script_execution_inspector: Option<Box<ScriptExecutionInspector>>,
pub tracer: Option<Box<TracingInspector>>,

// InspectorExt and other internal data.
pub enable_isolation: bool,
Expand All @@ -335,7 +337,7 @@ impl CheatcodesExecutor for InspectorStackInner {
Box::new(InspectorStackRefMut { cheatcodes: Some(cheats), inner: self })
}

fn tracing_inspector(&mut self) -> Option<&mut Option<TracingInspector>> {
fn tracing_inspector(&mut self) -> Option<&mut Option<Box<TracingInspector>>> {
Some(&mut self.tracer)
}
}
Expand Down Expand Up @@ -398,19 +400,19 @@ impl InspectorStack {
/// Set the cheatcodes inspector.
#[inline]
pub fn set_cheatcodes(&mut self, cheatcodes: Cheatcodes) {
self.cheatcodes = Some(cheatcodes);
self.cheatcodes = Some(cheatcodes.into());
}

/// Set the fuzzer inspector.
#[inline]
pub fn set_fuzzer(&mut self, fuzzer: Fuzzer) {
self.fuzzer = Some(fuzzer);
self.fuzzer = Some(fuzzer.into());
}

/// Set the Chisel inspector.
#[inline]
pub fn set_chisel(&mut self, final_pc: usize) {
self.chisel_state = Some(ChiselState::new(final_pc));
self.chisel_state = Some(ChiselState::new(final_pc).into());
}

/// Set whether to enable the line coverage collector.
Expand All @@ -422,7 +424,8 @@ impl InspectorStack {
/// Set whether to enable the edge coverage collector.
#[inline]
pub fn collect_edge_coverage(&mut self, yes: bool) {
self.edge_coverage = yes.then(EdgeCovInspector::new); // TODO configurable edge size?
// TODO: configurable edge size?
self.edge_coverage = yes.then(EdgeCovInspector::new).map(Into::into);
}

/// Set whether to enable call isolation.
Expand Down Expand Up @@ -459,11 +462,7 @@ impl InspectorStack {
/// Revert diagnostic inspector is activated when `mode != TraceMode::None`
#[inline]
pub fn tracing(&mut self, mode: TraceMode) {
if mode.is_none() {
self.revert_diag = None;
} else {
self.revert_diag = Some(RevertDiagnostic::default());
}
self.revert_diag = (!mode.is_none()).then(RevertDiagnostic::default).map(Into::into);

if let Some(config) = mode.into_config() {
*self.tracer.get_or_insert_with(Default::default).config_mut() = config;
Expand All @@ -480,7 +479,6 @@ impl InspectorStack {
}

/// Collects all the data gathered during inspection into a single struct.
#[inline]
pub fn collect(self) -> InspectorData {
let Self {
mut cheatcodes,
Expand Down Expand Up @@ -531,7 +529,7 @@ impl InspectorStack {

#[inline(always)]
fn as_mut(&mut self) -> InspectorStackRefMut<'_> {
InspectorStackRefMut { cheatcodes: self.cheatcodes.as_mut(), inner: &mut self.inner }
InspectorStackRefMut { cheatcodes: self.cheatcodes.as_deref_mut(), inner: &mut self.inner }
}
}

Expand Down Expand Up @@ -740,17 +738,16 @@ impl InspectorStackRefMut<'_> {
/// it.
fn with_stack<O>(&mut self, f: impl FnOnce(&mut InspectorStack) -> O) -> O {
let mut stack = InspectorStack {
cheatcodes: self
.cheatcodes
.as_deref_mut()
.map(|cheats| core::mem::replace(cheats, Cheatcodes::new(cheats.config.clone()))),
cheatcodes: self.cheatcodes.as_deref_mut().map(|cheats| {
core::mem::replace(cheats, Cheatcodes::new(cheats.config.clone())).into()
}),
inner: std::mem::take(self.inner),
};

let out = f(&mut stack);

if let Some(cheats) = self.cheatcodes.as_deref_mut() {
*cheats = stack.cheatcodes.take().unwrap();
*cheats = *stack.cheatcodes.take().unwrap();
}

*self.inner = stack.inner;
Expand Down Expand Up @@ -791,6 +788,11 @@ impl InspectorStackRefMut<'_> {
}
}

// We take extra care in optimizing `step` and `step_end`, as they're are likely the most
// hot functions in all of Foundry.
// We want to `#[inline(always)]` these functions so that `InspectorStack` does not
// delegate to `InspectorStackRefMut` in this case.

#[inline(always)]
fn step_inlined(
&mut self,
Expand All @@ -799,17 +801,18 @@ impl InspectorStackRefMut<'_> {
) {
call_inspectors!(
[
// These are sorted in definition order.
&mut self.edge_coverage,
&mut self.fuzzer,
&mut self.tracer,
&mut self.line_coverage,
&mut self.edge_coverage,
&mut self.script_execution_inspector,
&mut self.printer,
&mut self.revert_diag,
&mut self.script_execution_inspector,
&mut self.tracer,
// Keep `cheatcodes` last to make use of the tail call.
&mut self.cheatcodes,
],
|inspector| (*inspector).step(interpreter, ecx),
|inspector| (**inspector).step(interpreter, ecx),
);
}

Expand All @@ -821,14 +824,15 @@ impl InspectorStackRefMut<'_> {
) {
call_inspectors!(
[
&mut self.tracer,
// These are sorted in definition order.
&mut self.chisel_state,
&mut self.printer,
&mut self.revert_diag,
&mut self.tracer,
// Keep `cheatcodes` last to make use of the tail call.
&mut self.cheatcodes,
],
|inspector| (*inspector).step_end(interpreter, ecx),
|inspector| (**inspector).step_end(interpreter, ecx),
);
}
}
Expand Down
5 changes: 3 additions & 2 deletions crates/evm/fuzz/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ use revm::{
/// An inspector that can fuzz and collect data for that effect.
#[derive(Clone, Debug)]
pub struct Fuzzer {
/// Given a strategy, it generates a random call.
pub call_generator: Option<RandomCallGenerator>,
/// If set, it collects `stack` and `memory` values for fuzzing purposes.
pub collect: bool,
/// Given a strategy, it generates a random call.
pub call_generator: Option<RandomCallGenerator>,
/// If `collect` is set, we store the collected values in this fuzz dictionary.
pub fuzz_state: EvmFuzzState,
}
Expand All @@ -21,6 +21,7 @@ impl<CTX> Inspector<CTX> for Fuzzer
where
CTX: ContextTr<Journal: JournalExt>,
{
#[inline]
fn step(&mut self, interp: &mut Interpreter, _context: &mut CTX) {
// We only collect `stack` and `memory` data before and after calls.
if self.collect {
Expand Down