diff --git a/Cargo.lock b/Cargo.lock index 7d113584e..8d247bec9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,9 +79,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy-chains" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "805f7a974de5804f5c053edc6ca43b20883bdd3a733b3691200ae3a4b454a2db" +checksum = "8158b4878c67837e5413721cc44298e6a2d88d39203175ea025e51892a16ba4c" dependencies = [ "num_enum 0.7.2", "serde", diff --git a/crates/zksync/core/src/vm/inspect.rs b/crates/zksync/core/src/vm/inspect.rs index dc964e2de..5ce3ef439 100644 --- a/crates/zksync/core/src/vm/inspect.rs +++ b/crates/zksync/core/src/vm/inspect.rs @@ -1,6 +1,5 @@ use alloy_primitives::{hex, Log}; use era_test_node::{ - bootloader_debug::{BootloaderDebug, BootloaderDebugTracer}, config::node::ShowCalls, formatter, system_contracts::{Options, SystemContracts}, @@ -43,7 +42,11 @@ use crate::{ db::{ZKVMData, DEFAULT_CHAIN_ID}, env::{create_l1_batch_env, create_system_env}, storage_view::StorageView, - tracer::{CallContext, CheatcodeTracer, CheatcodeTracerContext}, + tracers::{ + bootloader::{BootloaderDebug, BootloaderDebugTracer}, + cheatcode::{CallContext, CheatcodeTracer, CheatcodeTracerContext}, + error::ErrorTracer, + }, }, }; use foundry_evm_abi::{ @@ -437,6 +440,7 @@ fn inspect_inner( let is_create = call_ctx.is_create; let bootloader_debug_tracer_result = Arc::new(OnceCell::default()); let tracers = vec![ + ErrorTracer.into_tracer_pointer(), CallTracer::new(call_tracer_result.clone()).into_tracer_pointer(), BootloaderDebugTracer { result: bootloader_debug_tracer_result.clone() } .into_tracer_pointer(), diff --git a/crates/zksync/core/src/vm/mod.rs b/crates/zksync/core/src/vm/mod.rs index a6cafac57..e3c4e9a98 100644 --- a/crates/zksync/core/src/vm/mod.rs +++ b/crates/zksync/core/src/vm/mod.rs @@ -4,10 +4,10 @@ mod farcall; mod inspect; mod runner; mod storage_view; -mod tracer; +mod tracers; pub use inspect::{ batch_factory_dependencies, inspect, inspect_as_batch, ZKVMExecutionResult, ZKVMResult, }; pub use runner::{balance, call, code_hash, create, encode_create_params, nonce, transact}; -pub use tracer::CheatcodeTracerContext; +pub use tracers::cheatcode::CheatcodeTracerContext; diff --git a/crates/zksync/core/src/vm/runner.rs b/crates/zksync/core/src/vm/runner.rs index 3996107be..4b719731a 100644 --- a/crates/zksync/core/src/vm/runner.rs +++ b/crates/zksync/core/src/vm/runner.rs @@ -21,7 +21,7 @@ use crate::{ vm::{ db::ZKVMData, inspect::{inspect, inspect_as_batch, ZKVMExecutionResult, ZKVMResult}, - tracer::{CallContext, CheatcodeTracerContext}, + tracers::cheatcode::{CallContext, CheatcodeTracerContext}, }, }; diff --git a/crates/zksync/core/src/vm/tracer.rs b/crates/zksync/core/src/vm/tracers/cheatcode.rs similarity index 99% rename from crates/zksync/core/src/vm/tracer.rs rename to crates/zksync/core/src/vm/tracers/cheatcode.rs index 661f1000f..ac991d0dc 100644 --- a/crates/zksync/core/src/vm/tracer.rs +++ b/crates/zksync/core/src/vm/tracers/cheatcode.rs @@ -27,12 +27,10 @@ use zksync_utils::bytecode::hash_bytecode; use crate::{ convert::{ConvertAddress, ConvertH160, ConvertH256, ConvertU256}, - vm::farcall::{CallAction, CallDepth}, + vm::farcall::{CallAction, CallDepth, FarCallHandler}, ZkPaymasterData, EMPTY_CODE, }; -use super::farcall::FarCallHandler; - /// Selector for retrieving account version. /// This is used to override the caller's account version when deploying a contract /// So non-EOA addresses can also deploy within the VM. diff --git a/crates/zksync/core/src/vm/tracers/error.rs b/crates/zksync/core/src/vm/tracers/error.rs new file mode 100644 index 000000000..5a166e075 --- /dev/null +++ b/crates/zksync/core/src/vm/tracers/error.rs @@ -0,0 +1,51 @@ +use multivm::{ + interface::dyn_tracers::vm_1_5_0::DynTracer, + vm_latest::{HistoryMode, SimpleMemory, VmTracer}, + zk_evm_latest::{ + tracing::{AfterDecodingData, VmLocalStateData}, + vm_state::ErrorFlags, + }, +}; +use zksync_state::{ReadStorage, WriteStorage}; + +/// A tracer to allow logging low-level vm errors. +#[derive(Debug, Default)] +pub struct ErrorTracer; + +impl DynTracer> for ErrorTracer { + fn after_decoding( + &mut self, + _state: VmLocalStateData<'_>, + data: AfterDecodingData, + _memory: &SimpleMemory, + ) { + if data.error_flags_accumulated.is_empty() { + return; + } + + let errors = parse_error_flags(&data.error_flags_accumulated); + tracing::error!("vm error: {}", errors.join(", ")); + } +} + +impl VmTracer for ErrorTracer {} + +fn parse_error_flags(error_flags: &ErrorFlags) -> Vec { + let mut errors = vec![]; + if error_flags.contains(ErrorFlags::INVALID_OPCODE) { + errors.push(String::from("Invalid opcode")); + } + if error_flags.contains(ErrorFlags::NOT_ENOUGH_ERGS) { + errors.push(String::from("Not enough gas")); + } + if error_flags.contains(ErrorFlags::PRIVILAGED_ACCESS_NOT_FROM_KERNEL) { + errors.push(String::from("Unauthorized privileged access")); + } + if error_flags.contains(ErrorFlags::WRITE_IN_STATIC_CONTEXT) { + errors.push(String::from("Write applied in static context")); + } + if error_flags.contains(ErrorFlags::CALLSTACK_IS_FULL) { + errors.push(String::from("Call stack full")); + } + errors +} diff --git a/crates/zksync/core/src/vm/tracers/mod.rs b/crates/zksync/core/src/vm/tracers/mod.rs new file mode 100644 index 000000000..020445f30 --- /dev/null +++ b/crates/zksync/core/src/vm/tracers/mod.rs @@ -0,0 +1,7 @@ +/// Contains tracer implementations for the zkEVM + +pub mod bootloader { + pub use era_test_node::bootloader_debug::{BootloaderDebug, BootloaderDebugTracer}; +} +pub mod cheatcode; +pub mod error;