Skip to content

Commit

Permalink
Merge pull request #38 from Moonsong-Labs/nish-zksync-v0.11.6
Browse files Browse the repository at this point in the history
chore: pull in new commits
  • Loading branch information
nbaztec authored Nov 5, 2024
2 parents 7e24d6c + f22a927 commit 7bb66e6
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @hedgar2017
* @nbaztec @elfedy @Karrq @Jrigada @dutterbutter @hedgar2017
12 changes: 6 additions & 6 deletions crates/artifacts/zksolc/src/output_selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ use std::collections::HashSet;
#[derive(Debug, Default, Serialize, Deserialize, Eq, PartialEq, Clone)]
pub struct OutputSelection {
/// Only the 'all' wildcard is available for robustness reasons.
#[serde(rename = "*", skip_serializing_if = "Option::is_none")]
pub all: Option<FileOutputSelection>,
#[serde(rename = "*")]
pub all: FileOutputSelection,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct FileOutputSelection {
/// The per-file output selections.
#[serde(rename = "", skip_serializing_if = "Option::is_none")]
pub per_file: Option<HashSet<OutputSelectionFlag>>,
#[serde(rename = "")]
pub per_file: HashSet<OutputSelectionFlag>,
/// The per-contract output selections.
#[serde(rename = "*", skip_serializing_if = "Option::is_none")]
pub per_contract: Option<HashSet<OutputSelectionFlag>>,
#[serde(rename = "*")]
pub per_contract: HashSet<OutputSelectionFlag>,
}

///
Expand Down
24 changes: 22 additions & 2 deletions crates/compilers/src/compilers/zksolc/input.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use super::{settings::ZkSolcSettings, ZkSettings};
use super::{
settings::{ZkSolcError, ZkSolcSettings, ZkSolcWarning},
ZkSettings,
};
use crate::{
compilers::{solc::SolcLanguage, CompilerInput},
solc,
Expand All @@ -8,6 +11,7 @@ use semver::Version;
use serde::{Deserialize, Serialize};
use std::{
borrow::Cow,
collections::HashSet,
path::{Path, PathBuf},
};

Expand All @@ -33,7 +37,7 @@ impl CompilerInput for ZkSolcVersionedInput {
version: Version,
) -> Self {
let ZkSolcSettings { settings, cli_settings } = settings;
let input = ZkSolcInput { language, sources, settings }.sanitized(&version);
let input = ZkSolcInput::new(language, sources, settings).sanitized(&version);

Self { solc_version: version, input, cli_settings }
}
Expand Down Expand Up @@ -65,10 +69,18 @@ impl CompilerInput for ZkSolcVersionedInput {

/// Input type `zksolc` expects.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ZkSolcInput {
pub language: SolcLanguage,
pub sources: Sources,
pub settings: ZkSettings,
// For `zksolc` versions <1.5.7, suppressed warnings / errors were specified on the same level
// as `settings`. For `zksolc` 1.5.7+, they are specified inside `settings`. Since we want to
// support both options at the time, we duplicate fields from `settings` here.
#[serde(default, skip_serializing_if = "HashSet::is_empty")]
pub suppressed_warnings: HashSet<ZkSolcWarning>,
#[serde(default, skip_serializing_if = "HashSet::is_empty")]
pub suppressed_errors: HashSet<ZkSolcError>,
}

/// Default `language` field is set to `"Solidity"`.
Expand All @@ -78,11 +90,19 @@ impl Default for ZkSolcInput {
language: SolcLanguage::Solidity,
sources: Sources::default(),
settings: ZkSettings::default(),
suppressed_warnings: HashSet::default(),
suppressed_errors: HashSet::default(),
}
}
}

