Skip to content

Commit 62af6f9

Browse files
authored
feat: add assemblycreate for warning suppression for zksolc 1.5.10 (#840)
* feat: add assemblycreate for error suppression for zksolc 1.5.9 * chore: remove warning and error enums in favour of era-solc dep * chore: bump default version to 1.5.9 and set flag * feat: bumps to 1.5.10 and updates assemblycreate to warningtype * fix: remove missing libs logic from handling output * chore: make use of commit 7000890 for object_format to get proper is_unlinked * chore: run make pr for lint / formatting * chore: make use of commit 0314731 to resolve null value error
1 parent b993907 commit 62af6f9

File tree

16 files changed

+445
-189
lines changed

16 files changed

+445
-189
lines changed

Cargo.lock

Lines changed: 270 additions & 38 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ zksync_vm_interface = { git = "https://github.com/matter-labs/zksync-era.git", r
256256
zksync_multivm = { git = "https://github.com/matter-labs/zksync-era.git", rev = "core-v25.4.0" }
257257
zksync_utils = { git = "https://github.com/matter-labs/zksync-era.git", rev = "core-v25.4.0" }
258258
zksync_contracts = { git = "https://github.com/matter-labs/zksync-era.git", rev = "core-v25.4.0" }
259+
era-solc = { git = "https://github.com/matter-labs/era-compiler-solidity.git", tag = "1.5.10", package = "era-solc" }
259260

260261
# macros
261262
proc-macro2 = "1.0"
@@ -303,7 +304,7 @@ regex = { version = "1", default-features = false }
303304
reqwest = { version = "0.12", default-features = false }
304305
semver = "1"
305306
serde = { version = "1.0", features = ["derive"] }
306-
serde_json = { version = "1.0", features = ["arbitrary_precision"] }
307+
serde_json = { version = "=1.0.128", features = ["arbitrary_precision"] }
307308
similar-asserts = "1.6"
308309
soldeer-commands = "=0.5.2"
309310
strum = "0.26"

crates/cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ tracing-tracy = { version = "0.11", optional = true }
5454

5555
# zk
5656
foundry-zksync-compilers.workspace = true
57+
era-solc.workspace = true
5758

5859
[dev-dependencies]
5960
tempfile.workspace = true

crates/cli/src/opts/build/zksync.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use std::{collections::HashSet, path::PathBuf};
22

33
use alloy_primitives::{hex, Address, Bytes};
44
use clap::Parser;
5+
use era_solc::standard_json::input::settings::{error_type::ErrorType, warning_type::WarningType};
56
use foundry_config::zksync::ZkSyncConfig;
6-
use foundry_zksync_compilers::compilers::zksolc::settings::{ZkSolcError, ZkSolcWarning};
77
use serde::Serialize;
88

99
#[derive(Clone, Debug, Default, Serialize, Parser)]
@@ -117,22 +117,24 @@ pub struct ZkSyncArgs {
117117
/// Set the warnings to suppress for zksolc.
118118
#[clap(
119119
long = "zk-suppressed-warnings",
120-
visible_alias = "suppressed-warnings",
120+
alias = "suppressed-warnings",
121+
visible_alias = "suppress-warnings",
121122
value_delimiter = ',',
122-
help = "Set the warnings to suppress for zksolc, possible values: [txorigin]"
123+
help = "Set the warnings to suppress for zksolc, possible values: [txorigin, assemblycreate]"
123124
)]
124125
#[serde(skip_serializing_if = "Option::is_none")]
125-
pub suppressed_warnings: Option<Vec<ZkSolcWarning>>,
126+
pub suppressed_warnings: Option<Vec<WarningType>>,
126127

127128
/// Set the errors to suppress for zksolc.
128129
#[clap(
129130
long = "zk-suppressed-errors",
130-
visible_alias = "suppressed-errors",
131+
alias = "suppressed-errors",
132+
visible_alias = "suppress-errors",
131133
value_delimiter = ',',
132134
help = "Set the errors to suppress for zksolc, possible values: [sendtransfer]"
133135
)]
134136
#[serde(skip_serializing_if = "Option::is_none")]
135-
pub suppressed_errors: Option<Vec<ZkSolcError>>,
137+
pub suppressed_errors: Option<Vec<ErrorType>>,
136138
}
137139

