Skip to content

Commit

Permalink
Merge branch 'foundry-update-4af6cfa' into nish-fix-upstream-create
Browse files Browse the repository at this point in the history
  • Loading branch information
nbaztec committed Jul 9, 2024
2 parents 4db8016 + e1bcfc6 commit d639c48
Show file tree
Hide file tree
Showing 37 changed files with 566 additions and 85 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ revm-primitives = { git = "https://github.com/bluealloy/revm.git", rev = "41e2f7
# era_test_node = { path = "../era-test-node" }

# [patch."https://github.com/Moonsong-Labs/compilers"]
# foundry-compilers = { path = "../msl-compilers" }
# foundry-compilers = { path = "../compilers/crates/compilers/" }

# [patch."https://github.com/matter-labs/era-boojum"]
# cs_derive = { git = "https://github.com/nbaztec/era-boojum", branch = "foundry-fix" }
Expand Down
40 changes: 36 additions & 4 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1788,7 +1788,7 @@ impl<DB: DatabaseExt + Send> Inspector<DB> for Cheatcodes {
let mut nonce = account.info.nonce;
let mut call_init_code = call.init_code.clone();

let zk_tx = if self.use_zk_vm {
let mut zk_tx = if self.use_zk_vm {
to = Some(TxKind::Call(CONTRACT_DEPLOYER_ADDRESS.to_address()));
nonce = foundry_zksync_core::nonce(broadcast.new_origin, ecx) as u64;
let contract = self
Expand All @@ -1810,13 +1810,45 @@ impl<DB: DatabaseExt + Send> Inspector<DB> for Cheatcodes {
);
call_init_code = Bytes::from(create_input);

Some(ZkTransactionMetadata { factory_deps })
Some(factory_deps)
} else {
None
};

let rpc = ecx.db.active_fork_url();
if let Some(factory_deps) = zk_tx {
let mut batched =
foundry_zksync_core::vm::batch_factory_dependencies(factory_deps);
debug!(batches = batched.len(), "splitting factory deps for broadcast");
// the last batch is the final one that does the deployment
zk_tx = batched.pop();

for factory_deps in batched {
self.broadcastable_transactions.push_back(BroadcastableTransaction {
rpc: rpc.clone(),
transaction: TransactionRequest {
from: Some(broadcast.new_origin),
to: Some(TxKind::Call(Address::ZERO)),
value: Some(call.value),
input: TransactionInput::default(),
nonce: Some(nonce),
gas: if is_fixed_gas_limit {
Some(call.gas_limit as u128)
} else {
None
},
..Default::default()
},
zk_tx: Some(ZkTransactionMetadata { factory_deps }),
});

//update nonce for each tx
nonce += 1;
}
}

self.broadcastable_transactions.push_back(BroadcastableTransaction {
rpc: ecx.db.active_fork_url(),
rpc: rpc.clone(),
transaction: TransactionRequest {
from: Some(broadcast.new_origin),
to,
Expand All @@ -1830,7 +1862,7 @@ impl<DB: DatabaseExt + Send> Inspector<DB> for Cheatcodes {
},
..Default::default()
},
zk_tx,
zk_tx: zk_tx.map(|factory_deps| ZkTransactionMetadata { factory_deps }),
});

let kind = match call.scheme {
Expand Down
3 changes: 3 additions & 0 deletions crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ rustc-hash.workspace = true
num-format.workspace = true
chrono.workspace = true

# zksync
globset = "0.4"

[dev-dependencies]
foundry-macros.workspace = true
similar-asserts.workspace = true
Expand Down
27 changes: 17 additions & 10 deletions crates/common/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,11 @@ impl ProjectCompiler {
}

/// Compiles the project.
pub fn zksync_compile(self, project: &Project<SolcCompiler>) -> Result<ZkProjectCompileOutput> {
pub fn zksync_compile(
self,
project: &Project<SolcCompiler>,
maybe_avoid_contracts: Option<Vec<globset::GlobMatcher>>,
) -> Result<ZkProjectCompileOutput> {
// TODO: Avoid process::exit
if !project.paths.has_input_files() && self.files.is_empty() {
println!("Nothing to compile");
Expand All @@ -288,15 +292,18 @@ impl ProjectCompiler {
)));
}
self.zksync_compile_with(&project.paths.root, || {
if !files.is_empty() {
foundry_compilers::zksync::project_compile_files(project, files)
/* TODO: evualuate supporting compiling with filters
} else if let Some(filter) = filter {
project.compile_sparse(filter)
*/
} else {
foundry_compilers::zksync::project_compile(project)
}
let files_to_compile =
if !files.is_empty() { files } else { project.paths.input_files() };
let avoid_contracts = maybe_avoid_contracts.unwrap_or_default();
let sources = Source::read_all(
files_to_compile
.into_iter()
.filter(|p| !avoid_contracts.iter().any(|c| c.is_match(p))),
)?;
foundry_compilers::zksync::compile::project::ProjectCompiler::with_sources(
project, sources,
)?
.compile()
.map_err(Into::into)
})
}
Expand Down
9 changes: 9 additions & 0 deletions crates/config/src/zksync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,13 @@ impl ZkSyncConfig {
solc: self.solc_path.clone(),
}
}

pub fn avoid_contracts(&self) -> Option<Vec<globset::GlobMatcher>> {
self.avoid_contracts.clone().map(|patterns| {
patterns
.into_iter()
.map(|pat| globset::Glob::new(&pat).expect("invalid pattern").compile_matcher())
.collect::<Vec<_>>()
})
}
}
8 changes: 6 additions & 2 deletions crates/evm/core/src/backend/cow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ use revm::{
},
Database, DatabaseCommit, JournaledState,
};
use std::{borrow::Cow, collections::BTreeMap};
use std::{
borrow::Cow,
collections::{BTreeMap, HashMap},
};

