From 73f2e3b2dac18a84c57e144de52f62e4b7c7c9b8 Mon Sep 17 00:00:00 2001 From: elfedy Date: Mon, 28 Oct 2024 14:48:59 -0300 Subject: [PATCH 01/20] chore: update foundry-block-explorers --- Cargo.lock | 195 +++++++++-------------------------------------------- 1 file changed, 32 insertions(+), 163 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 495a46ff8..d5e6c6ce1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2328,7 +2328,7 @@ dependencies = [ "foundry-block-explorers", "foundry-cli", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-evm", "foundry-test-utils", @@ -2427,7 +2427,7 @@ dependencies = [ "foundry-block-explorers", "foundry-cli", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-evm", "regex", @@ -4690,7 +4690,7 @@ dependencies = [ "foundry-block-explorers", "foundry-cli", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-debugger", "foundry-evm", @@ -4753,7 +4753,7 @@ dependencies = [ "derive_more 1.0.0", "eyre", "forge-fmt", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "itertools 0.13.0", "mdbook", @@ -4809,7 +4809,7 @@ dependencies = [ "foundry-cheatcodes", "foundry-cli", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-debugger", "foundry-evm", @@ -4840,7 +4840,7 @@ dependencies = [ "alloy-rpc-types", "eyre", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-zksync-core", "revm-inspectors", @@ -4881,7 +4881,7 @@ dependencies = [ "foundry-block-explorers", "foundry-cli", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-evm", "foundry-test-utils", @@ -4912,12 +4912,12 @@ dependencies = [ [[package]] name = "foundry-block-explorers" version = "0.7.3" -source = "git+https://github.com/Moonsong-Labs/block-explorers?branch=zksync-v0.7.3#9ebec2f71f0ee739f4ec4fb21df4d301aeb61936" +source = "git+https://github.com/Moonsong-Labs/block-explorers?branch=zksync-v0.7.3#ef81bf5a733517de496ae1d14024ea9b4fcd4d3c" dependencies = [ "alloy-chains", "alloy-json-abi", "alloy-primitives", - "foundry-compilers 0.11.1", + "foundry-compilers", "reqwest 0.12.8", "semver 1.0.23", "serde", @@ -4949,7 +4949,7 @@ dependencies = [ "foundry-cheatcodes-common", "foundry-cheatcodes-spec", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-evm-core", "foundry-wallets", @@ -5012,7 +5012,7 @@ dependencies = [ "eyre", "forge-fmt", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-debugger", "foundry-evm", @@ -5059,7 +5059,7 @@ dependencies = [ "eyre", "foundry-block-explorers", "foundry-common-fmt", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-zksync-compiler", "globset", @@ -5097,46 +5097,6 @@ dependencies = [ "yansi 1.0.1", ] -[[package]] -name = "foundry-compilers" -version = "0.11.1" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.1#e3f44379f6bfb3c50e3a69acbeaa8f6da0cb4aae" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "auto_impl", - "derivative", - "dirs 5.0.1", - "dyn-clone", - "foundry-compilers-artifacts 0.11.1", - "foundry-compilers-core 0.11.1", - "fs4 0.8.4", - "fs_extra", - "futures-util", - "home", - "itertools 0.13.0", - "md-5", - "once_cell", - "path-slash", - "rand 0.8.5", - "rayon", - "reqwest 0.12.8", - "semver 1.0.23", - "serde", - "serde_json", - "sha2 0.10.8", - "solang-parser", - "svm-rs 0.5.8", - "svm-rs-builds", - "tempfile", - "thiserror", - "tokio", - "tracing", - "walkdir", - "winnow 0.6.20", - "yansi 1.0.1", -] - [[package]] name = "foundry-compilers" version = "0.11.4" @@ -5148,8 +5108,8 @@ dependencies = [ "derivative", "dirs 5.0.1", "dyn-clone", - "foundry-compilers-artifacts 0.11.4", - "foundry-compilers-core 0.11.4", + "foundry-compilers-artifacts", + "foundry-compilers-core", "fs4 0.8.4", "fs_extra", "futures-util", @@ -5177,47 +5137,14 @@ dependencies = [ "yansi 1.0.1", ] -[[package]] -name = "foundry-compilers-artifacts" -version = "0.11.1" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.1#e3f44379f6bfb3c50e3a69acbeaa8f6da0cb4aae" -dependencies = [ - "foundry-compilers-artifacts-solc 0.11.1", - "foundry-compilers-artifacts-vyper 0.11.1", - "foundry-compilers-artifacts-zksolc 0.11.1", -] - [[package]] name = "foundry-compilers-artifacts" version = "0.11.4" source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.4#04cb9bd38c9dbd6388488a0d6cd9377db1e44a44" dependencies = [ - "foundry-compilers-artifacts-solc 0.11.4", - "foundry-compilers-artifacts-vyper 0.11.4", - "foundry-compilers-artifacts-zksolc 0.11.4", -] - -[[package]] -name = "foundry-compilers-artifacts-solc" -version = "0.11.1" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.1#e3f44379f6bfb3c50e3a69acbeaa8f6da0cb4aae" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "foundry-compilers-core 0.11.1", - "futures-util", - "md-5", - "path-slash", - "rayon", - "semver 1.0.23", - "serde", - "serde_json", - "serde_repr", - "thiserror", - "tokio", - "tracing", - "walkdir", - "yansi 1.0.1", + "foundry-compilers-artifacts-solc", + "foundry-compilers-artifacts-vyper", + "foundry-compilers-artifacts-zksolc", ] [[package]] @@ -5227,7 +5154,7 @@ source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.4#0 dependencies = [ "alloy-json-abi", "alloy-primitives", - "foundry-compilers-core 0.11.4", + "foundry-compilers-core", "futures-util", "md-5", "path-slash", @@ -5243,20 +5170,6 @@ dependencies = [ "yansi 1.0.1", ] -[[package]] -name = "foundry-compilers-artifacts-vyper" -version = "0.11.1" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.1#e3f44379f6bfb3c50e3a69acbeaa8f6da0cb4aae" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "foundry-compilers-artifacts-solc 0.11.1", - "foundry-compilers-core 0.11.1", - "path-slash", - "semver 1.0.23", - "serde", -] - [[package]] name = "foundry-compilers-artifacts-vyper" version = "0.11.4" @@ -5264,32 +5177,11 @@ source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.4#0 dependencies = [ "alloy-json-abi", "alloy-primitives", - "foundry-compilers-artifacts-solc 0.11.4", - "foundry-compilers-core 0.11.4", - "path-slash", - "semver 1.0.23", - "serde", -] - -[[package]] -name = "foundry-compilers-artifacts-zksolc" -version = "0.11.1" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.1#e3f44379f6bfb3c50e3a69acbeaa8f6da0cb4aae" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "foundry-compilers-artifacts-solc 0.11.1", - "foundry-compilers-core 0.11.1", - "md-5", + "foundry-compilers-artifacts-solc", + "foundry-compilers-core", "path-slash", - "rayon", "semver 1.0.23", "serde", - "serde_json", - "thiserror", - "tracing", - "walkdir", - "yansi 1.0.1", ] [[package]] @@ -5299,8 +5191,8 @@ source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.4#0 dependencies = [ "alloy-json-abi", "alloy-primitives", - "foundry-compilers-artifacts-solc 0.11.4", - "foundry-compilers-core 0.11.4", + "foundry-compilers-artifacts-solc", + "foundry-compilers-core", "md-5", "path-slash", "rayon", @@ -5313,29 +5205,6 @@ dependencies = [ "yansi 1.0.1", ] -[[package]] -name = "foundry-compilers-core" -version = "0.11.1" -source = "git+https://github.com/Moonsong-Labs/compilers?branch=zksync-v0.11.1#e3f44379f6bfb3c50e3a69acbeaa8f6da0cb4aae" -dependencies = [ - "alloy-primitives", - "cfg-if 1.0.0", - "dunce", - "fs_extra", - "memmap2", - "once_cell", - "path-slash", - "regex", - "semver 1.0.23", - "serde", - "serde_json", - "svm-rs 0.5.8", - "tempfile", - "thiserror", - "tokio", - "walkdir", -] - [[package]] name = "foundry-compilers-core" version = "0.11.4" @@ -5370,7 +5239,7 @@ dependencies = [ "eyre", "figment", "foundry-block-explorers", - "foundry-compilers 0.11.4", + "foundry-compilers", "glob", "globset", "mesc", @@ -5402,7 +5271,7 @@ dependencies = [ "crossterm 0.28.1", "eyre", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-evm-core", "foundry-evm-traces", "ratatui", @@ -5423,7 +5292,7 @@ dependencies = [ "eyre", "foundry-cheatcodes", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-evm-core", "foundry-evm-coverage", @@ -5494,7 +5363,7 @@ dependencies = [ "alloy-primitives", "eyre", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-evm-core", "rayon", "revm", @@ -5512,7 +5381,7 @@ dependencies = [ "alloy-primitives", "eyre", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-evm-core", "foundry-evm-coverage", @@ -5541,7 +5410,7 @@ dependencies = [ "foundry-block-explorers", "foundry-cheatcodes-spec", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "foundry-evm-core", "foundry-linking", @@ -5585,7 +5454,7 @@ name = "foundry-linking" version = "0.0.2" dependencies = [ "alloy-primitives", - "foundry-compilers 0.11.4", + "foundry-compilers", "semver 1.0.23", "thiserror", ] @@ -5611,7 +5480,7 @@ dependencies = [ "fd-lock", "foundry-block-explorers", "foundry-common", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "jsonrpc-core", "jsonrpc-http-server", @@ -5663,7 +5532,7 @@ version = "0.0.2" dependencies = [ "alloy-primitives", "eyre", - "foundry-compilers 0.11.4", + "foundry-compilers", "foundry-config", "semver 1.0.23", "serde", @@ -8519,7 +8388,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 3.2.0", + "proc-macro-crate 1.3.1", "proc-macro2 1.0.88", "quote 1.0.37", "syn 2.0.79", From 9de6ed73bffa853a68740f0de43968e32b4af495 Mon Sep 17 00:00:00 2001 From: elfedy Date: Mon, 28 Oct 2024 16:05:42 -0300 Subject: [PATCH 02/20] chore: remove deployments from LocalTraceIdentifier --- crates/evm/traces/src/identifier/local.rs | 15 ++++----------- crates/evm/traces/src/lib.rs | 3 --- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/crates/evm/traces/src/identifier/local.rs b/crates/evm/traces/src/identifier/local.rs index 97cc60aa4..fec31e4ae 100644 --- a/crates/evm/traces/src/identifier/local.rs +++ b/crates/evm/traces/src/identifier/local.rs @@ -1,9 +1,9 @@ use super::{AddressIdentity, TraceIdentifier}; use alloy_json_abi::JsonAbi; -use alloy_primitives::{Address, Bytes}; +use alloy_primitives::Address; use foundry_common::contracts::{bytecode_diff_score, ContractsByArtifact}; use foundry_compilers::ArtifactId; -use std::{borrow::Cow, collections::HashMap}; +use std::borrow::Cow; /// A trace identifier that tries to identify addresses using local contracts. pub struct LocalTraceIdentifier<'a> { @@ -11,8 +11,6 @@ pub struct LocalTraceIdentifier<'a> { known_contracts: &'a ContractsByArtifact, /// Vector of pairs of artifact ID and the runtime code length of the given artifact. ordered_ids: Vec<(&'a ArtifactId, usize)>, - /// Deployments generated during the setup - pub deployments: HashMap, } impl<'a> LocalTraceIdentifier<'a> { @@ -25,7 +23,7 @@ impl<'a> LocalTraceIdentifier<'a> { .map(|(id, bytecode)| (id, bytecode.len())) .collect::>(); ordered_ids.sort_by_key(|(_, len)| *len); - Self { known_contracts, ordered_ids, deployments: HashMap::new() } + Self { known_contracts, ordered_ids } } /// Returns the known contracts. @@ -139,12 +137,7 @@ impl TraceIdentifier for LocalTraceIdentifier<'_> { .filter_map(|(address, runtime_code, creation_code)| { let _span = trace_span!(target: "evm::traces", "identify", %address).entered(); trace!(target: "evm::traces", "identifying"); - let (id, abi) = - self.identify_code(runtime_code?, creation_code?).or_else(|| { - self.deployments - .get(address) - .and_then(|bytes| self.identify_code(bytes, bytes)) - })?; + let (id, abi) = self.identify_code(runtime_code?, creation_code?)?; trace!(target: "evm::traces", id=%id.identifier(), "identified"); diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index b4af1f53a..dd4a89664 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -8,7 +8,6 @@ #[macro_use] extern crate tracing; -use alloy_primitives::{Address, Bytes}; use foundry_common::contracts::{ContractsByAddress, ContractsByArtifact}; use revm::interpreter::OpCode; use revm_inspectors::tracing::{ @@ -232,10 +231,8 @@ impl TraceKind { pub fn load_contracts<'a>( traces: impl IntoIterator, known_contracts: &ContractsByArtifact, - deployments: &HashMap, ) -> ContractsByAddress { let mut local_identifier = LocalTraceIdentifier::new(known_contracts); - local_identifier.deployments.clone_from(deployments); let decoder = CallTraceDecoder::new(); let mut contracts = ContractsByAddress::new(); for trace in traces { From 4dfd89ee1d3150bf1cf3b16313e040dec1897aad Mon Sep 17 00:00:00 2001 From: elfedy Date: Mon, 28 Oct 2024 16:14:36 -0300 Subject: [PATCH 03/20] fix: use dyn DatabaseExt in TraceCollector --- crates/zksync/inspectors/src/trace.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/zksync/inspectors/src/trace.rs b/crates/zksync/inspectors/src/trace.rs index 15f71d81d..abf9d9eb5 100644 --- a/crates/zksync/inspectors/src/trace.rs +++ b/crates/zksync/inspectors/src/trace.rs @@ -1,5 +1,5 @@ use alloy_primitives::{Address, Bytes, Log, U256}; -use foundry_evm_core::InspectorExt; +use foundry_evm_core::{backend::DatabaseExt, InspectorExt}; use foundry_evm_traces::{ CallTraceArena, GethTraceBuilder, ParityTraceBuilder, TracingInspector, TracingInspectorConfig, }; @@ -186,11 +186,15 @@ where } } -impl InspectorExt for TraceCollector { - fn trace_zksync(&mut self, context: &mut EvmContext, call_traces: Vec) { - fn trace_call_recursive( +impl InspectorExt for TraceCollector { + fn trace_zksync( + &mut self, + context: &mut EvmContext<&mut dyn DatabaseExt>, + call_traces: Vec, + ) { + fn trace_call_recursive( tracer: &mut TracingInspector, - context: &mut EvmContext, + context: &mut EvmContext<&mut dyn DatabaseExt>, call: Call, suppressed_top_call: bool, ) -> u64 { From 386596be0a35d5290791e3f8fe1ae55a5d0a0b61 Mon Sep 17 00:00:00 2001 From: elfedy Date: Mon, 28 Oct 2024 16:22:18 -0300 Subject: [PATCH 04/20] chore: fix duplicate method definition --- crates/cheatcodes/src/inspector.rs | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 941fe2f00..e935012e9 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -18,11 +18,10 @@ use crate::{ Vm::{self, AccountAccess}, }; use alloy_primitives::{ - hex, + hex, keccak256, map::{AddressHashMap, HashMap}, Address, Bytes, Log, TxKind, B256, U256, }; -use alloy_primitives::{hex, keccak256, Address, Bytes, Log, TxKind, B256, U256}; use alloy_rpc_types::request::{TransactionInput, TransactionRequest}; use alloy_sol_types::{SolCall, SolInterface, SolValue}; use foundry_cheatcodes_common::{ @@ -37,12 +36,14 @@ use foundry_evm_core::{ backend::{DatabaseError, DatabaseExt, LocalForkId, RevertDiagnostic}, constants::{ CHEATCODE_ADDRESS, CHEATCODE_CONTRACT_HASH, DEFAULT_CREATE2_DEPLOYER, - DEFAULT_CREATE2_DEPLOYER_CODE, MAGIC_ASSUME, HARDHAT_CONSOLE_ADDRESS + DEFAULT_CREATE2_DEPLOYER_CODE, HARDHAT_CONSOLE_ADDRESS, MAGIC_ASSUME, }, decode::decode_console_log, utils::new_evm_with_existing_context, InspectorExt, }; +use foundry_evm_traces::{TracingInspector, TracingInspectorConfig}; +use foundry_wallets::multi_wallet::MultiWallet; use foundry_zksync_compiler::{DualCompiledContract, DualCompiledContracts}; use foundry_zksync_core::{ convert::{ConvertAddress, ConvertH160, ConvertH256, ConvertRU256, ConvertU256}, @@ -50,8 +51,6 @@ use foundry_zksync_core::{ ZkTransactionMetadata, DEFAULT_CREATE2_DEPLOYER_ZKSYNC, }; use foundry_zksync_inspectors::TraceCollector; -use foundry_evm_traces::{TracingInspector, TracingInspectorConfig}; -use foundry_wallets::multi_wallet::MultiWallet; use itertools::Itertools; use proptest::test_runner::{RngAlgorithm, TestRng, TestRunner}; use rand::Rng; @@ -154,12 +153,7 @@ pub trait CheatcodesExecutor { None } - fn trace_zksync( - &mut self, - ccx_state: &mut Cheatcodes, - ecx: &mut Ecx, - call_traces: Vec, - ) { + fn trace_zksync(&mut self, ccx_state: &mut Cheatcodes, ecx: &mut Ecx, call_traces: Vec) { self.get_inspector(ccx_state).trace_zksync(ecx, call_traces); } } @@ -935,7 +929,6 @@ impl Cheatcodes { mut input: Input, executor: &mut impl CheatcodesExecutor, ) -> Option - fn create_common(&mut self, ecx: Ecx, mut input: Input) -> Option where Input: CommonCreateInput, { @@ -2335,11 +2328,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { outcome } - fn create( - &mut self, - ecx: Ecx, - call: &mut CreateInputs, - ) -> Option { + fn create(&mut self, ecx: Ecx, call: &mut CreateInputs) -> Option { self.create_common(ecx, call, &mut TransparentCheatcodesExecutor) } @@ -2352,11 +2341,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { self.create_end_common(ecx, outcome) } - fn eofcreate( - &mut self, - ecx: Ecx, - call: &mut EOFCreateInputs, - ) -> Option { + fn eofcreate(&mut self, ecx: Ecx, call: &mut EOFCreateInputs) -> Option { self.create_common(ecx, call, &mut TransparentCheatcodesExecutor) } From fac89f78f1c05b3c8be770fa1d79fad2c4cc918a Mon Sep 17 00:00:00 2001 From: elfedy Date: Mon, 28 Oct 2024 16:38:27 -0300 Subject: [PATCH 05/20] fix: solve some dependency issues in cheatcodes crate --- Cargo.lock | 1 + crates/cheatcodes/Cargo.toml | 1 + crates/cheatcodes/src/inspector.rs | 12 ++++++------ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5e6c6ce1..89c2cd439 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4952,6 +4952,7 @@ dependencies = [ "foundry-compilers", "foundry-config", "foundry-evm-core", + "foundry-evm-traces", "foundry-wallets", "foundry-zksync-compiler", "foundry-zksync-core", diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index b7650dc2b..df3631ed3 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -28,6 +28,7 @@ foundry-common.workspace = true foundry-compilers.workspace = true foundry-config.workspace = true foundry-evm-core.workspace = true +foundry-evm-traces.workspace = true foundry-wallets.workspace = true foundry-zksync-core.workspace = true foundry-zksync-compiler.workspace = true diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index e935012e9..85d092a94 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -5,7 +5,7 @@ use crate::{ journaled_account, mapping::{self, MappingSlots}, prank::Prank, - DealRecord, GasRecord, RecordAccess, + DealRecord, GasRecord, }, inspector::utils::CommonCreateInput, script::{Broadcast, Wallets}, @@ -32,17 +32,17 @@ use foundry_cheatcodes_common::{ use foundry_common::{evm::Breakpoints, TransactionMaybeSigned, SELECTOR_LEN}; use foundry_config::Config; use foundry_evm_core::{ - abi::Vm::stopExpectSafeMemoryCall, + abi::{Vm::stopExpectSafeMemoryCall, HARDHAT_CONSOLE_ADDRESS}, backend::{DatabaseError, DatabaseExt, LocalForkId, RevertDiagnostic}, constants::{ CHEATCODE_ADDRESS, CHEATCODE_CONTRACT_HASH, DEFAULT_CREATE2_DEPLOYER, - DEFAULT_CREATE2_DEPLOYER_CODE, HARDHAT_CONSOLE_ADDRESS, MAGIC_ASSUME, + DEFAULT_CREATE2_DEPLOYER_CODE, MAGIC_ASSUME, }, decode::decode_console_log, utils::new_evm_with_existing_context, InspectorExt, }; -use foundry_evm_traces::{TracingInspector, TracingInspectorConfig}; +use foundry_evm_traces::TracingInspectorConfig; use foundry_wallets::multi_wallet::MultiWallet; use foundry_zksync_compiler::{DualCompiledContract, DualCompiledContracts}; use foundry_zksync_core::{ @@ -68,7 +68,7 @@ use revm::{ }; use serde_json::Value; use std::{ - collections::{BTreeMap, HashMap, HashSet, VecDeque}, + collections::{BTreeMap, HashSet, VecDeque}, fs::File, io::BufReader, ops::Range, @@ -1109,7 +1109,7 @@ impl Cheatcodes { ) -> Option where DB: DatabaseExt, - Input: CommonCreateInput, + Input: CommonCreateInput, { if self.skip_zk_vm { self.skip_zk_vm = false; // handled the skip, reset flag From 8dd722dfdb9f7e621256678976775a213855ffea Mon Sep 17 00:00:00 2001 From: elfedy Date: Mon, 28 Oct 2024 16:55:17 -0300 Subject: [PATCH 06/20] fix: adapt cheatcode crate to usage of dyn DatabaseExt --- crates/cheatcodes/src/inspector.rs | 21 ++++++++----------- crates/cheatcodes/src/test.rs | 8 +++---- .../zksync/core/src/vm/tracers/cheatcode.rs | 8 ++----- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 85d092a94..3a3585937 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -153,7 +153,12 @@ pub trait CheatcodesExecutor { None } - fn trace_zksync(&mut self, ccx_state: &mut Cheatcodes, ecx: &mut Ecx, call_traces: Vec) { + fn trace_zksync<'a>( + &mut self, + ccx_state: &'a mut Cheatcodes, + ecx: Ecx<'a, 'a, 'a>, + call_traces: Vec, + ) { self.get_inspector(ccx_state).trace_zksync(ecx, call_traces); } } @@ -729,11 +734,7 @@ impl Cheatcodes { /// Additionally: /// * Translates block information /// * Translates all persisted addresses - pub fn select_fork_vm( - &mut self, - data: &mut InnerEvmContext, - fork_id: LocalForkId, - ) { + pub fn select_fork_vm(&mut self, data: InnerEcx, fork_id: LocalForkId) { let fork_info = data.db.get_fork_info(fork_id).expect("failed getting fork info"); if fork_info.fork_type.is_evm() { self.select_evm(data) @@ -744,7 +745,7 @@ impl Cheatcodes { /// Switch to EVM and translate block info, balances, nonces and deployed codes for persistent /// accounts - pub fn select_evm(&mut self, data: &mut InnerEvmContext) { + pub fn select_evm(&mut self, data: InnerEcx) { if !self.use_zk_vm { tracing::info!("already in EVM"); return @@ -816,11 +817,7 @@ impl Cheatcodes { /// Switch to ZK-VM and translate block info, balances, nonces and deployed codes for persistent /// accounts - pub fn select_zk_vm( - &mut self, - data: &mut InnerEvmContext, - new_env: Option<&Env>, - ) { + pub fn select_zk_vm(&mut self, data: InnerEcx, new_env: Option<&Env>) { if self.use_zk_vm { tracing::info!("already in ZK-VM"); return diff --git a/crates/cheatcodes/src/test.rs b/crates/cheatcodes/src/test.rs index 79c18c1f0..04e43897d 100644 --- a/crates/cheatcodes/src/test.rs +++ b/crates/cheatcodes/src/test.rs @@ -14,7 +14,7 @@ pub(crate) mod assume; pub(crate) mod expect; impl Cheatcode for zkVmCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { enable } = *self; if enable { @@ -28,7 +28,7 @@ impl Cheatcode for zkVmCall { } impl Cheatcode for zkVmSkipCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { ccx.state.skip_zk_vm = ccx.state.use_zk_vm; Ok(Default::default()) @@ -36,7 +36,7 @@ impl Cheatcode for zkVmSkipCall { } impl Cheatcode for zkUsePaymasterCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { paymaster_address, paymaster_input } = self; ccx.state.paymaster_params = Some(ZkPaymasterData { address: *paymaster_address, input: paymaster_input.clone() }); @@ -45,7 +45,7 @@ impl Cheatcode for zkUsePaymasterCall { } impl Cheatcode for zkRegisterContractCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { name, evmBytecodeHash, diff --git a/crates/zksync/core/src/vm/tracers/cheatcode.rs b/crates/zksync/core/src/vm/tracers/cheatcode.rs index 0b2c0b20d..0725d07db 100644 --- a/crates/zksync/core/src/vm/tracers/cheatcode.rs +++ b/crates/zksync/core/src/vm/tracers/cheatcode.rs @@ -1,10 +1,6 @@ -use std::{ - cell::OnceCell, - collections::{BTreeMap, HashMap}, - sync::Arc, -}; +use std::{cell::OnceCell, collections::BTreeMap, sync::Arc}; -use alloy_primitives::{hex, Address, Bytes, U256 as rU256}; +use alloy_primitives::{hex, map::HashMap, Address, Bytes, U256 as rU256}; use foundry_cheatcodes_common::{ expect::ExpectedCallTracker, mock::{MockCallDataContext, MockCallReturnData}, From 9ed837ade40936bdc4de0e41dfcb7875bf8197f2 Mon Sep 17 00:00:00 2001 From: elfedy Date: Mon, 28 Oct 2024 18:20:33 -0300 Subject: [PATCH 07/20] fix: adapt to usage of hash maps with different hashes --- crates/cheatcodes/src/inspector.rs | 4 ++-- crates/cheatcodes/src/test/expect.rs | 1 - crates/zksync/core/src/vm/tracers/cheatcode.rs | 10 +++++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 3a3585937..74e1e06f8 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -68,7 +68,7 @@ use revm::{ }; use serde_json::Value; use std::{ - collections::{BTreeMap, HashSet, VecDeque}, + collections::{BTreeMap, HashMap as sHashMap, HashSet, VecDeque}, fs::File, io::BufReader, ops::Range, @@ -544,7 +544,7 @@ pub struct Cheatcodes { /// would be a significant refactor, we maintain the factory_dep part in the [Cheatcodes]. /// This can be done as each test runs with its own [Cheatcodes] instance, thereby /// providing the necessary level of isolation. - pub persisted_factory_deps: HashMap>, + pub persisted_factory_deps: sHashMap>, } // This is not derived because calling this in `fn new` with `..Default::default()` creates a second diff --git a/crates/cheatcodes/src/test/expect.rs b/crates/cheatcodes/src/test/expect.rs index 1c89af369..f5466ebad 100644 --- a/crates/cheatcodes/src/test/expect.rs +++ b/crates/cheatcodes/src/test/expect.rs @@ -12,7 +12,6 @@ use revm::interpreter::{ return_ok, InstructionResult, Interpreter, InterpreterAction, InterpreterResult, }; use spec::Vm; -use std::collections::hash_map::Entry; /// For some cheatcodes we may internally change the status of the call, i.e. in `expectRevert`. /// Solidity will see a successful call and attempt to decode the return data. Therefore, we need diff --git a/crates/zksync/core/src/vm/tracers/cheatcode.rs b/crates/zksync/core/src/vm/tracers/cheatcode.rs index 0725d07db..402994ae3 100644 --- a/crates/zksync/core/src/vm/tracers/cheatcode.rs +++ b/crates/zksync/core/src/vm/tracers/cheatcode.rs @@ -1,4 +1,8 @@ -use std::{cell::OnceCell, collections::BTreeMap, sync::Arc}; +use std::{ + cell::OnceCell, + collections::{BTreeMap, HashMap as sHashMap}, + sync::Arc, +}; use alloy_primitives::{hex, map::HashMap, Address, Bytes, U256 as rU256}; use foundry_cheatcodes_common::{ @@ -76,7 +80,7 @@ pub struct CheatcodeTracerContext<'a> { /// Recorded storage accesses pub accesses: Option<&'a mut RecordAccess>, /// Factory deps that were persisted across calls - pub persisted_factory_deps: Option<&'a mut HashMap>>, + pub persisted_factory_deps: Option<&'a mut sHashMap>>, /// Paymaster data pub paymaster_data: Option, } @@ -111,7 +115,7 @@ pub struct CallContext { pub is_static: bool, /// L1 block hashes to return when `BLOCKHASH` opcode is encountered. This ensures consistency /// when returning environment data in L2. - pub block_hashes: HashMap>, + pub block_hashes: sHashMap>, } /// A tracer to allow for foundry-specific functionality. From 8760b17a0649ece99f9bd6e2f1dc398f9e19e1dd Mon Sep 17 00:00:00 2001 From: elfedy Date: Mon, 28 Oct 2024 18:27:41 -0300 Subject: [PATCH 08/20] fix: further adaptations to dyn DatabaseExt usage --- crates/cheatcodes/src/inspector.rs | 16 ++++++---------- crates/cheatcodes/src/test/expect.rs | 4 +--- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 74e1e06f8..decb1775c 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -920,7 +920,7 @@ impl Cheatcodes { } // common create functionality for both legacy and EOF. - fn create_common( + fn create_common( &mut self, ecx: Ecx, mut input: Input, @@ -1098,14 +1098,13 @@ impl Cheatcodes { /// Try handling the `CREATE` within zkEVM. /// If `Some` is returned then the result must be returned immediately, else the call must be /// handled in EVM. - fn try_create_in_zk( + fn try_create_in_zk( &mut self, - ecx: &mut EvmContext, + ecx: Ecx, input: Input, executor: &mut impl CheatcodesExecutor, ) -> Option where - DB: DatabaseExt, Input: CommonCreateInput, { if self.skip_zk_vm { @@ -1726,16 +1725,13 @@ where { /// Try handling the `CALL` within zkEVM. /// If `Some` is returned then the result must be returned immediately, else the call must be /// handled in EVM. - fn try_call_in_zk( + fn try_call_in_zk( &mut self, factory_deps: Vec>, - ecx: &mut EvmContext, + ecx: Ecx, call: &mut CallInputs, executor: &mut impl CheatcodesExecutor, - ) -> Option - where - DB: DatabaseExt, - { + ) -> Option { // also skip if the target was created during a zkEVM skip self.skip_zk_vm = self.skip_zk_vm || self.skip_zk_vm_addresses.contains(&call.target_address); diff --git a/crates/cheatcodes/src/test/expect.rs b/crates/cheatcodes/src/test/expect.rs index f5466ebad..2b7ecb62c 100644 --- a/crates/cheatcodes/src/test/expect.rs +++ b/crates/cheatcodes/src/test/expect.rs @@ -1,8 +1,6 @@ use crate::{Cheatcode, Cheatcodes, CheatsCtxt, Error, Result, Vm::*}; use alloy_primitives::{ - address, hex, - map::{hash_map::Entry, HashMap}, - Address, Bytes, LogData as RawLog, U256, + address, hex, map::hash_map::Entry, Address, Bytes, LogData as RawLog, U256, }; use alloy_sol_types::{SolError, SolValue}; use foundry_cheatcodes_common::expect::{ExpectedCallData, ExpectedCallType}; From 0cd154f557eff701deb2a3530b2cc44eadf08f20 Mon Sep 17 00:00:00 2001 From: elfedy Date: Mon, 28 Oct 2024 18:30:29 -0300 Subject: [PATCH 09/20] fix: hardhat console import --- crates/cheatcodes/src/evm.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs index 19a402d32..6d1da5ce6 100644 --- a/crates/cheatcodes/src/evm.rs +++ b/crates/cheatcodes/src/evm.rs @@ -7,20 +7,18 @@ use crate::{ }; use alloy_consensus::TxEnvelope; use alloy_genesis::{Genesis, GenesisAccount}; -use alloy_primitives::{map::HashMap, Address, Bytes, B256, U256}; +use alloy_primitives::{Address, Bytes, B256, U256}; use alloy_rlp::Decodable; use alloy_sol_types::SolValue; use foundry_common::fs::{read_json_file, write_json_file}; use foundry_evm_core::{ + abi::HARDHAT_CONSOLE_ADDRESS, backend::{DatabaseExt, RevertStateSnapshotAction}, - constants::{CALLER, CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS, TEST_CONTRACT_ADDRESS}, + constants::{CALLER, CHEATCODE_ADDRESS, TEST_CONTRACT_ADDRESS}, }; use foundry_evm_traces::StackSnapshotType; use rand::Rng; -use revm::{ - primitives::{Account, Bytecode, SpecId, KECCAK_EMPTY}, - InnerEvmContext, -}; +use revm::primitives::{Account, Bytecode, SpecId, KECCAK_EMPTY}; use std::{collections::BTreeMap, path::Path}; mod record_debug_step; use record_debug_step::{convert_call_trace_to_debug_step, flatten_call_trace}; From 5e12e76ffbd55c777bd255ada1e5622dcd01a416 Mon Sep 17 00:00:00 2001 From: elfedy Date: Tue, 29 Oct 2024 09:53:52 -0300 Subject: [PATCH 10/20] fix: adapt zk mock code to multiple calls (#9024) --- .../zksync/core/src/vm/tracers/cheatcode.rs | 55 +++++++++++-------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/crates/zksync/core/src/vm/tracers/cheatcode.rs b/crates/zksync/core/src/vm/tracers/cheatcode.rs index 402994ae3..27209bc1f 100644 --- a/crates/zksync/core/src/vm/tracers/cheatcode.rs +++ b/crates/zksync/core/src/vm/tracers/cheatcode.rs @@ -1,6 +1,6 @@ use std::{ cell::OnceCell, - collections::{BTreeMap, HashMap as sHashMap}, + collections::{BTreeMap, HashMap as sHashMap, VecDeque}, sync::Arc, }; @@ -74,7 +74,7 @@ const SELECTOR_BLOCK_HASH: [u8; 4] = hex!("80b41246"); #[derive(Debug, Default)] pub struct CheatcodeTracerContext<'a> { /// Mocked calls. - pub mocked_calls: HashMap>, + pub mocked_calls: HashMap>>, /// Expected calls recorder. pub expected_calls: Option<&'a mut ExpectedCallTracker>, /// Recorded storage accesses @@ -122,7 +122,7 @@ pub struct CallContext { #[derive(Debug, Default)] pub struct CheatcodeTracer { /// List of mocked calls. - pub mocked_calls: HashMap>, + pub mocked_calls: HashMap>>, /// Tracked for foundry's expected calls. pub expected_calls: ExpectedCallTracker, /// Defines the current call context. @@ -136,7 +136,7 @@ pub struct CheatcodeTracer { impl CheatcodeTracer { /// Create an instance of [CheatcodeTracer]. pub fn new( - mocked_calls: HashMap>, + mocked_calls: HashMap>>, expected_calls: ExpectedCallTracker, result: Arc>, call_context: CallContext, @@ -220,29 +220,39 @@ impl DynTracer> for Cheatcode let call_contract = current.code_address.to_address(); let call_value = U256::from(current.context_u128_value).to_ru256(); - let mocks = self.mocked_calls.get(&call_contract); - if let Some(mocks) = &mocks { + let mut had_mocks = false; + if let Some(mocks) = self.mocked_calls.get_mut(&call_contract) { + had_mocks = true; let ctx = MockCallDataContext { calldata: Bytes::from(call_input.clone()), value: Some(call_value), }; - if let Some(return_data) = mocks.get(&ctx).or_else(|| { - mocks - .iter() + if let Some(return_data_queue) = match mocks.get_mut(&ctx) { + Some(queue) => Some(queue), + None => mocks + .iter_mut() .find(|(mock, _)| { call_input.get(..mock.calldata.len()) == Some(&mock.calldata[..]) && mock.value.map_or(true, |value| value == call_value) }) - .map(|(_, v)| v) - }) { - let return_data = return_data.data.clone().to_vec(); - tracing::info!( - "returning mocked value {:?} for {:?}", - hex::encode(&call_input), - hex::encode(&return_data) - ); - self.farcall_handler.set_immediate_return(return_data); - return; + .map(|(_, v)| v), + } { + if let Some(return_data) = if return_data_queue.len() == 1 { + // If the mocked calls stack has a single element in it, don't empty it + return_data_queue.front().map(|x| x.to_owned()) + } else { + // Else, we pop the front element + return_data_queue.pop_front() + } { + let return_data = return_data.data.clone().to_vec(); + tracing::info!( + "returning mocked value {:?} for {:?}", + hex::encode(&call_input), + hex::encode(&return_data) + ); + self.farcall_handler.set_immediate_return(return_data); + return; + } } } @@ -251,11 +261,8 @@ impl DynTracer> for Cheatcode if self.has_empty_code(storage, call_contract) { // issue a more targeted // error if we already had some mocks there - let had_mocks_message = if mocks.is_some() { - " - please ensure the current calldata is mocked" - } else { - "" - }; + let had_mocks_message = + if had_mocks { " - please ensure the current calldata is mocked" } else { "" }; tracing::error!( target = ?call_contract, From f73cd964d299e748bc0da70d5c12a26aa0648369 Mon Sep 17 00:00:00 2001 From: Nisheeth Barthwal Date: Wed, 30 Oct 2024 19:25:22 +0100 Subject: [PATCH 11/20] fix lifetime issues in trace_zksync --- crates/cheatcodes/src/inspector.rs | 43 +++++++++++++++++++++----- crates/evm/evm/src/inspectors/stack.rs | 2 +- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index decb1775c..70b93cf86 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -153,13 +153,42 @@ pub trait CheatcodesExecutor { None } - fn trace_zksync<'a>( - &mut self, - ccx_state: &'a mut Cheatcodes, - ecx: Ecx<'a, 'a, 'a>, - call_traces: Vec, - ) { - self.get_inspector(ccx_state).trace_zksync(ecx, call_traces); + fn trace_zksync(&mut self, ccx_state: &mut Cheatcodes, ecx: Ecx, call_traces: Vec) { + let mut inspector = self.get_inspector(ccx_state); + + // We recreate the EvmContext here to satisfy the lifetime parameters as 'static, with + // regards to the inspector's lifetime. + let error = std::mem::replace(&mut ecx.error, Ok(())); + let l1_block_info = std::mem::take(&mut ecx.l1_block_info); + let mut ecx_inner = EvmContext { + inner: InnerEvmContext { + env: std::mem::replace(&mut ecx.env, Default::default()), + journaled_state: std::mem::replace( + &mut ecx.journaled_state, + revm::JournaledState::new(Default::default(), Default::default()), + ), + db: &mut ecx.db as &mut dyn DatabaseExt, + error, + l1_block_info, + }, + precompiles: Default::default(), + }; + inspector.trace_zksync(&mut ecx_inner, call_traces); + + // re-apply the modified fields to the original ecx. + let env = std::mem::replace(&mut ecx_inner.env, Default::default()); + let journaled_state = std::mem::replace( + &mut ecx_inner.journaled_state, + revm::JournaledState::new(Default::default(), Default::default()), + ); + let error = std::mem::replace(&mut ecx_inner.error, Ok(())); + let l1_block_info = std::mem::take(&mut ecx_inner.l1_block_info); + drop(ecx_inner); + + ecx.env = env; + ecx.journaled_state = journaled_state; + ecx.error = error; + ecx.l1_block_info = l1_block_info; } } diff --git a/crates/evm/evm/src/inspectors/stack.rs b/crates/evm/evm/src/inspectors/stack.rs index 772fea63d..f312d123a 100644 --- a/crates/evm/evm/src/inspectors/stack.rs +++ b/crates/evm/evm/src/inspectors/stack.rs @@ -1031,7 +1031,7 @@ impl InspectorExt for InspectorStackRefMut<'_> { } fn trace_zksync(&mut self, ecx: &mut EvmContext<&mut dyn DatabaseExt>, call_traces: Vec) { - call_inspectors!([&mut self.tracer], |inspector| InspectorExt::::trace_zksync( + call_inspectors!([&mut self.tracer], |inspector| InspectorExt::trace_zksync( inspector, ecx, call_traces From 17cd6e78cc186b77efc1f3fcba661f94b04ddf7c Mon Sep 17 00:00:00 2001 From: Nisheeth Barthwal Date: Wed, 30 Oct 2024 19:28:46 +0100 Subject: [PATCH 12/20] inline env and l1_block_info fields --- crates/cheatcodes/src/inspector.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 70b93cf86..6cfd4e13a 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -158,8 +158,6 @@ pub trait CheatcodesExecutor { // We recreate the EvmContext here to satisfy the lifetime parameters as 'static, with // regards to the inspector's lifetime. - let error = std::mem::replace(&mut ecx.error, Ok(())); - let l1_block_info = std::mem::take(&mut ecx.l1_block_info); let mut ecx_inner = EvmContext { inner: InnerEvmContext { env: std::mem::replace(&mut ecx.env, Default::default()), @@ -167,9 +165,9 @@ pub trait CheatcodesExecutor { &mut ecx.journaled_state, revm::JournaledState::new(Default::default(), Default::default()), ), + error: std::mem::replace(&mut ecx.error, Ok(())), + l1_block_info: std::mem::take(&mut ecx.l1_block_info), db: &mut ecx.db as &mut dyn DatabaseExt, - error, - l1_block_info, }, precompiles: Default::default(), }; From b50fce12bb48dfb395656b609940d17f288e8b1e Mon Sep 17 00:00:00 2001 From: elfedy Date: Wed, 30 Oct 2024 17:43:44 -0300 Subject: [PATCH 13/20] fix: remove deployments and fix usage of different HashMaps on evm crate --- .../evm/evm/src/executors/invariant/replay.rs | 9 +++------ crates/evm/evm/src/executors/mod.rs | 19 ++----------------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/crates/evm/evm/src/executors/invariant/replay.rs b/crates/evm/evm/src/executors/invariant/replay.rs index 6b473350c..969f1587f 100644 --- a/crates/evm/evm/src/executors/invariant/replay.rs +++ b/crates/evm/evm/src/executors/invariant/replay.rs @@ -17,7 +17,7 @@ use indicatif::ProgressBar; use parking_lot::RwLock; use proptest::test_runner::TestError; use revm::primitives::U256; -use std::{collections::HashMap, sync::Arc}; +use std::sync::Arc; /// Replays a call sequence for collecting logs and traces. /// Returns counterexample to be used when the call sequence is a failed scenario. @@ -60,11 +60,8 @@ pub fn replay_run( } // Identify newly generated contracts, if they exist. - ided_contracts.extend(load_contracts( - call_result.traces.iter().map(|a| &a.arena), - known_contracts, - &HashMap::new(), - )); + ided_contracts + .extend(load_contracts(call_result.traces.iter().map(|a| &a.arena), known_contracts)); // Create counter example to be used in failed case. counterexample_sequence.push(BaseCounterExample::from_invariant_call( diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index 6b25a97a1..393fb6647 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -37,7 +37,7 @@ use revm::{ }, Database, }; -use std::borrow::Cow; +use std::{borrow::Cow, collections::HashMap as sHashMap}; mod builder; pub use builder::ExecutorBuilder; @@ -94,7 +94,7 @@ pub struct Executor { /// Sets up the next transaction to be executed as a ZK transaction. zk_tx: Option, // simulate persisted factory deps - zk_persisted_factory_deps: HashMap>, + zk_persisted_factory_deps: sHashMap>, pub use_zk: bool, } @@ -473,17 +473,6 @@ impl Executor { result_and_state.clone(), backend.has_state_snapshot_failure(), )?; - let state = result_and_state.state; - if let Some(traces) = &mut result.traces { - for trace_node in traces.nodes() { - if let Some(account_info) = state.get(&trace_node.trace.address) { - result.deployments.insert( - trace_node.trace.address, - account_info.info.code.clone().unwrap_or_default().bytes(), - ); - } - } - } self.commit(&mut result); Ok(result) @@ -823,14 +812,11 @@ pub struct RawCallResult { pub out: Option, /// The chisel state pub chisel_state: Option<(Vec, Vec, InstructionResult)>, - /// The deployments generated during the call - pub deployments: HashMap, } impl Default for RawCallResult { fn default() -> Self { Self { - deployments: HashMap::new(), exit_reason: InstructionResult::Continue, reverted: false, has_state_snapshot_failure: false, @@ -964,7 +950,6 @@ fn convert_executed_result( .filter(|txs| !txs.is_empty()); Ok(RawCallResult { - deployments: HashMap::new(), exit_reason, reverted: !matches!(exit_reason, return_ok!()), has_state_snapshot_failure, From 1b62be54f601a6d8470dbbc2d03b1e56dcde2389 Mon Sep 17 00:00:00 2001 From: elfedy Date: Wed, 30 Oct 2024 17:46:25 -0300 Subject: [PATCH 14/20] fix: remove stale std HashMap reference --- crates/script/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/script/src/lib.rs b/crates/script/src/lib.rs index 6b3ec3d6b..08b217c95 100644 --- a/crates/script/src/lib.rs +++ b/crates/script/src/lib.rs @@ -52,7 +52,6 @@ use foundry_evm::{ use foundry_wallets::MultiWalletOpts; use foundry_zksync_compiler::DualCompiledContracts; use serde::Serialize; -use std::collections::HashMap; use yansi::Paint; mod broadcast; From 03fb214a094b96655a1417d98b22434897f16402 Mon Sep 17 00:00:00 2001 From: elfedy Date: Wed, 30 Oct 2024 17:56:05 -0300 Subject: [PATCH 15/20] fix: clone zk_metadata before taking mutable reference --- crates/script/src/simulate.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/script/src/simulate.rs b/crates/script/src/simulate.rs index eaa102d33..cdeac8572 100644 --- a/crates/script/src/simulate.rs +++ b/crates/script/src/simulate.rs @@ -113,9 +113,10 @@ impl PreSimulationState { // Executes all transactions from the different forks concurrently. let futs = transactions .into_iter() - .map(|transaction| async { + .map(|mut transaction| async { let mut runner = runners.get(&transaction.rpc).expect("invalid rpc url").write(); + let zk_metadata = transaction.zk.clone(); let tx = transaction.tx_mut(); let to = if let Some(TxKind::Call(to)) = tx.to() { Some(to) } else { None }; let result = runner @@ -125,7 +126,7 @@ impl PreSimulationState { to, tx.input().map(Bytes::copy_from_slice), tx.value(), - (self.script_config.config.zksync.run_in_zk_mode(), transaction.zk.clone()), + (self.script_config.config.zksync.run_in_zk_mode(), zk_metadata), ) .wrap_err("Internal EVM error during simulation")?; From eb5ba9e1e116aea6da16ced48fa1958fda6e9be2 Mon Sep 17 00:00:00 2001 From: elfedy Date: Wed, 30 Oct 2024 18:01:23 -0300 Subject: [PATCH 16/20] fix: remove deployment references in forge --- crates/forge/src/result.rs | 17 ++--------------- crates/forge/src/runner.rs | 16 +++------------- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/crates/forge/src/result.rs b/crates/forge/src/result.rs index 2ce9d3a75..4fb88dfd0 100644 --- a/crates/forge/src/result.rs +++ b/crates/forge/src/result.rs @@ -6,7 +6,7 @@ use crate::{ }; use alloy_primitives::{ map::{AddressHashMap, HashMap}, - Address, Bytes, Log, + Address, Log, }; use eyre::Report; use foundry_common::{evm::Breakpoints, get_contract_name, get_file_name, shell}; @@ -741,8 +741,6 @@ impl TestKind { #[derive(Clone, Debug, Default)] pub struct TestSetup { - /// Deployments generated during the setup - pub deployments: HashMap, /// The address at which the test contract was deployed pub address: Address, /// The logs emitted during setup @@ -784,7 +782,6 @@ impl TestSetup { } pub fn success( - deployments: HashMap, address: Address, logs: Vec, traces: Traces, @@ -792,16 +789,7 @@ impl TestSetup { coverage: Option, fuzz_fixtures: FuzzFixtures, ) -> Self { - Self { - deployments, - address, - logs, - traces, - labeled_addresses, - reason: None, - coverage, - fuzz_fixtures, - } + Self { address, logs, traces, labeled_addresses, reason: None, coverage, fuzz_fixtures } } pub fn failed_with( @@ -811,7 +799,6 @@ impl TestSetup { reason: String, ) -> Self { Self { - deployments: HashMap::new(), address: Address::ZERO, logs, traces, diff --git a/crates/forge/src/runner.rs b/crates/forge/src/runner.rs index 5afd946c0..74e98d197 100644 --- a/crates/forge/src/runner.rs +++ b/crates/forge/src/runner.rs @@ -120,8 +120,6 @@ impl ContractRunner<'_> { // construction self.executor.set_balance(address, self.initial_balance)?; - let mut zk_setup_deployments = HashMap::new(); - // Deploy the test contract match self.executor.deploy( self.sender, @@ -151,8 +149,7 @@ impl ContractRunner<'_> { trace!("calling setUp"); let res = self.executor.setup(None, address, Some(self.revert_decoder)); let (setup_logs, setup_traces, labeled_addresses, reason, coverage) = match res { - Ok(RawCallResult { traces, labels, logs, coverage, deployments, .. }) => { - zk_setup_deployments.extend(deployments); + Ok(RawCallResult { traces, labels, logs, coverage, .. }) => { trace!(%address, "successfully called setUp"); (logs, traces, labels, None, coverage) } @@ -175,7 +172,6 @@ impl ContractRunner<'_> { logs.extend(setup_logs); TestSetup { - deployments: zk_setup_deployments, address, logs, traces, @@ -186,7 +182,6 @@ impl ContractRunner<'_> { } } else { TestSetup::success( - zk_setup_deployments, address, logs, traces, @@ -354,13 +349,8 @@ impl ContractRunner<'_> { find_time, ); - let identified_contracts = has_invariants.then(|| { - load_contracts( - setup.traces.iter().map(|(_, t)| &t.arena), - &known_contracts, - &setup.deployments, - ) - }); + let identified_contracts = has_invariants + .then(|| load_contracts(setup.traces.iter().map(|(_, t)| &t.arena), &known_contracts)); let test_results = functions .par_iter() From fc610bcebd6d9bc91e688edd1aa885d3c0b3f123 Mon Sep 17 00:00:00 2001 From: elfedy Date: Wed, 30 Oct 2024 21:05:20 -0300 Subject: [PATCH 17/20] fix: use u64 for gas limit --- crates/forge/bin/cmd/create.rs | 2 +- crates/zksync/core/src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/forge/bin/cmd/create.rs b/crates/forge/bin/cmd/create.rs index 0be17f77c..f01d46d3a 100644 --- a/crates/forge/bin/cmd/create.rs +++ b/crates/forge/bin/cmd/create.rs @@ -615,7 +615,7 @@ impl CreateArgs { .await?; deployer.tx.set_gas_limit(if let Some(gas_limit) = self.tx.gas_limit { - gas_limit.to::() + gas_limit.to::() } else { estimated_gas.limit }); diff --git a/crates/zksync/core/src/lib.rs b/crates/zksync/core/src/lib.rs index 1c64a4a1d..e2f63be4d 100644 --- a/crates/zksync/core/src/lib.rs +++ b/crates/zksync/core/src/lib.rs @@ -178,7 +178,7 @@ pub struct EstimatedGas { /// Estimated gas price. pub price: u128, /// Estimated gas limit. - pub limit: u128, + pub limit: u64, } /// Estimates the gas parameters for the provided transaction. @@ -222,7 +222,7 @@ pub async fn estimate_gas, T: Transport + Clone>( .await .map_err(|err| eyre!("failed rpc call for estimating fee: {:?}", err))?; - Ok(EstimatedGas { price: gas_price, limit: fee.gas_limit.low_u128() }) + Ok(EstimatedGas { price: gas_price, limit: fee.gas_limit.low_u64() }) } /// Returns true if the provided address is a reserved zkSync system address From 02641a9d39f898c1c9d9201ea7fc0ae3e2c0ddff Mon Sep 17 00:00:00 2001 From: elfedy Date: Wed, 30 Oct 2024 21:09:08 -0300 Subject: [PATCH 18/20] fix: adapt to compiler optimize being an Option --- crates/forge/bin/cmd/create.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/forge/bin/cmd/create.rs b/crates/forge/bin/cmd/create.rs index f01d46d3a..b111a13dc 100644 --- a/crates/forge/bin/cmd/create.rs +++ b/crates/forge/bin/cmd/create.rs @@ -670,8 +670,11 @@ impl CreateArgs { println!("Starting contract verification..."); - let num_of_optimizations = - if self.opts.compiler.optimize { self.opts.compiler.optimizer_runs } else { None }; + let num_of_optimizations = if self.opts.compiler.optimize.unwrap_or_default() { + self.opts.compiler.optimizer_runs + } else { + None + }; let verify = forge_verify::VerifyArgs { address, contract: Some(self.contract), From a0d3fb0ee4dcc6c0c6e71afddf73659d470abcf1 Mon Sep 17 00:00:00 2001 From: elfedy Date: Wed, 30 Oct 2024 21:45:38 -0300 Subject: [PATCH 19/20] fix: restore lost code during conflict resolution in tests --- crates/forge/tests/cli/script.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/forge/tests/cli/script.rs b/crates/forge/tests/cli/script.rs index a3474400a..38f8f9479 100644 --- a/crates/forge/tests/cli/script.rs +++ b/crates/forge/tests/cli/script.rs @@ -5,7 +5,7 @@ use alloy_primitives::{hex, Address, Bytes}; use anvil::{spawn, NodeConfig}; use foundry_test_utils::{ rpc, - util::{OTHER_SOLC_VERSION, SOLC_VERSION}, + util::{OutputExt, OTHER_SOLC_VERSION, SOLC_VERSION}, ScriptOutcome, ScriptTester, }; use regex::Regex; @@ -2106,7 +2106,7 @@ contract DeployScript is Script { let transactions: ZkTransactions = serde_json::from_str(&content).unwrap(); let transactions = transactions.transactions; assert_eq!(transactions.len(), 3); -} +}); // forgetest_async!(test_broadcast_raw_create2_deployer, |prj, cmd| { From bbbeee84d270b0fed19c97a182284c507e16ce25 Mon Sep 17 00:00:00 2001 From: elfedy Date: Thu, 31 Oct 2024 09:49:02 -0300 Subject: [PATCH 20/20] chore: remove uneeded uses of std HashMap --- crates/cheatcodes/src/inspector.rs | 4 ++-- crates/evm/core/src/backend/cow.rs | 7 ++----- crates/evm/core/src/backend/mod.rs | 4 ++-- crates/evm/evm/src/executors/mod.rs | 4 ++-- crates/zksync/core/src/vm/db.rs | 6 +++--- crates/zksync/core/src/vm/runner.rs | 4 ++-- crates/zksync/core/src/vm/tracers/cheatcode.rs | 6 +++--- 7 files changed, 16 insertions(+), 19 deletions(-) diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 6cfd4e13a..a39f232d2 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -68,7 +68,7 @@ use revm::{ }; use serde_json::Value; use std::{ - collections::{BTreeMap, HashMap as sHashMap, HashSet, VecDeque}, + collections::{BTreeMap, HashSet, VecDeque}, fs::File, io::BufReader, ops::Range, @@ -571,7 +571,7 @@ pub struct Cheatcodes { /// would be a significant refactor, we maintain the factory_dep part in the [Cheatcodes]. /// This can be done as each test runs with its own [Cheatcodes] instance, thereby /// providing the necessary level of isolation. - pub persisted_factory_deps: sHashMap>, + pub persisted_factory_deps: HashMap>, } // This is not derived because calling this in `fn new` with `..Default::default()` creates a second diff --git a/crates/evm/core/src/backend/cow.rs b/crates/evm/core/src/backend/cow.rs index 8af230713..e1879c33a 100644 --- a/crates/evm/core/src/backend/cow.rs +++ b/crates/evm/core/src/backend/cow.rs @@ -9,7 +9,7 @@ use crate::{ InspectorExt, }; use alloy_genesis::GenesisAccount; -use alloy_primitives::{Address, B256, U256}; +use alloy_primitives::{map::HashMap, Address, B256, U256}; use alloy_rpc_types::TransactionRequest; use eyre::WrapErr; use foundry_fork_db::DatabaseError; @@ -21,10 +21,7 @@ use revm::{ }, Database, DatabaseCommit, JournaledState, }; -use std::{ - borrow::Cow, - collections::{BTreeMap, HashMap}, -}; +use std::{borrow::Cow, collections::BTreeMap}; /// A wrapper around `Backend` that ensures only `revm::DatabaseRef` functions are called. /// diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index 23c400da1..1cac94852 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -8,7 +8,7 @@ use crate::{ InspectorExt, }; use alloy_genesis::GenesisAccount; -use alloy_primitives::{keccak256, uint, Address, B256, U256}; +use alloy_primitives::{keccak256, map::HashMap, uint, Address, B256, U256}; use alloy_rpc_types::{Block, BlockNumberOrTag, Transaction, TransactionRequest}; use alloy_serde::WithOtherFields; use eyre::Context; @@ -29,7 +29,7 @@ use revm::{ Database, DatabaseCommit, JournaledState, }; use std::{ - collections::{BTreeMap, HashMap, HashSet}, + collections::{BTreeMap, HashSet}, time::Instant, }; diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index 393fb6647..9dcbf8c66 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -37,7 +37,7 @@ use revm::{ }, Database, }; -use std::{borrow::Cow, collections::HashMap as sHashMap}; +use std::borrow::Cow; mod builder; pub use builder::ExecutorBuilder; @@ -94,7 +94,7 @@ pub struct Executor { /// Sets up the next transaction to be executed as a ZK transaction. zk_tx: Option, // simulate persisted factory deps - zk_persisted_factory_deps: sHashMap>, + zk_persisted_factory_deps: HashMap>, pub use_zk: bool, } diff --git a/crates/zksync/core/src/vm/db.rs b/crates/zksync/core/src/vm/db.rs index 301167d77..a475a5e80 100644 --- a/crates/zksync/core/src/vm/db.rs +++ b/crates/zksync/core/src/vm/db.rs @@ -4,9 +4,9 @@ /// in the Database object. /// This code doesn't do any mutatios to Database: after each transaction run, the Revm /// is usually collecing all the diffs - and applies them to database itself. -use std::{collections::HashMap, fmt::Debug}; +use std::{collections::HashMap as sHashMap, fmt::Debug}; -use alloy_primitives::{Address, U256 as rU256}; +use alloy_primitives::{map::HashMap, Address, U256 as rU256}; use foundry_cheatcodes_common::record::RecordAccess; use revm::{primitives::Account, Database, EvmContext, InnerEvmContext}; use zksync_basic_types::{L2ChainId, H160, H256, U256}; @@ -29,7 +29,7 @@ pub struct ZKVMData<'a, DB: Database> { // pub journaled_state: &'a mut JournaledState, ecx: &'a mut InnerEvmContext, pub factory_deps: HashMap>, - pub override_keys: HashMap, + pub override_keys: sHashMap, pub accesses: Option<&'a mut RecordAccess>, } diff --git a/crates/zksync/core/src/vm/runner.rs b/crates/zksync/core/src/vm/runner.rs index e7c9dd63a..f58f92d87 100644 --- a/crates/zksync/core/src/vm/runner.rs +++ b/crates/zksync/core/src/vm/runner.rs @@ -1,4 +1,4 @@ -use alloy_primitives::hex; +use alloy_primitives::{hex, map::HashMap}; use itertools::Itertools; use revm::{ interpreter::{CallInputs, CallScheme, CallValue}, @@ -12,7 +12,7 @@ use zksync_types::{ U256, }; -use std::{cmp::min, collections::HashMap, fmt::Debug}; +use std::{cmp::min, fmt::Debug}; use crate::{ convert::{ConvertAddress, ConvertH160, ConvertRU256, ConvertU256}, diff --git a/crates/zksync/core/src/vm/tracers/cheatcode.rs b/crates/zksync/core/src/vm/tracers/cheatcode.rs index 27209bc1f..b738adabb 100644 --- a/crates/zksync/core/src/vm/tracers/cheatcode.rs +++ b/crates/zksync/core/src/vm/tracers/cheatcode.rs @@ -1,6 +1,6 @@ use std::{ cell::OnceCell, - collections::{BTreeMap, HashMap as sHashMap, VecDeque}, + collections::{BTreeMap, VecDeque}, sync::Arc, }; @@ -80,7 +80,7 @@ pub struct CheatcodeTracerContext<'a> { /// Recorded storage accesses pub accesses: Option<&'a mut RecordAccess>, /// Factory deps that were persisted across calls - pub persisted_factory_deps: Option<&'a mut sHashMap>>, + pub persisted_factory_deps: Option<&'a mut HashMap>>, /// Paymaster data pub paymaster_data: Option, } @@ -115,7 +115,7 @@ pub struct CallContext { pub is_static: bool, /// L1 block hashes to return when `BLOCKHASH` opcode is encountered. This ensures consistency /// when returning environment data in L2. - pub block_hashes: sHashMap>, + pub block_hashes: HashMap>, } /// A tracer to allow for foundry-specific functionality.