Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: contract verification [upstream merge] #468

Merged
merged 3 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
}
Loading