Skip to content

Commit

Permalink
fix: contract verification [upstream merge] (#468)
Browse files Browse the repository at this point in the history
Co-authored-by: Nisheeth Barthwal <[email protected]>
  • Loading branch information
Karrq and nbaztec authored Jul 10, 2024
1 parent 6328ca9 commit 1866ebd
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 61 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.

1 change: 1 addition & 0 deletions crates/forge/bin/cmd/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ impl TestArgs {
zk_compiler.zksync_compile(&zk_project, config.zksync.avoid_contracts())?;
let dual_compiled_contracts =
DualCompiledContracts::new(&output, &zk_output, &project.paths);

(Some(zk_output), Some(dual_compiled_contracts))
} else {
(None, None)
Expand Down
3 changes: 3 additions & 0 deletions crates/verify/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ once_cell.workspace = true
yansi.workspace = true
itertools.workspace = true

# zk
foundry-zksync-compiler.workspace = true

[dev-dependencies]
tokio = { workspace = true, features = ["macros"] }
foundry-test-utils.workspace = true
Expand Down
18 changes: 12 additions & 6 deletions crates/verify/src/etherscan/flatten.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ use foundry_compilers::{
input::{ZkSolcInput, ZkSolcVersionedInput},
ZkSolc,
},
zksync::{
compile::output::AggregatedCompilerOutput as ZkAggregatedCompilerOutput, raw_build_info_new,
},
AggregatedCompilerOutput,
};
use semver::{BuildMetadata, Version};
Expand Down Expand Up @@ -84,8 +87,12 @@ impl EtherscanSourceProvider for EtherscanFlattenedSource {

if !args.force {
// solc dry run of flattened code
self.check_flattened(source.clone(), &context.compiler_version, &context.target_path)
.map_err(|err| {
self.zk_check_flattened(
source.clone(),
&context.compiler_version,
&context.target_path,
)
.map_err(|err| {
eyre::eyre!(
"Failed to compile the flattened code locally: `{}`\
To skip this solc dry, have a look at the `--force` flag of this command.",
Expand Down Expand Up @@ -178,17 +185,16 @@ Diagnostics: {diags}",
sources: BTreeMap::from([("contract.sol".into(), Source::new(content))]),
..Default::default()
},
solc_version: version,
solc_version: version.clone(),
allow_paths: Default::default(),
base_path: Default::default(),
include_paths: Default::default(),
};

let out = zksolc.compile(&mut input)?;
if out.has_error() {
let o = AggregatedCompilerOutput::<SolcCompiler>::default();
// TODO: RawBuildInfo cannot accept zksolc's CompilerOutput
// o.extend(version.clone(), RawBuildInfo::new(&input, &out, false)?, out);
let mut o = ZkAggregatedCompilerOutput::default();
o.extend(version.clone(), raw_build_info_new(&input, &out, false)?, out);
let diags = o.diagnostics(&[], &[], Default::default());

eyre::bail!(
Expand Down
36 changes: 3 additions & 33 deletions crates/verify/src/etherscan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,38 +373,7 @@ impl EtherscanVerificationProvider {
return Ok(None);
}

//TODO: remove when foundry-compilers zksolc detection is fixed for 1.5.0
let get_zksolc_compiler_version = |path: &std::path::Path| -> Result<Version> {
use std::process::*;
let mut cmd = Command::new(path);
cmd.arg("--version")
.stdin(Stdio::piped())
.stderr(Stdio::piped())
.stdout(Stdio::piped());
debug!(?cmd, "getting ZkSolc version");
let output = cmd.output().wrap_err("error retrieving --version for zksolc")?;

if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
let version = stdout
.lines()
.filter(|l| !l.trim().is_empty())
.last()
.ok_or(eyre!("Version not found in zksolc output"))?;
Ok(Version::from_str(
version
.split_whitespace()
.find(|s| s.starts_with('v'))
.ok_or(eyre!("Unable to retrieve version from zksolc output"))?
.trim_start_matches('v'),
)?)
} else {
Err(eyre!("zkSolc error: {}", String::from_utf8_lossy(&output.stderr)))
.wrap_err("Error retrieving zksolc version with --version")
}
};

let zksolc = get_zksolc_compiler_version(context.project.zksync_zksolc.zksolc.as_ref())?;
let zksolc = context.project.zksync_zksolc.version()?;
let mut is_zksync_solc = false;

let solc = if let Some(solc) = &context.config.zksync.solc_path {
Expand All @@ -414,7 +383,7 @@ impl EtherscanVerificationProvider {
Some(version)
} else {
//if there's no `solc_path` specified then we use the same
// as the project version, but the zksync forc
// as the project version, but the zksync fork
is_zksync_solc = true;
Some(context.compiler_version.clone())
};
Expand Down Expand Up @@ -473,6 +442,7 @@ impl EtherscanVerificationProvider {
&context.config,
)?;

//TODO: zk support
let creation_data = client.contract_creation_data(args.address).await?;
let transaction = provider
.get_transaction_by_hash(creation_data.transaction_hash)
Expand Down
25 changes: 4 additions & 21 deletions crates/verify/src/etherscan/standard_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::{EtherscanSourceProvider, VerifyArgs};
use crate::provider::VerificationContext;
use eyre::{Context, Result};
use foundry_block_explorers::verify::CodeFormat;
use foundry_compilers::artifacts::StandardJsonCompilerInput;
use foundry_compilers::{artifacts::StandardJsonCompilerInput, ArtifactOutput, Compiler, Project};

#[derive(Debug)]
pub struct EtherscanStandardJsonSource;
Expand Down Expand Up @@ -53,26 +53,9 @@ impl EtherscanSourceProvider for EtherscanStandardJsonSource {
_args: &VerifyArgs,
context: &VerificationContext,
) -> Result<(String, String, CodeFormat)> {
let mut input: StandardJsonCompilerInput = context
.project
// TODO this method does not exist on compilers
// .zksync_standard_json_input(&context.target_path)
.standard_json_input(&context.target_path)
.wrap_err("Failed to get zksync standard json input")?
.normalize_evm_version(&context.compiler_version);

input.settings.libraries.libs = input
.settings
.libraries
.libs
.into_iter()
.map(|(f, libs)| {
(f.strip_prefix(context.project.root()).unwrap_or(&f).to_path_buf(), libs)
})
.collect();

// remove all incompatible settings
input.settings.sanitize(&context.compiler_version);
let input =
foundry_zksync_compiler::standard_json_input(&context.project, &context.target_path)
.wrap_err("failed to get zksolc standard json")?;

let source =
serde_json::to_string(&input).wrap_err("Failed to parse zksync standard json input")?;
Expand Down
1 change: 1 addition & 0 deletions crates/verify/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ impl VerifyArgs {
output.artifact_ids().map(|(id, artifact)| (id, artifact.clone().into())),
);

//TODO: lookup for zksync
let Some((artifact_id, _)) = contracts.find_by_deployed_code_exact(&code) else {
eyre::bail!(format!(
"Bytecode at {} does not match any local contracts",
Expand Down
31 changes: 30 additions & 1 deletion crates/zksync/compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
/// ZKSolc specific logic.
mod zksolc;

use std::path::Path;

use foundry_config::{Config, SkipBuildFilters, SolcReq};
pub use zksolc::*;

pub mod libraries;

use foundry_compilers::{
artifacts::Severity, error::SolcError, solc::SolcCompiler, zksolc::ZkSolc,
zksync::config::ZkSolcConfig, Project, ProjectBuilder,
zksync::config::ZkSolcConfig, Compiler, Project, ProjectBuilder,
};

/// Ensures that the configured version is installed if explicitly set
Expand Down Expand Up @@ -113,3 +115,30 @@ pub fn create_project(

Ok(project)
}

/// Obtain a standard json input for zksolc
pub fn standard_json_input<C: Compiler>(
project: &Project<C>,
target_path: impl AsRef<Path>,
) -> Result<serde_json::Value, SolcError>
where
C::Settings: Into<foundry_compilers::artifacts::Settings>,
{
let mut input = project.standard_json_input(target_path)?;
tracing::debug!(?input.settings.remappings, "standard_json_input for zksync");

let mut settings = project.zksync_zksolc_config.settings.clone();
settings.remappings = std::mem::take(&mut input.settings.remappings);
settings.libraries.libs = settings
.libraries
.libs
.into_iter()
.map(|(f, libs)| (f.strip_prefix(project.root()).unwrap_or(&f).to_path_buf(), libs))
.collect();
let settings = serde_json::to_value(settings).expect("able to serialize settings as json");

let mut serialized = serde_json::to_value(input).expect("able to serialize input as json");
serialized["settings"] = settings;

Ok(serialized)
}

0 comments on commit 1866ebd

Please sign in to comment.