impl ZkSolcInput {
fn new(language: SolcLanguage, sources: Sources, settings: ZkSettings) -> Self {
let suppressed_warnings = settings.suppressed_warnings.clone();
let suppressed_errors = settings.suppressed_errors.clone();
Self { language, sources, settings, suppressed_warnings, suppressed_errors }
}

/// Removes the `base` path from all source files
pub fn strip_prefix(&mut self, base: impl AsRef<Path>) {
let base = base.as_ref();
Expand Down
7 changes: 3 additions & 4 deletions crates/compilers/src/compilers/zksolc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ use std::os::unix::fs::PermissionsExt;

pub mod input;
pub mod settings;
pub use settings::ZkSettings;
pub use settings::ZkSolcSettings;
pub use settings::{ZkSettings, ZkSolcSettings};

pub const ZKSOLC: &str = "zksolc";
pub const ZKSYNC_SOLC_RELEASE: Version = Version::new(1, 0, 1);
pub const ZKSOLC_VERSION: Version = Version::new(1, 5, 4);
pub const ZKSOLC_VERSION: Version = Version::new(1, 5, 7);

#[derive(Debug, Clone, Serialize)]
enum ZkSolcOS {
Expand Down Expand Up @@ -336,7 +335,7 @@ impl ZkSolc {
pub fn solc_available_versions() -> Vec<Version> {
let mut ret = vec![];
let min_max_patch_by_minor_versions =
vec![(4, 12, 26), (5, 0, 17), (6, 0, 12), (7, 0, 6), (8, 0, 27)];
vec![(4, 12, 26), (5, 0, 17), (6, 0, 12), (7, 0, 6), (8, 0, 28)];
for (minor, min_patch, max_patch) in min_max_patch_by_minor_versions {
for i in min_patch..=max_patch {
ret.push(Version::new(0, minor, i));
Expand Down
51 changes: 50 additions & 1 deletion crates/compilers/src/compilers/zksolc/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,43 @@ use foundry_compilers_artifacts::{
use semver::Version;
use serde::{Deserialize, Serialize};
use std::{
collections::BTreeSet,
collections::{BTreeSet, HashSet},
fmt,
path::{Path, PathBuf},
str::FromStr,
};

///
/// The Solidity compiler codegen.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Codegen {
/// The Yul IR.
#[default]
Yul,
/// The EVM legacy assembly IR.
EVMLA,
}

/// `zksolc` warnings that can be suppressed.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
#[non_exhaustive]
pub enum ZkSolcWarning {
/// `txorigin` warning: Using `tx.origin` in place of `msg.sender`.
TxOrigin,
}

/// `zksolc` errors that can be suppressed.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
#[non_exhaustive]
pub enum ZkSolcError {
/// `sendtransfer` error: Using `send()` or `transfer()` methods on `address payable` instead
/// of `call()`.
SendTransfer,
}

/// zksolc standard json input settings. See:
/// https://docs.zksync.io/zk-stack/components/compiler/toolchain/solidity.html#standard-json for differences
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
Expand All @@ -25,6 +56,9 @@ pub struct ZkSettings {
/// false by default.
#[serde(rename = "viaIR", default, skip_serializing_if = "Option::is_none")]
pub via_ir: Option<bool>,
/// The Solidity codegen.
#[serde(default)]
pub codegen: Codegen,
// TODO: era-compiler-solidity uses a BTreeSet of strings. In theory the serialization
// should be the same but maybe we should double check
#[serde(default, skip_serializing_if = "Vec::is_empty")]
Expand Down Expand Up @@ -66,6 +100,12 @@ pub struct ZkSettings {
/// Whether to compile via EVM assembly.
#[serde(default, rename = "forceEVMLA")]
pub force_evmla: bool,
/// Suppressed `zksolc` warnings.
#[serde(default, skip_serializing_if = "HashSet::is_empty")]
pub suppressed_warnings: HashSet<ZkSolcWarning>,
/// Suppressed `zksolc` errors.
#[serde(default, skip_serializing_if = "HashSet::is_empty")]
pub suppressed_errors: HashSet<ZkSolcError>,
}

// Analogous to SolcSettings for Zk compiler
Expand Down Expand Up @@ -143,6 +183,9 @@ impl Default for ZkSettings {
enable_eravm_extensions: false,
llvm_options: Default::default(),
force_evmla: false,
codegen: Default::default(),
suppressed_errors: Default::default(),
suppressed_warnings: Default::default(),
}
}
}
Expand All @@ -168,6 +211,9 @@ impl CompilerSettings for ZkSolcSettings {
enable_eravm_extensions,
llvm_options,
force_evmla,
codegen,
suppressed_warnings,
suppressed_errors,
},
..
} = self;
Expand All @@ -183,6 +229,9 @@ impl CompilerSettings for ZkSolcSettings {
&& *enable_eravm_extensions == other.settings.enable_eravm_extensions
&& *llvm_options == other.settings.llvm_options
&& *force_evmla == other.settings.force_evmla
&& *codegen == other.settings.codegen
&& *suppressed_warnings == other.settings.suppressed_warnings
&& *suppressed_errors == other.settings.suppressed_errors
}

fn with_remappings(mut self, remappings: &[Remapping]) -> Self {
Expand Down
128 changes: 126 additions & 2 deletions crates/compilers/tests/zksync.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
use std::{collections::HashMap, fs, path::PathBuf, str::FromStr};
use std::{
collections::{HashMap, HashSet},
fs,
path::PathBuf,
str::FromStr,
};

use foundry_compilers::{
buildinfo::BuildInfo,
cache::CompilerCache,
project_util::*,
resolver::parse::SolData,
zksolc::{input::ZkSolcInput, ZkSolcCompiler, ZkSolcSettings},
zksolc::{
input::ZkSolcInput,
settings::{ZkSolcError, ZkSolcWarning},
ZkSolc, ZkSolcCompiler, ZkSolcSettings,
},
zksync::{self, artifact_output::zk::ZkArtifactOutput},
Graph, ProjectBuilder, ProjectPathsConfig,
};
Expand Down Expand Up @@ -42,6 +51,121 @@ fn zksync_can_compile_dapp_sample() {
assert_eq!(cache, updated_cache);
}

fn test_zksync_can_compile_contract_with_suppressed_errors(compiler: ZkSolcCompiler) {
let _ = tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.try_init()
.ok();
let mut project = TempProject::<ZkSolcCompiler, ZkArtifactOutput>::dapptools().unwrap();
project.project_mut().compiler = compiler;

project
.add_source(
"Erroneous",
r#"
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.10;
contract Erroneous {
function distribute(address payable recipient) public {
recipient.send(1);
recipient.transfer(1);
}
}
"#,
)
.unwrap();

let compiled = zksync::project_compile(project.project()).unwrap();
assert!(compiled.has_compiler_errors());

project.project_mut().settings.settings.suppressed_errors =
HashSet::from([ZkSolcError::SendTransfer]);

let compiled = zksync::project_compile(project.project()).unwrap();
compiled.assert_success();
assert!(compiled.find_first("Erroneous").is_some());
}

#[test]
fn zksync_can_compile_contract_with_suppressed_errors() {
test_zksync_can_compile_contract_with_suppressed_errors(ZkSolcCompiler::default());
}

#[test]
fn zksync_pre_1_5_7_can_compile_contract_with_suppressed_errors() {
let compiler = ZkSolcCompiler {
zksolc: ZkSolc::get_path_for_version(&semver::Version::new(1, 5, 6)).unwrap(),
solc: Default::default(),
};
test_zksync_can_compile_contract_with_suppressed_errors(compiler);
}

fn test_zksync_can_compile_contract_with_suppressed_warnings(compiler: ZkSolcCompiler) {
let _ = tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.try_init()
.ok();
let mut project = TempProject::<ZkSolcCompiler, ZkArtifactOutput>::dapptools().unwrap();
project.project_mut().compiler = compiler;

project
.add_source(
"Warning",
r#"
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.10;
contract Warning {
function test() public view {
require(tx.origin != address(0), "what");
}
}
"#,
)
.unwrap();

let compiled = zksync::project_compile(project.project()).unwrap();
compiled.assert_success();
assert!(
compiled
.compiler_output
.errors
.iter()
.any(|err| err.is_warning() && err.message.contains("tx.origin")),
"{:#?}",
compiled.compiler_output.errors
);

project.project_mut().settings.settings.suppressed_warnings =
HashSet::from([ZkSolcWarning::TxOrigin]);

let compiled = zksync::project_compile(project.project()).unwrap();
compiled.assert_success();
assert!(compiled.find_first("Warning").is_some());
assert!(
!compiled
.compiler_output
.errors
.iter()
.any(|err| err.is_warning() && err.message.contains("tx.origin")),
"{:#?}",
compiled.compiler_output.errors
);
}

#[test]
fn zksync_can_compile_contract_with_suppressed_warnings() {
test_zksync_can_compile_contract_with_suppressed_warnings(ZkSolcCompiler::default());
}

#[test]
fn zksync_pre_1_5_7_can_compile_contract_with_suppressed_warnings() {
let compiler = ZkSolcCompiler {
zksolc: ZkSolc::get_path_for_version(&semver::Version::new(1, 5, 6)).unwrap(),
solc: Default::default(),
};
test_zksync_can_compile_contract_with_suppressed_warnings(compiler);
}

#[test]
fn zksync_can_compile_dapp_detect_changes_in_libs() {
let _ = tracing_subscriber::fmt()
Expand Down

0 comments on commit 7bb66e6

Please sign in to comment.