Skip to content

Commit

Permalink
feat: add inner zk traces, fix create not registering logs (#558)
Browse files Browse the repository at this point in the history
* add inner zk traces, fix create not registering logs

* rename trace to trace_zksync
  • Loading branch information
nbaztec authored Sep 4, 2024
1 parent 65a9555 commit fcd9bae
Show file tree
Hide file tree
Showing 12 changed files with 879 additions and 19 deletions.
32 changes: 28 additions & 4 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use foundry_evm_core::{
use foundry_zksync_compiler::{DualCompiledContract, DualCompiledContracts};
use foundry_zksync_core::{
convert::{ConvertH160, ConvertH256, ConvertRU256, ConvertU256},
get_account_code_key, get_balance_key, get_nonce_key, ZkTransactionMetadata,
get_account_code_key, get_balance_key, get_nonce_key, Call, ZkTransactionMetadata,
};
use itertools::Itertools;
use revm::{
Expand Down Expand Up @@ -158,6 +158,15 @@ pub trait CheatcodesExecutor {
fn console_log<DB: DatabaseExt>(&mut self, ccx: &mut CheatsCtxt<DB>, message: String) {
self.get_inspector::<DB>(ccx.state).console_log(message);
}

fn trace<DB: DatabaseExt>(
&mut self,
ccx_state: &mut Cheatcodes,
ecx: &mut EvmContext<DB>,
call_traces: Vec<Call>,
) {
self.get_inspector::<DB>(ccx_state).trace_zksync(ecx, call_traces);
}
}

/// Basic implementation of [CheatcodesExecutor] that simply returns the [Cheatcodes] instance as an
Expand Down Expand Up @@ -729,6 +738,7 @@ impl Cheatcodes {
&mut self,
ecx: &mut EvmContext<DB>,
mut input: Input,
executor: &mut impl CheatcodesExecutor,
) -> Option<CreateOutcome>
where
DB: DatabaseExt,
Expand Down Expand Up @@ -926,7 +936,6 @@ impl Cheatcodes {
}

// append console logs from zkEVM to the current executor's LogTracer
let executor = &mut TransparentCheatcodesExecutor;
result.logs.iter().filter_map(decode_console_log).for_each(|decoded_log| {
executor.console_log(
&mut CheatsCtxt {
Expand All @@ -940,6 +949,9 @@ impl Cheatcodes {
);
});

// append traces
executor.trace(self, ecx, result.call_traces);

// for each log in cloned logs call handle_expect_emit
if !self.expected_emits.is_empty() {
for log in result.logs {
Expand Down Expand Up @@ -1102,6 +1114,15 @@ impl Cheatcodes {
outcome
}

pub fn create_with_executor<DB: DatabaseExt>(
&mut self,
ecx: &mut EvmContext<DB>,
call: &mut CreateInputs,
executor: &mut impl CheatcodesExecutor,
) -> Option<CreateOutcome> {
self.create_common(ecx, call, executor)
}

pub fn call_with_executor<DB: DatabaseExt>(
&mut self,
ecx: &mut EvmContext<DB>,
Expand Down Expand Up @@ -1419,6 +1440,9 @@ impl Cheatcodes {
}));
}

// append traces
executor.trace(self, ecx, result.call_traces);

// for each log in cloned logs call handle_expect_emit
if !self.expected_emits.is_empty() {
for log in result.logs {
Expand Down Expand Up @@ -1856,7 +1880,7 @@ impl<DB: DatabaseExt> Inspector<DB> for Cheatcodes {
ecx: &mut EvmContext<DB>,
call: &mut CreateInputs,
) -> Option<CreateOutcome> {
self.create_common(ecx, call)
self.create_common(ecx, call, &mut TransparentCheatcodesExecutor)
}

fn create_end(
Expand All @@ -1873,7 +1897,7 @@ impl<DB: DatabaseExt> Inspector<DB> for Cheatcodes {
ecx: &mut EvmContext<DB>,
call: &mut EOFCreateInputs,
) -> Option<CreateOutcome> {
self.create_common(ecx, call)
self.create_common(ecx, call, &mut TransparentCheatcodesExecutor)
}

fn eofcreate_end(
Expand Down
4 changes: 4 additions & 0 deletions crates/evm/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

use auto_impl::auto_impl;
use foundry_zksync_core::Call;
use revm::{inspectors::NoOpInspector, interpreter::CreateInputs, Database, EvmContext, Inspector};
use revm_inspectors::access_list::AccessListInspector;

Expand Down Expand Up @@ -47,6 +48,9 @@ pub trait InspectorExt<DB: Database>: Inspector<DB> {

// Simulates `console.log` invocation.
fn console_log(&mut self, _input: String) {}

// Appends provided zksync traces.
fn trace_zksync(&mut self, _context: &mut EvmContext<DB>, _call_traces: Vec<Call>) {}
}

impl<DB: Database> InspectorExt<DB> for NoOpInspector {}
Expand Down
3 changes: 3 additions & 0 deletions crates/evm/evm/src/inspectors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ pub use logs::LogCollector;

mod stack;
pub use stack::{InspectorData, InspectorStack, InspectorStackBuilder};

mod trace;
pub use trace::TraceCollector;
27 changes: 23 additions & 4 deletions crates/evm/evm/src/inspectors/stack.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use super::{
Cheatcodes, CheatsConfig, ChiselState, CoverageCollector, Fuzzer, LogCollector,
TracingInspector,
Cheatcodes, CheatsConfig, ChiselState, CoverageCollector, Fuzzer, LogCollector, TraceCollector,
};
use alloy_primitives::{Address, Bytes, Log, TxKind, U256};
use foundry_cheatcodes::CheatcodesExecutor;
Expand All @@ -10,6 +9,7 @@ use foundry_evm_core::{
};
use foundry_evm_coverage::HitMaps;
use foundry_evm_traces::{CallTraceArena, TraceMode};
use foundry_zksync_core::Call;
use revm::{
inspectors::CustomPrintTracer,
interpreter::{
Expand Down Expand Up @@ -282,7 +282,7 @@ pub struct InspectorStackInner {
pub fuzzer: Option<Fuzzer>,
pub log_collector: Option<LogCollector>,
pub printer: Option<CustomPrintTracer>,
pub tracer: Option<TracingInspector>,
pub tracer: Option<TraceCollector>,
pub enable_isolation: bool,

/// Flag marking if we are in the inner EVM context.
Expand Down Expand Up @@ -751,12 +751,23 @@ impl<'a, DB: DatabaseExt> Inspector<DB> for InspectorStackRefMut<'a> {

call_inspectors_adjust_depth!(
#[ret]
[&mut self.tracer, &mut self.coverage, &mut self.cheatcodes],
[&mut self.tracer, &mut self.coverage],
|inspector| inspector.create(ecx, create).map(Some),
self,
ecx
);

ecx.journaled_state.depth += self.in_inner_context as usize;
if let Some(cheatcodes) = self.cheatcodes.as_deref_mut() {
if let Some(output) = cheatcodes.create_with_executor(ecx, create, self.inner) {
if output.result.result != InstructionResult::Continue {
ecx.journaled_state.depth -= self.in_inner_context as usize;
return Some(output);
}
}
}
ecx.journaled_state.depth -= self.in_inner_context as usize;

if !matches!(create.scheme, CreateScheme::Create2 { .. }) &&
self.enable_isolation &&
!self.in_inner_context &&
Expand Down Expand Up @@ -915,6 +926,14 @@ impl<'a, DB: DatabaseExt> InspectorExt<DB> for InspectorStackRefMut<'a> {
inspector, input
));
}

fn trace_zksync(&mut self, ecx: &mut EvmContext<DB>, call_traces: Vec<Call>) {
call_inspectors!([&mut self.tracer], |inspector| InspectorExt::<DB>::trace_zksync(
inspector,
ecx,
call_traces
));
}
}

impl<DB: DatabaseExt> Inspector<DB> for InspectorStack {
Expand Down
Loading

0 comments on commit fcd9bae

Please sign in to comment.