use super::ForkInfo;

Expand Down Expand Up @@ -61,13 +64,14 @@ impl<'a> CowBackend<'a> {
pub fn inspect_ref_zk(
&mut self,
env: &mut Env,
persisted_factory_deps: &mut HashMap<foundry_zksync_core::H256, Vec<u8>>,
factory_deps: Option<Vec<Vec<u8>>>,
) -> eyre::Result<ResultAndState> {
// this is a new call to inspect with a new env, so even if we've cloned the backend
// already, we reset the initialized state
self.is_initialized = false;

foundry_zksync_core::vm::transact(factory_deps, env, self)
foundry_zksync_core::vm::transact(Some(persisted_factory_deps), factory_deps, env, self)
}

/// Executes the configured transaction of the `env` without committing state changes
Expand Down
3 changes: 2 additions & 1 deletion crates/evm/core/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,11 +856,12 @@ impl Backend {
pub fn inspect_ref_zk(
&mut self,
env: &mut EnvWithHandlerCfg,
persisted_factory_deps: &mut HashMap<foundry_zksync_core::H256, Vec<u8>>,
factory_deps: Option<Vec<Vec<u8>>>,
) -> eyre::Result<ResultAndState> {
self.initialize(env);

foundry_zksync_core::vm::transact(factory_deps, env, self)
foundry_zksync_core::vm::transact(Some(persisted_factory_deps), factory_deps, env, self)
}

/// Returns true if the address is a precompile
Expand Down
29 changes: 26 additions & 3 deletions crates/evm/evm/src/executors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ pub struct Executor {

/// Sets up the next transaction to be executed as a ZK transaction.
zk_tx: Option<ZkTransactionMetadata>,
// simulate persisted factory deps
zk_persisted_factory_deps: HashMap<foundry_zksync_core::H256, Vec<u8>>,

pub use_zk: bool,
}
Expand All @@ -113,7 +115,15 @@ impl Executor {
},
);

Self { backend, env, inspector, gas_limit, zk_tx: None, use_zk: false }
Self {
backend,
env,
inspector,
gas_limit,
zk_tx: None,
zk_persisted_factory_deps: Default::default(),
use_zk: false,
}
}