138140
impl ZkSyncArgs {

crates/common/src/compile.rs

Lines changed: 6 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,14 @@ use foundry_compilers::{
1919
solc::SolcSettings,
2020
Artifact, Project, ProjectBuilder, ProjectCompileOutput, ProjectPathsConfig, SolcConfig,
2121
};
22-
use foundry_zksync_compilers::{
23-
compilers::{
24-
artifact_output::zk::ZkArtifactOutput,
25-
zksolc::{ZkSolc, ZkSolcCompiler},
26-
},
27-
libraries::{self, ZkMissingLibrary},
22+
use foundry_zksync_compilers::compilers::{
23+
artifact_output::zk::ZkArtifactOutput,
24+
zksolc::{ZkSolc, ZkSolcCompiler},
2825
};
2926

3027
use num_format::{Locale, ToFormattedString};
3128
use std::{
32-
collections::{BTreeMap, HashSet},
29+
collections::BTreeMap,
3330
fmt::Display,
3431
io::IsTerminal,
3532
path::{Path, PathBuf},
@@ -336,7 +333,7 @@ impl ProjectCompiler {
336333
let zksolc_version = ZkSolc::get_version_for_path(&project.compiler.zksolc)?;
337334
Report::new(SpinnerReporter::spawn_with(format!("Using zksolc-{zksolc_version}")));
338335
}
339-
self.zksync_compile_with(&project.paths.root, || {
336+
self.zksync_compile_with(|| {
340337
let files_to_compile =
341338
if !files.is_empty() { files } else { project.paths.input_files() };
342339
let sources = Source::read_all(files_to_compile)?;
@@ -349,7 +346,6 @@ impl ProjectCompiler {
349346
#[instrument(target = "forge::compile", skip_all)]
350347
fn zksync_compile_with<F>(
351348
self,
352-
root_path: impl AsRef<Path>,
353349
f: F,
354350
) -> Result<ProjectCompileOutput<ZkSolcCompiler, ZkArtifactOutput>>
355351
where
@@ -394,7 +390,7 @@ impl ProjectCompiler {
394390
sh_println!("{output}")?;
395391
}
396392

397-
self.zksync_handle_output(root_path, &output)?;
393+
self.zksync_handle_output(&output)?;
398394
}
399395

400396
Ok(output)
@@ -403,71 +399,11 @@ impl ProjectCompiler {
403399
/// If configured, this will print sizes or names
404400
fn zksync_handle_output(
405401
&self,
406-
root_path: impl AsRef<Path>,
407402
output: &ProjectCompileOutput<ZkSolcCompiler, ZkArtifactOutput>,
408403
) -> Result<()> {
409404
let print_names = self.print_names.unwrap_or(false);
410405
let print_sizes = self.print_sizes.unwrap_or(false);
411406

412-
// Process missing libraries
413-
// TODO: skip this if project was not compiled using --detect-missing-libraries
414-
let mut missing_libs_unique: HashSet<String> = HashSet::new();
415-
for (artifact_id, artifact) in output.artifact_ids() {
416-
// TODO: when compiling specific files, the output might still add cached artifacts
417-
// that are not part of the file list to the output, which may cause missing libraries
418-
// error to trigger for files that were not intended to be compiled.
419-
// This behaviour needs to be investigated better on the foundry-compilers side.
420-
// For now we filter, checking only the files passed to compile.
421-
let is_target_file =
422-
self.files.is_empty() || self.files.iter().any(|f| artifact_id.path == *f);
423-
if is_target_file {
424-
if let Some(mls) = artifact.missing_libraries() {
425-
missing_libs_unique.extend(mls.clone());
426-
}
427-
}
428-
}
429-
430-
let missing_libs: Vec<ZkMissingLibrary> = missing_libs_unique
431-
.into_iter()
432-
.map(|ml| {
433-
let mut split = ml.split(':');
434-
let contract_path =
435-
split.next().expect("Failed to extract contract path for missing library");
436-
let contract_name =
437-
split.next().expect("Failed to extract contract name for missing library");
438-
439-
let mut abs_path_buf = PathBuf::new();
440-
abs_path_buf.push(root_path.as_ref());
441-
abs_path_buf.push(contract_path);
442-
443-
let art = output.find(abs_path_buf.as_path(), contract_name).unwrap_or_else(|| {
444-
panic!(
445-
"Could not find contract {contract_name} at path {contract_path} for compilation output"
446-
)
447-
});
448-
449-
ZkMissingLibrary {
450-
contract_path: contract_path.to_string(),
451-
contract_name: contract_name.to_string(),
452-
missing_libraries: art.missing_libraries().cloned().unwrap_or_default(),
453-
}
454-
})
455-
.collect();
456-
457-
if !missing_libs.is_empty() {
458-
libraries::add_dependencies_to_missing_libraries_cache(
459-
root_path,
460-
missing_libs.as_slice(),
461-
)
462-
.expect("Error while adding missing libraries");
463-
let missing_libs_list = missing_libs
464-
.iter()
465-
.map(|ml| format!("{}:{}", ml.contract_path, ml.contract_name))
466-
.collect::<Vec<String>>()
467-
.join(", ");
468-
eyre::bail!("Missing libraries detected: {missing_libs_list}\n\nRun the following command in order to deploy each missing library:\n\nforge create <LIBRARY> --private-key <PRIVATE_KEY> --rpc-url <RPC_URL> --chain <CHAIN_ID> --zksync\n\nThen pass the library addresses using the --libraries option");
469-
}
470-
471407
// print any sizes or names
472408
if print_names {
473409
let mut artifacts: BTreeMap<_, Vec<_>> = BTreeMap::new();

crates/config/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ yansi.workspace = true
4848

4949
# zksync
5050
foundry-zksync-compilers.workspace = true
51+
era-solc.workspace = true
5152

5253
[target.'cfg(target_os = "windows")'.dependencies]
5354
path-slash = "0.2"

crates/config/src/zksync.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use era_solc::standard_json::input::settings::{error_type::ErrorType, warning_type::WarningType};
12
use foundry_compilers::{
23
artifacts::{EvmVersion, Libraries, Severity},
34
error::SolcError,
@@ -11,14 +12,13 @@ use foundry_zksync_compilers::{
1112
zksolc::{
1213
get_solc_version_info,
1314
settings::{
14-
BytecodeHash, Codegen, Optimizer, OptimizerDetails, SettingsMetadata, ZkSolcError,
15-
ZkSolcSettings, ZkSolcWarning,
15+
BytecodeHash, Codegen, Optimizer, OptimizerDetails, SettingsMetadata,
16+
ZkSolcSettings,
1617
},
1718
ZkSettings, ZkSolc, ZkSolcCompiler,
1819
},
1920
},
2021
};
21-
2222
use semver::Version;
2323
use serde::{Deserialize, Serialize};
2424
use std::{collections::HashSet, path::PathBuf};
@@ -70,10 +70,10 @@ pub struct ZkSyncConfig {
7070
pub optimizer_details: Option<OptimizerDetails>,
7171

7272
// zksolc suppressed warnings.
73-
pub suppressed_warnings: HashSet<ZkSolcWarning>,
73+
pub suppressed_warnings: HashSet<WarningType>,
7474

7575
// zksolc suppressed errors.
76-
pub suppressed_errors: HashSet<ZkSolcError>,
76+
pub suppressed_errors: HashSet<ErrorType>,
7777
}
7878

7979
impl Default for ZkSyncConfig {
@@ -198,7 +198,7 @@ pub fn config_create_project(
198198
{
199199
zksolc
200200
} else if !config.offline {
201-
let default_version = semver::Version::new(1, 5, 7);
201+
let default_version = semver::Version::new(1, 5, 10);
202202
let mut zksolc = ZkSolc::find_installed_version(&default_version)?;
203203
if zksolc.is_none() {
204204
ZkSolc::blocking_install(&default_version)?;

crates/forge/tests/it/test_helpers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ impl ForgeTestProfile {
201201
zk_config.zksync.startup = true;
202202
zk_config.zksync.fallback_oz = true;
203203
zk_config.zksync.optimizer_mode = '3';
204-
zk_config.zksync.zksolc = Some(foundry_config::SolcReq::Version(Version::new(1, 5, 7)));
204+
zk_config.zksync.zksolc = Some(foundry_config::SolcReq::Version(Version::new(1, 5, 10)));
205205
zk_config.fuzz.no_zksync_reserved_addresses = true;
206206
zk_config.invariant.depth = 15;
207207

crates/zksync/compilers/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ path-slash = "0.2"
3131

3232
# zk
3333
zksync_types.workspace = true
34+
era-solc.workspace = true
3435

3536
[dev-dependencies]
3637
similar-asserts.workspace = true

crates/zksync/compilers/src/artifacts/contract.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,45 @@ use foundry_compilers_artifacts_solc::{
88
use serde::{Deserialize, Serialize};
99
use std::{borrow::Cow, collections::BTreeMap};
1010

11+
/// zksolc: Binary object format.
12+
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)]
13+
#[serde(try_from = "String", into = "String")]
14+
pub enum ObjectFormat {
15+
/// Linked
16+
#[default]
17+
Raw,
18+
/// Unlinked
19+
Elf,
20+
}
21+
22+
impl From<ObjectFormat> for String {
23+
fn from(val: ObjectFormat) -> Self {
24+
match val {
25+
ObjectFormat::Raw => "raw",
26+
ObjectFormat::Elf => "elf",
27+
}
28+
.to_string()
29+
}
30+
}
31+
32+
impl TryFrom<String> for ObjectFormat {
33+
type Error = String;
34+
fn try_from(s: String) -> Result<Self, Self::Error> {
35+
match s.as_str() {
36+
"raw" => Ok(Self::Raw),
37+
"elf" => Ok(Self::Elf),
38+
s => Err(format!("Unknown zksolc object format: {s}")),
39+
}
40+
}
41+
}
42+
43+
impl ObjectFormat {
44+
/// Returns `true` if the bytecode is unlinked
45+
pub fn is_unlinked(&self) -> bool {
46+
matches!(self, Self::Elf)
47+
}
48+
}
49+
1150
/// Represents a compiled solidity contract
1251
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
1352
#[serde(rename_all = "camelCase")]
@@ -44,6 +83,14 @@ pub struct Contract {
4483
/// The contract's unlinked libraries
4584
#[serde(default)]
4685
pub missing_libraries: Vec<String>,
86+
/// zksolc's binary object format
87+
///
88+
/// Tells whether the bytecode has been linked.
89+
///
90+
/// Introduced in 1.5.8, beforehand we can assume the bytecode
91+
/// was always fully linked
92+
#[serde(default)]
93+
pub object_format: Option<ObjectFormat>,
4794
}
4895

4996
fn storage_layout_is_empty(storage_layout: &StorageLayout) -> bool {
@@ -53,7 +100,7 @@ fn storage_layout_is_empty(storage_layout: &StorageLayout) -> bool {
53100
impl Contract {
54101
/// Returns true if contract is not linked
55102
pub fn is_unlinked(&self) -> bool {
56-
self.hash.is_none() || !self.missing_libraries.is_empty()
103+
self.object_format.as_ref().map(|format| format.is_unlinked()).unwrap_or_default()
57104
}
58105

59106
/// takes missing libraries output and transforms into link references

0 commit comments

Comments
 (0)