Skip to content

Commit

Permalink
Adding support for forge test on zksync VM (#125)
Browse files Browse the repository at this point in the history
* broken -but partially works

* hacked up version works

* getting ready for REVM

* cleanup

* cleanup and added tests

* parse json using a struct

* tests passing

* migrated errors to eyre

* cleaned up warnings

* changed dependencies to git

* revert fmt changes

* final touches

* review
  • Loading branch information
mm-zk authored Oct 17, 2023
1 parent 2a5ab4c commit ee6078d
Show file tree
Hide file tree
Showing 15 changed files with 6,094 additions and 1,053 deletions.
6,052 changes: 5,263 additions & 789 deletions Cargo.lock

Large diffs are not rendered by default.

33 changes: 21 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ resolver = "2"
[profile.dev]
# Disabling debug info speeds up builds a bunch,
# and we don't rely on it for debugging that much
debug = 0

# These speed up local tests
[profile.dev.package.ethers-solc]
Expand Down Expand Up @@ -61,16 +60,16 @@ panic = "abort"
strip = true

[workspace.dependencies]
ethers = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
ethers-addressbook = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
ethers-core = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
ethers-contract = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
ethers-contract-abigen = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
ethers-providers = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
ethers-signers = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
ethers-middleware = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
ethers-etherscan = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
ethers-solc = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
ethers = { git = "https://github.com/mm-zk/ethers-rs", branch = "main_with_public_artifacts", default-features = false }
ethers-addressbook = { git = "https://github.com/mm-zk/ethers-rs", branch = "main_with_public_artifacts", default-features = false }
ethers-core = { git = "https://github.com/mm-zk/ethers-rs", branch = "main_with_public_artifacts", default-features = false }
ethers-contract = { git = "https://github.com/mm-zk/ethers-rs", branch = "main_with_public_artifacts", default-features = false }
ethers-contract-abigen = { git = "https://github.com/mm-zk/ethers-rs", branch = "main_with_public_artifacts", default-features = false }
ethers-providers = { git = "https://github.com/mm-zk/ethers-rs", branch = "main_with_public_artifacts", default-features = false }
ethers-signers = { git = "https://github.com/mm-zk/ethers-rs", branch = "main_with_public_artifacts", default-features = false }
ethers-middleware = { git = "https://github.com/mm-zk/ethers-rs", branch = "main_with_public_artifacts", default-features = false }
ethers-etherscan = { git = "https://github.com/mm-zk/ethers-rs", branch = "main_with_public_artifacts", default-features = false }
ethers-solc = { git = "https://github.com/mm-zk/ethers-rs", branch = "main_with_public_artifacts", default-features = false }

solang-parser = "=0.3.1"

Expand All @@ -87,4 +86,14 @@ solang-parser = "=0.3.1"
#ethers-solc = { path = "../ethers-rs/ethers-solc" }

[patch.crates-io]
revm = { git = "https://github.com/bluealloy/revm/", branch = "release/v25" }
# Original revm - we had to fork it, due to compilation issues with SHA
# revm = { git = "https://github.com/bluealloy/revm/", branch = "release/v25" }

revm = { git = "https://github.com/mm-zk/revm.git", branch = "release_v25_with_old_sha", version = "3", default-features = false, features = [
"std",
"serde",
"memory_limit",
"optional_eip3607",
"optional_block_gas_limit",
"optional_no_base_fee"
] }
8 changes: 7 additions & 1 deletion anvil/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ license = "MIT OR Apache-2.0"
[dependencies]
# foundry internal
foundry-evm = { path = "../../evm" }
revm = { version = "3", default-features = false, features = ["std", "serde", "memory_limit"] }
# Original REVM - we had to fork it, due to compilation issues with SHA
# revm = { version = "3", default-features = false, features = ["std", "serde", "memory_limit"] }
revm = { git = "https://github.com/mm-zk/revm.git", branch = "release_v25_with_old_sha", version = "3", default-features = false, features = [
"std",
"serde",
"memory_limit",
] }

ethers-core = { workspace = true }
serde = { version = "1", features = ["derive"], optional = true }
Expand Down
5 changes: 4 additions & 1 deletion chisel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ serde = "1"
serde_json = { version = "1", features = ["raw_value"] }
semver = "1"
bytes = "1"
revm = "3"
# Original REVM. We had to fork it, due to conflicts in SHA.
# revm = "3"

revm = { git = "https://github.com/mm-zk/revm.git", branch = "release_v25_with_old_sha", version = "3" }
eyre = "0.6"
dirs = "5"
time = { version = "0.3", features = ["formatting"] }
Expand Down
2 changes: 2 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ pkg-config = "0.3.26"

#zksync
zksync-web3-rs = {git = "https://github.com/lambdaclass/zksync-web3-rs.git", rev = "70327ae5413c517bd4d27502507cdd96ee40cd22"}
era_revm = { git = "https://github.com/matter-labs/era-revm.git", rev = "792cb820587eccdc35bbecb45f343cf1b891b6d2"}


ansi_term = "0.12.1"
anyhow = {version = "1.0.70"}
Expand Down
2 changes: 1 addition & 1 deletion cli/src/cmd/forge/test/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{fmt, path::Path};
/// The filter to use during testing.
///
/// See also `FileFilter`.
#[derive(Clone, Parser)]
#[derive(Clone, Parser, Default)]
#[clap(next_help_heading = "Test filtering")]
pub struct FilterArgs {
/// Only run test functions matching the specified regex pattern.
Expand Down
99 changes: 31 additions & 68 deletions cli/src/cmd/forge/test/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
//! Test command
use crate::{
cmd::{
forge::{build::CoreBuildArgs, debug::DebugArgs, install, watch::WatchArgs},
forge::{
build::CoreBuildArgs,
debug::DebugArgs,
install,
watch::WatchArgs,
zksolc::{ZkSolc, ZkSolcOpts},
zksolc_manager::{ZkSolcManagerBuilder, ZkSolcManagerOpts, DEFAULT_ZKSOLC_VERSION},
},
LoadConfig,
},
suggestions, utils,
};
use cast::fuzz::CounterExample;
use clap::Parser;
use ethers::{abi::Abi, types::U256};
use ethers::types::U256;
use forge::{
decode::decode_console_logs,
executor::inspector::CheatsConfig,
Expand All @@ -18,16 +25,12 @@ use forge::{
identifier::{EtherscanIdentifier, LocalTraceIdentifier, SignaturesIdentifier},
CallTraceDecoderBuilder, TraceKind,
},
MultiContractRunner, MultiContractRunnerBuilder, TestOptions, TestOptionsBuilder,
MultiContractRunner, MultiContractRunnerBuilder, TestOptions,
};
use foundry_common::{
compile::{self, ProjectCompiler},
evm::EvmArgs,
get_contract_name, get_file_name,
};
use foundry_config::{figment, get_available_profiles, Config};
use foundry_common::{evm::EvmArgs, get_contract_name, get_file_name};
use foundry_config::{figment, Config};
use regex::Regex;
use std::{collections::BTreeMap, fs, path::PathBuf, sync::mpsc::channel, time::Duration};
use std::{collections::BTreeMap, path::PathBuf, sync::mpsc::channel, time::Duration};
use tracing::trace;
use watchexec::config::{InitConfig, RuntimeConfig};
use yansi::Paint;
Expand All @@ -42,13 +45,11 @@ use foundry_config::figment::{
};
use foundry_evm::utils::evm_spec;

use ethers::types::Bytes;

// Loads project's figment and merges the build cli arguments into it
foundry_config::merge_impl_figment_convert!(TestArgs, opts, evm_opts);

/// CLI arguments for `forge test`.
#[derive(Debug, Clone, Parser)]
#[derive(Debug, Clone, Parser, Default)]
#[clap(next_help_heading = "Test options")]
pub struct TestArgs {
/// Run a test in the debugger.
Expand Down Expand Up @@ -151,27 +152,22 @@ impl TestArgs {
project = config.project()?;
}

let compiler = ProjectCompiler::default();
let output = if config.sparse_mode {
compiler.compile_sparse(&project, filter.clone())
} else if self.opts.silent {
compile::suppress_compile(&project)
} else {
compiler.compile(&project)
}?;

// Create test options from general project settings
// and compiler output
let project_root = &project.paths.root;
let toml = config.get_config_path();
let profiles = get_available_profiles(toml)?;

let test_options: TestOptions = TestOptionsBuilder::default()
.fuzz(config.fuzz)
.invariant(config.invariant)
.compile_output(&output)
.profiles(profiles)
.build(project_root)?;
let project_root = project.paths.root.clone();

let zksolc_manager =
ZkSolcManagerBuilder::new(ZkSolcManagerOpts::new(DEFAULT_ZKSOLC_VERSION.to_owned()))
.build()
.unwrap();

let zksolc_opts = ZkSolcOpts {
compiler_path: zksolc_manager.get_full_compiler_path(),
is_system: false,
force_evmla: false,
};

let mut zksolc = ZkSolc::new(zksolc_opts, project);
let output = zksolc.compile().unwrap();
let test_options = TestOptions::default();

// Determine print verbosity and executor verbosity
let verbosity = evm_opts.verbosity;
Expand All @@ -190,15 +186,7 @@ impl TestArgs {
.sender(evm_opts.sender)
.with_fork(evm_opts.get_fork(&config, env.clone()))
.with_cheats_config(CheatsConfig::new(&config, &evm_opts))
.with_test_options(test_options.clone())
.build(project_root, output, env, evm_opts)?;

println!("{:#?}, <-------> runner fork", runner.fork);
// let (_contract, _bytes, _bytes_v) =
// runner.contracts.clone().into_iter().nth(0).unwrap().1; println!("{:#?},
// <-------> _contract", _contract); println!("{:#?}, <-------> _bytes", _bytes);

// zk_evm::
.build(&project_root, output, env, evm_opts)?;

if self.debug.is_some() {
filter.args_mut().test_pattern = self.debug;
Expand Down Expand Up @@ -524,31 +512,6 @@ async fn test(
gas_reporting: bool,
fail_fast: bool,
) -> eyre::Result<TestOutcome> {
let project = config.project().unwrap();

//get bytecode
let contract_path = "src/Greeter.sol:Greeter";
let output_path: &str =
&format!("{}/zksolc/{}/combined.json", project.paths.artifacts.display(), "Greeter.sol");
let data = fs::read_to_string(output_path).expect("Unable to read file");
//convert to json Value
let res: serde_json::Value = serde_json::from_str(&data).expect("Unable to parse");
let bytecode: Bytes =
serde_json::from_value(res["contracts"][&contract_path]["bin"].clone()).unwrap();
let bytecode_v = bytecode.to_vec();
//get abi
let abi: Abi = serde_json::from_value(res["contracts"][&contract_path]["abi"].clone()).unwrap();
let a = runner.known_contracts.clone().0.into_iter();
for (art, _ctx) in a {
if &art.name == "Greeter" {
// println!(
// "{:#?}, before contracts",
// runner.known_contracts.0.get_key_value(&art).unwrap().1
// );
runner.known_contracts.0.insert(art, (abi.clone(), bytecode_v.clone()));
}
}

trace!(target: "forge::test", "running all tests");
if runner.count_filtered_tests(&filter) == 0 {
let filter_str = filter.to_string();
Expand Down
Loading

0 comments on commit ee6078d

Please sign in to comment.