/// Returns the spec ID of the executor.
Expand Down Expand Up @@ -376,7 +386,14 @@ impl Executor {
pub fn call_with_env(&self, mut env: EnvWithHandlerCfg) -> eyre::Result<RawCallResult> {
let mut inspector = self.inspector.clone();
let mut backend = CowBackend::new(&self.backend);
let result = backend.inspect(&mut env, &mut inspector)?;
let result = match &self.zk_tx {
None => backend.inspect(&mut env, &mut inspector)?,
Some(zk_tx) => backend.inspect_ref_zk(
&mut env,
&mut self.zk_persisted_factory_deps.clone(),
Some(zk_tx.factory_deps.clone()),
)?,
};
convert_executed_result(env, inspector, result, backend.has_snapshot_failure())
}

Expand All @@ -386,7 +403,13 @@ impl Executor {
let backend = &mut self.backend;
let result = match self.zk_tx.take() {
None => backend.inspect(&mut env, &mut inspector)?,
Some(zk_tx) => backend.inspect_ref_zk(&mut env, Some(zk_tx.factory_deps))?,
Some(zk_tx) => backend.inspect_ref_zk(
&mut env,
// this will persist the added factory deps,
// no need to commit them later
&mut self.zk_persisted_factory_deps,
Some(zk_tx.factory_deps),
)?,
};

let mut result =
Expand Down
3 changes: 2 additions & 1 deletion crates/forge/bin/cmd/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ impl BuildArgs {
.quiet(self.format_json)
.bail(!self.format_json);

let zk_output = zk_compiler.zksync_compile(&zk_project)?;
let zk_output =
zk_compiler.zksync_compile(&zk_project, config.zksync.avoid_contracts())?;
if self.format_json {
println!("{}", serde_json::to_string_pretty(&zk_output.output())?);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/forge/bin/cmd/coverage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ impl CoverageArgs {
..Default::default()
})
.set_coverage(true)
.build(&root, output, env, evm_opts, DualCompiledContracts::default(), false)?;
.build(&root, output, None, env, evm_opts, DualCompiledContracts::default(), false)?;

let known_contracts = runner.known_contracts.clone();

Expand Down
20 changes: 18 additions & 2 deletions crates/forge/bin/cmd/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pub struct CreateArgs {
long,
value_hint = ValueHint::FilePath,
value_name = "PATH",
conflicts_with = "constructor_args",
)]
constructor_args_path: Option<PathBuf>,

Expand Down Expand Up @@ -355,6 +356,7 @@ impl CreateArgs {
evm_version: self.opts.compiler.evm_version,
show_standard_json_input: self.show_standard_json_input,
guess_constructor_args: false,
zksync: self.opts.compiler.zk.enabled(),
};

// Check config for Etherscan API Keys to avoid preflight check failing if no
Expand Down Expand Up @@ -451,7 +453,7 @@ impl CreateArgs {
.constructor()
.ok_or_else(|| eyre::eyre!("could not find constructor"))?
.abi_encode_input(&args)?;
constructor_args = Some(hex::encode(encoded_args));
constructor_args = Some(hex::encode_prefixed(encoded_args));
}

self.verify_preflight_check(constructor_args.clone(), chain).await?;
Expand Down Expand Up @@ -503,6 +505,7 @@ impl CreateArgs {
evm_version: self.opts.compiler.evm_version,
show_standard_json_input: self.show_standard_json_input,
guess_constructor_args: false,
zksync: self.opts.compiler.zk.enabled(),
};
println!("Waiting for {} to detect contract deployment...", verify.verifier.verifier);
verify.run().await
Expand Down Expand Up @@ -661,14 +664,27 @@ impl CreateArgs {
constructor: &Constructor,
constructor_args: &[String],
) -> Result<Vec<DynSolValue>> {
let mut params = Vec::with_capacity(constructor.inputs.len());
let expected_params = constructor.inputs.len();

let mut params = Vec::with_capacity(expected_params);
for (input, arg) in constructor.inputs.iter().zip(constructor_args) {
// resolve the input type directly
let ty = input
.resolve()
.wrap_err_with(|| format!("Could not resolve constructor arg: input={input}"))?;
params.push((ty, arg));
}

let actual_params = params.len();

if actual_params != expected_params {
tracing::warn!(
given = actual_params,
expected = expected_params,
"Constructor argument mismatch: expected {expected_params} arguments, but received {actual_params}. Ensure that the number of arguments provided matches the constructor definition."
);
}

let params = params.iter().map(|(ty, arg)| (ty, arg.as_str()));
parse_tokens(params).map_err(Into::into)
}
Expand Down
2 changes: 1 addition & 1 deletion crates/forge/bin/cmd/script/broadcast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ impl ScriptArgs {
.nonce(legacy_or_1559.nonce().unwrap())
.gas_price(legacy_or_1559.gas_price().unwrap())
.max_fee_per_gas(legacy_or_1559.max_cost().unwrap())
.data(legacy_or_1559.data().cloned().unwrap())
.data(legacy_or_1559.data().cloned().unwrap_or_default())
.custom_data(custom_data);

let gas_price = provider.get_gas_price().await?;
Expand Down
2 changes: 1 addition & 1 deletion crates/forge/bin/cmd/script/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl ScriptArgs {
contracts: &ContractsByArtifact,
dual_compiled_contracts: Option<DualCompiledContracts>,
) -> Result<VecDeque<TransactionWithMetadata>> {
trace!(target: "script", "executing onchain simulation");
trace!(target: "script", ?transactions, "executing onchain simulation");

let runners = Arc::new(
self.build_runners(script_config, dual_compiled_contracts)
Expand Down
8 changes: 5 additions & 3 deletions crates/forge/bin/cmd/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ impl TestArgs {

let output = compiler.compile(&project)?;

let dual_compiled_contracts = if config.zksync.should_compile() {
let (zk_output, dual_compiled_contracts) = if config.zksync.should_compile() {
let zk_project = foundry_zksync_compiler::create_project(&config, config.cache, false)?;

let sources_to_compile =
Expand All @@ -283,9 +283,10 @@ impl TestArgs {
.files(sources_to_compile);

let zk_output = zk_compiler.zksync_compile(&zk_project)?;
Some(DualCompiledContracts::new(&output, &zk_output, &project.paths))
let dual_compiled_contracts = DualCompiledContracts::new(&output, &zk_output, &project.paths);
(Some(zk_output), Some(dual_compiled_contracts))
} else {
None
(None, None)
};

// Create test options from general project settings and compiler output.
Expand Down Expand Up @@ -326,6 +327,7 @@ impl TestArgs {
.build(
project_root,
output,
zk_output,
env,
evm_opts,
dual_compiled_contracts.unwrap_or_default(),
Expand Down
Loading

0 comments on commit d639c48

Please sign in to comment.