diff --git a/.gitignore b/.gitignore index cafc3d13..5c0d0763 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,5 @@ *.bak # Test solc versions -solc-bin/ +**/solc-bin/ +**/solc-bin-upstream/ diff --git a/CHANGELOG.md b/CHANGELOG.md index fd6abbd0..63f132ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ - Moved suppressed messages inside `settings` in standard JSON input - Moved EraVM artifacts to `contract.eravm` in standard JSON output +### Fixed + +- Different bytecode for compile-time and post-compile-time library linking + ### Deprecated - Suppressed messages at the root of standard JSON input @@ -36,7 +40,7 @@ ### Fixed -- The compilation pipeline that was not run without output parameters +- Skipped compilation if no output parameters are provided - Broken `--output-dir` output paths for non-Solidity contracts - `solc` that was not picked up from `${PATH}` in standard JSON mode - `solc` exit code check which is now before the output parsing @@ -337,7 +341,7 @@ ### Changed -- Internal function pointers now trigger a compile-time error with the EVMLA pipeline +- Internal function pointers now trigger a compile-time error with the EVMLA codegen - Calldata instructions now return 0 in deploy code ### Removed @@ -356,7 +360,7 @@ ### Added -- Better errors for unsupported `type(X).runtimeCode` with the Yul pipeline +- Better errors for unsupported `type(X).runtimeCode` with the Yul codegen - An option to disable the `solc` optimizer ### Changed @@ -366,9 +370,9 @@ ### Fixed -- Another stack overflow issue with the EVMLA pipeline -- `CODECOPY` in runtime code now does not copy calldata with the EVMLA pipeline -- `CODESIZE` in runtime code now returns 0 with the EVMLA pipeline +- Another stack overflow issue with the EVMLA codegen +- `CODECOPY` in runtime code now does not copy calldata with the EVMLA codegen +- `CODESIZE` in runtime code now returns 0 with the EVMLA codegen - Hexadecimal arguments in EVMLA are now parsed as case-insensitive ## [1.3.7] - 2023-03-15 @@ -421,7 +425,7 @@ ### Fixed - The `send` and `transfer` now produce a warning again due to false-positives -- Malfunctioned `CODECOPY` in some cases with the EVMLA pipeline +- Malfunctioned `CODECOPY` in some cases with the EVMLA codegen - The near call exception handling for the requests to system contracts ## [1.3.2] - 2023-02-14 diff --git a/Cargo.lock b/Cargo.lock index 637843e0..91bb1b82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" [[package]] name = "anyhow" @@ -203,6 +203,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "boolinator" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" + [[package]] name = "bstr" version = "1.10.0" @@ -234,15 +240,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cc" -version = "1.1.30" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "shlex", ] @@ -496,9 +502,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -512,7 +518,7 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "era-compiler-common" version = "1.5.0" -source = "git+https://github.com/matter-labs/era-compiler-common?branch=main#ce91855778bd5e1821f9b46751f92bafafd88435" +source = "git+https://github.com/matter-labs/era-compiler-common?branch=main#11cc7ed039fb96ef04d45d71c009e8dc8fffda9a" dependencies = [ "anyhow", "base58", @@ -527,8 +533,8 @@ dependencies = [ [[package]] name = "era-compiler-downloader" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-compiler-common?branch=main#ce91855778bd5e1821f9b46751f92bafafd88435" +version = "1.5.0" +source = "git+https://github.com/matter-labs/era-compiler-common?branch=main#11cc7ed039fb96ef04d45d71c009e8dc8fffda9a" dependencies = [ "anyhow", "colored", @@ -541,7 +547,7 @@ dependencies = [ [[package]] name = "era-compiler-llvm-context" version = "1.5.0" -source = "git+https://github.com/matter-labs/era-compiler-llvm-context?branch=main#c226149995a9efd8e26d74bfa01c0da0764979fd" +source = "git+https://github.com/matter-labs/era-compiler-llvm-context?branch=main#67bb2349e221627f15b09893e59f807094ab81ca" dependencies = [ "anyhow", "era-compiler-common", @@ -559,6 +565,7 @@ version = "1.5.6" dependencies = [ "anyhow", "assert_cmd", + "boolinator", "era-compiler-common", "era-compiler-downloader", "era-compiler-llvm-context", @@ -1033,7 +1040,7 @@ source = "git+https://github.com/matter-labs-forks/inkwell?branch=llvm-17#c50692 dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1120,9 +1127,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libmimalloc-sys" @@ -1386,9 +1393,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.67" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b8cefcf97f41316955f9294cd61f639bdcfa9f2f230faac6cb896aa8ab64704" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -1407,7 +1414,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1418,9 +1425,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.3.2+3.3.2" +version = "300.4.0+3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a211a18d945ef7e648cc6e0058f4c548ee46aab922ea203e0d30e966ea23647b" +checksum = "a709e02f2b4aca747929cca5ed248880847c650233cf8b8cdc48f40aaf4898a6" dependencies = [ "cc", ] @@ -1522,9 +1529,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -1644,9 +1651,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -1852,9 +1859,9 @@ checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" dependencies = [ "bitflags 2.6.0", "errno", @@ -1977,7 +1984,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -2186,9 +2193,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", @@ -2265,7 +2272,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -2276,7 +2283,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", "test-case-core", ] @@ -2306,7 +2313,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -2335,9 +2342,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", @@ -2551,7 +2558,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", "wasm-bindgen-shared", ] @@ -2585,7 +2592,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2818,7 +2825,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] diff --git a/docs/src/02-command-line-interface.md b/docs/src/02-command-line-interface.md index e58978f5..baa1fe8f 100644 --- a/docs/src/02-command-line-interface.md +++ b/docs/src/02-command-line-interface.md @@ -52,7 +52,7 @@ zksolc './Simple.sol' --bin Output: -``` +```text ======= Simple.sol:Simple ======= Binary: 0000008003000039000000400030043f0000000100200190000000130000c13d... @@ -66,7 +66,7 @@ zksolc './Simple.sol' Output: -``` +```text Compiler run successful. No output requested. Use flags --metadata, --asm, --bin. ``` @@ -116,7 +116,7 @@ zksolc Simple.sol --asm Output: -``` +```text ======= Simple.sol:Simple ======= EraVM assembly: .text @@ -151,7 +151,7 @@ zksolc Simple.sol --metadata Output: -``` +```text ======= Simple.sol:Simple ======= Metadata: {"llvm_options":[],"optimizer_settings":{"is_debug_logging_enabled":false,"is_fallback_to_size_enabled":false,"is_verify_each_enabled":false,"level_back_end":"Aggressive","level_middle_end":"Aggressive","level_middle_end_size":"Zero"},"solc_version":"","solc_zkvm_edition":null,"source_metadata":{...},"zk_version":""} @@ -200,7 +200,7 @@ zksolc --yul Simple.yul --bin Output: -``` +```text ======= Simple.yul ======= Binary: 0000000100200190000000060000c13d0000002a01000039000000000010043f... @@ -230,7 +230,7 @@ zksolc --llvm-ir Simple.ll --bin Output: -``` +```text ======= Simple.ll ======= Binary: 000000000002004b000000070000613d0000002001000039000000000010043f... @@ -254,7 +254,7 @@ zksolc --eravm-assembly Simple.zasm --bin Output: -``` +```text ======= Simple.zasm ======= Binary: 000000000120008c000000070000613d00000020010000390000000000100435... @@ -294,7 +294,7 @@ cat './input.hex' Output: -``` +```text 0x0000008003000039000000400030043f0000000100200190000000140000c13d00000000020... ``` @@ -307,7 +307,7 @@ zksolc --disassemble './input.hex' Output: -``` +```text File `input.hex` disassembly: 0: 00 00 00 80 03 00 00 39 add 128, r0, r3 @@ -350,7 +350,7 @@ zksolc Simple.sol --bin --target evm Output: -``` +```text ======= Simple.sol:Simple ======= Binary: 5b60806040523415600e575f5ffd5b630000007f630000002760808282823960808092505050f35b5f5f6080604052369150600482106032575f3560e01c9050633df4ddf48114603657635a8ac02d81811480915050605a575b5f5ffd5b3415603f575f5ffd5b60015f036004830313604f575f5ffd5b602a60805260206080f35b34156063575f5ffd5b60015f0360048303136073575f5ffd5b60405160638152602090f3 diff --git a/docs/src/04-standard-json.md b/docs/src/04-standard-json.md index 79120b2f..d39e71bf 100644 --- a/docs/src/04-standard-json.md +++ b/docs/src/04-standard-json.md @@ -21,7 +21,7 @@ The input JSON provides the compiler with the source code and settings for the c Internally, *zksolc* extracts all *zksolc*-specific options and converts the input JSON to the subset expected by *solc* before calling it. -```json +```javascript { // Required: Source code language. // Currently supported: "Solidity", "Yul", "LLVM IR", "EraVM Assembly". @@ -171,7 +171,7 @@ The output JSON contains all artifacts produced by both *zksolc* and *solc* comp If *solc* is provided to *zksolc*, the output JSON is initially generated by *solc*, and ZKsync-specific data is appended by *zksolc* afterwards. If *solc* is not provided, the output JSON is generated by *zksolc* alone. -```json +```javascript { // Required: File-level outputs. "sources": { diff --git a/era-compiler-solidity/Cargo.toml b/era-compiler-solidity/Cargo.toml index 3820c339..6839b4f4 100644 --- a/era-compiler-solidity/Cargo.toml +++ b/era-compiler-solidity/Cargo.toml @@ -18,6 +18,7 @@ doctest = false structopt = { version = "=0.3.26", default-features = false } thiserror = "=1.0.64" anyhow = "=1.0.89" +boolinator = "=2.4.0" which = "=6.0.3" path-slash = "=0.2.1" normpath = "=1.3.0" diff --git a/era-compiler-solidity/src/build_eravm/contract.rs b/era-compiler-solidity/src/build_eravm/contract.rs index cf785617..1c86ff75 100644 --- a/era-compiler-solidity/src/build_eravm/contract.rs +++ b/era-compiler-solidity/src/build_eravm/contract.rs @@ -180,8 +180,14 @@ impl Contract { .bin_runtime .clone_from(&combined_json_contract.bin); - combined_json_contract.assembly = self.build.assembly.map(serde_json::Value::String); - combined_json_contract.factory_deps = Some(self.build.factory_dependencies); + combined_json_contract.assembly = self + .build + .assembly + .map(serde_json::Value::String) + .unwrap_or_default(); + combined_json_contract + .factory_deps + .extend(self.build.factory_dependencies); Ok(()) } @@ -196,7 +202,7 @@ impl Contract { let bytecode = hex::encode(self.build.bytecode.as_slice()); let assembly = self.build.assembly; - standard_json_contract.metadata = Some(self.metadata_json); + standard_json_contract.metadata = self.metadata_json; standard_json_contract.eravm = Some(StandardJsonOutputContractEraVM::new( bytecode.clone(), assembly.clone(), diff --git a/era-compiler-solidity/src/build_eravm/mod.rs b/era-compiler-solidity/src/build_eravm/mod.rs index ca3cc583..eee4e331 100644 --- a/era-compiler-solidity/src/build_eravm/mod.rs +++ b/era-compiler-solidity/src/build_eravm/mod.rs @@ -113,7 +113,6 @@ impl Build { standard_json: &mut StandardJsonOutput, solc_version: Option<&SolcVersion>, ) -> anyhow::Result<()> { - let standard_json_contracts = standard_json.contracts.get_or_insert_with(BTreeMap::new); let mut errors = Vec::with_capacity(self.contracts.len()); for (full_path, build) in self.contracts.into_iter() { let mut full_path_split = full_path.split(':'); @@ -121,7 +120,8 @@ impl Build { let name = full_path_split.next().unwrap_or(path); match build { - Ok(build) => match standard_json_contracts + Ok(build) => match standard_json + .contracts .get_mut(path) .and_then(|contracts| contracts.get_mut(name)) { @@ -129,7 +129,7 @@ impl Build { build.write_to_standard_json(contract)?; } None => { - let contracts = standard_json_contracts.entry(path.to_owned()).or_default(); + let contracts = standard_json.contracts.entry(path.to_owned()).or_default(); let mut contract = StandardJsonOutputContract::default(); build.write_to_standard_json(&mut contract)?; contracts.insert(name.to_owned(), contract); @@ -139,10 +139,7 @@ impl Build { } } - standard_json - .errors - .get_or_insert_with(Vec::new) - .extend(errors); + standard_json.errors.extend(errors); if let Some(solc_version) = solc_version { standard_json.version = Some(solc_version.default.to_string()); standard_json.long_version = Some(solc_version.long.to_owned()); diff --git a/era-compiler-solidity/src/build_evm/contract.rs b/era-compiler-solidity/src/build_evm/contract.rs index 57fa931c..774d96de 100644 --- a/era-compiler-solidity/src/build_evm/contract.rs +++ b/era-compiler-solidity/src/build_evm/contract.rs @@ -182,7 +182,7 @@ impl Contract { let deploy_bytecode = hex::encode(self.deploy_build.as_slice()); let runtime_bytecode = hex::encode(self.runtime_build.as_slice()); - standard_json_contract.metadata = Some(self.metadata_json); + standard_json_contract.metadata = self.metadata_json; standard_json_contract .evm .get_or_insert_with(StandardJsonOutputContractEVM::default) diff --git a/era-compiler-solidity/src/build_evm/mod.rs b/era-compiler-solidity/src/build_evm/mod.rs index 61dd8bd7..8725c9e0 100644 --- a/era-compiler-solidity/src/build_evm/mod.rs +++ b/era-compiler-solidity/src/build_evm/mod.rs @@ -116,7 +116,6 @@ impl Build { standard_json: &mut StandardJsonOutput, solc_version: Option<&SolcVersion>, ) -> anyhow::Result<()> { - let standard_json_contracts = standard_json.contracts.get_or_insert_with(BTreeMap::new); let mut errors = Vec::with_capacity(self.contracts.len()); for (full_path, build) in self.contracts.into_iter() { let mut full_path_split = full_path.split(':'); @@ -124,7 +123,8 @@ impl Build { let name = full_path_split.next().unwrap_or(path); match build { - Ok(build) => match standard_json_contracts + Ok(build) => match standard_json + .contracts .get_mut(path) .and_then(|contracts| contracts.get_mut(name)) { @@ -132,7 +132,7 @@ impl Build { build.write_to_standard_json(contract)?; } None => { - let contracts = standard_json_contracts.entry(path.to_owned()).or_default(); + let contracts = standard_json.contracts.entry(path.to_owned()).or_default(); let mut contract = StandardJsonOutputContract::default(); build.write_to_standard_json(&mut contract)?; contracts.insert(name.to_owned(), contract); @@ -142,10 +142,7 @@ impl Build { } } - standard_json - .errors - .get_or_insert_with(Vec::new) - .extend(errors); + standard_json.errors.extend(errors); if let Some(solc_version) = solc_version { standard_json.version = Some(solc_version.default.to_string()); standard_json.long_version = Some(solc_version.long.to_owned()); diff --git a/era-compiler-solidity/src/evmla/assembly/mod.rs b/era-compiler-solidity/src/evmla/assembly/mod.rs index aec88661..f066a8ce 100644 --- a/era-compiler-solidity/src/evmla/assembly/mod.rs +++ b/era-compiler-solidity/src/evmla/assembly/mod.rs @@ -37,10 +37,10 @@ pub struct Assembly { #[serde(skip_serializing_if = "Option::is_none")] pub full_path: Option, /// The factory dependency paths. - #[serde(default)] + #[serde(default, skip_serializing_if = "HashSet::is_empty")] pub factory_dependencies: HashSet, /// The EVMLA extra metadata. - #[serde(skip_serializing)] + #[serde(skip_serializing_if = "Option::is_none")] pub extra_metadata: Option, } diff --git a/era-compiler-solidity/src/evmla/ethereal_ir/function/block/element/mod.rs b/era-compiler-solidity/src/evmla/ethereal_ir/function/block/element/mod.rs index 1b4dd48d..8510f03d 100644 --- a/era-compiler-solidity/src/evmla/ethereal_ir/function/block/element/mod.rs +++ b/era-compiler-solidity/src/evmla/ethereal_ir/function/block/element/mod.rs @@ -185,11 +185,8 @@ where .value .ok_or_else(|| anyhow::anyhow!("Instruction value missing"))?; - Ok(Some( - context - .resolve_library(path.as_str())? - .as_basic_value_enum(), - )) + era_compiler_llvm_context::eravm_evm_call::linker_symbol(context, path.as_str()) + .map(Some) } InstructionName::PUSH_Data => { let value = self diff --git a/era-compiler-solidity/src/lib.rs b/era-compiler-solidity/src/lib.rs index dc60b0c5..d198181f 100644 --- a/era-compiler-solidity/src/lib.rs +++ b/era-compiler-solidity/src/lib.rs @@ -14,7 +14,6 @@ pub mod build_evm; pub mod r#const; pub mod error_type; pub mod evmla; -pub mod libraries; pub mod process; pub mod project; pub mod solc; @@ -26,7 +25,6 @@ pub use self::build_eravm::Build as EraVMBuild; pub use self::build_evm::contract::Contract as EVMContractBuild; pub use self::build_evm::Build as EVMBuild; pub use self::error_type::ErrorType; -pub use self::libraries::Libraries; pub use self::process::input_eravm::Input as EraVMProcessInput; pub use self::process::input_evm::Input as EVMProcessInput; pub use self::process::output_eravm::Output as EraVMProcessOutput; @@ -36,13 +34,15 @@ pub use self::process::EXECUTABLE; pub use self::project::contract::Contract as ProjectContract; pub use self::project::Project; pub use self::r#const::*; -pub use self::solc::codegen::Codegen as SolcCodegen; pub use self::solc::combined_json::contract::Contract as SolcCombinedJsonContract; pub use self::solc::combined_json::CombinedJson as SolcCombinedJson; pub use self::solc::standard_json::input::language::Language as SolcStandardJsonInputLanguage; +pub use self::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +pub use self::solc::standard_json::input::settings::libraries::missing::MissingLibraries; +pub use self::solc::standard_json::input::settings::libraries::Libraries as SolcStandardJsonInputSettingsLibraries; pub use self::solc::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata; pub use self::solc::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer; -pub use self::solc::standard_json::input::settings::selection::file::flag::Flag as SolcStandardJsonInputSettingsSelectionFileFlag; +pub use self::solc::standard_json::input::settings::selection::file::flag::Flag as SolcStandardJsonInputSettingsSelectionFlag; pub use self::solc::standard_json::input::settings::selection::file::File as SolcStandardJsonInputSettingsSelectionFile; pub use self::solc::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection; pub use self::solc::standard_json::input::settings::Settings as SolcStandardJsonInputSettings; @@ -75,7 +75,7 @@ pub type Result = std::result::Result; /// pub fn yul_to_eravm( paths: &[PathBuf], - libraries: Vec, + libraries: &[String], solc_path: Option, messages: &mut Vec, enable_eravm_extensions: bool, @@ -86,14 +86,15 @@ pub fn yul_to_eravm( threads: Option, debug_config: Option, ) -> anyhow::Result { - let libraries = Libraries::into_standard_json(libraries)?; + let libraries = SolcStandardJsonInputSettingsLibraries::try_from(libraries)?; + let linker_symbols = libraries.as_linker_symbols()?; let solc_version = match solc_path { Some(solc_path) => { if enable_eravm_extensions { anyhow::bail!("Yul validation cannot be done if EraVM extensions are enabled. Consider compiling without `solc`.") } - let solc_compiler = SolcCompiler::new(solc_path.as_str())?; + let solc_compiler = SolcCompiler::try_from_path(solc_path.as_str())?; solc_compiler.validate_yul_paths(paths, libraries.clone(), messages)?; Some(solc_compiler.version) } @@ -111,6 +112,7 @@ pub fn yul_to_eravm( let build = project.compile_to_eravm( messages, enable_eravm_extensions, + linker_symbols, metadata_hash_type, optimizer_settings, llvm_options, @@ -126,7 +128,7 @@ pub fn yul_to_eravm( /// pub fn yul_to_evm( paths: &[PathBuf], - libraries: Vec, + libraries: &[String], solc_path: Option, messages: &mut Vec, metadata_hash_type: era_compiler_common::HashType, @@ -135,11 +137,11 @@ pub fn yul_to_evm( threads: Option, debug_config: Option, ) -> anyhow::Result { - let libraries = Libraries::into_standard_json(libraries)?; + let libraries = SolcStandardJsonInputSettingsLibraries::try_from(libraries)?; let solc_version = match solc_path { Some(solc_path) => { - let solc_compiler = SolcCompiler::new(solc_path.as_str())?; + let solc_compiler = SolcCompiler::try_from_path(solc_path.as_str())?; solc_compiler.validate_yul_paths(paths, libraries.clone(), messages)?; Some(solc_compiler.version) } @@ -170,6 +172,7 @@ pub fn yul_to_evm( /// pub fn llvm_ir_to_eravm( paths: &[PathBuf], + libraries: &[String], messages: &mut Vec, metadata_hash_type: era_compiler_common::HashType, optimizer_settings: era_compiler_llvm_context::OptimizerSettings, @@ -178,11 +181,15 @@ pub fn llvm_ir_to_eravm( threads: Option, debug_config: Option, ) -> anyhow::Result { - let project = Project::try_from_llvm_ir_paths(paths, None)?; + let libraries = SolcStandardJsonInputSettingsLibraries::try_from(libraries)?; + let linker_symbols = libraries.as_linker_symbols()?; + + let project = Project::try_from_llvm_ir_paths(paths, libraries, None)?; let build = project.compile_to_eravm( messages, false, + linker_symbols, metadata_hash_type, optimizer_settings, llvm_options, @@ -198,6 +205,7 @@ pub fn llvm_ir_to_eravm( /// pub fn llvm_ir_to_evm( paths: &[PathBuf], + libraries: &[String], messages: &mut Vec, metadata_hash_type: era_compiler_common::HashType, optimizer_settings: era_compiler_llvm_context::OptimizerSettings, @@ -205,7 +213,9 @@ pub fn llvm_ir_to_evm( threads: Option, debug_config: Option, ) -> anyhow::Result { - let project = Project::try_from_llvm_ir_paths(paths, None)?; + let libraries = SolcStandardJsonInputSettingsLibraries::try_from(libraries)?; + + let project = Project::try_from_llvm_ir_paths(paths, libraries, None)?; let build = project.compile_to_evm( messages, @@ -236,6 +246,7 @@ pub fn eravm_assembly( let build = project.compile_to_eravm( messages, false, + BTreeMap::new(), metadata_hash_type, optimizer_settings, llvm_options, @@ -251,10 +262,10 @@ pub fn eravm_assembly( /// pub fn standard_output_eravm( paths: &[PathBuf], - libraries: Vec, + libraries: &[String], solc_compiler: &SolcCompiler, messages: &mut Vec, - codegen: Option, + codegen: Option, evm_version: Option, enable_eravm_extensions: bool, metadata_hash_type: era_compiler_common::HashType, @@ -272,7 +283,7 @@ pub fn standard_output_eravm( debug_config: Option, ) -> anyhow::Result { let solc_version = solc_compiler.version.to_owned(); - let solc_pipeline = SolcCodegen::new(&solc_version, codegen); + let solc_codegen = SolcStandardJsonInputSettingsCodegen::new(&solc_version, codegen); let mut solc_input = SolcStandardJsonInput::try_from_solidity_paths( paths, @@ -282,7 +293,7 @@ pub fn standard_output_eravm( codegen, evm_version, enable_eravm_extensions, - SolcStandardJsonInputSettingsSelection::new_required(Some(solc_pipeline)), + SolcStandardJsonInputSettingsSelection::new_required(solc_codegen), SolcStandardJsonInputSettingsMetadata::new(use_literal_content, metadata_hash_type), llvm_options.clone(), suppressed_errors, @@ -290,10 +301,10 @@ pub fn standard_output_eravm( false, false, )?; - let libraries = solc_input.settings.libraries.clone(); + let mut solc_output = solc_compiler.standard_json( &mut solc_input, - Some(solc_pipeline), + Some(solc_codegen), messages, base_path, include_paths, @@ -302,9 +313,11 @@ pub fn standard_output_eravm( solc_output.take_and_write_warnings(); solc_output.collect_errors()?; + let linker_symbols = solc_input.settings.libraries.as_linker_symbols()?; + let project = Project::try_from_solc_output( - libraries, - solc_pipeline, + solc_input.settings.libraries, + solc_codegen, &mut solc_output, solc_compiler, debug_config.as_ref(), @@ -315,6 +328,7 @@ pub fn standard_output_eravm( let build = project.compile_to_eravm( messages, enable_eravm_extensions, + linker_symbols, metadata_hash_type, optimizer_settings, llvm_options, @@ -330,10 +344,10 @@ pub fn standard_output_eravm( /// pub fn standard_output_evm( paths: &[PathBuf], - libraries: Vec, + libraries: &[String], solc_compiler: &SolcCompiler, messages: &mut Vec, - codegen: Option, + codegen: Option, evm_version: Option, metadata_hash_type: era_compiler_common::HashType, use_literal_content: bool, @@ -347,7 +361,7 @@ pub fn standard_output_evm( debug_config: Option, ) -> anyhow::Result { let solc_version = solc_compiler.version.to_owned(); - let solc_pipeline = SolcCodegen::new(&solc_version, codegen); + let solc_codegen = SolcStandardJsonInputSettingsCodegen::new(&solc_version, codegen); let mut solc_input = SolcStandardJsonInput::try_from_solidity_paths( paths, @@ -357,7 +371,7 @@ pub fn standard_output_evm( codegen, evm_version, false, - SolcStandardJsonInputSettingsSelection::new_required(Some(solc_pipeline)), + SolcStandardJsonInputSettingsSelection::new_required(solc_codegen), SolcStandardJsonInputSettingsMetadata::new(use_literal_content, metadata_hash_type), llvm_options.clone(), vec![], @@ -365,10 +379,10 @@ pub fn standard_output_evm( false, false, )?; - let libraries = solc_input.settings.libraries.clone(); + let mut solc_output = solc_compiler.standard_json( &mut solc_input, - Some(solc_pipeline), + Some(solc_codegen), messages, base_path, include_paths, @@ -378,8 +392,8 @@ pub fn standard_output_evm( solc_output.collect_errors()?; let project = Project::try_from_solc_output( - libraries, - solc_pipeline, + solc_input.settings.libraries, + solc_codegen, &mut solc_output, solc_compiler, debug_config.as_ref(), @@ -403,7 +417,7 @@ pub fn standard_output_evm( /// pub fn standard_json_eravm( solc_compiler: Option, - codegen: Option, + codegen: Option, enable_eravm_extensions: bool, detect_missing_libraries: bool, json_path: Option, @@ -416,15 +430,14 @@ pub fn standard_json_eravm( ) -> anyhow::Result<()> { let mut solc_input = SolcStandardJsonInput::try_from(json_path.as_deref())?; let language = solc_input.language; - let libraries = solc_input.settings.libraries.clone(); - let prune_output = solc_input.settings.get_unset_required(); - + let prune_output = solc_input.settings.selection_to_prune(); + let linker_symbols = solc_input.settings.libraries.as_linker_symbols()?; let optimizer_settings = era_compiler_llvm_context::OptimizerSettings::try_from(&solc_input.settings.optimizer)?; let llvm_options = solc_input.settings.llvm_options.clone(); let codegen = if solc_input.settings.force_evmla { - Some(SolcCodegen::EVMLA) + Some(SolcStandardJsonInputSettingsCodegen::EVMLA) } else { codegen }; @@ -436,23 +449,24 @@ pub fn standard_json_eravm( let output_assembly = solc_input .settings .output_selection - .as_ref() - .map(|selection| selection.contains_eravm_assembly()) - .unwrap_or_default(); + .contains(&SolcStandardJsonInputSettingsSelectionFlag::EraVMAssembly); let (mut solc_output, solc_version, project) = match (language, solc_compiler) { (SolcStandardJsonInputLanguage::Solidity, solc_compiler) => { let solc_compiler = match solc_compiler { Some(solc_compiler) => solc_compiler, - None => SolcCompiler::new(SolcCompiler::DEFAULT_EXECUTABLE_NAME)?, + None => SolcCompiler::try_from_default()?, }; - let solc_pipeline = SolcCodegen::new(&solc_compiler.version, codegen); - solc_input.normalize(Some(solc_pipeline)); + let solc_codegen = + SolcStandardJsonInputSettingsCodegen::new(&solc_compiler.version, codegen); + solc_input.extend_selection(SolcStandardJsonInputSettingsSelection::new_required( + solc_codegen, + )); let mut solc_output = solc_compiler.standard_json( &mut solc_input, - Some(solc_pipeline), + Some(solc_codegen), messages, base_path, include_paths, @@ -463,8 +477,8 @@ pub fn standard_json_eravm( } let project = Project::try_from_solc_output( - libraries, - solc_pipeline, + solc_input.settings.libraries, + solc_codegen, &mut solc_output, &solc_compiler, debug_config.as_ref(), @@ -484,7 +498,7 @@ pub fn standard_json_eravm( let project = Project::try_from_yul_sources( solc_input.sources, - libraries, + solc_input.settings.libraries, Some(&mut solc_output), Some(&solc_compiler.version), debug_config.as_ref(), @@ -500,7 +514,7 @@ pub fn standard_json_eravm( let project = Project::try_from_yul_sources( solc_input.sources, - libraries, + solc_input.settings.libraries, Some(&mut solc_output), None, debug_config.as_ref(), @@ -517,8 +531,11 @@ pub fn standard_json_eravm( (SolcStandardJsonInputLanguage::LLVMIR, None) => { let mut solc_output = SolcStandardJsonOutput::new(&solc_input.sources, messages); - let project = - Project::try_from_llvm_ir_sources(solc_input.sources, Some(&mut solc_output))?; + let project = Project::try_from_llvm_ir_sources( + solc_input.sources, + solc_input.settings.libraries, + Some(&mut solc_output), + )?; if solc_output.has_errors() { solc_output.write_and_exit(prune_output); } @@ -550,6 +567,7 @@ pub fn standard_json_eravm( let build = project.compile_to_eravm( messages, enable_eravm_extensions, + linker_symbols, metadata_hash_type, optimizer_settings, llvm_options, @@ -567,7 +585,7 @@ pub fn standard_json_eravm( /// pub fn standard_json_evm( solc_compiler: Option, - codegen: Option, + codegen: Option, json_path: Option, messages: &mut Vec, base_path: Option, @@ -578,8 +596,7 @@ pub fn standard_json_evm( ) -> anyhow::Result<()> { let mut solc_input = SolcStandardJsonInput::try_from(json_path.as_deref())?; let language = solc_input.language; - let libraries = solc_input.settings.libraries.clone(); - let prune_output = solc_input.settings.get_unset_required(); + let prune_output = solc_input.settings.selection_to_prune(); let optimizer_settings = era_compiler_llvm_context::OptimizerSettings::try_from(&solc_input.settings.optimizer)?; @@ -591,15 +608,18 @@ pub fn standard_json_evm( (SolcStandardJsonInputLanguage::Solidity, solc_compiler) => { let solc_compiler = match solc_compiler { Some(solc_compiler) => solc_compiler, - None => SolcCompiler::new(SolcCompiler::DEFAULT_EXECUTABLE_NAME)?, + None => SolcCompiler::try_from_default()?, }; - let solc_pipeline = SolcCodegen::new(&solc_compiler.version, codegen); - solc_input.normalize(Some(solc_pipeline)); + let solc_codegen = + SolcStandardJsonInputSettingsCodegen::new(&solc_compiler.version, codegen); + solc_input.extend_selection(SolcStandardJsonInputSettingsSelection::new_required( + solc_codegen, + )); let mut solc_output = solc_compiler.standard_json( &mut solc_input, - Some(solc_pipeline), + Some(solc_codegen), messages, base_path, include_paths, @@ -610,8 +630,8 @@ pub fn standard_json_evm( } let project = Project::try_from_solc_output( - libraries, - solc_pipeline, + solc_input.settings.libraries, + solc_codegen, &mut solc_output, &solc_compiler, debug_config.as_ref(), @@ -631,7 +651,7 @@ pub fn standard_json_evm( let project = Project::try_from_yul_sources( solc_input.sources, - libraries, + solc_input.settings.libraries, Some(&mut solc_output), Some(&solc_compiler.version), debug_config.as_ref(), @@ -647,7 +667,7 @@ pub fn standard_json_evm( let project = Project::try_from_yul_sources( solc_input.sources, - libraries, + solc_input.settings.libraries, Some(&mut solc_output), None, debug_config.as_ref(), @@ -664,8 +684,11 @@ pub fn standard_json_evm( (SolcStandardJsonInputLanguage::LLVMIR, None) => { let mut solc_output = SolcStandardJsonOutput::new(&solc_input.sources, messages); - let project = - Project::try_from_llvm_ir_sources(solc_input.sources, Some(&mut solc_output))?; + let project = Project::try_from_llvm_ir_sources( + solc_input.sources, + solc_input.settings.libraries, + Some(&mut solc_output), + )?; if solc_output.has_errors() { solc_output.write_and_exit(prune_output); } @@ -695,10 +718,10 @@ pub fn standard_json_evm( pub fn combined_json_eravm( format: String, paths: &[PathBuf], - libraries: Vec, + libraries: &[String], solc_compiler: &SolcCompiler, messages: &mut Vec, - codegen: Option, + codegen: Option, evm_version: Option, enable_eravm_extensions: bool, metadata_hash_type: era_compiler_common::HashType, @@ -766,10 +789,10 @@ pub fn combined_json_eravm( pub fn combined_json_evm( format: String, paths: &[PathBuf], - libraries: Vec, + libraries: &[String], solc_compiler: &SolcCompiler, messages: &mut Vec, - codegen: Option, + codegen: Option, evm_version: Option, metadata_hash_type: era_compiler_common::HashType, use_literal_content: bool, @@ -876,7 +899,7 @@ pub fn disassemble_eravm(paths: Vec) -> anyhow::Result<()> { /// /// Runs the linker for EraVM bytecode file, modifying it in place. /// -pub fn link_eravm(paths: Vec, libraries: Vec) -> anyhow::Result<()> { +pub fn link_eravm(paths: Vec, libraries: &[String]) -> anyhow::Result<()> { let bytecodes = paths .into_par_iter() .map(|path| { @@ -890,7 +913,8 @@ pub fn link_eravm(paths: Vec, libraries: Vec) -> anyhow::Result< }) .collect::>>>()?; - let linker_symbols = Libraries::into_linker(libraries)?; + let linker_symbols = + SolcStandardJsonInputSettingsLibraries::try_from(libraries)?.as_linker_symbols()?; let mut linked_objects = serde_json::Map::new(); let mut unlinked_objects = serde_json::Map::new(); let mut ignored_objects = serde_json::Map::new(); diff --git a/era-compiler-solidity/src/libraries.rs b/era-compiler-solidity/src/libraries.rs deleted file mode 100644 index 131d7fc4..00000000 --- a/era-compiler-solidity/src/libraries.rs +++ /dev/null @@ -1,119 +0,0 @@ -//! -//! The Solidity libraries. -//! - -use std::collections::BTreeMap; -use std::collections::HashSet; - -use crate::solc::standard_json::output::Output as StandardJsonOutput; -use crate::solc::version::Version as SolcVersion; - -/// -/// The Solidity libraries. -/// -pub struct Libraries { - /// The libraries. - pub contract_libraries: BTreeMap>, -} - -impl Libraries { - /// - /// A shortcut constructor. - /// - pub fn new(contract_libraries: BTreeMap>) -> Self { - Self { contract_libraries } - } - - /// - /// Writes the missing libraries to the standard JSON. - /// - pub fn write_to_standard_json( - mut self, - standard_json: &mut StandardJsonOutput, - solc_version: Option<&SolcVersion>, - ) { - let contracts = standard_json.contracts.get_or_insert_with(BTreeMap::new); - - for (path, contracts) in contracts.iter_mut() { - for (name, contract) in contracts.iter_mut() { - let full_name = format!("{path}:{name}"); - let missing_libraries = self.contract_libraries.remove(full_name.as_str()); - - if let Some(missing_libraries) = missing_libraries { - contract.missing_libraries = Some(missing_libraries); - } - } - } - - if let Some(solc_version) = solc_version { - standard_json.version = Some(solc_version.default.to_string()); - standard_json.long_version = Some(solc_version.long.to_owned()); - } - } - - /// - /// Parses the library list and returns their double hashmap with path and name as keys. - /// - pub fn into_standard_json( - libraries: Vec, - ) -> anyhow::Result>> { - let mut result = BTreeMap::new(); - for (index, library) in libraries.into_iter().enumerate() { - let mut path_and_address = library.split('='); - let path = path_and_address - .next() - .ok_or_else(|| anyhow::anyhow!("The library #{} path is missing.", index))?; - let mut file_and_contract = path.split(':'); - let file = file_and_contract - .next() - .ok_or_else(|| anyhow::anyhow!("The library `{}` file name is missing.", path))?; - let contract = file_and_contract.next().ok_or_else(|| { - anyhow::anyhow!("The library `{}` contract name is missing.", path) - })?; - let address = path_and_address - .next() - .ok_or_else(|| anyhow::anyhow!("The library `{}` address is missing.", path))?; - result - .entry(file.to_owned()) - .or_insert_with(BTreeMap::new) - .insert(contract.to_owned(), address.to_owned()); - } - Ok(result) - } - - /// - /// Parses the library list and returns a mapping of library paths to their addresses. - /// - pub fn into_linker( - libraries: Vec, - ) -> anyhow::Result> { - let mut result = BTreeMap::new(); - for (index, library) in libraries.into_iter().enumerate() { - let mut path_and_address = library.split('='); - let path = path_and_address - .next() - .ok_or_else(|| anyhow::anyhow!("Path of the library #{} is missing.", index))?; - - let address = path_and_address - .next() - .ok_or_else(|| anyhow::anyhow!("Address of the library `{}` is missing.", path))?; - let address: [u8; era_compiler_common::BYTE_LENGTH_ETH_ADDRESS] = - hex::decode(address.strip_prefix("0x").unwrap_or(address)) - .map_err(|error| { - anyhow::anyhow!("Invalid address of library `{path}`: {error}.") - }) - .and_then(|address| { - address.try_into().map_err(|address: Vec| { - anyhow::anyhow!( - "Invalid address size of library `{path}`: expected {}, found {}.", - era_compiler_common::BYTE_LENGTH_ETH_ADDRESS, - address.len(), - ) - }) - })?; - - result.insert(path.to_owned(), address); - } - Ok(result) - } -} diff --git a/era-compiler-solidity/src/process/input_eravm/dependency_data.rs b/era-compiler-solidity/src/process/input_eravm/dependency_data.rs index 263f283d..80f7feaf 100644 --- a/era-compiler-solidity/src/process/input_eravm/dependency_data.rs +++ b/era-compiler-solidity/src/process/input_eravm/dependency_data.rs @@ -16,8 +16,6 @@ pub struct DependencyData { pub solc_version: Option, /// The mapping of auxiliary identifiers, e.g. Yul object names, to full contract paths. pub identifier_paths: BTreeMap, - /// The library addresses. - pub libraries: BTreeMap>, /// The dependencies required by specific contract. pub dependencies: BTreeMap, } @@ -29,12 +27,10 @@ impl DependencyData { pub fn new( solc_version: Option, identifier_paths: BTreeMap, - libraries: BTreeMap>, ) -> Self { Self { solc_version, identifier_paths, - libraries, dependencies: BTreeMap::new(), } } @@ -67,17 +63,4 @@ impl era_compiler_llvm_context::Dependency for DependencyData { ) }) } - - fn resolve_library(&self, path: &str) -> Option { - for (file_path, contracts) in self.libraries.iter() { - for (contract_name, address) in contracts.iter() { - let key = format!("{file_path}:{contract_name}"); - if key.as_str() == path { - return Some(address["0x".len()..].to_owned()); - } - } - } - - None - } } diff --git a/era-compiler-solidity/src/process/input_eravm/mod.rs b/era-compiler-solidity/src/process/input_eravm/mod.rs index 436a245f..02ca8668 100644 --- a/era-compiler-solidity/src/process/input_eravm/mod.rs +++ b/era-compiler-solidity/src/process/input_eravm/mod.rs @@ -6,6 +6,8 @@ pub mod dependency_data; +use std::collections::BTreeMap; + use crate::project::contract::Contract; use self::dependency_data::DependencyData; @@ -21,6 +23,8 @@ pub struct Input { pub dependency_data: DependencyData, /// Whether to enable EraVM extensions. pub enable_eravm_extensions: bool, + /// The linker symbols. + pub linker_symbols: BTreeMap, /// The metadata hash type. pub metadata_hash_type: era_compiler_common::HashType, /// The optimizer settings. @@ -41,6 +45,7 @@ impl Input { contract: Option, dependency_data: DependencyData, enable_eravm_extensions: bool, + linker_symbols: BTreeMap, metadata_hash_type: era_compiler_common::HashType, optimizer_settings: era_compiler_llvm_context::OptimizerSettings, llvm_options: Vec, @@ -51,6 +56,7 @@ impl Input { contract, dependency_data, enable_eravm_extensions, + linker_symbols, metadata_hash_type, optimizer_settings, llvm_options, diff --git a/era-compiler-solidity/src/process/input_evm/dependency_data.rs b/era-compiler-solidity/src/process/input_evm/dependency_data.rs index 35b84431..6d394289 100644 --- a/era-compiler-solidity/src/process/input_evm/dependency_data.rs +++ b/era-compiler-solidity/src/process/input_evm/dependency_data.rs @@ -16,8 +16,6 @@ pub struct DependencyData { pub solc_version: Option, /// The mapping of auxiliary identifiers, e.g. Yul object names, to full contract paths. pub identifier_paths: BTreeMap, - /// The library addresses. - pub libraries: BTreeMap>, /// The dependencies required by specific contract. pub dependencies: BTreeMap, } @@ -29,12 +27,10 @@ impl DependencyData { pub fn new( solc_version: Option, identifier_paths: BTreeMap, - libraries: BTreeMap>, ) -> Self { Self { solc_version, identifier_paths, - libraries, dependencies: BTreeMap::new(), } } @@ -62,17 +58,4 @@ impl era_compiler_llvm_context::Dependency for DependencyData { ) }) } - - fn resolve_library(&self, path: &str) -> Option { - for (file_path, contracts) in self.libraries.iter() { - for (contract_name, address) in contracts.iter() { - let key = format!("{file_path}:{contract_name}"); - if key.as_str() == path { - return Some(address["0x".len()..].to_owned()); - } - } - } - - None - } } diff --git a/era-compiler-solidity/src/process/mod.rs b/era-compiler-solidity/src/process/mod.rs index 95d2b20e..e547c232 100644 --- a/era-compiler-solidity/src/process/mod.rs +++ b/era-compiler-solidity/src/process/mod.rs @@ -41,6 +41,7 @@ pub fn run(target: era_compiler_common::Target) -> anyhow::Result<()> { .compile_to_eravm( input.dependency_data, input.enable_eravm_extensions, + input.linker_symbols, input.metadata_hash_type, input.optimizer_settings, input.llvm_options, diff --git a/era-compiler-solidity/src/project/contract/ir/yul.rs b/era-compiler-solidity/src/project/contract/ir/yul.rs index 5b5282fd..1758ace0 100644 --- a/era-compiler-solidity/src/project/contract/ir/yul.rs +++ b/era-compiler-solidity/src/project/contract/ir/yul.rs @@ -25,12 +25,11 @@ impl Yul { /// pub fn try_from_source( name: &era_compiler_common::ContractName, - source_code: Option<&str>, + source_code: &str, debug_config: Option<&era_compiler_llvm_context::DebugConfig>, ) -> anyhow::Result> { - let source_code = match source_code { - None | Some("") => return Ok(None), - Some(ir_optimized) => ir_optimized, + if source_code.is_empty() { + return Ok(None); }; if let Some(debug_config) = debug_config { diff --git a/era-compiler-solidity/src/project/contract/mod.rs b/era-compiler-solidity/src/project/contract/mod.rs index 5f8e4b20..bdaa2fd7 100644 --- a/era-compiler-solidity/src/project/contract/mod.rs +++ b/era-compiler-solidity/src/project/contract/mod.rs @@ -6,6 +6,7 @@ pub mod factory_dependency; pub mod ir; pub mod metadata; +use std::collections::BTreeMap; use std::collections::HashSet; use era_compiler_llvm_context::IContext; @@ -72,6 +73,7 @@ impl Contract { mut self, dependency_data: EraVMProcessInputDependencyData, enable_eravm_extensions: bool, + linker_symbols: BTreeMap, metadata_hash_type: era_compiler_common::HashType, optimizer_settings: era_compiler_llvm_context::OptimizerSettings, llvm_options: Vec, @@ -136,6 +138,7 @@ impl Contract { context.build( self.name.full_path.as_str(), + &linker_symbols, metadata_hash, output_assembly, false, @@ -145,7 +148,7 @@ impl Contract { let solc_version = dependency_data .solc_version .clone() - .expect("The EVM assembly pipeline cannot be executed without `solc`"); + .expect("The EVM assembly codegen cannot be executed without `solc`"); let module = llvm.create_module(self.name.full_path.as_str()); let mut context = era_compiler_llvm_context::EraVMContext::new( @@ -170,6 +173,7 @@ impl Contract { context.build( self.name.full_path.as_str(), + &linker_symbols, metadata_hash, output_assembly, false, @@ -194,6 +198,7 @@ impl Contract { ); context.build( self.name.full_path.as_str(), + &linker_symbols, metadata_hash, output_assembly, false, @@ -218,6 +223,7 @@ impl Contract { }; era_compiler_llvm_context::eravm_build( bytecode_buffer, + &linker_symbols, metadata_hash, assembly_text, )? diff --git a/era-compiler-solidity/src/project/mod.rs b/era-compiler-solidity/src/project/mod.rs index 6b29a4da..fd9b0c79 100644 --- a/era-compiler-solidity/src/project/mod.rs +++ b/era-compiler-solidity/src/project/mod.rs @@ -17,13 +17,14 @@ use rayon::iter::ParallelIterator; use crate::build_eravm::Build as EraVMBuild; use crate::build_evm::Build as EVMBuild; -use crate::libraries::Libraries; use crate::process::input_eravm::dependency_data::DependencyData as EraVMProcessInputDependencyData; use crate::process::input_eravm::Input as EraVMProcessInput; use crate::process::input_evm::dependency_data::DependencyData as EVMProcessInputDependencyData; use crate::process::input_evm::Input as EVMProcessInput; -use crate::solc::codegen::Codegen as SolcCodegen; use crate::solc::standard_json::input::language::Language as SolcStandardJsonInputLanguage; +use crate::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +use crate::solc::standard_json::input::settings::libraries::missing::MissingLibraries; +use crate::solc::standard_json::input::settings::libraries::Libraries as SolcStandardJsonInputLibraries; use crate::solc::standard_json::input::source::Source as SolcStandardJsonInputSource; use crate::solc::standard_json::output::contract::Contract as SolcStandardJsonOutputContract; use crate::solc::standard_json::output::error::Error as SolcStandardJsonOutputError; @@ -53,7 +54,7 @@ pub struct Project { /// The mapping of auxiliary identifiers, e.g. Yul object names, to full contract paths. pub identifier_paths: BTreeMap, /// The library addresses. - pub libraries: BTreeMap>, + pub libraries: SolcStandardJsonInputLibraries, } impl Project { @@ -64,7 +65,7 @@ impl Project { language: SolcStandardJsonInputLanguage, solc_version: Option, contracts: BTreeMap, - libraries: BTreeMap>, + libraries: SolcStandardJsonInputLibraries, ) -> Self { let mut identifier_paths = BTreeMap::new(); for (path, contract) in contracts.iter() { @@ -84,25 +85,21 @@ impl Project { /// Parses the Solidity `sources` and returns a Solidity project. /// pub fn try_from_solc_output( - libraries: BTreeMap>, - pipeline: SolcCodegen, + libraries: SolcStandardJsonInputLibraries, + codegen: SolcStandardJsonInputSettingsCodegen, solc_output: &mut SolcStandardJsonOutput, solc_compiler: &SolcCompiler, debug_config: Option<&era_compiler_llvm_context::DebugConfig>, ) -> anyhow::Result { - if let SolcCodegen::EVMLA = pipeline { + if let SolcStandardJsonInputSettingsCodegen::EVMLA = codegen { solc_output.preprocess_dependencies()?; } let solc_version = solc_compiler.version.to_owned(); - let files = solc_output - .contracts - .as_ref() - .ok_or_else(|| anyhow::anyhow!("No input sources specified."))?; - let mut input_contracts = Vec::with_capacity(files.len()); - for (path, contracts) in files.iter() { - for (name, contract) in contracts.iter() { + let mut input_contracts = Vec::with_capacity(solc_output.contracts.len()); + for (path, file) in solc_output.contracts.iter() { + for (name, contract) in file.iter() { input_contracts.push((path, name, contract)); } } @@ -123,25 +120,23 @@ impl Project { ); let full_path = name.full_path.clone(); - let result = match pipeline { - SolcCodegen::Yul => ContractYul::try_from_source( - &name, - contract.ir_optimized.as_deref(), - debug_config, - ) - .map(|ir| ir.map(ContractYul::into)), - SolcCodegen::EVMLA => { + let result = match codegen { + SolcStandardJsonInputSettingsCodegen::Yul => { + ContractYul::try_from_source( + &name, + contract.ir_optimized.as_str(), + debug_config, + ) + .map(|ir| ir.map(ContractYul::into)) + } + SolcStandardJsonInputSettingsCodegen::EVMLA => { Ok(ContractEVMLA::try_from_contract(contract) .map(ContractEVMLA::into)) } } .map(|source| { source.map(|source| { - Contract::new( - name, - source, - contract.metadata.to_owned().expect("Always exists"), - ) + Contract::new(name, source, contract.metadata.to_owned()) }) }); (full_path, result) @@ -172,7 +167,7 @@ impl Project { /// pub fn try_from_yul_paths( paths: &[PathBuf], - libraries: BTreeMap>, + libraries: SolcStandardJsonInputLibraries, solc_output: Option<&mut SolcStandardJsonOutput>, solc_version: Option<&SolcVersion>, debug_config: Option<&era_compiler_llvm_context::DebugConfig>, @@ -192,7 +187,7 @@ impl Project { /// pub fn try_from_yul_sources( sources: BTreeMap, - libraries: BTreeMap>, + libraries: SolcStandardJsonInputLibraries, mut solc_output: Option<&mut SolcStandardJsonOutput>, solc_version: Option<&SolcVersion>, debug_config: Option<&era_compiler_llvm_context::DebugConfig>, @@ -208,8 +203,8 @@ impl Project { let source_hash = era_compiler_common::Hash::keccak256(source_code.as_bytes()); let result = - ContractYul::try_from_source(&name, Some(source_code.as_str()), debug_config) - .map(|ir| { + ContractYul::try_from_source(&name, source_code.as_str(), debug_config).map( + |ir| { ir.map(ContractYul::into).map(|ir| { Contract::new( name, @@ -220,7 +215,8 @@ impl Project { }), ) }) - }); + }, + ); (path, result) }) @@ -252,6 +248,7 @@ impl Project { /// pub fn try_from_llvm_ir_paths( paths: &[PathBuf], + libraries: SolcStandardJsonInputLibraries, solc_output: Option<&mut SolcStandardJsonOutput>, ) -> anyhow::Result { let sources = paths @@ -261,7 +258,7 @@ impl Project { (path.to_string_lossy().to_string(), source) }) .collect::>(); - Self::try_from_llvm_ir_sources(sources, solc_output) + Self::try_from_llvm_ir_sources(sources, libraries, solc_output) } /// @@ -269,6 +266,7 @@ impl Project { /// pub fn try_from_llvm_ir_sources( sources: BTreeMap, + libraries: SolcStandardJsonInputLibraries, mut solc_output: Option<&mut SolcStandardJsonOutput>, ) -> anyhow::Result { let results = sources @@ -309,7 +307,7 @@ impl Project { SolcStandardJsonInputLanguage::LLVMIR, None, contracts, - BTreeMap::new(), + libraries, )) } @@ -375,7 +373,7 @@ impl Project { SolcStandardJsonInputLanguage::EraVMAssembly, None, contracts, - BTreeMap::new(), + SolcStandardJsonInputLibraries::default(), )) } @@ -386,6 +384,7 @@ impl Project { self, messages: &mut Vec, enable_eravm_extensions: bool, + linker_symbols: BTreeMap, metadata_hash_type: era_compiler_common::HashType, optimizer_settings: era_compiler_llvm_context::OptimizerSettings, llvm_options: Vec, @@ -394,16 +393,14 @@ impl Project { debug_config: Option, ) -> anyhow::Result { let identifier_paths = self.identifier_paths.clone(); - let dependency_data = EraVMProcessInputDependencyData::new( - self.solc_version, - self.identifier_paths.clone(), - self.libraries.clone(), - ); + let dependency_data = + EraVMProcessInputDependencyData::new(self.solc_version, self.identifier_paths.clone()); let input_template = EraVMProcessInput::new( None, dependency_data, enable_eravm_extensions, + linker_symbols, metadata_hash_type, optimizer_settings, llvm_options, @@ -462,11 +459,8 @@ impl Project { threads: Option, debug_config: Option, ) -> anyhow::Result { - let dependency_data = EVMProcessInputDependencyData::new( - self.solc_version, - self.identifier_paths, - self.libraries, - ); + let dependency_data = + EVMProcessInputDependencyData::new(self.solc_version, self.identifier_paths); let input_template = EVMProcessInput::new( None, @@ -485,9 +479,10 @@ impl Project { /// /// Get the list of missing deployable libraries. /// - pub fn get_missing_libraries(&self) -> Libraries { + pub fn get_missing_libraries(&self) -> MissingLibraries { let deployed_libraries = self .libraries + .as_inner() .iter() .flat_map(|(file, names)| { names @@ -506,6 +501,6 @@ impl Project { .collect::>(); missing_deployable_libraries.insert(contract_path.to_owned(), missing_libraries); } - Libraries::new(missing_deployable_libraries) + MissingLibraries::new(missing_deployable_libraries) } } diff --git a/era-compiler-solidity/src/solc/combined_json/contract.rs b/era-compiler-solidity/src/solc/combined_json/contract.rs index 797f0cc8..dae33b6d 100644 --- a/era-compiler-solidity/src/solc/combined_json/contract.rs +++ b/era-compiler-solidity/src/solc/combined_json/contract.rs @@ -12,43 +12,43 @@ use std::collections::HashSet; #[serde(rename_all = "kebab-case")] pub struct Contract { /// The `solc` hashes output. - #[serde(skip_serializing_if = "Option::is_none")] - pub hashes: Option>, + #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] + pub hashes: BTreeMap, /// The `solc` ABI output. - #[serde(skip_serializing_if = "Option::is_none")] - pub abi: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub abi: serde_json::Value, /// The `solc` metadata output. - #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default, skip_serializing_if = "Option::is_none")] pub metadata: Option, /// The `solc` developer documentation output. - #[serde(skip_serializing_if = "Option::is_none")] - pub devdoc: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub devdoc: serde_json::Value, /// The `solc` user documentation output. - #[serde(skip_serializing_if = "Option::is_none")] - pub userdoc: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub userdoc: serde_json::Value, /// The `solc` storage layout output. - #[serde(skip_serializing_if = "Option::is_none")] - pub storage_layout: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub storage_layout: serde_json::Value, /// The `solc` AST output. - #[serde(skip_serializing_if = "Option::is_none")] - pub ast: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub ast: serde_json::Value, /// The `solc` assembly output. - #[serde(skip_serializing_if = "Option::is_none")] - pub asm: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub asm: serde_json::Value, /// The `solc` hexadecimal binary output. - #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default, skip_serializing_if = "Option::is_none")] pub bin: Option, /// The `solc` hexadecimal binary runtime part output. - #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default, skip_serializing_if = "Option::is_none")] pub bin_runtime: Option, /// The EraVM assembly. - #[serde(skip_serializing_if = "Option::is_none")] - pub assembly: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub assembly: serde_json::Value, /// The factory dependencies. - #[serde(skip_serializing_if = "Option::is_none")] - pub factory_deps: Option>, + #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] + pub factory_deps: BTreeMap, /// The missing libraries. - #[serde(skip_serializing_if = "Option::is_none")] - pub missing_libraries: Option>, + #[serde(default, skip_serializing_if = "HashSet::is_empty")] + pub missing_libraries: HashSet, } diff --git a/era-compiler-solidity/src/solc/combined_json/mod.rs b/era-compiler-solidity/src/solc/combined_json/mod.rs index 4a3828a9..2d8cc33f 100644 --- a/era-compiler-solidity/src/solc/combined_json/mod.rs +++ b/era-compiler-solidity/src/solc/combined_json/mod.rs @@ -15,14 +15,14 @@ use self::contract::Contract; #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct CombinedJson { /// The contract entries. + #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] pub contracts: BTreeMap, /// The list of source files. - #[serde(rename = "sourceList")] - #[serde(skip_serializing_if = "Option::is_none")] - pub source_list: Option>, + #[serde(default, rename = "sourceList", skip_serializing_if = "Vec::is_empty")] + pub source_list: Vec, /// The source code extra data, including the AST. - #[serde(skip_serializing_if = "Option::is_none")] - pub sources: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub sources: serde_json::Value, /// The `solc` compiler version. pub version: String, /// The `zksolc` compiler version. diff --git a/era-compiler-solidity/src/solc/mod.rs b/era-compiler-solidity/src/solc/mod.rs index e85abbbd..8740d661 100644 --- a/era-compiler-solidity/src/solc/mod.rs +++ b/era-compiler-solidity/src/solc/mod.rs @@ -2,21 +2,21 @@ //! The Solidity compiler. //! -pub mod codegen; pub mod combined_json; pub mod standard_json; pub mod version; -use std::collections::BTreeMap; use std::collections::HashMap; use std::io::Write; use std::path::PathBuf; use std::sync::OnceLock; use std::sync::RwLock; -use self::codegen::Codegen; use self::combined_json::CombinedJson; +use self::standard_json::input::settings::codegen::Codegen as StandardJsonInputSettingsCodegen; +use self::standard_json::input::settings::libraries::Libraries as StandardJsonInputSettingsLibraries; use self::standard_json::input::settings::optimizer::Optimizer as StandardJsonInputSettingsOptimizer; +use self::standard_json::input::settings::selection::Selection as StandardJsonInputSettingsSelection; use self::standard_json::input::Input as StandardJsonInput; use self::standard_json::output::error::Error as StandardJsonOutputError; use self::standard_json::output::Output as StandardJsonOutput; @@ -58,7 +58,7 @@ impl Compiler { /// Different tools may use different `executable` names. For example, the integration tester /// uses `solc-` format. /// - pub fn new(executable: &str) -> anyhow::Result { + pub fn try_from_path(executable: &str) -> anyhow::Result { if let Some(executable) = Self::executables() .read() .expect("Sync") @@ -70,7 +70,7 @@ impl Compiler { let mut executables = Self::executables().write().expect("Sync"); if let Err(error) = which::which(executable) { - anyhow::bail!("The `{executable}` executable not found in ${{PATH}}: {error}. Please add it to ${{PATH}} or provide it explicitly with the `--solc` option."); + anyhow::bail!("The `{executable}` executable not found: {error}. Please add it to ${{PATH}} or provide it explicitly with the `--solc` option."); } let version = Self::parse_version(executable)?; let compiler = Self { @@ -82,13 +82,20 @@ impl Compiler { Ok(compiler) } + /// + /// Initializes the Solidity compiler with the default executable name. + /// + pub fn try_from_default() -> anyhow::Result { + Self::try_from_path(Self::DEFAULT_EXECUTABLE_NAME) + } + /// /// The Solidity `--standard-json` mirror. /// pub fn standard_json( &self, input: &mut StandardJsonInput, - pipeline: Option, + codegen: Option, messages: &mut Vec, base_path: Option, include_paths: Vec, @@ -157,29 +164,30 @@ impl Compiler { } }; - let errors = solc_output.errors.get_or_insert_with(Vec::new); - errors.retain(|error| match error.error_code.as_deref() { - Some(code) => !StandardJsonOutputError::IGNORED_WARNING_CODES.contains(&code), - None => true, - }); - errors.append(messages); + solc_output + .errors + .retain(|error| match error.error_code.as_deref() { + Some(code) => !StandardJsonOutputError::IGNORED_WARNING_CODES.contains(&code), + None => true, + }); + solc_output.errors.append(messages); if !input.suppressed_errors.is_empty() { - errors.push(StandardJsonOutputError::new_warning( + solc_output.errors.push(StandardJsonOutputError::new_warning( "`suppressedErrors` at the root of standard JSON input are deprecated. Please move them to `settings`.", None, None, )); } if !input.suppressed_warnings.is_empty() { - errors.push(StandardJsonOutputError::new_warning( + solc_output.errors.push(StandardJsonOutputError::new_warning( "`suppressedWarnings` at the root of standard JSON input are deprecated. Please move them to `settings`.", None, None, )); } - if let Some(pipeline) = pipeline { + if let Some(codegen) = codegen { let mut suppressed_errors = input.suppressed_errors.clone(); suppressed_errors.extend_from_slice(input.settings.suppressed_errors.as_slice()); @@ -190,7 +198,7 @@ impl Compiler { solc_output.preprocess_ast( &input.sources, &self.version, - pipeline, + codegen, suppressed_errors.as_slice(), suppressed_warnings.as_slice(), )?; @@ -265,16 +273,16 @@ impl Compiler { for filtered_flag in filtered_flags.into_iter() { for (_path, contract) in combined_json.contracts.iter_mut() { match filtered_flag { - "asm" => contract.asm = Some(serde_json::Value::Null), - "bin" => contract.bin = Some("".to_owned()), - "bin-runtime" => contract.bin_runtime = Some("".to_owned()), + "asm" => contract.asm = serde_json::Value::Null, + "bin" => contract.bin = None, + "bin-runtime" => contract.bin_runtime = None, _ => continue, } } } if combined_json_fake_flag_pushed { - combined_json.source_list = None; - combined_json.sources = None; + combined_json.source_list.clear(); + combined_json.sources = serde_json::Value::Null; } combined_json.remove_evm(); @@ -287,19 +295,12 @@ impl Compiler { pub fn validate_yul_paths( &self, paths: &[PathBuf], - libraries: BTreeMap>, + libraries: StandardJsonInputSettingsLibraries, messages: &mut Vec, ) -> anyhow::Result { - if self.version.default != Self::LAST_SUPPORTED_VERSION { - anyhow::bail!( - "Yul validation is only supported with the latest supported version of the Solidity compiler: {}", - Self::LAST_SUPPORTED_VERSION, - ); - } - let mut solc_input = StandardJsonInput::from_yul_paths( paths, - libraries.clone(), + libraries, StandardJsonInputSettingsOptimizer::default(), vec![], ); @@ -321,7 +322,7 @@ impl Compiler { ); } - solc_input.normalize_yul_validation(); + solc_input.extend_selection(StandardJsonInputSettingsSelection::new_yul_validation()); let solc_output = self.standard_json(solc_input, None, messages, None, vec![], None)?; Ok(solc_output) } @@ -342,11 +343,10 @@ impl Compiler { command.arg("--version"); let output = command .output() - .map_err(|error| anyhow::anyhow!("{} subprocess: {:?}", executable, error))?; + .map_err(|error| anyhow::anyhow!("`{executable}` subprocess: {error:?}."))?; if !output.status.success() { anyhow::bail!( - "{} version getting: {}", - executable, + "`{executable}` version getting: {}", String::from_utf8_lossy(output.stderr.as_slice()).to_string() ); } @@ -355,22 +355,19 @@ impl Compiler { let long = stdout .lines() .nth(1) - .ok_or_else(|| anyhow::anyhow!("{} version parsing: not enough lines", executable))? + .ok_or_else(|| anyhow::anyhow!("`{executable}` version parsing: not enough lines."))? .split(' ') .nth(1) .ok_or_else(|| { - anyhow::anyhow!( - "{} version parsing: not enough words in the 2nd line", - executable - ) + anyhow::anyhow!("`{executable}` version parsing: not enough words in the 2nd line.") })? .to_owned(); let default: semver::Version = long .split('+') .next() - .ok_or_else(|| anyhow::anyhow!("{} version parsing: metadata dropping", executable))? + .expect("Always exists") .parse() - .map_err(|error| anyhow::anyhow!("{} version parsing: {}", executable, error))?; + .map_err(|error| anyhow::anyhow!("`{executable}` version parsing: {error}."))?; let l2_revision: Option = stdout .lines() @@ -382,14 +379,14 @@ impl Compiler { let version = Version::new(long, default, l2_revision); if version.default < Self::FIRST_SUPPORTED_VERSION { anyhow::bail!( - "`solc` versions <{} are not supported, found {}", + "`{executable}` versions older than {} are not supported, found {}. Please upgrade to the latest supported version.", Self::FIRST_SUPPORTED_VERSION, version.default ); } if version.default > Self::LAST_SUPPORTED_VERSION { anyhow::bail!( - "`solc` versions >{} are not supported, found {}", + "`{executable}` versions newer than {} are not supported, found {}. Please check if you are using the latest version of zksolc.", Self::LAST_SUPPORTED_VERSION, version.default ); diff --git a/era-compiler-solidity/src/solc/standard_json/input/mod.rs b/era-compiler-solidity/src/solc/standard_json/input/mod.rs index 91ee4ff7..2bad3396 100644 --- a/era-compiler-solidity/src/solc/standard_json/input/mod.rs +++ b/era-compiler-solidity/src/solc/standard_json/input/mod.rs @@ -16,8 +16,8 @@ use rayon::iter::IntoParallelRefMutIterator; use rayon::iter::ParallelIterator; use crate::error_type::ErrorType; -use crate::libraries::Libraries; -use crate::solc::codegen::Codegen as SolcCodegen; +use crate::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +use crate::solc::standard_json::input::settings::libraries::Libraries as SolcStandardJsonInputSettingsLibraries; use crate::solc::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata; use crate::solc::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer; use crate::solc::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection; @@ -76,10 +76,10 @@ impl Input { /// pub fn try_from_solidity_paths( paths: &[PathBuf], - libraries: Vec, + libraries: &[String], remappings: BTreeSet, optimizer: SolcStandardJsonInputSettingsOptimizer, - codegen: Option, + codegen: Option, evm_version: Option, enable_eravm_extensions: bool, output_selection: SolcStandardJsonInputSettingsSelection, @@ -91,8 +91,8 @@ impl Input { via_ir: bool, ) -> anyhow::Result { let mut paths: BTreeSet = paths.iter().cloned().collect(); - let libraries = Libraries::into_standard_json(libraries)?; - for library_file in libraries.keys() { + let libraries = SolcStandardJsonInputSettingsLibraries::try_from(libraries)?; + for library_file in libraries.as_inner().keys() { paths.insert(PathBuf::from(library_file)); } @@ -127,10 +127,10 @@ impl Input { /// pub fn try_from_solidity_sources( sources: BTreeMap, - libraries: BTreeMap>, + libraries: SolcStandardJsonInputSettingsLibraries, remappings: BTreeSet, optimizer: SolcStandardJsonInputSettingsOptimizer, - codegen: Option, + codegen: Option, evm_version: Option, enable_eravm_extensions: bool, output_selection: SolcStandardJsonInputSettingsSelection, @@ -169,7 +169,7 @@ impl Input { /// pub fn from_yul_sources( sources: BTreeMap, - libraries: BTreeMap>, + libraries: SolcStandardJsonInputSettingsLibraries, optimizer: SolcStandardJsonInputSettingsOptimizer, llvm_options: Vec, ) -> Self { @@ -203,7 +203,7 @@ impl Input { /// pub fn from_yul_paths( paths: &[PathBuf], - libraries: BTreeMap>, + libraries: SolcStandardJsonInputSettingsLibraries, optimizer: SolcStandardJsonInputSettingsOptimizer, llvm_options: Vec, ) -> Self { @@ -220,17 +220,10 @@ impl Input { } /// - /// Sets the necessary defaults for EraVM compilation. + /// Extends the output selection with another one. /// - pub fn normalize(&mut self, pipeline: Option) { - self.settings.normalize(pipeline); - } - - /// - /// Sets the necessary defaults for Yul validation. - /// - pub fn normalize_yul_validation(&mut self) { - self.settings.normalize_yul_validation(); + pub fn extend_selection(&mut self, selection: SolcStandardJsonInputSettingsSelection) { + self.settings.extend_selection(selection); } /// diff --git a/era-compiler-solidity/src/solc/codegen.rs b/era-compiler-solidity/src/solc/standard_json/input/settings/codegen.rs similarity index 90% rename from era-compiler-solidity/src/solc/codegen.rs rename to era-compiler-solidity/src/solc/standard_json/input/settings/codegen.rs index b614e29f..09fa75b0 100644 --- a/era-compiler-solidity/src/solc/codegen.rs +++ b/era-compiler-solidity/src/solc/standard_json/input/settings/codegen.rs @@ -10,7 +10,7 @@ use crate::solc::Compiler as SolcCompiler; /// /// The Solidity compiler codegen. /// -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Deserialize)] #[serde(rename_all = "lowercase")] pub enum Codegen { /// The Yul IR. @@ -40,7 +40,7 @@ impl FromStr for Codegen { "yul" => Ok(Self::Yul), "evmla" => Ok(Self::EVMLA), string => anyhow::bail!( - "Invalid codegen: {string}. Available options: {}", + "Invalid codegen: `{string}`. Available options: {}.", [Self::EVMLA, Self::Yul] .into_iter() .map(|codegen| codegen.to_string()) diff --git a/era-compiler-solidity/src/solc/standard_json/input/settings/libraries/missing.rs b/era-compiler-solidity/src/solc/standard_json/input/settings/libraries/missing.rs new file mode 100644 index 00000000..b315c2bb --- /dev/null +++ b/era-compiler-solidity/src/solc/standard_json/input/settings/libraries/missing.rs @@ -0,0 +1,51 @@ +//! +//! The missing libraries. +//! + +use std::collections::BTreeMap; +use std::collections::HashSet; + +use crate::solc::standard_json::output::Output as StandardJsonOutput; +use crate::solc::version::Version as SolcVersion; + +/// +/// The missing libraries. +/// +pub struct MissingLibraries { + /// The libraries. + pub contract_libraries: BTreeMap>, +} + +impl MissingLibraries { + /// + /// A shortcut constructor. + /// + pub fn new(contract_libraries: BTreeMap>) -> Self { + Self { contract_libraries } + } + + /// + /// Writes the missing libraries to the standard JSON. + /// + pub fn write_to_standard_json( + mut self, + standard_json: &mut StandardJsonOutput, + solc_version: Option<&SolcVersion>, + ) { + for (path, file) in standard_json.contracts.iter_mut() { + for (name, contract) in file.iter_mut() { + let full_name = format!("{path}:{name}"); + let missing_libraries = self.contract_libraries.remove(full_name.as_str()); + + if let Some(missing_libraries) = missing_libraries { + contract.missing_libraries = Some(missing_libraries); + } + } + } + + if let Some(solc_version) = solc_version { + standard_json.version = Some(solc_version.default.to_string()); + standard_json.long_version = Some(solc_version.long.to_owned()); + } + } +} diff --git a/era-compiler-solidity/src/solc/standard_json/input/settings/libraries/mod.rs b/era-compiler-solidity/src/solc/standard_json/input/settings/libraries/mod.rs new file mode 100644 index 00000000..8d957014 --- /dev/null +++ b/era-compiler-solidity/src/solc/standard_json/input/settings/libraries/mod.rs @@ -0,0 +1,97 @@ +//! +//! The Solidity libraries. +//! + +pub mod missing; + +use std::collections::BTreeMap; + +/// +/// The Solidity libraries. +/// +#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)] +pub struct Libraries { + /// The unified representation of libraries. + #[serde(flatten)] + pub inner: BTreeMap>, +} + +impl Libraries { + /// + /// Returns a representation of libraries suitable for the LLVM linker. + /// + pub fn as_linker_symbols( + &self, + ) -> anyhow::Result> { + let mut linker_symbols = BTreeMap::new(); + for (file, contracts) in self.inner.iter() { + for (name, address) in contracts.iter() { + let path = format!("{file}:{name}"); + + let address_stripped = address.strip_prefix("0x").unwrap_or(address.as_str()); + let address_vec = hex::decode(address_stripped).map_err(|error| { + anyhow::anyhow!("Invalid address `{address}` of library `{path}`: {error}.") + })?; + let address_array: [u8; era_compiler_common::BYTE_LENGTH_ETH_ADDRESS] = address_vec.try_into().map_err(|address_vec: Vec| { + anyhow::anyhow!( + "Incorrect size of address `{address}` of library `{path}`: expected {}, found {}.", + era_compiler_common::BYTE_LENGTH_ETH_ADDRESS, + address_vec.len(), + ) + })?; + + linker_symbols.insert(path, address_array); + } + } + Ok(linker_symbols) + } + + /// + /// Checks whether the libraries are empty. + /// + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + + /// + /// Returns the reference to the inner value. + /// + pub fn as_inner(&self) -> &BTreeMap> { + &self.inner + } +} + +impl From>> for Libraries { + fn from(inner: BTreeMap>) -> Self { + Self { inner } + } +} + +impl TryFrom<&[String]> for Libraries { + type Error = anyhow::Error; + + fn try_from(arguments: &[String]) -> Result { + let mut libraries = BTreeMap::new(); + for (index, library) in arguments.iter().enumerate() { + let mut path_and_address = library.split('='); + let path = path_and_address + .next() + .ok_or_else(|| anyhow::anyhow!("Library #{} path is missing.", index))?; + let mut file_and_contract = path.split(':'); + let file = file_and_contract + .next() + .ok_or_else(|| anyhow::anyhow!("Library `{}` file name is missing.", path))?; + let contract = file_and_contract + .next() + .ok_or_else(|| anyhow::anyhow!("Library `{}` contract name is missing.", path))?; + let address = path_and_address + .next() + .ok_or_else(|| anyhow::anyhow!("Library `{}` address is missing.", path))?; + libraries + .entry(file.to_owned()) + .or_insert_with(BTreeMap::new) + .insert(contract.to_owned(), address.to_owned()); + } + Ok(Self { inner: libraries }) + } +} diff --git a/era-compiler-solidity/src/solc/standard_json/input/settings/mod.rs b/era-compiler-solidity/src/solc/standard_json/input/settings/mod.rs index 2a1ec6b7..5534fc2c 100644 --- a/era-compiler-solidity/src/solc/standard_json/input/settings/mod.rs +++ b/era-compiler-solidity/src/solc/standard_json/input/settings/mod.rs @@ -2,21 +2,21 @@ //! The `solc --standard-json` input settings. //! +pub mod codegen; +pub mod libraries; pub mod metadata; pub mod optimizer; pub mod selection; -use std::collections::BTreeMap; use std::collections::BTreeSet; -use std::collections::HashSet; use crate::error_type::ErrorType; -use crate::solc::codegen::Codegen as SolcCodegen; use crate::warning_type::WarningType; +use self::codegen::Codegen; +use self::libraries::Libraries; use self::metadata::Metadata; use self::optimizer::Optimizer; -use self::selection::file::flag::Flag as SelectionFlag; use self::selection::Selection; /// @@ -30,8 +30,8 @@ pub struct Settings { pub optimizer: Optimizer, /// The linker library addresses. - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub libraries: BTreeMap>, + #[serde(default, skip_serializing_if = "Libraries::is_empty")] + pub libraries: Libraries, /// The sorted list of remappings. #[serde(default, skip_serializing_if = "BTreeSet::is_empty")] pub remappings: BTreeSet, @@ -40,15 +40,15 @@ pub struct Settings { #[serde(skip_serializing_if = "Option::is_none")] pub evm_version: Option, /// The output selection filters. - #[serde(skip_serializing_if = "Option::is_none")] - pub output_selection: Option, + #[serde(default)] + pub output_selection: Selection, /// The metadata settings. #[serde(default)] pub metadata: Metadata, /// The Solidity codegen. #[serde(skip_serializing)] - pub codegen: Option, + pub codegen: Option, /// Whether to compile via EVM assembly. #[serde(default, rename = "forceEVMLA", skip_serializing)] pub force_evmla: bool, @@ -87,10 +87,10 @@ impl Settings { pub fn new( optimizer: Optimizer, - libraries: BTreeMap>, + libraries: Libraries, remappings: BTreeSet, - codegen: Option, + codegen: Option, evm_version: Option, enable_eravm_extensions: bool, @@ -111,10 +111,10 @@ impl Settings { codegen, evm_version, - force_evmla: codegen == Some(SolcCodegen::EVMLA), + force_evmla: codegen == Some(Codegen::EVMLA), enable_eravm_extensions, - output_selection: Some(output_selection), + output_selection, metadata, llvm_options, suppressed_errors, @@ -126,21 +126,10 @@ impl Settings { } /// - /// Sets the necessary defaults for EraVM compilation. - /// - pub fn normalize(&mut self, pipeline: Option) { - self.output_selection - .get_or_insert_with(Selection::default) - .extend_with_required(pipeline); - } - - /// - /// Sets the necessary defaults for Yul validation. + /// Extends the output selection with another one. /// - pub fn normalize_yul_validation(&mut self) { - self.output_selection - .get_or_insert_with(Selection::new_yul_validation) - .extend_with_yul_validation(); + pub fn extend_selection(&mut self, selection: Selection) { + self.output_selection.extend(selection); } /// @@ -149,10 +138,7 @@ impl Settings { /// /// Afterwards, the flags are used to prune JSON output before returning it. /// - pub fn get_unset_required(&self) -> HashSet { - self.output_selection - .as_ref() - .map(|selection| selection.get_unset_required()) - .unwrap_or_else(|| Selection::default().get_unset_required()) + pub fn selection_to_prune(&self) -> Selection { + self.output_selection.selection_to_prune() } } diff --git a/era-compiler-solidity/src/solc/standard_json/input/settings/optimizer.rs b/era-compiler-solidity/src/solc/standard_json/input/settings/optimizer.rs index 7bac63fb..80076add 100644 --- a/era-compiler-solidity/src/solc/standard_json/input/settings/optimizer.rs +++ b/era-compiler-solidity/src/solc/standard_json/input/settings/optimizer.rs @@ -23,12 +23,7 @@ pub struct Optimizer { impl Default for Optimizer { fn default() -> Self { - Self { - mode: Self::default_mode(), - fallback_to_optimizing_for_size: false, - - enabled: Self::default_enabled(), - } + Self::new(Self::default_mode(), false) } } diff --git a/era-compiler-solidity/src/solc/standard_json/input/settings/selection/file/flag.rs b/era-compiler-solidity/src/solc/standard_json/input/settings/selection/file/flag.rs index c37f1422..17050ac3 100644 --- a/era-compiler-solidity/src/solc/standard_json/input/settings/selection/file/flag.rs +++ b/era-compiler-solidity/src/solc/standard_json/input/settings/selection/file/flag.rs @@ -2,7 +2,7 @@ //! The `solc --standard-json` expected output selection flag. //! -use crate::solc::codegen::Codegen as SolcCodegen; +use crate::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; /// /// The `solc --standard-json` expected output selection flag. @@ -44,11 +44,11 @@ pub enum Flag { EraVMAssembly, } -impl From for Flag { - fn from(pipeline: SolcCodegen) -> Self { - match pipeline { - SolcCodegen::Yul => Self::Yul, - SolcCodegen::EVMLA => Self::EVMLA, +impl From for Flag { + fn from(codegen: SolcStandardJsonInputSettingsCodegen) -> Self { + match codegen { + SolcStandardJsonInputSettingsCodegen::Yul => Self::Yul, + SolcStandardJsonInputSettingsCodegen::EVMLA => Self::EVMLA, } } } diff --git a/era-compiler-solidity/src/solc/standard_json/input/settings/selection/file/mod.rs b/era-compiler-solidity/src/solc/standard_json/input/settings/selection/file/mod.rs index e6353386..ba9d8cb5 100644 --- a/era-compiler-solidity/src/solc/standard_json/input/settings/selection/file/mod.rs +++ b/era-compiler-solidity/src/solc/standard_json/input/settings/selection/file/mod.rs @@ -6,8 +6,6 @@ pub mod flag; use std::collections::HashSet; -use crate::solc::codegen::Codegen as SolcCodegen; - use self::flag::Flag as SelectionFlag; /// @@ -16,93 +14,42 @@ use self::flag::Flag as SelectionFlag; #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] pub struct File { /// The per-file output selections. - #[serde(rename = "", skip_serializing_if = "Option::is_none")] - pub per_file: Option>, + #[serde(rename = "", skip_serializing_if = "HashSet::is_empty")] + pub per_file: HashSet, /// The per-contract output selections. - #[serde(rename = "*", skip_serializing_if = "Option::is_none")] - pub per_contract: Option>, + #[serde(rename = "*", skip_serializing_if = "HashSet::is_empty")] + pub per_contract: HashSet, } impl File { /// - /// Creates the selection required by EraVM compilation process. - /// - pub fn new_required(pipeline: Option) -> Self { - let pipeline_ir_flag = pipeline - .map(SelectionFlag::from) - .unwrap_or(SelectionFlag::Yul); - - let per_file = HashSet::from_iter([SelectionFlag::AST]); - let per_contract = HashSet::from_iter([ - SelectionFlag::MethodIdentifiers, - SelectionFlag::Metadata, - pipeline_ir_flag, - ]); - Self { - per_file: Some(per_file), - per_contract: Some(per_contract), - } - } - - /// - /// Creates the selection required by Yul validation process. + /// A shortcut constructor. /// - pub fn new_yul_validation() -> Self { - Self { - per_file: Some(HashSet::new()), - per_contract: Some(HashSet::from_iter([SelectionFlag::EVM])), + pub fn new(flags: Vec) -> Self { + let mut per_file = HashSet::new(); + let mut per_contract = HashSet::new(); + for flag in flags.into_iter() { + match flag { + SelectionFlag::AST => { + per_file.insert(SelectionFlag::AST); + } + flag => { + per_contract.insert(flag); + } + } } - } - - /// - /// Creates the selection for EraVM assembly. - /// - pub fn new_eravm_assembly() -> Self { Self { - per_file: Some(HashSet::new()), - per_contract: Some(HashSet::from_iter([SelectionFlag::EraVMAssembly])), + per_file, + per_contract, } } /// - /// Extends the output selection with flag required by EraVM compilation process. - /// - pub fn extend_with_required(&mut self, pipeline: Option) -> &mut Self { - let required = Self::new_required(pipeline); - self.per_file - .get_or_insert_with(HashSet::default) - .extend(required.per_file.unwrap_or_default()); - self.per_contract - .get_or_insert_with(HashSet::default) - .extend(required.per_contract.unwrap_or_default()); - self - } - - /// - /// Extends the output selection with flag required by the Yul validation. - /// - pub fn extend_with_yul_validation(&mut self) -> &mut Self { - let yul_validation = Self::new_yul_validation(); - self.per_file - .get_or_insert_with(HashSet::default) - .extend(yul_validation.per_file.unwrap_or_default()); - self.per_contract - .get_or_insert_with(HashSet::default) - .extend(yul_validation.per_contract.unwrap_or_default()); - self - } - - /// - /// Extends the output selection with EraVM assembly flag. + /// Extends the output selection with another one. /// - pub fn extend_with_eravm_assembly(&mut self) -> &mut Self { - let eravm_assembly = Self::new_eravm_assembly(); - self.per_file - .get_or_insert_with(HashSet::default) - .extend(eravm_assembly.per_file.unwrap_or_default()); - self.per_contract - .get_or_insert_with(HashSet::default) - .extend(eravm_assembly.per_contract.unwrap_or_default()); + pub fn extend(&mut self, other: Self) -> &mut Self { + self.per_file.extend(other.per_file); + self.per_contract.extend(other.per_contract); self } @@ -112,7 +59,7 @@ impl File { /// /// Afterwards, the flags are used to prune JSON output before returning it. /// - pub fn get_unset_required(&self) -> HashSet { + pub fn selection_to_prune(&self) -> Self { let required_per_file = vec![SelectionFlag::AST]; let required_per_contract = vec![ SelectionFlag::MethodIdentifiers, @@ -120,29 +67,40 @@ impl File { SelectionFlag::Yul, SelectionFlag::EVMLA, ]; - let mut flags = - HashSet::with_capacity(required_per_file.len() + required_per_contract.len()); + + let mut unset_per_file = HashSet::with_capacity(required_per_file.len()); + let mut unset_per_contract = HashSet::with_capacity(required_per_contract.len()); for flag in required_per_file { - if !self - .per_file - .as_ref() - .map(|per_file| per_file.contains(&flag)) - .unwrap_or_default() - { - flags.insert(flag); + if !self.per_file.contains(&flag) { + unset_per_file.insert(flag); } } for flag in required_per_contract { - if !self - .per_contract - .as_ref() - .map(|per_contract| per_contract.contains(&flag)) - .unwrap_or_default() - { - flags.insert(flag); + if !self.per_contract.contains(&flag) { + unset_per_contract.insert(flag); } } - flags + Self { + per_file: unset_per_file, + per_contract: unset_per_contract, + } + } + + /// + /// Whether the flag is requested. + /// + pub fn contains(&self, flag: &SelectionFlag) -> bool { + match flag { + flag @ SelectionFlag::AST => self.per_file.contains(flag), + flag => self.per_contract.contains(flag), + } + } + + /// + /// Checks whether the selection is empty. + /// + pub fn is_empty(&self) -> bool { + self.per_file.is_empty() && self.per_contract.is_empty() } } diff --git a/era-compiler-solidity/src/solc/standard_json/input/settings/selection/mod.rs b/era-compiler-solidity/src/solc/standard_json/input/settings/selection/mod.rs index d69a7f0c..e272c888 100644 --- a/era-compiler-solidity/src/solc/standard_json/input/settings/selection/mod.rs +++ b/era-compiler-solidity/src/solc/standard_json/input/settings/selection/mod.rs @@ -4,9 +4,7 @@ pub mod file; -use std::collections::HashSet; - -use crate::solc::codegen::Codegen as SolcCodegen; +use crate::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; use self::file::flag::Flag as SelectionFlag; use self::file::File as FileSelection; @@ -17,65 +15,44 @@ use self::file::File as FileSelection; #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] pub struct Selection { /// Only the 'all' wildcard is available for robustness reasons. - #[serde(rename = "*", skip_serializing_if = "Option::is_none")] - pub all: Option, + #[serde(default, rename = "*", skip_serializing_if = "FileSelection::is_empty")] + pub all: FileSelection, } impl Selection { /// - /// Creates the selection required by EraVM compilation process. - /// - pub fn new_required(pipeline: Option) -> Self { - Self { - all: Some(FileSelection::new_required(pipeline)), - } - } - - /// - /// Creates the selection required by Yul validation process. + /// Creates the selection with arbitrary flags. /// - pub fn new_yul_validation() -> Self { + pub fn new(flags: Vec) -> Self { Self { - all: Some(FileSelection::new_yul_validation()), + all: FileSelection::new(flags), } } /// - /// Creates the selection for EraVM assembly. - /// - pub fn new_eravm_assembly() -> Self { - Self { - all: Some(FileSelection::new_eravm_assembly()), - } - } - - /// - /// Extends the output selection with flag required by EraVM compilation process. + /// Creates the selection required by EraVM compilation process. /// - pub fn extend_with_required(&mut self, pipeline: Option) -> &mut Self { - self.all - .get_or_insert_with(|| FileSelection::new_required(pipeline)) - .extend_with_required(pipeline); - self + pub fn new_required(codegen: SolcStandardJsonInputSettingsCodegen) -> Self { + Self::new(vec![ + SelectionFlag::AST, + SelectionFlag::MethodIdentifiers, + SelectionFlag::Metadata, + codegen.into(), + ]) } /// - /// Extends the output selection with flag required by the Yul validation. + /// Creates the selection required by Yul validation process. /// - pub fn extend_with_yul_validation(&mut self) -> &mut Self { - self.all - .get_or_insert_with(FileSelection::new_yul_validation) - .extend_with_yul_validation(); - self + pub fn new_yul_validation() -> Self { + Self::new(vec![SelectionFlag::EVM]) } /// - /// Extends the output selection with EraVM assembly. + /// Extends the output selection with another one. /// - pub fn extend_with_eravm_assembly(&mut self) -> &mut Self { - self.all - .get_or_insert_with(FileSelection::new_eravm_assembly) - .extend_with_eravm_assembly(); + pub fn extend(&mut self, other: Self) -> &mut Self { + self.all.extend(other.all); self } @@ -85,21 +62,16 @@ impl Selection { /// /// Afterwards, the flags are used to prune JSON output before returning it. /// - pub fn get_unset_required(&self) -> HashSet { - self.all - .as_ref() - .map(|selection| selection.get_unset_required()) - .unwrap_or_else(|| FileSelection::default().get_unset_required()) + pub fn selection_to_prune(&self) -> Self { + Self { + all: self.all.selection_to_prune(), + } } /// - /// Whether EraVM assembly is requested. + /// Whether the flag is requested. /// - pub fn contains_eravm_assembly(&self) -> bool { - self.all - .as_ref() - .and_then(|file| file.per_contract.as_ref()) - .map(|contract| contract.contains(&SelectionFlag::EraVMAssembly)) - .unwrap_or_default() + pub fn contains(&self, flag: &SelectionFlag) -> bool { + self.all.contains(flag) } } diff --git a/era-compiler-solidity/src/solc/standard_json/output/contract/eravm.rs b/era-compiler-solidity/src/solc/standard_json/output/contract/eravm.rs index 9d482449..a710ec76 100644 --- a/era-compiler-solidity/src/solc/standard_json/output/contract/eravm.rs +++ b/era-compiler-solidity/src/solc/standard_json/output/contract/eravm.rs @@ -5,7 +5,7 @@ /// /// The `solc --standard-json` output contract EraVM data. /// -#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Clone, serde::Serialize)] #[serde(rename_all = "camelCase")] pub struct EraVM { /// The contract bytecode. diff --git a/era-compiler-solidity/src/solc/standard_json/output/contract/evm/extra_metadata/mod.rs b/era-compiler-solidity/src/solc/standard_json/output/contract/evm/extra_metadata/mod.rs index b7d905c8..cc4425cb 100644 --- a/era-compiler-solidity/src/solc/standard_json/output/contract/evm/extra_metadata/mod.rs +++ b/era-compiler-solidity/src/solc/standard_json/output/contract/evm/extra_metadata/mod.rs @@ -28,17 +28,21 @@ impl ExtraMetadata { for function in self.recursive_functions.iter() { match block_key.code_type { era_compiler_llvm_context::CodeType::Deploy => { - if let Some(creation_tag) = function.creation_tag { - if num::BigUint::from(creation_tag) == block_key.tag { - return Some(function); - } + if function + .creation_tag + .map(|creation_tag| num::BigUint::from(creation_tag) == block_key.tag) + .unwrap_or_default() + { + return Some(function); } } era_compiler_llvm_context::CodeType::Runtime => { - if let Some(runtime_tag) = function.runtime_tag { - if num::BigUint::from(runtime_tag) == block_key.tag { - return Some(function); - } + if function + .runtime_tag + .map(|runtime_tag| num::BigUint::from(runtime_tag) == block_key.tag) + .unwrap_or_default() + { + return Some(function); } } } diff --git a/era-compiler-solidity/src/solc/standard_json/output/contract/evm/mod.rs b/era-compiler-solidity/src/solc/standard_json/output/contract/evm/mod.rs index d3583502..2b2b9eda 100644 --- a/era-compiler-solidity/src/solc/standard_json/output/contract/evm/mod.rs +++ b/era-compiler-solidity/src/solc/standard_json/output/contract/evm/mod.rs @@ -29,7 +29,7 @@ pub struct EVM { pub method_identifiers: Option>, /// The contract EraVM assembly code. - #[serde(skip_serializing_if = "Option::is_none")] + #[serde(skip_serializing_if = "Option::is_none", skip_deserializing)] pub assembly: Option, /// The extra EVMLA metadata. #[serde(skip_serializing_if = "Option::is_none")] diff --git a/era-compiler-solidity/src/solc/standard_json/output/contract/mod.rs b/era-compiler-solidity/src/solc/standard_json/output/contract/mod.rs index a2ebeffe..4162ed5b 100644 --- a/era-compiler-solidity/src/solc/standard_json/output/contract/mod.rs +++ b/era-compiler-solidity/src/solc/standard_json/output/contract/mod.rs @@ -18,42 +18,42 @@ use self::evm::EVM; #[serde(rename_all = "camelCase")] pub struct Contract { /// The contract ABI. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub abi: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub abi: serde_json::Value, /// The contract storage layout. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub storage_layout: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub storage_layout: serde_json::Value, /// The contract storage layout. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub transient_storage_layout: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub transient_storage_layout: serde_json::Value, /// The contract metadata. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub metadata: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub metadata: serde_json::Value, /// The contract developer documentation. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub devdoc: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub devdoc: serde_json::Value, /// The contract user documentation. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub userdoc: Option, + #[serde(default, skip_serializing_if = "serde_json::Value::is_null")] + pub userdoc: serde_json::Value, /// The contract optimized IR code. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub ir_optimized: Option, + #[serde(default, skip_serializing_if = "String::is_empty")] + pub ir_optimized: String, /// The EraVM data of the contract. - #[serde(default, skip_serializing_if = "Option::is_none")] + #[serde(default, skip_serializing_if = "Option::is_none", skip_deserializing)] pub eravm: Option, /// The EVM data of the contract. #[serde(default, skip_serializing_if = "Option::is_none")] pub evm: Option, /// The contract EraVM bytecode hash. - #[serde(default, skip_serializing_if = "Option::is_none")] + #[serde(default, skip_serializing_if = "Option::is_none", skip_deserializing)] pub hash: Option, /// The contract factory dependencies. - #[serde(default)] + #[serde(default, skip_deserializing)] pub factory_dependencies: BTreeMap, /// The contract missing libraries. - #[serde(default, skip_serializing_if = "Option::is_none")] + #[serde(default, skip_serializing_if = "Option::is_none", skip_deserializing)] pub missing_libraries: Option>, } @@ -62,14 +62,15 @@ impl Contract { /// Checks if all fields are unset or empty. /// pub fn is_empty(&self) -> bool { - self.abi.is_none() - && self.storage_layout.is_none() - && self.transient_storage_layout.is_none() - && self.metadata.is_none() - && self.devdoc.is_none() - && self.userdoc.is_none() + self.abi.is_null() + && self.storage_layout.is_null() + && self.transient_storage_layout.is_null() + && self.metadata.is_null() + && self.devdoc.is_null() + && self.userdoc.is_null() + && self.ir_optimized.is_empty() && self.evm.is_none() - && self.ir_optimized.is_none() + && self.eravm.is_none() && self.hash.is_none() && self.factory_dependencies.is_empty() && self.missing_libraries.is_none() diff --git a/era-compiler-solidity/src/solc/standard_json/output/error/mod.rs b/era-compiler-solidity/src/solc/standard_json/output/error/mod.rs index 5127eef1..25581cc7 100644 --- a/era-compiler-solidity/src/solc/standard_json/output/error/mod.rs +++ b/era-compiler-solidity/src/solc/standard_json/output/error/mod.rs @@ -187,10 +187,10 @@ You may disable this error with: sources: &BTreeMap, ) -> Self { let message = r#" -Internal function pointers are not supported in the EVM assembly pipeline. +Internal function pointers are not supported in the EVM assembly codegen. Please do one of the following: 1. Use the ZKsync fork of the Solidity compiler: https://github.com/matter-labs/era-solidity/releases - 2. Switch to the latest solc with Yul assembly pipeline: https://docs.soliditylang.org/en/latest/yul.html + 2. Switch to the latest solc with Yul assembly codegen: https://docs.soliditylang.org/en/latest/yul.html "#; Self::new_error( diff --git a/era-compiler-solidity/src/solc/standard_json/output/error/source_location.rs b/era-compiler-solidity/src/solc/standard_json/output/error/source_location.rs index e6dc435a..29da4c52 100644 --- a/era-compiler-solidity/src/solc/standard_json/output/error/source_location.rs +++ b/era-compiler-solidity/src/solc/standard_json/output/error/source_location.rs @@ -67,16 +67,3 @@ impl SourceLocation { )) } } - -impl std::fmt::Display for SourceLocation { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.file)?; - if self.start > 0 { - write!(f, ":{}", self.start)?; - if self.end > 0 { - write!(f, ":{}", self.end)?; - } - } - Ok(()) - } -} diff --git a/era-compiler-solidity/src/solc/standard_json/output/mod.rs b/era-compiler-solidity/src/solc/standard_json/output/mod.rs index 79b33904..5bdeabb6 100644 --- a/era-compiler-solidity/src/solc/standard_json/output/mod.rs +++ b/era-compiler-solidity/src/solc/standard_json/output/mod.rs @@ -7,7 +7,6 @@ pub mod error; pub mod source; use std::collections::BTreeMap; -use std::collections::HashSet; use rayon::iter::IntoParallelIterator; use rayon::iter::IntoParallelRefIterator; @@ -16,8 +15,9 @@ use rayon::iter::ParallelIterator; use crate::error_type::ErrorType; use crate::evmla::assembly::instruction::Instruction; use crate::evmla::assembly::Assembly; -use crate::solc::codegen::Codegen as SolcCodegen; +use crate::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; use crate::solc::standard_json::input::settings::selection::file::flag::Flag as SelectionFlag; +use crate::solc::standard_json::input::settings::selection::Selection; use crate::solc::standard_json::input::source::Source as StandardJSONInputSource; use crate::solc::standard_json::output::contract::evm::EVM as StandardJSONOutputContractEVM; use crate::solc::version::Version as SolcVersion; @@ -35,14 +35,14 @@ use self::source::Source; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct Output { /// The file-contract hashmap. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub contracts: Option>>, + #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] + pub contracts: BTreeMap>, /// The source code mapping data. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub sources: Option>, + #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] + pub sources: BTreeMap, /// The compilation errors and warnings. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub errors: Option>, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub errors: Vec, /// The `solc` compiler version. #[serde(skip_serializing_if = "Option::is_none")] @@ -72,9 +72,9 @@ impl Output { .collect::>(); Self { - contracts: Some(BTreeMap::new()), - sources: Some(sources), - errors: Some(std::mem::take(messages)), + contracts: BTreeMap::new(), + sources, + errors: std::mem::take(messages), version: None, long_version: None, @@ -89,9 +89,9 @@ impl Output { /// pub fn new_with_messages(messages: Vec) -> Self { Self { - contracts: None, - sources: None, - errors: Some(messages), + contracts: BTreeMap::new(), + sources: BTreeMap::new(), + errors: messages, version: None, long_version: None, @@ -102,40 +102,31 @@ impl Output { /// /// Prunes the output JSON and prints it to stdout. /// - pub fn write_and_exit(mut self, prune_output: HashSet) -> ! { - let sources = self - .sources - .as_mut() - .map(|sources| sources.values_mut().collect::>()) - .unwrap_or_default(); + pub fn write_and_exit(mut self, selection_to_prune: Selection) -> ! { + let sources = self.sources.values_mut().collect::>(); for source in sources.into_iter() { - if prune_output.contains(&SelectionFlag::AST) { + if selection_to_prune.contains(&SelectionFlag::AST) { source.ast = None; } } let contracts = self .contracts - .as_mut() - .map(|contracts| { - contracts - .values_mut() - .flat_map(|contracts| contracts.values_mut()) - .collect::>() - }) - .unwrap_or_default(); + .values_mut() + .flat_map(|contracts| contracts.values_mut()) + .collect::>(); for contract in contracts.into_iter() { - if prune_output.contains(&SelectionFlag::Metadata) { - contract.metadata = None; + if selection_to_prune.contains(&SelectionFlag::Metadata) { + contract.metadata = serde_json::Value::Null; } - if prune_output.contains(&SelectionFlag::Yul) { - contract.ir_optimized = None; + if selection_to_prune.contains(&SelectionFlag::Yul) { + contract.ir_optimized = String::new(); } if let Some(ref mut evm) = contract.evm { - if prune_output.contains(&SelectionFlag::EVMLA) { + if selection_to_prune.contains(&SelectionFlag::EVMLA) { evm.legacy_assembly = None; } - if prune_output.contains(&SelectionFlag::MethodIdentifiers) { + if selection_to_prune.contains(&SelectionFlag::MethodIdentifiers) { evm.method_identifiers = None; } evm.extra_metadata = None; @@ -150,37 +141,10 @@ impl Output { } } - if let Some(ref mut files) = self.contracts { - files.retain(|_, contracts| { - contracts.retain(|_, contract| !contract.is_empty()); - !contracts.is_empty() - }); - } - - if self - .contracts - .as_ref() - .map(|contracts| contracts.is_empty()) - .unwrap_or_default() - { - self.contracts = None; - } - if self - .sources - .as_ref() - .map(|sources| sources.is_empty()) - .unwrap_or_default() - { - self.sources = None; - } - if self - .errors - .as_ref() - .map(|errors| errors.is_empty()) - .unwrap_or_default() - { - self.errors = None; - } + self.contracts.retain(|_, contracts| { + contracts.retain(|_, contract| !contract.is_empty()); + !contracts.is_empty() + }); serde_json::to_writer(std::io::stdout(), &self).expect("Stdout writing error"); std::process::exit(era_compiler_common::EXIT_CODE_SUCCESS); @@ -190,12 +154,10 @@ impl Output { /// Removes EVM artifacts to prevent their accidental usage. /// pub fn remove_evm(&mut self) { - if let Some(files) = self.contracts.as_mut() { - for (_, file) in files.iter_mut() { - for (_, contract) in file.iter_mut() { - if let Some(evm) = contract.evm.as_mut() { - evm.bytecode = None; - } + for (_, file) in self.contracts.iter_mut() { + for (_, contract) in file.iter_mut() { + if let Some(evm) = contract.evm.as_mut() { + evm.bytecode = None; } } } @@ -207,13 +169,11 @@ impl Output { /// Please do not push project-general errors without paths here. /// pub fn push_error(&mut self, path: Option, error: anyhow::Error) { - self.errors - .get_or_insert_with(Vec::new) - .push(JsonOutputError::new_error( - error, - path.map(JsonOutputErrorSourceLocation::new), - None, - )); + self.errors.push(JsonOutputError::new_error( + error, + path.map(JsonOutputErrorSourceLocation::new), + None, + )); } /// @@ -223,20 +183,18 @@ impl Output { &mut self, sources: &BTreeMap, version: &SolcVersion, - pipeline: SolcCodegen, + codegen: SolcStandardJsonInputSettingsCodegen, suppressed_errors: &[ErrorType], suppressed_warnings: &[WarningType], ) -> anyhow::Result<()> { - let source_asts = match self.sources.as_ref() { - Some(sources) => sources, - None => return Ok(()), - }; - let id_paths: BTreeMap = source_asts + let id_paths: BTreeMap = self + .sources .iter() .map(|(path, source)| (source.id, path)) .collect(); - let messages: Vec = source_asts + let messages: Vec = self + .sources .par_iter() .map(|(_path, source)| { source @@ -248,7 +206,7 @@ impl Output { &id_paths, sources, version, - pipeline, + codegen, suppressed_errors, suppressed_warnings, ) @@ -257,7 +215,7 @@ impl Output { }) .flatten() .collect(); - self.errors.get_or_insert_with(Vec::new).extend(messages); + self.errors.extend(messages); Ok(()) } @@ -266,14 +224,10 @@ impl Output { /// The pass, which replaces with dependency indexes with actual data. /// pub fn preprocess_dependencies(&mut self) -> anyhow::Result<()> { - let files = match self.contracts.as_mut() { - Some(files) => files, - None => return Ok(()), - }; let mut hash_path_mapping = BTreeMap::new(); - for (path, contracts) in files.iter() { - for (name, contract) in contracts.iter() { + for (path, file) in self.contracts.iter() { + for (name, contract) in file.iter() { let full_path = format!("{path}:{name}"); let hash = match contract .evm @@ -290,8 +244,8 @@ impl Output { } let mut assemblies = BTreeMap::new(); - for (path, contracts) in files.iter_mut() { - for (name, contract) in contracts.iter_mut() { + for (path, file) in self.contracts.iter_mut() { + for (name, contract) in file.iter_mut() { let full_path = format!("{path}:{name}"); let assembly = match contract .evm @@ -354,28 +308,20 @@ impl Output { impl CollectableError for Output { fn errors(&self) -> Vec<&JsonOutputError> { - match self.errors { - Some(ref errors) => errors - .iter() - .filter(|error| error.severity == "error") - .collect(), - None => vec![], - } + self.errors + .iter() + .filter(|error| error.severity == "error") + .collect() } fn warnings(&self) -> Vec<&JsonOutputError> { - match self.errors { - Some(ref errors) => errors - .iter() - .filter(|error| error.severity == "warning") - .collect(), - None => vec![], - } + self.errors + .iter() + .filter(|error| error.severity == "warning") + .collect() } fn remove_warnings(&mut self) { - if let Some(ref mut errors) = self.errors { - errors.retain(|error| error.severity != "warning"); - } + self.errors.retain(|error| error.severity != "warning"); } } diff --git a/era-compiler-solidity/src/solc/standard_json/output/source.rs b/era-compiler-solidity/src/solc/standard_json/output/source.rs index f104a2fd..1fe5853b 100644 --- a/era-compiler-solidity/src/solc/standard_json/output/source.rs +++ b/era-compiler-solidity/src/solc/standard_json/output/source.rs @@ -4,8 +4,10 @@ use std::collections::BTreeMap; +use boolinator::Boolinator; + use crate::error_type::ErrorType; -use crate::solc::codegen::Codegen as SolcCodegen; +use crate::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; use crate::solc::standard_json::input::source::Source as StandardJSONInputSource; use crate::solc::standard_json::output::error::Error as SolcStandardJsonOutputError; use crate::solc::version::Version as SolcVersion; @@ -45,18 +47,12 @@ impl Source { ) -> Option { let ast = ast.as_object()?; - if ast.get("nodeType")?.as_str()? != "FunctionCall" { - return None; - } + (ast.get("nodeType")?.as_str()? == "FunctionCall").as_option()?; let expression = ast.get("expression")?.as_object()?; - if expression.get("nodeType")?.as_str()? != "MemberAccess" { - return None; - } + (expression.get("nodeType")?.as_str()? == "MemberAccess").as_option()?; let member_name = expression.get("memberName")?.as_str()?; - if !["send", "transfer"].contains(&member_name) { - return None; - } + ["send", "transfer"].contains(&member_name).as_option()?; let expression = expression.get("expression")?.as_object()?; let type_descriptions = expression.get("typeDescriptions")?.as_object()?; @@ -65,9 +61,7 @@ impl Source { if solc_version.default < semver::Version::new(0, 5, 0) { affected_types.push("t_address"); } - if !affected_types.contains(&type_identifier) { - return None; - } + affected_types.contains(&type_identifier).as_option()?; Some(SolcStandardJsonOutputError::error_send_and_transfer( ast.get("src")?.as_str(), @@ -86,22 +80,16 @@ impl Source { ) -> Option { let ast = ast.as_object()?; - if ast.get("nodeType")?.as_str()? != "MemberAccess" { - return None; - } - if ast.get("memberName")?.as_str()? != "runtimeCode" { - return None; - } + (ast.get("nodeType")?.as_str()? == "MemberAccess").as_option()?; + (ast.get("memberName")?.as_str()? == "runtimeCode").as_option()?; let expression = ast.get("expression")?.as_object()?; let type_descriptions = expression.get("typeDescriptions")?.as_object()?; - if !type_descriptions + type_descriptions .get("typeIdentifier")? .as_str()? .starts_with("t_magic_meta_type") - { - return None; - } + .as_option()?; Some(SolcStandardJsonOutputError::error_runtime_code( ast.get("src")?.as_str(), @@ -120,18 +108,14 @@ impl Source { ) -> Option { let ast = ast.as_object()?; - if ast.get("nodeType")?.as_str()? != "VariableDeclaration" { - return None; - } + (ast.get("nodeType")?.as_str()? == "VariableDeclaration").as_option()?; let type_descriptions = ast.get("typeDescriptions")?.as_object()?; - if !type_descriptions + type_descriptions .get("typeIdentifier")? .as_str()? .contains("function_internal") - { - return None; - } + .as_option()?; Some( SolcStandardJsonOutputError::error_internal_function_pointer( @@ -152,20 +136,12 @@ impl Source { ) -> Option { let ast = ast.as_object()?; - if ast.get("nodeType")?.as_str()? != "MemberAccess" { - return None; - } - if ast.get("memberName")?.as_str()? != "origin" { - return None; - } + (ast.get("nodeType")?.as_str()? == "MemberAccess").as_option()?; + (ast.get("memberName")?.as_str()? == "origin").as_option()?; let expression = ast.get("expression")?.as_object()?; - if expression.get("nodeType")?.as_str()? != "Identifier" { - return None; - } - if expression.get("name")?.as_str()? != "tx" { - return None; - } + (expression.get("nodeType")?.as_str()? == "Identifier").as_option()?; + (expression.get("name")?.as_str()? == "tx").as_option()?; Some(SolcStandardJsonOutputError::warning_tx_origin( ast.get("src")?.as_str(), @@ -187,20 +163,18 @@ impl Source { match ast.get("nodeType")?.as_str()? { "InlineAssembly" if solc_version.default < semver::Version::new(0, 6, 0) => { - if !ast.get("operations")?.as_str()?.contains("origin()") { - return None; - } + ast.get("operations")? + .as_str()? + .contains("origin()") + .as_option()?; } "YulFunctionCall" if solc_version.default >= semver::Version::new(0, 6, 0) => { - if ast - .get("functionName")? + (ast.get("functionName")? .as_object()? .get("name")? .as_str()? - != "origin" - { - return None; - } + == "origin") + .as_option()?; } _ => return None, } @@ -220,7 +194,7 @@ impl Source { id_paths: &BTreeMap, sources: &BTreeMap, solc_version: &SolcVersion, - solc_pipeline: SolcCodegen, + solc_codegen: SolcStandardJsonInputSettingsCodegen, suppressed_errors: &[ErrorType], suppressed_warnings: &[WarningType], ) -> Vec { @@ -235,7 +209,9 @@ impl Source { if let Some(message) = Self::check_runtime_code(ast, id_paths, sources) { messages.push(message); } - if SolcCodegen::EVMLA == solc_pipeline && solc_version.l2_revision.is_none() { + if SolcStandardJsonInputSettingsCodegen::EVMLA == solc_codegen + && solc_version.l2_revision.is_none() + { if let Some(message) = Self::check_internal_function_pointer(ast, id_paths, sources) { messages.push(message); } @@ -258,7 +234,7 @@ impl Source { id_paths, sources, solc_version, - solc_pipeline, + solc_codegen, suppressed_errors, suppressed_warnings, )); @@ -271,7 +247,7 @@ impl Source { id_paths, sources, solc_version, - solc_pipeline, + solc_codegen, suppressed_errors, suppressed_warnings, )); diff --git a/era-compiler-solidity/src/solc/version.rs b/era-compiler-solidity/src/solc/version.rs index 33bb1df3..98b59645 100644 --- a/era-compiler-solidity/src/solc/version.rs +++ b/era-compiler-solidity/src/solc/version.rs @@ -30,15 +30,4 @@ impl Version { l2_revision, } } - - /// - /// A shortcut constructor for a simple version. - /// - pub fn new_simple(version: semver::Version) -> Self { - Self { - long: version.to_string(), - default: version, - l2_revision: None, - } - } } diff --git a/era-compiler-solidity/src/yul/parser/statement/expression/function_call/mod.rs b/era-compiler-solidity/src/yul/parser/statement/expression/function_call/mod.rs index dc91405e..de1d643d 100644 --- a/era-compiler-solidity/src/yul/parser/statement/expression/function_call/mod.rs +++ b/era-compiler-solidity/src/yul/parser/statement/expression/function_call/mod.rs @@ -895,11 +895,8 @@ impl FunctionCall { anyhow::anyhow!("{} Linker symbol literal is missing", location) })?; - Ok(Some( - context - .resolve_library(path.as_str())? - .as_basic_value_enum(), - )) + era_compiler_llvm_context::eravm_evm_call::linker_symbol(context, path.as_str()) + .map(Some) } Name::MemoryGuard => { let arguments = self.pop_arguments_llvm::(context)?; diff --git a/era-compiler-solidity/src/zksolc/arguments.rs b/era-compiler-solidity/src/zksolc/arguments.rs index 829f41b6..e5d76d68 100644 --- a/era-compiler-solidity/src/zksolc/arguments.rs +++ b/era-compiler-solidity/src/zksolc/arguments.rs @@ -157,9 +157,9 @@ pub struct Arguments { /// Specify the `solc` codegen. /// Available options: `evmla`, `yul`. #[structopt(long = "codegen")] - pub codegen: Option, + pub codegen: Option, - /// Forcibly switch to EVM legacy assembly pipeline. + /// Forcibly switch to EVM legacy assembly codegen. /// It is useful for older revisions of `solc` 0.8, where Yul was considered highly experimental /// and contained more bugs than today. /// Deprecated: use `--codegen` instead. @@ -542,7 +542,7 @@ impl Arguments { } if self.force_evmla { messages.push(SolcStandardJsonOutputError::new_warning( - "EVM legacy assembly pipeline CLI flag `--force-evmla` is deprecated in standard JSON mode and must be passed in JSON as `settings.forceEVMLA`.", None, None + "EVM legacy assembly codegen CLI flag `--force-evmla` is deprecated in standard JSON mode and must be passed in JSON as `settings.forceEVMLA`.", None, None )); } if self.detect_missing_libraries { diff --git a/era-compiler-solidity/src/zksolc/main.rs b/era-compiler-solidity/src/zksolc/main.rs index 15933eab..eed6b8ce 100644 --- a/era-compiler-solidity/src/zksolc/main.rs +++ b/era-compiler-solidity/src/zksolc/main.rs @@ -4,7 +4,6 @@ pub mod arguments; -use std::collections::HashSet; use std::io::Write; use std::path::PathBuf; use std::str::FromStr; @@ -35,7 +34,9 @@ fn main() -> anyhow::Result<()> { if is_standard_json { let output = era_compiler_solidity::SolcStandardJsonOutput::new_with_messages(messages); - output.write_and_exit(HashSet::new()); + output.write_and_exit( + era_compiler_solidity::SolcStandardJsonInputSettingsSelection::default(), + ); } let exit_code = if messages.iter().any(|error| error.severity == "error") { @@ -143,125 +144,130 @@ fn main_inner( match target { era_compiler_common::Target::EraVM => { - let build = if arguments.yul { - era_compiler_solidity::yul_to_eravm( - input_files.as_slice(), - arguments.libraries, - arguments.solc, - messages, - enable_eravm_extensions, - metadata_hash_type, - optimizer_settings, - llvm_options, - arguments.output_assembly, - arguments.threads, - debug_config, - ) - } else if arguments.llvm_ir { - era_compiler_solidity::llvm_ir_to_eravm( - input_files.as_slice(), - messages, - metadata_hash_type, - optimizer_settings, - llvm_options, - arguments.output_assembly, - arguments.threads, - debug_config, - ) - } else if arguments.eravm_assembly { - era_compiler_solidity::eravm_assembly( - input_files.as_slice(), - messages, - metadata_hash_type, - llvm_options, - arguments.output_assembly, - arguments.threads, - debug_config, - ) - } else if arguments.disassemble { - return era_compiler_solidity::disassemble_eravm(arguments.inputs); - } else if arguments.link { - return era_compiler_solidity::link_eravm(arguments.inputs, arguments.libraries); - } else if let Some(standard_json) = arguments.standard_json { - let solc_compiler = match arguments.solc.as_deref() { - Some(executable) => Some(era_compiler_solidity::SolcCompiler::new(executable)?), - None => None, - }; - return era_compiler_solidity::standard_json_eravm( - solc_compiler, - arguments.codegen, - enable_eravm_extensions, - arguments.detect_missing_libraries, - standard_json.map(PathBuf::from), - messages, - arguments.base_path, - arguments.include_path, - arguments.allow_paths, - arguments.threads, - debug_config, - ); - } else if let Some(format) = arguments.combined_json { - let solc_compiler = era_compiler_solidity::SolcCompiler::new( - arguments - .solc - .as_deref() - .unwrap_or(era_compiler_solidity::SolcCompiler::DEFAULT_EXECUTABLE_NAME), - )?; - return era_compiler_solidity::combined_json_eravm( - format, - input_files.as_slice(), - arguments.libraries, - &solc_compiler, - messages, - arguments.codegen, - arguments.evm_version, - enable_eravm_extensions, - metadata_hash_type, - arguments.metadata_literal, - arguments.base_path, - arguments.include_path, - arguments.allow_paths, - remappings, - arguments.output_directory, - arguments.overwrite, - optimizer_settings, - llvm_options, - arguments.output_assembly, - suppressed_errors, - suppressed_warnings, - arguments.threads, - debug_config, - ); - } else { - let solc_compiler = era_compiler_solidity::SolcCompiler::new( - arguments - .solc - .as_deref() - .unwrap_or(era_compiler_solidity::SolcCompiler::DEFAULT_EXECUTABLE_NAME), - )?; - era_compiler_solidity::standard_output_eravm( - input_files.as_slice(), - arguments.libraries, - &solc_compiler, - messages, - arguments.codegen, - arguments.evm_version, - enable_eravm_extensions, - metadata_hash_type, - arguments.metadata_literal, - arguments.base_path, - arguments.include_path, - arguments.allow_paths, - remappings, - optimizer_settings, - llvm_options, - arguments.output_assembly, - suppressed_errors, - suppressed_warnings, - arguments.threads, - debug_config, - ) - }?; + let build = + if arguments.yul { + era_compiler_solidity::yul_to_eravm( + input_files.as_slice(), + arguments.libraries.as_slice(), + arguments.solc, + messages, + enable_eravm_extensions, + metadata_hash_type, + optimizer_settings, + llvm_options, + arguments.output_assembly, + arguments.threads, + debug_config, + ) + } else if arguments.llvm_ir { + era_compiler_solidity::llvm_ir_to_eravm( + input_files.as_slice(), + arguments.libraries.as_slice(), + messages, + metadata_hash_type, + optimizer_settings, + llvm_options, + arguments.output_assembly, + arguments.threads, + debug_config, + ) + } else if arguments.eravm_assembly { + era_compiler_solidity::eravm_assembly( + input_files.as_slice(), + messages, + metadata_hash_type, + llvm_options, + arguments.output_assembly, + arguments.threads, + debug_config, + ) + } else if arguments.disassemble { + return era_compiler_solidity::disassemble_eravm(arguments.inputs); + } else if arguments.link { + return era_compiler_solidity::link_eravm( + arguments.inputs, + arguments.libraries.as_slice(), + ); + } else if let Some(standard_json) = arguments.standard_json { + let solc_compiler = match arguments.solc.as_deref() { + Some(executable) => Some( + era_compiler_solidity::SolcCompiler::try_from_path(executable)?, + ), + None => None, + }; + return era_compiler_solidity::standard_json_eravm( + solc_compiler, + arguments.codegen, + enable_eravm_extensions, + arguments.detect_missing_libraries, + standard_json.map(PathBuf::from), + messages, + arguments.base_path, + arguments.include_path, + arguments.allow_paths, + arguments.threads, + debug_config, + ); + } else if let Some(format) = arguments.combined_json { + let solc_compiler = era_compiler_solidity::SolcCompiler::try_from_path( + arguments.solc.as_deref().unwrap_or( + era_compiler_solidity::SolcCompiler::DEFAULT_EXECUTABLE_NAME, + ), + )?; + return era_compiler_solidity::combined_json_eravm( + format, + input_files.as_slice(), + arguments.libraries.as_slice(), + &solc_compiler, + messages, + arguments.codegen, + arguments.evm_version, + enable_eravm_extensions, + metadata_hash_type, + arguments.metadata_literal, + arguments.base_path, + arguments.include_path, + arguments.allow_paths, + remappings, + arguments.output_directory, + arguments.overwrite, + optimizer_settings, + llvm_options, + arguments.output_assembly, + suppressed_errors, + suppressed_warnings, + arguments.threads, + debug_config, + ); + } else { + let solc_compiler = era_compiler_solidity::SolcCompiler::try_from_path( + arguments.solc.as_deref().unwrap_or( + era_compiler_solidity::SolcCompiler::DEFAULT_EXECUTABLE_NAME, + ), + )?; + era_compiler_solidity::standard_output_eravm( + input_files.as_slice(), + arguments.libraries.as_slice(), + &solc_compiler, + messages, + arguments.codegen, + arguments.evm_version, + enable_eravm_extensions, + metadata_hash_type, + arguments.metadata_literal, + arguments.base_path, + arguments.include_path, + arguments.allow_paths, + remappings, + optimizer_settings, + llvm_options, + arguments.output_assembly, + suppressed_errors, + suppressed_warnings, + arguments.threads, + debug_config, + ) + }?; if let Some(output_directory) = arguments.output_directory { build.write_to_directory( @@ -279,102 +285,104 @@ fn main_inner( } } era_compiler_common::Target::EVM => { - let build = if arguments.yul { - era_compiler_solidity::yul_to_evm( - input_files.as_slice(), - arguments.libraries, - arguments.solc, - messages, - metadata_hash_type, - optimizer_settings, - llvm_options, - arguments.threads, - debug_config, - ) - } else if arguments.llvm_ir { - era_compiler_solidity::llvm_ir_to_evm( - input_files.as_slice(), - messages, - metadata_hash_type, - optimizer_settings, - llvm_options, - arguments.threads, - debug_config, - ) - } else if arguments.disassemble { - anyhow::bail!("The EVM target does not support disassembling yet."); - } else if arguments.link { - anyhow::bail!("The EVM target does not support linking yet."); - } else if let Some(standard_json) = arguments.standard_json { - let solc_compiler = match arguments.solc.as_deref() { - Some(executable) => Some(era_compiler_solidity::SolcCompiler::new(executable)?), - None => None, - }; - return era_compiler_solidity::standard_json_evm( - solc_compiler, - arguments.codegen, - standard_json.map(PathBuf::from), - messages, - arguments.base_path, - arguments.include_path, - arguments.allow_paths, - arguments.threads, - debug_config, - ); - } else if let Some(format) = arguments.combined_json { - let solc_compiler = era_compiler_solidity::SolcCompiler::new( - arguments - .solc - .as_deref() - .unwrap_or(era_compiler_solidity::SolcCompiler::DEFAULT_EXECUTABLE_NAME), - )?; - return era_compiler_solidity::combined_json_evm( - format, - input_files.as_slice(), - arguments.libraries, - &solc_compiler, - messages, - arguments.codegen, - arguments.evm_version, - metadata_hash_type, - arguments.metadata_literal, - arguments.base_path, - arguments.include_path, - arguments.allow_paths, - remappings, - arguments.output_directory, - arguments.overwrite, - optimizer_settings, - llvm_options, - arguments.threads, - debug_config, - ); - } else { - let solc = era_compiler_solidity::SolcCompiler::new( - arguments - .solc - .as_deref() - .unwrap_or(era_compiler_solidity::SolcCompiler::DEFAULT_EXECUTABLE_NAME), - )?; - era_compiler_solidity::standard_output_evm( - input_files.as_slice(), - arguments.libraries, - &solc, - messages, - arguments.codegen, - arguments.evm_version, - metadata_hash_type, - arguments.metadata_literal, - arguments.base_path, - arguments.include_path, - arguments.allow_paths, - remappings, - optimizer_settings, - llvm_options, - arguments.threads, - debug_config, - ) - }?; + let build = + if arguments.yul { + era_compiler_solidity::yul_to_evm( + input_files.as_slice(), + arguments.libraries.as_slice(), + arguments.solc, + messages, + metadata_hash_type, + optimizer_settings, + llvm_options, + arguments.threads, + debug_config, + ) + } else if arguments.llvm_ir { + era_compiler_solidity::llvm_ir_to_evm( + input_files.as_slice(), + arguments.libraries.as_slice(), + messages, + metadata_hash_type, + optimizer_settings, + llvm_options, + arguments.threads, + debug_config, + ) + } else if arguments.disassemble { + anyhow::bail!("The EVM target does not support disassembling yet."); + } else if arguments.link { + anyhow::bail!("The EVM target does not support linking yet."); + } else if let Some(standard_json) = arguments.standard_json { + let solc_compiler = match arguments.solc.as_deref() { + Some(executable) => Some( + era_compiler_solidity::SolcCompiler::try_from_path(executable)?, + ), + None => None, + }; + return era_compiler_solidity::standard_json_evm( + solc_compiler, + arguments.codegen, + standard_json.map(PathBuf::from), + messages, + arguments.base_path, + arguments.include_path, + arguments.allow_paths, + arguments.threads, + debug_config, + ); + } else if let Some(format) = arguments.combined_json { + let solc_compiler = era_compiler_solidity::SolcCompiler::try_from_path( + arguments.solc.as_deref().unwrap_or( + era_compiler_solidity::SolcCompiler::DEFAULT_EXECUTABLE_NAME, + ), + )?; + return era_compiler_solidity::combined_json_evm( + format, + input_files.as_slice(), + arguments.libraries.as_slice(), + &solc_compiler, + messages, + arguments.codegen, + arguments.evm_version, + metadata_hash_type, + arguments.metadata_literal, + arguments.base_path, + arguments.include_path, + arguments.allow_paths, + remappings, + arguments.output_directory, + arguments.overwrite, + optimizer_settings, + llvm_options, + arguments.threads, + debug_config, + ); + } else { + let solc = era_compiler_solidity::SolcCompiler::try_from_path( + arguments.solc.as_deref().unwrap_or( + era_compiler_solidity::SolcCompiler::DEFAULT_EXECUTABLE_NAME, + ), + )?; + era_compiler_solidity::standard_output_evm( + input_files.as_slice(), + arguments.libraries.as_slice(), + &solc, + messages, + arguments.codegen, + arguments.evm_version, + metadata_hash_type, + arguments.metadata_literal, + arguments.base_path, + arguments.include_path, + arguments.allow_paths, + remappings, + optimizer_settings, + llvm_options, + arguments.threads, + debug_config, + ) + }?; if let Some(output_directory) = arguments.output_directory { build.write_to_directory( diff --git a/era-compiler-solidity/tests/cli/codegen.rs b/era-compiler-solidity/tests/cli/codegen.rs index b00b38c7..fe194ec3 100644 --- a/era-compiler-solidity/tests/cli/codegen.rs +++ b/era-compiler-solidity/tests/cli/codegen.rs @@ -1,11 +1,11 @@ use crate::{cli, common}; -use era_compiler_solidity::SolcCodegen; +use era_compiler_solidity::SolcStandardJsonInputSettingsCodegen; use predicates::prelude::*; use test_case::test_case; -#[test_case(SolcCodegen::EVMLA)] -#[test_case(SolcCodegen::Yul)] -fn with_codegen(codegen: SolcCodegen) -> anyhow::Result<()> { +#[test_case(SolcStandardJsonInputSettingsCodegen::EVMLA)] +#[test_case(SolcStandardJsonInputSettingsCodegen::Yul)] +fn with_codegen(codegen: SolcStandardJsonInputSettingsCodegen) -> anyhow::Result<()> { common::setup()?; let codegen = codegen.to_string(); @@ -24,9 +24,9 @@ fn with_codegen(codegen: SolcCodegen) -> anyhow::Result<()> { Ok(()) } -#[test_case(SolcCodegen::EVMLA)] -#[test_case(SolcCodegen::Yul)] -fn with_codegen_yul_mode(codegen: SolcCodegen) -> anyhow::Result<()> { +#[test_case(SolcStandardJsonInputSettingsCodegen::EVMLA)] +#[test_case(SolcStandardJsonInputSettingsCodegen::Yul)] +fn with_codegen_yul_mode(codegen: SolcStandardJsonInputSettingsCodegen) -> anyhow::Result<()> { common::setup()?; let codegen = codegen.to_string(); @@ -46,9 +46,9 @@ fn with_codegen_yul_mode(codegen: SolcCodegen) -> anyhow::Result<()> { Ok(()) } -#[test_case(SolcCodegen::EVMLA)] -#[test_case(SolcCodegen::Yul)] -fn with_codegen_llvm_ir_mode(codegen: SolcCodegen) -> anyhow::Result<()> { +#[test_case(SolcStandardJsonInputSettingsCodegen::EVMLA)] +#[test_case(SolcStandardJsonInputSettingsCodegen::Yul)] +fn with_codegen_llvm_ir_mode(codegen: SolcStandardJsonInputSettingsCodegen) -> anyhow::Result<()> { common::setup()?; let codegen = codegen.to_string(); @@ -68,9 +68,11 @@ fn with_codegen_llvm_ir_mode(codegen: SolcCodegen) -> anyhow::Result<()> { Ok(()) } -#[test_case(SolcCodegen::EVMLA)] -#[test_case(SolcCodegen::Yul)] -fn with_codegen_eravm_assembly_mode(codegen: SolcCodegen) -> anyhow::Result<()> { +#[test_case(SolcStandardJsonInputSettingsCodegen::EVMLA)] +#[test_case(SolcStandardJsonInputSettingsCodegen::Yul)] +fn with_codegen_eravm_assembly_mode( + codegen: SolcStandardJsonInputSettingsCodegen, +) -> anyhow::Result<()> { common::setup()?; let codegen = codegen.to_string(); @@ -90,9 +92,11 @@ fn with_codegen_eravm_assembly_mode(codegen: SolcCodegen) -> anyhow::Result<()> Ok(()) } -#[test_case(SolcCodegen::EVMLA)] -#[test_case(SolcCodegen::Yul)] -fn with_codegen_standard_json_mode(codegen: SolcCodegen) -> anyhow::Result<()> { +#[test_case(SolcStandardJsonInputSettingsCodegen::EVMLA)] +#[test_case(SolcStandardJsonInputSettingsCodegen::Yul)] +fn with_codegen_standard_json_mode( + codegen: SolcStandardJsonInputSettingsCodegen, +) -> anyhow::Result<()> { common::setup()?; let codegen = codegen.to_string(); @@ -110,3 +114,22 @@ fn with_codegen_standard_json_mode(codegen: SolcCodegen) -> anyhow::Result<()> { Ok(()) } + +#[test] +fn with_codegen_invalid() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + "--codegen", + "invalid", + "--bin", + cli::TEST_SOLIDITY_CONTRACT_PATH, + ]; + + let result = cli::execute_zksolc(args)?; + result + .failure() + .stderr(predicate::str::contains("Invalid value for \'--codegen \': Invalid codegen: `invalid`. Available options: evmla, yul")); + + Ok(()) +} diff --git a/era-compiler-solidity/tests/cli/combined_json.rs b/era-compiler-solidity/tests/cli/combined_json.rs index a9040922..14bfcbfb 100644 --- a/era-compiler-solidity/tests/cli/combined_json.rs +++ b/era-compiler-solidity/tests/cli/combined_json.rs @@ -37,6 +37,32 @@ fn with_combined_json_loop_args() -> anyhow::Result<()> { Ok(()) } +#[test] +fn with_combined_json_two_files() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + cli::TEST_SOLIDITY_CONTRACT_PATH, + cli::TEST_SOLIDITY_CONTRACT_GREETER_PATH, + "--combined-json", + "bin", + ]; + + let result = cli::execute_zksolc(args)?; + let status_code = result + .success() + .stdout(predicate::str::contains("contracts")) + .get_output() + .status + .code() + .expect("No exit code."); + + let solc_result = cli::execute_solc(args)?; + solc_result.code(status_code); + + Ok(()) +} + #[test] fn with_combined_json_no_args() -> anyhow::Result<()> { common::setup()?; diff --git a/era-compiler-solidity/tests/cli/eravm_assembly.rs b/era-compiler-solidity/tests/cli/eravm_assembly.rs index 75ab76e9..77399d3a 100644 --- a/era-compiler-solidity/tests/cli/eravm_assembly.rs +++ b/era-compiler-solidity/tests/cli/eravm_assembly.rs @@ -19,7 +19,7 @@ fn with_eravm_assembly() -> anyhow::Result<()> { } #[test] -fn with_double_eravm_options() -> anyhow::Result<()> { +fn with_eravm_assembly_duplicate_flag() -> anyhow::Result<()> { common::setup()?; let args = &[ "--eravm-assembly", @@ -36,7 +36,24 @@ fn with_double_eravm_options() -> anyhow::Result<()> { } #[test] -fn with_incompatible_input_format() -> anyhow::Result<()> { +fn with_eravm_assembly_invalid() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + "--eravm-assembly", + cli::TEST_ERAVM_ASSEMBLY_CONTRACT_INVALID_PATH, + ]; + + let result = cli::execute_zksolc(args)?; + result + .failure() + .stderr(predicate::str::contains("error: cannot parse operand")); + + Ok(()) +} + +#[test] +fn with_wrong_input_format() -> anyhow::Result<()> { common::setup()?; let args = &[ "--eravm-assembly", @@ -66,6 +83,41 @@ fn with_incompatible_input_format_without_output() -> anyhow::Result<()> { Ok(()) } +#[test] +fn with_incompatible_json_modes_combined_json() -> anyhow::Result<()> { + common::setup()?; + let args = &[ + cli::TEST_ERAVM_ASSEMBLY_CONTRACT_PATH, + "--eravm-assembly", + "--combined-json", + "anyarg", + ]; + + let result = cli::execute_zksolc(args)?; + result.failure().stderr(predicate::str::contains( + "Only one mode is allowed at the same time", + )); + + Ok(()) +} + +#[test] +fn with_incompatible_json_modes_standard_json() -> anyhow::Result<()> { + common::setup()?; + let args = &[ + cli::TEST_ERAVM_ASSEMBLY_CONTRACT_PATH, + "--eravm-assembly", + "--standard-json", + ]; + + let result = cli::execute_zksolc(args)?; + result.success().stdout(predicate::str::contains( + "Only one mode is allowed at the same time", + )); + + Ok(()) +} + #[test] fn with_incompatible_json_modes() -> anyhow::Result<()> { common::setup()?; @@ -157,3 +209,20 @@ fn with_standard_json_invalid() -> anyhow::Result<()> { Ok(()) } + +#[test] +fn with_standard_json_missing_file() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + "--standard-json", + cli::TEST_ERAVM_ASSEMBLY_STANDARD_JSON_MISSING_FILE_PATH, + ]; + + let result = cli::execute_zksolc(args)?; + result.success().stdout(predicate::str::contains( + "Error: File \\\"tests/data/contracts/eravm_assembly/Missing.zasm\\\" reading:", + )); + + Ok(()) +} diff --git a/era-compiler-solidity/tests/cli/libraries.rs b/era-compiler-solidity/tests/cli/libraries.rs index 82411bc2..825a929d 100644 --- a/era-compiler-solidity/tests/cli/libraries.rs +++ b/era-compiler-solidity/tests/cli/libraries.rs @@ -94,7 +94,8 @@ fn with_libraries_missing_contract_name() -> anyhow::Result<()> { common::setup()?; let args = &[ - cli::TEST_SOLIDITY_CONTRACT_PATH, + "--yul", + cli::TEST_YUL_CONTRACT_PATH, "--libraries", cli::LIBRARY_CONTRACT_NAME_MISSING, ]; @@ -102,7 +103,7 @@ fn with_libraries_missing_contract_name() -> anyhow::Result<()> { let result = cli::execute_zksolc(args)?; result.failure().stderr(predicate::str::contains( - "The library `tests/data/contracts/solidity/MiniMath.sol` contract name is missing.", + "Library `tests/data/contracts/solidity/MiniMath.sol` contract name is missing.", )); Ok(()) @@ -113,7 +114,8 @@ fn with_libraries_missing_address() -> anyhow::Result<()> { common::setup()?; let args = &[ - cli::TEST_SOLIDITY_CONTRACT_PATH, + "--yul", + cli::TEST_YUL_CONTRACT_PATH, "--libraries", cli::LIBRARY_ADDRESS_MISSING, ]; @@ -121,7 +123,7 @@ fn with_libraries_missing_address() -> anyhow::Result<()> { let result = cli::execute_zksolc(args)?; result.failure().stderr(predicate::str::contains( - "The library `tests/data/contracts/solidity/MiniMath.sol:MiniMath` address is missing.", + "Error: Library `tests/data/contracts/solidity/MiniMath.sol:MiniMath` address is missing.", )); Ok(()) @@ -132,7 +134,8 @@ fn with_libraries_invalid_address() -> anyhow::Result<()> { common::setup()?; let args = &[ - cli::TEST_SOLIDITY_CONTRACT_PATH, + "--yul", + cli::TEST_YUL_CONTRACT_PATH, "--libraries", cli::LIBRARY_ADDRESS_INVALID, ]; @@ -140,7 +143,7 @@ fn with_libraries_invalid_address() -> anyhow::Result<()> { let result = cli::execute_zksolc(args)?; result.failure().stderr(predicate::str::contains( - "Error: Library address is not prefixed with \"0x\"", + "Error: Invalid address `INVALID` of library `tests/data/contracts/solidity/MiniMath.sol:MiniMath`: Odd number of digits", )); Ok(()) diff --git a/era-compiler-solidity/tests/cli/link.rs b/era-compiler-solidity/tests/cli/link.rs index e318bf9d..20232a2c 100644 --- a/era-compiler-solidity/tests/cli/link.rs +++ b/era-compiler-solidity/tests/cli/link.rs @@ -79,8 +79,8 @@ fn with_libraries_contract_name_missing() -> anyhow::Result<()> { ]; let result = cli::execute_zksolc(args)?; - result.success().stdout(predicate::str::contains( - "{\"ignored\":{},\"linked\":{},\"unlinked\":{\"tests/data/bytecodes/linker.hex\":[\"test.sol:GreaterHelper\"]}}", + result.failure().stderr(predicate::str::contains( + "Error: Library `test.sol` contract name is missing.", )); Ok(()) @@ -99,7 +99,7 @@ fn with_libraries_address_missing() -> anyhow::Result<()> { let result = cli::execute_zksolc(args)?; result.failure().stderr(predicate::str::contains( - "Address of the library `test.sol:GreaterHelper` is missing.", + "Error: Library `test.sol:GreaterHelper` address is missing.", )); Ok(()) @@ -118,7 +118,7 @@ fn with_libraries_address_invalid() -> anyhow::Result<()> { let result = cli::execute_zksolc(args)?; result.failure().stderr(predicate::str::contains( - "Invalid address of library `test.sol:GreaterHelper`: Odd number of digits.", + "Error: Invalid address `XINVALID` of library `test.sol:GreaterHelper`: Invalid character \'X\' at position 0.", )); Ok(()) @@ -137,7 +137,7 @@ fn with_libraries_address_incorrect_size() -> anyhow::Result<()> { let result = cli::execute_zksolc(args)?; result.failure().stderr(predicate::str::contains( - "Invalid address size of library `test.sol:GreaterHelper`: expected 20, found 4.", + "Error: Incorrect size of address `0x12345678` of library `test.sol:GreaterHelper`: expected 20, found 4.", )); Ok(()) diff --git a/era-compiler-solidity/tests/cli/llvm_ir.rs b/era-compiler-solidity/tests/cli/llvm_ir.rs index da8bf54a..72bcaf4f 100644 --- a/era-compiler-solidity/tests/cli/llvm_ir.rs +++ b/era-compiler-solidity/tests/cli/llvm_ir.rs @@ -5,15 +5,12 @@ use predicates::prelude::*; fn with_llvm_ir() -> anyhow::Result<()> { common::setup()?; let args = &[cli::TEST_LLVM_IR_CONTRACT_PATH, "--llvm-ir"]; - let invalid_args = &["--llvm-ir", "anyarg"]; let result = cli::execute_zksolc(args)?; - let invalid_result = cli::execute_zksolc(invalid_args)?; result.success().stderr(predicate::str::contains( "Compiler run successful. No output requested.", )); - invalid_result.failure(); Ok(()) } @@ -31,6 +28,20 @@ fn with_llvm_ir_duplicate_flag() -> anyhow::Result<()> { Ok(()) } +#[test] +fn with_llvm_ir_invalid() -> anyhow::Result<()> { + common::setup()?; + + let args = &["--llvm-ir", cli::TEST_LLVM_IR_CONTRACT_INVALID_PATH]; + + let result = cli::execute_zksolc(args)?; + result.failure().stderr(predicate::str::contains( + "error: use of undefined value \'%runtime\'", + )); + + Ok(()) +} + #[test] fn with_wrong_input_format() -> anyhow::Result<()> { common::setup()?; @@ -44,6 +55,20 @@ fn with_wrong_input_format() -> anyhow::Result<()> { Ok(()) } +#[test] +fn with_incompatible_input_format_without_output() -> anyhow::Result<()> { + common::setup()?; + + let args = &["--eravm-assembly", cli::TEST_BROKEN_INPUT_PATH]; + + let result = cli::execute_zksolc(args)?; + result + .failure() + .stderr(predicate::str::contains("error: cannot parse operand")); + + Ok(()) +} + #[test] fn with_incompatible_json_modes_combined_json() -> anyhow::Result<()> { common::setup()?; @@ -65,7 +90,11 @@ fn with_incompatible_json_modes_combined_json() -> anyhow::Result<()> { #[test] fn with_incompatible_json_modes_standard_json() -> anyhow::Result<()> { common::setup()?; - let args = &[cli::TEST_YUL_CONTRACT_PATH, "--llvm-ir", "--standard-json"]; + let args = &[ + cli::TEST_LLVM_IR_CONTRACT_PATH, + "--llvm-ir", + "--standard-json", + ]; let result = cli::execute_zksolc(args)?; result.success().stdout(predicate::str::contains( @@ -91,3 +120,20 @@ fn with_standard_json_invalid() -> anyhow::Result<()> { Ok(()) } + +#[test] +fn with_standard_json_missing_file() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + "--standard-json", + cli::TEST_LLVM_IR_STANDARD_JSON_MISSING_FILE_PATH, + ]; + + let result = cli::execute_zksolc(args)?; + result.success().stdout(predicate::str::contains( + "Error: File \\\"tests/data/contracts/llvm_ir/Missing.ll\\\" reading:", + )); + + Ok(()) +} diff --git a/era-compiler-solidity/tests/cli/mod.rs b/era-compiler-solidity/tests/cli/mod.rs index 62f25047..068dd47b 100644 --- a/era-compiler-solidity/tests/cli/mod.rs +++ b/era-compiler-solidity/tests/cli/mod.rs @@ -46,6 +46,15 @@ mod threads; mod version; mod yul; +macro_rules! test_script_path { + ($name:ident, $base:expr) => { + #[cfg(target_os = "windows")] + pub const $name: &str = concat!($base, ".bat"); + #[cfg(not(target_os = "windows"))] + pub const $name: &str = concat!($base, ".sh"); + }; +} + /// A test input file. pub const TEST_CONTRACTS_PATH: &str = "tests/data/contracts/"; @@ -55,6 +64,9 @@ pub const TEST_SOLIDITY_CONTRACT_NAME: &str = "Test.sol"; /// A test input file. pub const TEST_SOLIDITY_CONTRACT_PATH: &str = "tests/data/contracts/solidity/Test.sol"; +/// A test input file. +pub const TEST_SOLIDITY_CONTRACT_GREETER_PATH: &str = "tests/data/contracts/solidity/Greeter.sol"; + /// A test input file. pub const SOLIDITY_BIN_OUTPUT_NAME: &str = "C.zbin"; @@ -67,9 +79,16 @@ pub const TEST_YUL_CONTRACT_PATH: &str = "tests/data/contracts/yul/Default.yul"; /// A test input file. pub const TEST_LLVM_IR_CONTRACT_PATH: &str = "tests/data/contracts/llvm_ir/Test.ll"; +/// A test input file. +pub const TEST_LLVM_IR_CONTRACT_INVALID_PATH: &str = "tests/data/contracts/llvm_ir/Invalid.ll"; + /// A test input file. pub const TEST_ERAVM_ASSEMBLY_CONTRACT_PATH: &str = "tests/data/contracts/eravm_assembly/Test.zasm"; +/// A test input file. +pub const TEST_ERAVM_ASSEMBLY_CONTRACT_INVALID_PATH: &str = + "tests/data/contracts/eravm_assembly/Invalid.zasm"; + /// A test input file. pub const TEST_SOLIDITY_STANDARD_JSON_NON_EXISTENT_PATH: &str = "tests/data/standard_json_input/non_existent.json"; @@ -82,10 +101,6 @@ pub const TEST_SOLIDITY_STANDARD_JSON_INVALID_UTF8_PATH: &str = pub const TEST_SOLIDITY_STANDARD_JSON_SOLC_PATH: &str = "tests/data/standard_json_input/solidity_solc.json"; -/// A test input file. -pub const TEST_SOLIDITY_STANDARD_JSON_SOLC_RECURSION_PATH: &str = - "tests/data/standard_json_input/solidity_solc_recursion.json"; - /// A test input file. pub const TEST_SOLIDITY_STANDARD_JSON_SOLC_EMPTY_SOURCES_PATH: &str = "tests/data/standard_json_input/solidity_solc_empty_sources.json"; @@ -99,7 +114,15 @@ pub const TEST_SOLIDITY_STANDARD_JSON_SOLC_INVALID_PATH: &str = "tests/data/standard_json_input/solidity_solc_invalid.json"; /// A test input file. -pub const TEST_SOLIDITY_STANDARD_JSON_INVALID_BY_ZKSOLC_PATH: &str = +pub const TEST_SOLIDITY_STANDARD_JSON_ZKSOLC_RECURSION_PATH: &str = + "tests/data/standard_json_input/solidity_zksolc_recursion.json"; + +/// A test input file. +pub const TEST_SOLIDITY_STANDARD_JSON_ZKSOLC_INTERNAL_FUNCTION_POINTERS_PATH: &str = + "tests/data/standard_json_input/solidity_zksolc_internal_function_pointers.json"; + +/// A test input file. +pub const TEST_SOLIDITY_STANDARD_JSON_ZKSOLC_INVALID_PATH: &str = "tests/data/standard_json_input/solidity_zksolc_invalid.json"; /// A test input file. @@ -129,6 +152,10 @@ pub const TEST_LLVM_IR_STANDARD_JSON_PATH: &str = pub const TEST_LLVM_IR_STANDARD_JSON_INVALID_PATH: &str = "tests/data/standard_json_input/llvm_ir_urls_invalid.json"; +/// A test input file. +pub const TEST_LLVM_IR_STANDARD_JSON_MISSING_FILE_PATH: &str = + "tests/data/standard_json_input/llvm_ir_urls_missing_file.json"; + /// A test input file. pub const TEST_ERAVM_ASSEMBLY_STANDARD_JSON_PATH: &str = "tests/data/standard_json_input/eravm_assembly_urls.json"; @@ -137,6 +164,10 @@ pub const TEST_ERAVM_ASSEMBLY_STANDARD_JSON_PATH: &str = pub const TEST_ERAVM_ASSEMBLY_STANDARD_JSON_INVALID_PATH: &str = "tests/data/standard_json_input/eravm_assembly_urls_invalid.json"; +/// A test input file. +pub const TEST_ERAVM_ASSEMBLY_STANDARD_JSON_MISSING_FILE_PATH: &str = + "tests/data/standard_json_input/eravm_assembly_urls_missing_file.json"; + /// A test input file. pub const TEST_JSON_CONTRACT_PATH_SUPPRESSED_ERRORS_AND_WARNINGS: &str = "tests/data/standard_json_input/suppressed_errors_and_warnings.json"; @@ -167,6 +198,32 @@ pub const TEST_LINKER_BYTECODE_COPY_PATH: &str = "tests/data/bytecodes/linker_co /// The broken input file path. pub const TEST_BROKEN_INPUT_PATH: &str = "tests/data/broken.bad"; +/// Shell script test constants. +test_script_path!( + TEST_SCRIPT_SOLC_VERSION_OUTPUT_ERROR_PATH, + "tests/scripts/solc_version_output_error" +); +test_script_path!( + TEST_SCRIPT_SOLC_VERSION_TOO_OLD_PATH, + "tests/scripts/solc_version_too_old" +); +test_script_path!( + TEST_SCRIPT_SOLC_VERSION_TOO_NEW_PATH, + "tests/scripts/solc_version_too_new" +); +test_script_path!( + TEST_SCRIPT_SOLC_VERSION_NOT_ENOUGH_LINES_PATH, + "tests/scripts/solc_version_not_enough_lines" +); +test_script_path!( + TEST_SCRIPT_SOLC_VERSION_NOT_ENOUGH_WORDS_IN_2ND_LINE_PATH, + "tests/scripts/solc_version_not_enough_words_in_2nd_line" +); +test_script_path!( + TEST_SCRIPT_SOLC_VERSION_PARSING_ERROR_PATH, + "tests/scripts/solc_version_parsing_error" +); + /// A test constant. pub const LIBRARY_DEFAULT: &str = "tests/data/contracts/solidity/MiniMath.sol:MiniMath=0xF9702469Dfb84A9aC171E284F71615bd3D3f1EdC"; @@ -193,7 +250,7 @@ pub const LIBRARY_LINKER_CONTRACT_NAME_MISSING: &str = pub const LIBRARY_LINKER_ADDRESS_MISSING: &str = "test.sol:GreaterHelper"; /// A test constant. -pub const LIBRARY_LINKER_ADDRESS_INVALID: &str = "test.sol:GreaterHelper=INVALID"; +pub const LIBRARY_LINKER_ADDRESS_INVALID: &str = "test.sol:GreaterHelper=XINVALID"; /// A test constant. pub const LIBRARY_LINKER_ADDRESS_INCORRECT_SIZE: &str = "test.sol:GreaterHelper=0x12345678"; @@ -236,6 +293,7 @@ pub fn execute_zksolc_with_target( pub fn execute_solc(args: &[&str]) -> anyhow::Result { let solc_compiler = crate::common::get_solc_compiler( &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, )? .executable; let mut cmd = Command::new(solc_compiler); diff --git a/era-compiler-solidity/tests/cli/solc.rs b/era-compiler-solidity/tests/cli/solc.rs index dacbdc3a..e213c18c 100644 --- a/era-compiler-solidity/tests/cli/solc.rs +++ b/era-compiler-solidity/tests/cli/solc.rs @@ -7,18 +7,20 @@ use predicates::prelude::predicate; fn with_solc() -> anyhow::Result<()> { common::setup()?; - let mut zksolc = Command::cargo_bin(era_compiler_solidity::DEFAULT_EXECUTABLE_NAME)?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; - let assert = zksolc - .arg(cli::TEST_SOLIDITY_CONTRACT_PATH) - .arg("--solc") - .arg(solc_compiler) - .assert(); + let args = &[ + cli::TEST_SOLIDITY_CONTRACT_PATH, + "--solc", + solc_compiler.as_str(), + ]; - assert + let result = cli::execute_zksolc(args)?; + result .success() .stderr(predicate::str::contains("Compiler run successful")); @@ -31,12 +33,11 @@ fn without_solc() -> anyhow::Result<()> { let mut zksolc = Command::cargo_bin(era_compiler_solidity::DEFAULT_EXECUTABLE_NAME)?; - let assert = zksolc + let result = zksolc .arg(cli::TEST_SOLIDITY_CONTRACT_PATH) .env("PATH", "./solc-bin") .assert(); - - assert + result .success() .stderr(predicate::str::contains("Compiler run successful")); @@ -47,19 +48,21 @@ fn without_solc() -> anyhow::Result<()> { fn with_solc_standard_json_mode() -> anyhow::Result<()> { common::setup()?; - let mut zksolc = Command::cargo_bin(era_compiler_solidity::DEFAULT_EXECUTABLE_NAME)?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; - - let assert = zksolc - .arg("--solc") - .arg(solc_compiler) - .arg("--standard-json") - .arg(cli::TEST_SOLIDITY_STANDARD_JSON_SOLC_PATH) - .assert(); + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; - assert + let args = &[ + "--solc", + solc_compiler.as_str(), + "--standard-json", + cli::TEST_SOLIDITY_STANDARD_JSON_SOLC_PATH, + ]; + + let result = cli::execute_zksolc(args)?; + result .success() .stdout(predicate::str::contains("bytecode")); @@ -70,16 +73,15 @@ fn with_solc_standard_json_mode() -> anyhow::Result<()> { fn without_solc_standard_json_mode() -> anyhow::Result<()> { common::setup()?; - let mut zksolc = Command::cargo_bin(era_compiler_solidity::DEFAULT_EXECUTABLE_NAME)?; - - let assert = zksolc - .arg("--standard-json") - .arg(cli::TEST_SOLIDITY_STANDARD_JSON_SOLC_PATH) - .assert(); + let args = &[ + "--standard-json", + cli::TEST_SOLIDITY_STANDARD_JSON_SOLC_PATH, + ]; - assert.success().stdout(predicate::str::contains( - "The `solc` executable not found in ${PATH}", - )); + let result = cli::execute_zksolc(args)?; + result + .success() + .stdout(predicate::str::contains("bytecode")); Ok(()) } @@ -88,9 +90,11 @@ fn without_solc_standard_json_mode() -> anyhow::Result<()> { fn with_solc_llvm_ir_mode() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--solc", @@ -112,9 +116,11 @@ fn with_solc_llvm_ir_mode() -> anyhow::Result<()> { fn with_solc_eravm_assembly_mode() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--solc", @@ -131,3 +137,134 @@ fn with_solc_eravm_assembly_mode() -> anyhow::Result<()> { Ok(()) } + +#[test] +fn with_solc_not_found() -> anyhow::Result<()> { + common::setup()?; + + let path = "solc-not-found"; + let args = &[cli::TEST_SOLIDITY_CONTRACT_PATH, "--solc", path]; + + let result = cli::execute_zksolc(args)?; + result.failure().stderr(predicate::str::contains( + format!("The `{path}` executable not found:").as_str(), + )); + + Ok(()) +} + +#[test] +fn with_solc_version_output_error() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + cli::TEST_SOLIDITY_CONTRACT_PATH, + "--solc", + cli::TEST_SCRIPT_SOLC_VERSION_OUTPUT_ERROR_PATH, + ]; + + let result = cli::execute_zksolc(args)?; + result + .failure() + .stderr(predicate::str::contains("version getting:")); + + Ok(()) +} + +#[test] +fn with_solc_version_too_old() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + cli::TEST_SOLIDITY_CONTRACT_PATH, + "--solc", + cli::TEST_SCRIPT_SOLC_VERSION_TOO_OLD_PATH, + ]; + + let version_supported = era_compiler_solidity::SolcCompiler::FIRST_SUPPORTED_VERSION; + let mut version_not_supported = version_supported.clone(); + version_not_supported.patch -= 1; + + let result = cli::execute_zksolc(args)?; + result + .failure() + .stderr(predicate::str::contains(format!("versions older than {version_supported} are not supported, found {version_not_supported}.").as_str())); + + Ok(()) +} + +#[test] +fn with_solc_version_too_new() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + cli::TEST_SOLIDITY_CONTRACT_PATH, + "--solc", + cli::TEST_SCRIPT_SOLC_VERSION_TOO_NEW_PATH, + ]; + + let version_supported = era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION; + let mut version_not_supported = version_supported.clone(); + version_not_supported.patch += 1; + + let result = cli::execute_zksolc(args)?; + result + .failure() + .stderr(predicate::str::contains(format!("versions newer than {version_supported} are not supported, found {version_not_supported}.").as_str())); + + Ok(()) +} + +#[test] +fn with_solc_version_not_enough_lines() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + cli::TEST_SOLIDITY_CONTRACT_PATH, + "--solc", + cli::TEST_SCRIPT_SOLC_VERSION_NOT_ENOUGH_LINES_PATH, + ]; + + let result = cli::execute_zksolc(args)?; + result.failure().stderr(predicate::str::contains( + "version parsing: not enough lines.", + )); + + Ok(()) +} + +#[test] +fn with_solc_version_not_enough_words_in_2nd_line() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + cli::TEST_SOLIDITY_CONTRACT_PATH, + "--solc", + cli::TEST_SCRIPT_SOLC_VERSION_NOT_ENOUGH_WORDS_IN_2ND_LINE_PATH, + ]; + + let result = cli::execute_zksolc(args)?; + result.failure().stderr(predicate::str::contains( + "version parsing: not enough words in the 2nd line.", + )); + + Ok(()) +} + +#[test] +fn with_solc_version_parsing_error() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + cli::TEST_SOLIDITY_CONTRACT_PATH, + "--solc", + cli::TEST_SCRIPT_SOLC_VERSION_PARSING_ERROR_PATH, + ]; + + let result = cli::execute_zksolc(args)?; + result + .failure() + .stderr(predicate::str::contains("version parsing:")); + + Ok(()) +} diff --git a/era-compiler-solidity/tests/cli/standard_json.rs b/era-compiler-solidity/tests/cli/standard_json.rs index 690ad45e..fae726e0 100644 --- a/era-compiler-solidity/tests/cli/standard_json.rs +++ b/era-compiler-solidity/tests/cli/standard_json.rs @@ -5,9 +5,11 @@ use predicates::prelude::*; fn with_standard_json() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--solc", @@ -60,9 +62,11 @@ fn with_standard_json_incompatible_input() -> anyhow::Result<()> { fn with_standard_json_invalid_by_solc() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--solc", @@ -96,19 +100,21 @@ fn with_standard_json_invalid_by_solc() -> anyhow::Result<()> { fn with_standard_json_invalid_by_zksolc() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--solc", solc_compiler.as_str(), "--standard-json", - cli::TEST_SOLIDITY_STANDARD_JSON_INVALID_BY_ZKSOLC_PATH, + cli::TEST_SOLIDITY_STANDARD_JSON_ZKSOLC_INVALID_PATH, ]; let args_solc = &[ "--standard-json", - cli::TEST_SOLIDITY_STANDARD_JSON_INVALID_BY_ZKSOLC_PATH, + cli::TEST_SOLIDITY_STANDARD_JSON_ZKSOLC_INVALID_PATH, ]; let result = cli::execute_zksolc(args)?; @@ -126,9 +132,11 @@ fn with_standard_json_invalid_by_zksolc() -> anyhow::Result<()> { fn with_standard_json_with_suppressed_messages() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--solc", @@ -162,7 +170,24 @@ fn with_standard_json_recursion() -> anyhow::Result<()> { let args = &[ "--standard-json", - cli::TEST_SOLIDITY_STANDARD_JSON_SOLC_RECURSION_PATH, + cli::TEST_SOLIDITY_STANDARD_JSON_ZKSOLC_RECURSION_PATH, + ]; + + let result = cli::execute_zksolc(args)?; + result + .success() + .stdout(predicate::str::contains("bytecode")); + + Ok(()) +} + +#[test] +fn with_standard_json_internal_function_pointers() -> anyhow::Result<()> { + common::setup()?; + + let args = &[ + "--standard-json", + cli::TEST_SOLIDITY_STANDARD_JSON_ZKSOLC_INTERNAL_FUNCTION_POINTERS_PATH, ]; let result = cli::execute_zksolc(args)?; @@ -398,9 +423,11 @@ fn with_standard_json_neither_urls_nor_content() -> anyhow::Result<()> { fn with_standard_json_yul_with_solc() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--solc", @@ -443,9 +470,11 @@ fn with_standard_json_llvm_ir() -> anyhow::Result<()> { fn with_standard_json_llvm_ir_with_solc() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--standard-json", @@ -483,9 +512,11 @@ fn with_standard_json_eravm_assembly() -> anyhow::Result<()> { fn with_standard_json_eravm_assembly_with_solc() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--standard-json", diff --git a/era-compiler-solidity/tests/cli/suppress_errors.rs b/era-compiler-solidity/tests/cli/suppress_errors.rs index 8a34fee7..67a6d6bd 100644 --- a/era-compiler-solidity/tests/cli/suppress_errors.rs +++ b/era-compiler-solidity/tests/cli/suppress_errors.rs @@ -64,9 +64,11 @@ fn with_suppressed_errors_invalid() -> anyhow::Result<()> { fn with_suppressed_warnings_invalid_standard_json() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--solc", @@ -87,9 +89,11 @@ fn with_suppressed_warnings_invalid_standard_json() -> anyhow::Result<()> { fn with_suppressed_errors_invalid_standard_json() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--solc", diff --git a/era-compiler-solidity/tests/cli/yul.rs b/era-compiler-solidity/tests/cli/yul.rs index 64c07184..a4013c72 100644 --- a/era-compiler-solidity/tests/cli/yul.rs +++ b/era-compiler-solidity/tests/cli/yul.rs @@ -136,9 +136,11 @@ fn with_yul_and_standard_json() -> anyhow::Result<()> { fn with_yul_and_solc() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ cli::TEST_YUL_CONTRACT_PATH, @@ -159,9 +161,11 @@ fn with_yul_and_solc() -> anyhow::Result<()> { fn with_yul_and_solc_and_eravm_extensions() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ cli::TEST_YUL_CONTRACT_PATH, @@ -183,9 +187,11 @@ fn with_yul_and_solc_and_eravm_extensions() -> anyhow::Result<()> { fn with_standard_json_and_solc_invalid_by_solc() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--solc", @@ -223,9 +229,11 @@ fn with_standard_json_invalid_by_zksolc() -> anyhow::Result<()> { fn with_standard_json_and_solc_invalid_by_zksolc() -> anyhow::Result<()> { common::setup()?; - let solc_compiler = - common::get_solc_compiler(&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION)? - .executable; + let solc_compiler = common::get_solc_compiler( + &era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION, + false, + )? + .executable; let args = &[ "--solc", diff --git a/era-compiler-solidity/tests/common/mod.rs b/era-compiler-solidity/tests/common/mod.rs index 99b3e8e6..88f0ebe8 100644 --- a/era-compiler-solidity/tests/common/mod.rs +++ b/era-compiler-solidity/tests/common/mod.rs @@ -15,7 +15,8 @@ use assert_cmd::Command; use era_compiler_solidity::error_type::ErrorType; use era_compiler_solidity::project::Project; -use era_compiler_solidity::solc::codegen::Codegen as SolcCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::libraries::Libraries as SolcStandardJsonInputSettingsLibraries; use era_compiler_solidity::solc::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata; use era_compiler_solidity::solc::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer; use era_compiler_solidity::solc::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection; @@ -29,64 +30,93 @@ use era_compiler_solidity::warning_type::WarningType; /// Synchronization for `solc` downloads. static DOWNLOAD_SOLC: Once = Once::new(); -/// Download directory for `solc` binaries. +/// Synchronization for upstream `solc` downloads. +static DOWNLOAD_SOLC_UPSTREAM: Once = Once::new(); + +/// Download directory for `solc` executables. pub const SOLC_DOWNLOAD_DIRECTORY: &str = "solc-bin"; -/// Path to the `solc` binary configuration file. +/// Download directory for upstream `solc` executables. +pub const SOLC_UPSTREAM_DOWNLOAD_DIRECTORY: &str = "solc-bin-upstream"; + +/// Path to the `solc` executable configuration file. pub const SOLC_BIN_CONFIG_PATH: &str = "tests/solc-bin.json"; +/// Path to the upstream `solc` executable configuration file. +pub const SOLC_BIN_UPSTREAM_CONFIG_PATH: &str = "tests/solc-bin-upstream.json"; + /// -/// Returns the `solc` compiler for the given version. +/// Setup required test dependencies. /// -pub fn get_solc_compiler(solc_version: &semver::Version) -> anyhow::Result { - let solc_path = PathBuf::from(SOLC_DOWNLOAD_DIRECTORY).join(format!( - "{}-{solc_version}{}", - SolcCompiler::DEFAULT_EXECUTABLE_NAME, - std::env::consts::EXE_SUFFIX, - )); +pub fn setup() -> anyhow::Result<()> { + // Download `solc` executables once + DOWNLOAD_SOLC.call_once(|| { + download_executables(SOLC_BIN_CONFIG_PATH, true) + .expect("Unable to download `solc` executables"); + }); + if cfg!(not(all(target_arch = "aarch64", target_os = "linux"))) { + // Download upstream `solc` executables once + DOWNLOAD_SOLC_UPSTREAM.call_once(|| { + download_executables(SOLC_BIN_UPSTREAM_CONFIG_PATH, false) + .expect("Unable to download upstream `solc` executables"); + }); + } - SolcCompiler::new(solc_path.to_str().unwrap()) + // Set the `zksolc` binary path + let zksolc_bin = Command::cargo_bin(era_compiler_solidity::DEFAULT_EXECUTABLE_NAME)?; + let _ = era_compiler_solidity::process::EXECUTABLE.set(PathBuf::from(zksolc_bin.get_program())); + + // Enable LLVM pretty stack trace + inkwell::support::enable_llvm_pretty_stack_trace(); + + Ok(()) } /// -/// Downloads the necessary compiler binaries. +/// Downloads the necessary compiler executables. /// -pub fn download_binaries() -> anyhow::Result<()> { +pub fn download_executables(config_path: &str, create_alias: bool) -> anyhow::Result<()> { let mut http_client_builder = reqwest::blocking::ClientBuilder::new(); http_client_builder = http_client_builder.connect_timeout(Duration::from_secs(60)); http_client_builder = http_client_builder.pool_idle_timeout(Duration::from_secs(60)); http_client_builder = http_client_builder.timeout(Duration::from_secs(60)); let http_client = http_client_builder.build()?; - let config_path = Path::new(SOLC_BIN_CONFIG_PATH); + let config_path = Path::new(config_path); era_compiler_downloader::Downloader::new(http_client.clone()).download(config_path)?; - // Copy the latest `solc-*` binary to `solc` for CLI tests - let latest_solc = - PathBuf::from(get_solc_compiler(&SolcCompiler::LAST_SUPPORTED_VERSION)?.executable); - let mut solc = latest_solc.clone(); - solc.set_file_name(format!("solc{}", std::env::consts::EXE_SUFFIX)); - std::fs::copy(latest_solc, solc)?; + if create_alias { + // Copy the latest `solc-*` binary to `solc` for CLI tests + let latest_solc = PathBuf::from( + get_solc_compiler(&SolcCompiler::LAST_SUPPORTED_VERSION, false)?.executable, + ); + let mut solc = latest_solc.clone(); + solc.set_file_name(format!("solc{}", std::env::consts::EXE_SUFFIX)); + std::fs::copy(latest_solc, solc)?; + } Ok(()) } /// -/// Setup required test dependencies. +/// Returns the `solc` compiler for the given version. /// -pub fn setup() -> anyhow::Result<()> { - // Download `solc` binaries once - DOWNLOAD_SOLC.call_once(|| { - download_binaries().expect("Unable to download solc binaries. Aborting..."); - }); - - // Set the `zksolc` binary path - let zksolc_bin = Command::cargo_bin(era_compiler_solidity::DEFAULT_EXECUTABLE_NAME)?; - let _ = era_compiler_solidity::process::EXECUTABLE.set(PathBuf::from(zksolc_bin.get_program())); +pub fn get_solc_compiler( + version: &semver::Version, + use_upstream: bool, +) -> anyhow::Result { + let directory = if use_upstream { + SOLC_UPSTREAM_DOWNLOAD_DIRECTORY + } else { + SOLC_DOWNLOAD_DIRECTORY + }; + let solc_path = PathBuf::from(directory).join(format!( + "{}-{version}{}", + SolcCompiler::DEFAULT_EXECUTABLE_NAME, + std::env::consts::EXE_SUFFIX, + )); - // Enable LLVM pretty stack trace - inkwell::support::enable_llvm_pretty_stack_trace(); - Ok(()) + SolcCompiler::try_from_path(solc_path.to_str().expect("Always valid")) } /// @@ -94,15 +124,16 @@ pub fn setup() -> anyhow::Result<()> { /// pub fn build_solidity( sources: BTreeMap, - libraries: BTreeMap>, + libraries: SolcStandardJsonInputSettingsLibraries, + metadata_hash_type: era_compiler_common::HashType, remappings: BTreeSet, solc_version: &semver::Version, - solc_pipeline: SolcCodegen, + solc_codegen: SolcStandardJsonInputSettingsCodegen, optimizer_settings: era_compiler_llvm_context::OptimizerSettings, ) -> anyhow::Result { self::setup()?; - let solc_compiler = get_solc_compiler(solc_version)?; + let solc_compiler = get_solc_compiler(solc_version, false)?; era_compiler_llvm_context::initialize_target(era_compiler_common::Target::EraVM); @@ -116,10 +147,10 @@ pub fn build_solidity( libraries.clone(), remappings, SolcStandardJsonInputSettingsOptimizer::default(), - Some(solc_pipeline), + Some(solc_codegen), None, true, - SolcStandardJsonInputSettingsSelection::new_required(Some(solc_pipeline)), + SolcStandardJsonInputSettingsSelection::new_required(solc_codegen), SolcStandardJsonInputSettingsMetadata::default(), vec![], vec![], @@ -130,7 +161,7 @@ pub fn build_solidity( let mut solc_output = solc_compiler.standard_json( &mut solc_input, - Some(solc_pipeline), + Some(solc_codegen), &mut vec![], None, vec![], @@ -138,9 +169,11 @@ pub fn build_solidity( )?; solc_output.collect_errors()?; + let linker_symbols = libraries.as_linker_symbols()?; + let project = Project::try_from_solc_output( libraries, - solc_pipeline, + solc_codegen, &mut solc_output, &solc_compiler, None, @@ -150,7 +183,8 @@ pub fn build_solidity( let build = project.compile_to_eravm( &mut vec![], true, - era_compiler_common::HashType::Ipfs, + linker_symbols, + metadata_hash_type, optimizer_settings, vec![], false, @@ -168,13 +202,13 @@ pub fn build_solidity( /// pub fn build_solidity_and_detect_missing_libraries( sources: BTreeMap, - libraries: BTreeMap>, + libraries: SolcStandardJsonInputSettingsLibraries, solc_version: &semver::Version, - solc_pipeline: SolcCodegen, + solc_codegen: SolcStandardJsonInputSettingsCodegen, ) -> anyhow::Result { self::setup()?; - let solc_compiler = get_solc_compiler(solc_version)?; + let solc_compiler = get_solc_compiler(solc_version, false)?; era_compiler_llvm_context::initialize_target(era_compiler_common::Target::EraVM); @@ -188,10 +222,10 @@ pub fn build_solidity_and_detect_missing_libraries( libraries.clone(), BTreeSet::new(), SolcStandardJsonInputSettingsOptimizer::default(), - Some(solc_pipeline), + Some(solc_codegen), None, false, - SolcStandardJsonInputSettingsSelection::new_required(Some(solc_pipeline)), + SolcStandardJsonInputSettingsSelection::new_required(solc_codegen), SolcStandardJsonInputSettingsMetadata::default(), vec![], vec![], @@ -202,7 +236,7 @@ pub fn build_solidity_and_detect_missing_libraries( let mut solc_output = solc_compiler.standard_json( &mut solc_input, - Some(solc_pipeline), + Some(solc_codegen), &mut vec![], None, vec![], @@ -211,7 +245,7 @@ pub fn build_solidity_and_detect_missing_libraries( let project = Project::try_from_solc_output( libraries, - solc_pipeline, + solc_codegen, &mut solc_output, &solc_compiler, None, @@ -243,7 +277,7 @@ pub fn build_yul(sources: BTreeMap) -> anyhow::Result) -> anyhow::Result>, + libraries: SolcStandardJsonInputSettingsLibraries, solc_version: &semver::Version, - solc_pipeline: SolcCodegen, - skip_for_zksync_edition: bool, + solc_codegen: SolcStandardJsonInputSettingsCodegen, + solc_use_upstream: bool, suppressed_errors: Vec, suppressed_warnings: Vec, ) -> anyhow::Result { self::setup()?; - let solc_compiler = get_solc_compiler(solc_version)?; - - if skip_for_zksync_edition && solc_compiler.version.l2_revision.is_some() { - return Ok(true); - } + let solc_compiler = get_solc_compiler(solc_version, solc_use_upstream)?; let mut sources = BTreeMap::new(); sources.insert( @@ -412,10 +450,10 @@ pub fn check_solidity_message( libraries, BTreeSet::new(), SolcStandardJsonInputSettingsOptimizer::default(), - Some(solc_pipeline), + Some(solc_codegen), None, false, - SolcStandardJsonInputSettingsSelection::new_required(Some(solc_pipeline)), + SolcStandardJsonInputSettingsSelection::new_required(solc_codegen), SolcStandardJsonInputSettingsMetadata::default(), vec![], suppressed_errors, @@ -426,7 +464,7 @@ pub fn check_solidity_message( let solc_output = solc_compiler.standard_json( &mut solc_input, - Some(solc_pipeline), + Some(solc_codegen), &mut vec![], None, vec![], @@ -434,7 +472,6 @@ pub fn check_solidity_message( )?; let contains_warning = solc_output .errors - .ok_or_else(|| anyhow::anyhow!("Solidity compiler messages not found"))? .iter() .any(|error| error.formatted_message.contains(warning_substring)); diff --git a/era-compiler-solidity/tests/data/broken.bad b/era-compiler-solidity/tests/data/broken.bad index d6da9820..28baddeb 100644 --- a/era-compiler-solidity/tests/data/broken.bad +++ b/era-compiler-solidity/tests/data/broken.bad @@ -1 +1 @@ -This is a broken file that must be rejected by the compiler. +This is a broken file that must be rejected for various reasons. diff --git a/era-compiler-solidity/tests/data/contracts/solidity/InternalFunctionPointers.sol b/era-compiler-solidity/tests/data/contracts/solidity/InternalFunctionPointers.sol new file mode 100644 index 00000000..d104b6fa --- /dev/null +++ b/era-compiler-solidity/tests/data/contracts/solidity/InternalFunctionPointers.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Unlicensed + +pragma solidity >=0.4.22; + +contract Test { + uint x; + + function() internal pure returns (uint) fp1; + function() internal pure returns (uint) fp2; + + function c0() internal pure returns (uint) { return 0xc0; } + function c1() internal pure returns (uint) { return 0xc1; } + + constructor(int i) public { + if (i == 0) { fp1 = c0; } + if (i == 1) { fp2 = c1; } + x = fp1() + fp2(); + } + + function m() public view returns (uint) { + return x + fp1() + fp2(); + } +} \ No newline at end of file diff --git a/era-compiler-solidity/tests/data/contracts/solidity/Recursion.sol b/era-compiler-solidity/tests/data/contracts/solidity/Recursion.sol index 89edee1c..d9024a46 100644 --- a/era-compiler-solidity/tests/data/contracts/solidity/Recursion.sol +++ b/era-compiler-solidity/tests/data/contracts/solidity/Recursion.sol @@ -3,6 +3,12 @@ pragma solidity >=0.4.16; contract Test { + uint64 x; + + constructor(uint8 i) public { + x = fib(i); + } + function fib(uint8 n) public pure returns(uint64) { if (n <= 1) { return n; diff --git a/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls.json b/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls.json index b244c185..29442c30 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls.json +++ b/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls.json @@ -22,6 +22,9 @@ ] } }, + "metadata": { + "hashType": "ipfs" + }, "libraries": {} } } \ No newline at end of file diff --git a/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls_invalid.json b/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls_invalid.json index 8390a4c3..6cf1bb56 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls_invalid.json +++ b/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls_invalid.json @@ -22,6 +22,9 @@ ] } }, + "metadata": { + "hashType": "ipfs" + }, "libraries": {} } } \ No newline at end of file diff --git a/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls_missing.json b/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls_missing.json new file mode 100644 index 00000000..bbc63abd --- /dev/null +++ b/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls_missing.json @@ -0,0 +1,27 @@ +{ + "language": "EraVM Assembly", + "sources": { + "Test": { + "urls": [ + "tests/data/contracts/eravm_assembly/Missing.zasm" + ] + } + }, + "settings": { + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "": [ + "metadata" + ], + "*": [ + "abi", + "evm.methodIdentifiers" + ] + } + }, + "libraries": {} + } + } \ No newline at end of file diff --git a/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls_missing_file.json b/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls_missing_file.json new file mode 100644 index 00000000..82fffb8a --- /dev/null +++ b/era-compiler-solidity/tests/data/standard_json_input/eravm_assembly_urls_missing_file.json @@ -0,0 +1,30 @@ +{ + "language": "EraVM Assembly", + "sources": { + "Test": { + "urls": [ + "tests/data/contracts/eravm_assembly/Missing.zasm" + ] + } + }, + "settings": { + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "": [ + "metadata" + ], + "*": [ + "abi", + "evm.methodIdentifiers" + ] + } + }, + "metadata": { + "hashType": "ipfs" + }, + "libraries": {} + } + } \ No newline at end of file diff --git a/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls.json b/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls.json index 04396fff..b9f87e68 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls.json +++ b/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls.json @@ -22,6 +22,9 @@ ] } }, + "metadata": { + "hashType": "ipfs" + }, "libraries": {} } } \ No newline at end of file diff --git a/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls_invalid.json b/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls_invalid.json index 235e3af3..b7a8337d 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls_invalid.json +++ b/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls_invalid.json @@ -22,6 +22,9 @@ ] } }, + "metadata": { + "hashType": "ipfs" + }, "libraries": {} } } \ No newline at end of file diff --git a/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls_missing.json b/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls_missing.json new file mode 100644 index 00000000..4b14143f --- /dev/null +++ b/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls_missing.json @@ -0,0 +1,27 @@ +{ + "language": "LLVM IR", + "sources": { + "Test": { + "urls": [ + "tests/data/contracts/llvm_ir/Missing.ll" + ] + } + }, + "settings": { + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "": [ + "metadata" + ], + "*": [ + "abi", + "evm.methodIdentifiers" + ] + } + }, + "libraries": {} + } + } \ No newline at end of file diff --git a/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls_missing_file.json b/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls_missing_file.json new file mode 100644 index 00000000..f64927a6 --- /dev/null +++ b/era-compiler-solidity/tests/data/standard_json_input/llvm_ir_urls_missing_file.json @@ -0,0 +1,30 @@ +{ + "language": "LLVM IR", + "sources": { + "Test": { + "urls": [ + "tests/data/contracts/llvm_ir/Missing.ll" + ] + } + }, + "settings": { + "optimizer": { + "enabled": true + }, + "outputSelection": { + "*": { + "": [ + "metadata" + ], + "*": [ + "abi", + "evm.methodIdentifiers" + ] + } + }, + "metadata": { + "hashType": "ipfs" + }, + "libraries": {} + } + } \ No newline at end of file diff --git a/era-compiler-solidity/tests/data/standard_json_input/solidity_solc.json b/era-compiler-solidity/tests/data/standard_json_input/solidity_solc.json index 1fef6043..0567e1c7 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/solidity_solc.json +++ b/era-compiler-solidity/tests/data/standard_json_input/solidity_solc.json @@ -1,24 +1,26 @@ { - "language": "Solidity", - "sources": - { - "A": - { - "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity >=0.0; contract C {}" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200, - "details": { - "peephole": true, - "jumpdestRemover": true, - "orderLiterals": true, - "deduplicate": true, - "cse": true, - "constantOptimizer": true - } - } - } + "language": "Solidity", + "sources": + { + "A": + { + "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity >=0.0; contract C {}" + } + }, + "settings": { + "optimizer": { + "runs": 200, + "details": { + "peephole": true, + "jumpdestRemover": true, + "orderLiterals": true, + "deduplicate": true, + "cse": true, + "constantOptimizer": true + } + }, + "metadata": { + "useLiteralContent": true + } + } } diff --git a/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_empty_sources.json b/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_empty_sources.json index 4b0c3f01..22ef9576 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_empty_sources.json +++ b/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_empty_sources.json @@ -1,10 +1,13 @@ { - "language": "Solidity", - "sources": {}, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - } - } + "language": "Solidity", + "sources": {}, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "useLiteralContent": true + } + } } diff --git a/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_invalid.json b/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_invalid.json index 5105e7a5..2dc15484 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_invalid.json +++ b/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_invalid.json @@ -1,16 +1,19 @@ { - "language": "Solidity", - "sources": - { - "A": - { - "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity >=0.0; contract C { xxx }" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - } - } + "language": "Solidity", + "sources": + { + "A": + { + "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity >=0.0; contract C { xxx }" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "useLiteralContent": true + } + } } diff --git a/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_missing_sources.json b/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_missing_sources.json index 2e436f7c..45f1fd30 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_missing_sources.json +++ b/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_missing_sources.json @@ -1,9 +1,12 @@ { - "language": "Solidity", - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - } - } + "language": "Solidity", + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "useLiteralContent": true + } + } } diff --git a/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_recursion.json b/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_recursion.json deleted file mode 100644 index 4e03422a..00000000 --- a/era-compiler-solidity/tests/data/standard_json_input/solidity_solc_recursion.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "language": "Solidity", - "sources": - { - "A": - { - "urls": [ - "tests/data/contracts/solidity/Recursion.sol" - ] - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200, - "details": { - "peephole": true, - "jumpdestRemover": true, - "orderLiterals": true, - "deduplicate": true, - "cse": true, - "constantOptimizer": true - } - } - } -} diff --git a/era-compiler-solidity/tests/data/standard_json_input/solidity_zksolc_internal_function_pointers.json b/era-compiler-solidity/tests/data/standard_json_input/solidity_zksolc_internal_function_pointers.json new file mode 100644 index 00000000..32b0ca7c --- /dev/null +++ b/era-compiler-solidity/tests/data/standard_json_input/solidity_zksolc_internal_function_pointers.json @@ -0,0 +1,36 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "urls": [ + "tests/data/contracts/solidity/InternalFunctionPointers.sol" + ] + } + }, + "settings": { + "optimizer": { + "mode": "3", + "fallbackToOptimizingForSize": true + }, + "outputSelection": { + "*": { + "": [ + "metadata" + ], + "*": [ + "abi", + "evm.methodIdentifiers" + ] + } + }, + "metadata": { + "hashType": "ipfs" + }, + "libraries": {}, + "codegen": "evmla", + "enableEraVMExtensions": true, + "forceEVMLA": true + } +} diff --git a/era-compiler-solidity/tests/data/standard_json_input/solidity_zksolc_invalid.json b/era-compiler-solidity/tests/data/standard_json_input/solidity_zksolc_invalid.json index c1b01823..e2df1a90 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/solidity_zksolc_invalid.json +++ b/era-compiler-solidity/tests/data/standard_json_input/solidity_zksolc_invalid.json @@ -1,16 +1,34 @@ { - "language": "Solidity", - "sources": - { - "A": - { - "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity >=0.0; contract C { function distribute(address payable recipient) public { recipient.send(1); recipient.transfer(1); payable(tx.origin).transfer(1); } }" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - } - } + "language": "Solidity", + "sources": + { + "A": + { + "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity >=0.0; contract C { function distribute(address payable recipient) public { recipient.send(1); recipient.transfer(1); payable(tx.origin).transfer(1); } }" + } + }, + "settings": { + "optimizer": { + "mode": "3", + "fallbackToOptimizingForSize": false + }, + "outputSelection": { + "*": { + "": [ + "metadata" + ], + "*": [ + "abi", + "evm.methodIdentifiers" + ] + } + }, + "metadata": { + "hashType": "ipfs" + }, + "libraries": {}, + "codegen": "evmla", + "enableEraVMExtensions": true, + "forceEVMLA": true + } } diff --git a/era-compiler-solidity/tests/data/standard_json_input/solidity_zksolc_recursion.json b/era-compiler-solidity/tests/data/standard_json_input/solidity_zksolc_recursion.json new file mode 100644 index 00000000..85819c2d --- /dev/null +++ b/era-compiler-solidity/tests/data/standard_json_input/solidity_zksolc_recursion.json @@ -0,0 +1,36 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "urls": [ + "tests/data/contracts/solidity/Recursion.sol" + ] + } + }, + "settings": { + "optimizer": { + "mode": "3", + "fallbackToOptimizingForSize": true + }, + "outputSelection": { + "*": { + "": [ + "metadata" + ], + "*": [ + "abi", + "evm.methodIdentifiers" + ] + } + }, + "metadata": { + "hashType": "ipfs" + }, + "libraries": {}, + "codegen": "evmla", + "enableEraVMExtensions": true, + "forceEVMLA": true + } +} diff --git a/era-compiler-solidity/tests/data/standard_json_input/suppressed_errors_and_warnings.json b/era-compiler-solidity/tests/data/standard_json_input/suppressed_errors_and_warnings.json index 412438b4..9c284a7b 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/suppressed_errors_and_warnings.json +++ b/era-compiler-solidity/tests/data/standard_json_input/suppressed_errors_and_warnings.json @@ -7,9 +7,29 @@ }, "settings": { "optimizer": { - "enabled": true, - "runs": 200 - } + "mode": "3", + "fallbackToOptimizingForSize": false + }, + "outputSelection": { + "*": { + "": [ + "metadata" + ], + "*": [ + "abi", + "evm.methodIdentifiers" + ] + } + }, + "metadata": { + "hashType": "ipfs" + }, + "libraries": {}, + "codegen": "yul", + "enableEraVMExtensions": true, + "forceEVMLA": false, + "suppressedErrors": ["sendtransfer"], + "suppressedWarnings": ["txorigin"] }, "suppressedErrors": ["sendtransfer"], "suppressedWarnings": ["txorigin"] diff --git a/era-compiler-solidity/tests/data/standard_json_input/suppressed_errors_invalid.json b/era-compiler-solidity/tests/data/standard_json_input/suppressed_errors_invalid.json index 9a4e6519..ff700ec5 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/suppressed_errors_invalid.json +++ b/era-compiler-solidity/tests/data/standard_json_input/suppressed_errors_invalid.json @@ -7,9 +7,29 @@ }, "settings": { "optimizer": { - "enabled": true, - "runs": 200 - } + "mode": "3", + "fallbackToOptimizingForSize": false + }, + "outputSelection": { + "*": { + "": [ + "metadata" + ], + "*": [ + "abi", + "evm.methodIdentifiers" + ] + } + }, + "metadata": { + "hashType": "ipfs" + }, + "libraries": {}, + "codegen": "yul", + "enableEraVMExtensions": true, + "forceEVMLA": false, + "suppressedErrors": ["INVALID_SUPPRESSED_ERROR_TYPE"], + "suppressedWarnings": ["txorigin"] }, "suppressedErrors": ["INVALID_SUPPRESSED_ERROR_TYPE"], "suppressedWarnings": ["txorigin"] diff --git a/era-compiler-solidity/tests/data/standard_json_input/suppressed_warnings_invalid.json b/era-compiler-solidity/tests/data/standard_json_input/suppressed_warnings_invalid.json index f9cdd501..a84e5235 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/suppressed_warnings_invalid.json +++ b/era-compiler-solidity/tests/data/standard_json_input/suppressed_warnings_invalid.json @@ -7,9 +7,29 @@ }, "settings": { "optimizer": { - "enabled": true, - "runs": 200 - } + "mode": "3", + "fallbackToOptimizingForSize": false + }, + "outputSelection": { + "*": { + "": [ + "metadata" + ], + "*": [ + "abi", + "evm.methodIdentifiers" + ] + } + }, + "metadata": { + "hashType": "ipfs" + }, + "libraries": {}, + "codegen": "yul", + "enableEraVMExtensions": true, + "forceEVMLA": false, + "suppressedErrors": ["sendtransfer"], + "suppressedWarnings": ["INVALID_SUPPRESSED_WARNING_TYPE"] }, "suppressedErrors": ["sendtransfer"], "suppressedWarnings": ["INVALID_SUPPRESSED_WARNING_TYPE"] diff --git a/era-compiler-solidity/tests/data/standard_json_input/yul_solc.json b/era-compiler-solidity/tests/data/standard_json_input/yul_solc.json index 60dbd027..289dfcaf 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/yul_solc.json +++ b/era-compiler-solidity/tests/data/standard_json_input/yul_solc.json @@ -9,6 +9,9 @@ "optimizer": { "enabled": true }, + "metadata": { + "useLiteralContent": true + }, "outputSelection": { "*": { "": [ diff --git a/era-compiler-solidity/tests/data/standard_json_input/yul_solc_urls.json b/era-compiler-solidity/tests/data/standard_json_input/yul_solc_urls.json index a4092d36..f0e6c8bd 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/yul_solc_urls.json +++ b/era-compiler-solidity/tests/data/standard_json_input/yul_solc_urls.json @@ -11,6 +11,9 @@ "optimizer": { "enabled": true }, + "metadata": { + "useLiteralContent": true + }, "outputSelection": { "*": { "": [ diff --git a/era-compiler-solidity/tests/data/standard_json_input/yul_solc_urls_invalid.json b/era-compiler-solidity/tests/data/standard_json_input/yul_solc_urls_invalid.json index 494dfa4a..89494b55 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/yul_solc_urls_invalid.json +++ b/era-compiler-solidity/tests/data/standard_json_input/yul_solc_urls_invalid.json @@ -11,6 +11,9 @@ "optimizer": { "enabled": true }, + "metadata": { + "useLiteralContent": true + }, "outputSelection": { "*": { "": [ diff --git a/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc.json b/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc.json index b0a41423..015b7515 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc.json +++ b/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc.json @@ -2,16 +2,14 @@ "language": "Yul", "sources": { "EventWriter.yul": { - "content": "/**\n * @author Matter Labs\n * @custom:security-contact security@matterlabs.dev\n * @notice The contract responsible for decoding and writing events using low-level instructions.\n * @dev The metadata and topics are passed via registers, and the first accessible register contains their number.\n * The rest of the data is passed via calldata without copying.\n */\nobject \"EventWriter\" {\n code {\n return(0, 0)\n }\n object \"EventWriter_deployed\" {\n code {\n ////////////////////////////////////////////////////////////////\n // HELPER FUNCTIONS\n ////////////////////////////////////////////////////////////////\n \n // For the documentation of the helper functions, please refer to \n // the corresponding functions in the SystemContractHelper.sol.\n\n /// @notice Returns the 0-th extraAbiParam for the current call.\n /// @dev It is equal to the value of the 2-th register at the start of the call.\n function getExtraAbiData_0() -> extraAbiData {\n extraAbiData := verbatim_0i_1o(\"get_global::extra_abi_data_0\")\n }\n\n /// @notice Returns the 1-th extraAbiParam for the current call.\n /// @dev It is equal to the value of the 3-th register at the start of the call.\n function getExtraAbiData_1() -> extraAbiData {\n extraAbiData := verbatim_0i_1o(\"get_global::extra_abi_data_1\")\n }\n\n /// @notice Returns the 2-th extraAbiParam for the current call.\n /// @dev It is equal to the value of the 4-th register at the start of the call.\n function getExtraAbiData_2() -> extraAbiData {\n extraAbiData := verbatim_0i_1o(\"get_global::extra_abi_data_2\")\n }\n\n /// @notice Returns the 3-th extraAbiParam for the current call.\n /// @dev It is equal to the value of the 5-th register at the start of the call.\n function getExtraAbiData_3() -> extraAbiData {\n extraAbiData := verbatim_0i_1o(\"get_global::extra_abi_data_3\")\n }\n\n /// @notice Returns the 4-th extraAbiParam for the current call.\n /// @dev It is equal to the value of the 6-th register at the start of the call.\n function getExtraAbiData_4() -> extraAbiData {\n extraAbiData := verbatim_0i_1o(\"get_global::extra_abi_data_4\")\n }\n\n /// @notice Returns the call flags for the current call.\n /// @dev Call flags is the value of the first register at the start of the call.\n /// @dev The zero bit of the callFlags indicates whether the call is\n /// a constructor call. The first bit of the callFlags indicates whether\n /// the call is a system one.\n function getCallFlags() -> ret {\n ret := verbatim_0i_1o(\"get_global::call_flags\")\n }\n\n /// @notice Initialize a new event\n /// @param initializer The event initializing value\n /// @param value1 The first topic or data chunk.\n function eventInitialize(initializer, value1) {\n verbatim_2i_0o(\"event_initialize\", initializer, value1)\n }\n\n /// @notice Continue writing the previously initialized event.\n /// @param value1 The first topic or data chunk.\n /// @param value2 The second topic or data chunk.\n function eventWrite(value1, value2) {\n verbatim_2i_0o(\"event_write\", value1, value2)\n }\n \n // @dev Write 1-th topic and first data chunk\n function writeFirstTopicWithDataChunk() {\n let topic1 := getExtraAbiData_1()\n let dataChunk := calldataload(0)\n eventWrite(topic1, dataChunk)\n }\n\n // @dev Write 1-th and 2-th event topics \n function writeFirstTwoTopics() {\n let topic1 := getExtraAbiData_1()\n let topic2 := getExtraAbiData_2()\n eventWrite(topic1, topic2)\n }\n\n // @dev Write 3-th topic and first data chunk\n function writeThirdTopicWithDataChunk() {\n let topic3 := getExtraAbiData_3()\n let dataChunk := calldataload(0)\n eventWrite(topic3, dataChunk)\n }\n\n // @dev Write 3-th and 4-th event topics \n function writeSecondTwoTopics() {\n let topic3 := getExtraAbiData_3()\n let topic4 := getExtraAbiData_4()\n eventWrite(topic3, topic4)\n }\n\n // @dev Reverts the call if a caller hasn't set the \"isSystem\" flag before calling\n // Note: this method is different from the `onlySystemCall` modifier that is used in system contracts.\n function onlySystemCall() {\n let callFlags := getCallFlags()\n let isSystemCall := and(callFlags, 2)\n\n if iszero(isSystemCall) {\n revert(0, 0)\n }\n }\n\n ////////////////////////////////////////////////////////////////\n // FALLBACK\n ////////////////////////////////////////////////////////////////\n \n // Ensure that contract is called on purpose\n onlySystemCall()\n\n let numberOfTopics := getExtraAbiData_0()\n // Only 4 indexed fields are allowed, same as on EVM\n if gt(numberOfTopics, 4) {\n revert(0, 0)\n }\n \n let dataLength := calldatasize()\n // Increment number of topics to include the `msg.sender` as a topic\n let initializer := add(shl(32, dataLength), add(numberOfTopics, 1))\n eventInitialize(initializer, caller())\n\n // Save the pointer to written data\n let dataCursor\n\n // Handle every case separately, to save gas on loops (alternative approach)\n switch numberOfTopics\n case 0 {\n // Nothing to publish\n }\n case 1 {\n writeFirstTopicWithDataChunk()\n dataCursor := add(dataCursor, 0x20)\n }\n case 2 {\n writeFirstTwoTopics()\n }\n case 3 { \n writeFirstTwoTopics()\n writeThirdTopicWithDataChunk()\n dataCursor := add(dataCursor, 0x20)\n }\n case 4 { \n writeFirstTwoTopics()\n writeSecondTwoTopics()\n }\n default {\n // Unreachable\n revert(0, 0)\n }\n\n // Write all the event data, two words at a time\n for {} lt(dataCursor, dataLength) {\n dataCursor := add(dataCursor, 0x40)\n } {\n let chunk1 := calldataload(dataCursor)\n let chunk2 := calldataload(add(dataCursor, 0x20))\n eventWrite(chunk1, chunk2)\n }\n }\n }\n}\n" + "content": "/**\n * @author Matter Labs\n * @custom:security-contact security@matterlabs.dev\n * @notice The contract responsible for decoding and writing events using low-level instructions.\n * @dev The metadata and topics are passed via registers, and the first accessible register contains their number.\n * The rest of the data is passed via calldata without copying.\n */\nobject \"EventWriter\" {\n code {\n return(0, 0)\n }\n object \"EventWriter_deployed\" {\n code {\n ////////////////////////////////////////////////////////////////\n // HELPER FUNCTIONS\n ////////////////////////////////////////////////////////////////\n \n // For the documentation of the helper functions, please refer to \n // the corresponding functions in the SystemContractHelper.sol.\n\n /// @notice Returns the 0-th extraAbiParam for the current call.\n /// @dev It is equal to the value of the 2-th register at the start of the call.\n function getExtraAbiData_0() -> extraAbiData {\n extraAbiData := verbatim_0i_1o(\"get_global::extra_abi_data_0\")\n }\n\n /// @notice Returns the 1-th extraAbiParam for the current call.\n /// @dev It is equal to the value of the 3-th register at the start of the call.\n function getExtraAbiData_1() -> extraAbiData {\n extraAbiData := verbatim_0i_1o(\"get_global::extra_abi_data_1\")\n }\n\n /// @notice Returns the 2-th extraAbiParam for the current call.\n /// @dev It is equal to the value of the 4-th register at the start of the call.\n function getExtraAbiData_2() -> extraAbiData {\n extraAbiData := verbatim_0i_1o(\"get_global::extra_abi_data_2\")\n }\n\n /// @notice Returns the 3-th extraAbiParam for the current call.\n /// @dev It is equal to the value of the 5-th register at the start of the call.\n function getExtraAbiData_3() -> extraAbiData {\n extraAbiData := verbatim_0i_1o(\"get_global::extra_abi_data_3\")\n }\n\n /// @notice Returns the 4-th extraAbiParam for the current call.\n /// @dev It is equal to the value of the 6-th register at the start of the call.\n function getExtraAbiData_4() -> extraAbiData {\n extraAbiData := verbatim_0i_1o(\"get_global::extra_abi_data_4\")\n }\n\n /// @notice Returns the call flags for the current call.\n /// @dev Call flags is the value of the first register at the start of the call.\n /// @dev The zero bit of the callFlags indicates whether the call is\n /// a constructor call. The first bit of the callFlags indicates whether\n /// the call is a system one.\n function getCallFlags() -> ret {\n ret := verbatim_0i_1o(\"get_global::call_flags\")\n }\n\n /// @notice Initialize a new event\n /// @param initializer The event initializing value\n /// @param value1 The first topic or data chunk.\n function eventInitialize(initializer, value1) {\n verbatim_2i_0o(\"event_initialize\", initializer, value1)\n }\n\n /// @notice Continue writing the previously initialized event.\n /// @param value1 The first topic or data chunk.\n /// @param value2 The second topic or data chunk.\n function eventWrite(value1, value2) {\n verbatim_2i_0o(\"event_write\", value1, value2)\n }\n \n // @dev Write 1-th topic and first data chunk\n function writeFirstTopicWithDataChunk() {\n let topic1 := getExtraAbiData_1()\n let dataChunk := calldataload(0)\n eventWrite(topic1, dataChunk)\n }\n\n // @dev Write 1-th and 2-th event topics \n function writeFirstTwoTopics() {\n let topic1 := getExtraAbiData_1()\n let topic2 := getExtraAbiData_2()\n eventWrite(topic1, topic2)\n }\n\n // @dev Write 3-th topic and first data chunk\n function writeThirdTopicWithDataChunk() {\n let topic3 := getExtraAbiData_3()\n let dataChunk := calldataload(0)\n eventWrite(topic3, dataChunk)\n }\n\n // @dev Write 3-th and 4-th event topics \n function writeSecondTwoTopics() {\n let topic3 := getExtraAbiData_3()\n let topic4 := getExtraAbiData_4()\n eventWrite(topic3, topic4)\n }\n\n // @dev Reverts the call if a caller hasn't set the \"enableEraVMExtensions\" flag before calling\n // Note: this method is different from the `onlySystemCall` modifier that is used in system contracts.\n function onlySystemCall() {\n let callFlags := getCallFlags()\n let enableEraVMExtensionsCall := and(callFlags, 2)\n\n if iszero(enableEraVMExtensionsCall) {\n revert(0, 0)\n }\n }\n\n ////////////////////////////////////////////////////////////////\n // FALLBACK\n ////////////////////////////////////////////////////////////////\n \n // Ensure that contract is called on purpose\n onlySystemCall()\n\n let numberOfTopics := getExtraAbiData_0()\n // Only 4 indexed fields are allowed, same as on EVM\n if gt(numberOfTopics, 4) {\n revert(0, 0)\n }\n \n let dataLength := calldatasize()\n // Increment number of topics to include the `msg.sender` as a topic\n let initializer := add(shl(32, dataLength), add(numberOfTopics, 1))\n eventInitialize(initializer, caller())\n\n // Save the pointer to written data\n let dataCursor\n\n // Handle every case separately, to save gas on loops (alternative approach)\n switch numberOfTopics\n case 0 {\n // Nothing to publish\n }\n case 1 {\n writeFirstTopicWithDataChunk()\n dataCursor := add(dataCursor, 0x20)\n }\n case 2 {\n writeFirstTwoTopics()\n }\n case 3 { \n writeFirstTwoTopics()\n writeThirdTopicWithDataChunk()\n dataCursor := add(dataCursor, 0x20)\n }\n case 4 { \n writeFirstTwoTopics()\n writeSecondTwoTopics()\n }\n default {\n // Unreachable\n revert(0, 0)\n }\n\n // Write all the event data, two words at a time\n for {} lt(dataCursor, dataLength) {\n dataCursor := add(dataCursor, 0x40)\n } {\n let chunk1 := calldataload(dataCursor)\n let chunk2 := calldataload(add(dataCursor, 0x20))\n eventWrite(chunk1, chunk2)\n }\n }\n }\n}\n" } }, "settings": { "optimizer": { - "enabled": true, - "mode": "3", + "mode": "3", "details": null, - "fallbackToOptimizingForSize": false, - "disableSystemRequestMemoization": true + "fallbackToOptimizingForSize": true }, "outputSelection": { "*": { @@ -24,9 +22,12 @@ ] } }, + "metadata": { + "hashType": "keccak256" + }, "libraries": {}, - "isSystem": false, - "forceEvmla": false, + "enableEraVMExtensions": true, + "forceEVMLA": false, "areLibrariesMissing": false } } \ No newline at end of file diff --git a/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_both_urls_and_content.json b/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_both_urls_and_content.json index 10971c9b..15231e25 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_both_urls_and_content.json +++ b/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_both_urls_and_content.json @@ -1,20 +1,18 @@ { - "language": "Yul", - "sources": { - "A": { - "urls": [ - "tests/data/contracts/yul/Test.yul" - ], - "content": "object \"Test\" { code { { return(0, 0) } } object \"Test_deployed\" { code { { return(0, 0) } } } }" - } - }, + "language": "Yul", + "sources": { + "A": { + "urls": [ + "tests/data/contracts/yul/Test.yul" + ], + "content": "object \"Test\" { code { { return(0, 0) } } object \"Test_deployed\" { code { { return(0, 0) } } } }" + } + }, "settings": { "optimizer": { - "enabled": true, - "mode": "3", + "mode": "3", "details": null, - "fallbackToOptimizingForSize": false, - "disableSystemRequestMemoization": true + "fallbackToOptimizingForSize": false }, "outputSelection": { "*": { @@ -27,9 +25,12 @@ ] } }, + "metadata": { + "hashType": "keccak256" + }, "libraries": {}, - "isSystem": false, - "forceEvmla": false, + "enableEraVMExtensions": true, + "forceEVMLA": false, "areLibrariesMissing": false } } diff --git a/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_neither_urls_nor_content.json b/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_neither_urls_nor_content.json index 36747543..a2bf18fe 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_neither_urls_nor_content.json +++ b/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_neither_urls_nor_content.json @@ -1,16 +1,14 @@ { - "language": "Yul", - "sources": - { - "A": {} - }, + "language": "Yul", + "sources": + { + "A": {} + }, "settings": { "optimizer": { - "enabled": true, - "mode": "3", + "mode": "3", "details": null, - "fallbackToOptimizingForSize": false, - "disableSystemRequestMemoization": true + "fallbackToOptimizingForSize": false }, "outputSelection": { "*": { @@ -23,9 +21,12 @@ ] } }, + "metadata": { + "hashType": "keccak256" + }, "libraries": {}, - "isSystem": false, - "forceEvmla": false, + "enableEraVMExtensions": true, + "forceEVMLA": false, "areLibrariesMissing": false } } diff --git a/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_urls.json b/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_urls.json index bb5c577c..068c010b 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_urls.json +++ b/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_urls.json @@ -9,11 +9,8 @@ }, "settings": { "optimizer": { - "enabled": true, "mode": "3", - "details": null, - "fallbackToOptimizingForSize": false, - "disableSystemRequestMemoization": true + "fallbackToOptimizingForSize": false }, "outputSelection": { "*": { @@ -26,9 +23,11 @@ ] } }, + "metadata": { + "hashType": "ipfs" + }, "libraries": {}, - "isSystem": false, - "forceEvmla": false, - "areLibrariesMissing": false + "enableEraVMExtensions": true, + "forceEVMLA": false } } \ No newline at end of file diff --git a/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_urls_invalid.json b/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_urls_invalid.json index f7b3004b..bda9b234 100644 --- a/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_urls_invalid.json +++ b/era-compiler-solidity/tests/data/standard_json_input/yul_zksolc_urls_invalid.json @@ -9,11 +9,8 @@ }, "settings": { "optimizer": { - "enabled": true, "mode": "3", - "details": null, - "fallbackToOptimizingForSize": false, - "disableSystemRequestMemoization": true + "fallbackToOptimizingForSize": false }, "outputSelection": { "*": { @@ -26,9 +23,11 @@ ] } }, + "metadata": { + "hashType": "ipfs" + }, "libraries": {}, - "isSystem": false, - "forceEvmla": false, - "areLibrariesMissing": false + "enableEraVMExtensions": true, + "forceEVMLA": false } } \ No newline at end of file diff --git a/era-compiler-solidity/tests/scripts/solc_version_not_enough_lines.bat b/era-compiler-solidity/tests/scripts/solc_version_not_enough_lines.bat new file mode 100755 index 00000000..029013f4 --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_not_enough_lines.bat @@ -0,0 +1,2 @@ +@ECHO OFF +echo 'solc, the solidity compiler commandline interface' diff --git a/era-compiler-solidity/tests/scripts/solc_version_not_enough_lines.sh b/era-compiler-solidity/tests/scripts/solc_version_not_enough_lines.sh new file mode 100755 index 00000000..3375c942 --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_not_enough_lines.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo 'solc, the solidity compiler commandline interface' diff --git a/era-compiler-solidity/tests/scripts/solc_version_not_enough_words_in_2nd_line.bat b/era-compiler-solidity/tests/scripts/solc_version_not_enough_words_in_2nd_line.bat new file mode 100755 index 00000000..03037b51 --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_not_enough_words_in_2nd_line.bat @@ -0,0 +1,3 @@ +@ECHO OFF +echo 'solc, the solidity compiler commandline interface' +echo 'Version:' diff --git a/era-compiler-solidity/tests/scripts/solc_version_not_enough_words_in_2nd_line.sh b/era-compiler-solidity/tests/scripts/solc_version_not_enough_words_in_2nd_line.sh new file mode 100755 index 00000000..f5c55867 --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_not_enough_words_in_2nd_line.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo 'solc, the solidity compiler commandline interface' +echo 'Version:' diff --git a/era-compiler-solidity/tests/scripts/solc_version_output_error.bat b/era-compiler-solidity/tests/scripts/solc_version_output_error.bat new file mode 100755 index 00000000..68f96a20 --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_output_error.bat @@ -0,0 +1,2 @@ +@ECHO OFF +exit 1 diff --git a/era-compiler-solidity/tests/scripts/solc_version_output_error.sh b/era-compiler-solidity/tests/scripts/solc_version_output_error.sh new file mode 100755 index 00000000..d87f29ee --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_output_error.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +exit 1 diff --git a/era-compiler-solidity/tests/scripts/solc_version_parsing_error.bat b/era-compiler-solidity/tests/scripts/solc_version_parsing_error.bat new file mode 100755 index 00000000..41ca088d --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_parsing_error.bat @@ -0,0 +1,3 @@ +@ECHO OFF +echo 'solc, the solidity compiler commandline interface' +echo 'Version: x.y.z+commit.deadbeef.platform.toolchain' diff --git a/era-compiler-solidity/tests/scripts/solc_version_parsing_error.sh b/era-compiler-solidity/tests/scripts/solc_version_parsing_error.sh new file mode 100755 index 00000000..16109416 --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_parsing_error.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo 'solc, the solidity compiler commandline interface' +echo 'Version: x.y.z+commit.deadbeef.platform.toolchain' diff --git a/era-compiler-solidity/tests/scripts/solc_version_too_new.bat b/era-compiler-solidity/tests/scripts/solc_version_too_new.bat new file mode 100755 index 00000000..9c4ab9f4 --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_too_new.bat @@ -0,0 +1,3 @@ +@ECHO OFF +echo 'solc, the solidity compiler commandline interface' +echo 'Version: 0.8.29+commit.deadbeef.platform.toolchain' diff --git a/era-compiler-solidity/tests/scripts/solc_version_too_new.sh b/era-compiler-solidity/tests/scripts/solc_version_too_new.sh new file mode 100755 index 00000000..22c3afdb --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_too_new.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo 'solc, the solidity compiler commandline interface' +echo 'Version: 0.8.29+commit.deadbeef.platform.toolchain' diff --git a/era-compiler-solidity/tests/scripts/solc_version_too_old.bat b/era-compiler-solidity/tests/scripts/solc_version_too_old.bat new file mode 100755 index 00000000..1aa2dc9e --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_too_old.bat @@ -0,0 +1,3 @@ +@ECHO OFF +echo 'solc, the solidity compiler commandline interface' +echo 'Version: 0.4.11+commit.deadbeef.platform.toolchain' diff --git a/era-compiler-solidity/tests/scripts/solc_version_too_old.sh b/era-compiler-solidity/tests/scripts/solc_version_too_old.sh new file mode 100755 index 00000000..2335270b --- /dev/null +++ b/era-compiler-solidity/tests/scripts/solc_version_too_old.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo 'solc, the solidity compiler commandline interface' +echo 'Version: 0.4.11+commit.deadbeef.platform.toolchain' diff --git a/era-compiler-solidity/tests/solc-bin-upstream.json b/era-compiler-solidity/tests/solc-bin-upstream.json new file mode 100644 index 00000000..77bcd346 --- /dev/null +++ b/era-compiler-solidity/tests/solc-bin-upstream.json @@ -0,0 +1,40 @@ +{ + "binaries": { + "0.4.26": { + "is_enabled": true, + "protocol": "compiler-bin-list", + "source": "https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/${PLATFORM}/list.json", + "destination": "./solc-bin-upstream/solc-${VERSION}" + }, + "0.5.17": { + "is_enabled": true, + "protocol": "compiler-bin-list", + "source": "https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/${PLATFORM}/list.json", + "destination": "./solc-bin-upstream/solc-${VERSION}" + }, + "0.6.12": { + "is_enabled": true, + "protocol": "compiler-bin-list", + "source": "https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/${PLATFORM}/list.json", + "destination": "./solc-bin-upstream/solc-${VERSION}" + }, + "0.7.6": { + "is_enabled": true, + "protocol": "compiler-bin-list", + "source": "https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/${PLATFORM}/list.json", + "destination": "./solc-bin-upstream/solc-${VERSION}" + }, + "0.8.28": { + "is_enabled": true, + "protocol": "compiler-bin-list", + "source": "https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/${PLATFORM}/list.json", + "destination": "./solc-bin-upstream/solc-${VERSION}" + } + }, + "platforms": { + "linux-amd64": "linux-amd64", + "macos-amd64": "macosx-amd64", + "macos-arm64": "macosx-amd64", + "windows-amd64": "windows-amd64" + } +} \ No newline at end of file diff --git a/era-compiler-solidity/tests/unit/factory_dependency.rs b/era-compiler-solidity/tests/unit/factory_dependency.rs index c59e4e46..8e24c9b4 100644 --- a/era-compiler-solidity/tests/unit/factory_dependency.rs +++ b/era-compiler-solidity/tests/unit/factory_dependency.rs @@ -5,7 +5,8 @@ use std::collections::BTreeMap; use std::collections::BTreeSet; -use era_compiler_solidity::solc::codegen::Codegen as SolcCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::libraries::Libraries; use era_compiler_solidity::solc::Compiler as SolcCompiler; use crate::common; @@ -13,28 +14,46 @@ use crate::common; #[test] #[cfg_attr(target_os = "windows", ignore)] fn default_04_evmla() { - default(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn default_05_evmla() { - default(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_06_evmla() { - default(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_07_evmla() { - default(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_08_evmla() { - default(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + default( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_08_yul() { - default(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + default( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } pub const MAIN_CODE: &str = r#" @@ -72,17 +91,18 @@ contract Callable { } "#; -fn default(version: semver::Version, pipeline: SolcCodegen) { +fn default(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { let mut sources = BTreeMap::new(); sources.insert("main.sol".to_owned(), MAIN_CODE.to_owned()); sources.insert("callable.sol".to_owned(), CALLABLE_CODE.to_owned()); let output = common::build_solidity( sources.clone(), - BTreeMap::new(), + Libraries::default(), + era_compiler_common::HashType::Ipfs, BTreeSet::new(), &version, - pipeline, + codegen, era_compiler_llvm_context::OptimizerSettings::cycles(), ) .expect("Build failure"); @@ -90,8 +110,6 @@ fn default(version: semver::Version, pipeline: SolcCodegen) { assert_eq!( output .contracts - .as_ref() - .expect("Missing field `contracts`") .get("main.sol") .expect("Missing file `main.sol`") .get("Main") @@ -104,8 +122,6 @@ fn default(version: semver::Version, pipeline: SolcCodegen) { assert_eq!( output .contracts - .as_ref() - .expect("Missing field `contracts`") .get("callable.sol") .expect("Missing file `callable.sol`") .get("Callable") diff --git a/era-compiler-solidity/tests/unit/ir_artifacts.rs b/era-compiler-solidity/tests/unit/ir_artifacts.rs index c7b0e96b..fa3f4c67 100644 --- a/era-compiler-solidity/tests/unit/ir_artifacts.rs +++ b/era-compiler-solidity/tests/unit/ir_artifacts.rs @@ -7,7 +7,8 @@ use std::collections::BTreeMap; use std::collections::BTreeSet; -use era_compiler_solidity::solc::codegen::Codegen as SolcCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::libraries::Libraries; use era_compiler_solidity::solc::Compiler as SolcCompiler; use crate::common; @@ -56,32 +57,29 @@ fn yul(version: semver::Version) { let build = common::build_solidity( sources.clone(), - BTreeMap::new(), + Libraries::default(), + era_compiler_common::HashType::Ipfs, BTreeSet::new(), &version, - SolcCodegen::Yul, + SolcStandardJsonInputSettingsCodegen::Yul, era_compiler_llvm_context::OptimizerSettings::cycles(), ) .expect("Test failure"); assert!( - build + !build .contracts - .as_ref() - .expect("Always exists") .get("test.sol") .expect("Always exists") .get("Test") .expect("Always exists") .ir_optimized - .is_some(), - "Yul IR is missing" + .is_empty(), + "Yul is missing" ); assert!( build .contracts - .as_ref() - .expect("Always exists") .get("test.sol") .expect("Always exists") .get("Test") @@ -91,7 +89,7 @@ fn yul(version: semver::Version) { .expect("EVM object is missing") .legacy_assembly .is_none(), - "EVM assembly IR is present although not requested" + "EVM assembly is present although not requested" ); } @@ -101,18 +99,17 @@ fn evmla(version: semver::Version) { let build = common::build_solidity( sources.clone(), - BTreeMap::new(), + Libraries::default(), + era_compiler_common::HashType::Ipfs, BTreeSet::new(), &version, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, era_compiler_llvm_context::OptimizerSettings::cycles(), ) .expect("Test failure"); assert!( build .contracts - .as_ref() - .expect("Always exists") .get("test.sol") .expect("Always exists") .get("Test") @@ -122,19 +119,17 @@ fn evmla(version: semver::Version) { .expect("EVM object is missing") .legacy_assembly .is_some(), - "EVM assembly IR is missing", + "EVM assembly is missing", ); assert!( build .contracts - .as_ref() - .expect("Always exists") .get("test.sol") .expect("Always exists") .get("Test") .expect("Always exists") .ir_optimized - .is_none(), - "Yul IR is present although not requested", + .is_empty(), + "Yul is present although not requested", ); } diff --git a/era-compiler-solidity/tests/unit/libraries.rs b/era-compiler-solidity/tests/unit/libraries.rs index f36e3bf5..938764ff 100644 --- a/era-compiler-solidity/tests/unit/libraries.rs +++ b/era-compiler-solidity/tests/unit/libraries.rs @@ -4,7 +4,8 @@ use std::collections::BTreeMap; -use era_compiler_solidity::solc::codegen::Codegen as SolcCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::libraries::Libraries; use era_compiler_solidity::solc::Compiler as SolcCompiler; use crate::common; @@ -12,55 +13,91 @@ use crate::common; #[test] #[cfg_attr(target_os = "windows", ignore)] fn not_specified_04_evmla() { - not_specified(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + not_specified( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn not_specified_05_evmla() { - not_specified(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + not_specified( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn not_specified_06_evmla() { - not_specified(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + not_specified( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn not_specified_07_evmla() { - not_specified(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + not_specified( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn not_specified_08_evmla() { - not_specified(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + not_specified( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn not_specified_08_yul() { - not_specified(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + not_specified( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn specified_04_evmla() { - specified(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + specified( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn specified_05_evmla() { - specified(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + specified( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn specified_06_evmla() { - specified(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + specified( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn specified_07_evmla() { - specified(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + specified( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn specified_08_evmla() { - specified(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + specified( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn specified_08_yul() { - specified(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + specified( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } pub const LIBRARY_TEST_SOURCE: &str = r#" @@ -90,22 +127,20 @@ contract SimpleContract { } "#; -fn not_specified(version: semver::Version, pipeline: SolcCodegen) { +fn not_specified(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { let mut sources = BTreeMap::new(); sources.insert("test.sol".to_owned(), LIBRARY_TEST_SOURCE.to_owned()); let output = common::build_solidity_and_detect_missing_libraries( sources.clone(), - BTreeMap::new(), + Libraries::default(), &version, - pipeline, + codegen, ) .expect("Test failure"); assert!( output .contracts - .as_ref() - .expect("Always exists") .get("test.sol") .expect("Always exists") .get("SimpleContract") @@ -118,7 +153,7 @@ fn not_specified(version: semver::Version, pipeline: SolcCodegen) { ); } -fn specified(version: semver::Version, pipeline: SolcCodegen) { +fn specified(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { let mut sources = BTreeMap::new(); sources.insert("test.sol".to_owned(), LIBRARY_TEST_SOURCE.to_owned()); @@ -128,19 +163,14 @@ fn specified(version: semver::Version, pipeline: SolcCodegen) { .or_insert_with(BTreeMap::new) .entry("SimpleLibrary".to_string()) .or_insert("0x00000000000000000000000000000000DEADBEEF".to_string()); + let libraries = Libraries::from(libraries); - let output = common::build_solidity_and_detect_missing_libraries( - sources.clone(), - libraries.clone(), - &version, - pipeline, - ) - .expect("Test failure"); + let output = + common::build_solidity_and_detect_missing_libraries(sources, libraries, &version, codegen) + .expect("Test failure"); assert!( output .contracts - .as_ref() - .expect("Always exists") .get("test.sol") .expect("Always exists") .get("SimpleContract") diff --git a/era-compiler-solidity/tests/unit/linker.rs b/era-compiler-solidity/tests/unit/linker.rs index 4f1d22f1..0ebe7ca0 100644 --- a/era-compiler-solidity/tests/unit/linker.rs +++ b/era-compiler-solidity/tests/unit/linker.rs @@ -5,70 +5,94 @@ use std::collections::BTreeMap; use std::collections::BTreeSet; -use era_compiler_solidity::libraries::Libraries; -use era_compiler_solidity::solc::codegen::Codegen as SolcCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::libraries::Libraries; use era_compiler_solidity::solc::Compiler as SolcCompiler; use crate::common; #[test] fn library_not_passed_compile_time_08_evmla() { - library_not_passed_compile_time(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + library_not_passed_compile_time( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn library_not_passed_compile_time_08_yul() { - library_not_passed_compile_time(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + library_not_passed_compile_time( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] fn library_not_passed_post_compile_time_08_evmla() { - library_not_passed_post_compile_time(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + library_not_passed_post_compile_time( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn library_not_passed_post_compile_time_08_yul() { - library_not_passed_post_compile_time(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + library_not_passed_post_compile_time( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] fn library_passed_compile_time_08_evmla() { - library_passed_compile_time(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + library_passed_compile_time( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn library_passed_compile_time_08_yul() { - library_passed_compile_time(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + library_passed_compile_time( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] fn library_passed_post_compile_time_08_evmla() { - library_passed_post_compile_time(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + library_passed_post_compile_time( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn library_passed_post_compile_time_08_yul() { - library_passed_post_compile_time(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + library_passed_post_compile_time( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] fn library_passed_post_compile_time_second_call_08_evmla() { library_passed_post_compile_time_second_call( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, ); } #[test] fn library_passed_post_compile_time_second_call_08_yul() { library_passed_post_compile_time_second_call( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::Yul, + SolcStandardJsonInputSettingsCodegen::Yul, ); } #[test] fn library_passed_post_compile_time_redundant_args_08_evmla() { library_passed_post_compile_time_redundant_args( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, ); } #[test] fn library_passed_post_compile_time_redundant_args_08_yul() { library_passed_post_compile_time_redundant_args( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::Yul, + SolcStandardJsonInputSettingsCodegen::Yul, ); } #[test] @@ -76,7 +100,7 @@ fn library_passed_post_compile_time_redundant_args_08_yul() { fn library_passed_post_compile_time_non_elf_08_evmla() { library_passed_post_compile_time_non_elf( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, ); } #[test] @@ -84,7 +108,21 @@ fn library_passed_post_compile_time_non_elf_08_evmla() { fn library_passed_post_compile_time_non_elf_08_yul() { library_passed_post_compile_time_non_elf( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::Yul, + SolcStandardJsonInputSettingsCodegen::Yul, + ); +} +#[test] +fn library_produce_equal_bytecode_in_both_cases_08_evmla() { + library_produce_equal_bytecode_in_both_cases( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); +} +#[test] +fn library_produce_equal_bytecode_in_both_cases_08_yul() { + library_produce_equal_bytecode_in_both_cases( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, ); } @@ -123,9 +161,9 @@ contract Greeter { "#; fn get_bytecode( - libraries: BTreeMap>, + libraries: Libraries, version: &semver::Version, - pipeline: SolcCodegen, + codegen: SolcStandardJsonInputSettingsCodegen, ) -> Vec { let mut sources = BTreeMap::new(); sources.insert("test.sol".to_owned(), SOURCE_CODE.to_owned()); @@ -133,16 +171,15 @@ fn get_bytecode( let build = common::build_solidity( sources, libraries, + era_compiler_common::HashType::None, BTreeSet::new(), version, - pipeline, + codegen, era_compiler_llvm_context::OptimizerSettings::none(), ) .expect("Build failure"); let bytecode_hexadecimal = build .contracts - .as_ref() - .expect("Missing field `contracts`") .get("test.sol") .expect("Missing file `test.sol`") .get("Greeter") @@ -158,8 +195,11 @@ fn get_bytecode( hex::decode(bytecode_hexadecimal).expect("Invalid bytecode") } -fn library_not_passed_compile_time(version: semver::Version, pipeline: SolcCodegen) { - let bytecode = get_bytecode(BTreeMap::new(), &version, pipeline); +fn library_not_passed_compile_time( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, +) { + let bytecode = get_bytecode(Libraries::default(), &version, codegen); let memory_buffer = inkwell::memory_buffer::MemoryBuffer::create_from_memory_range( bytecode.as_slice(), @@ -172,8 +212,11 @@ fn library_not_passed_compile_time(version: semver::Version, pipeline: SolcCodeg ); } -fn library_not_passed_post_compile_time(version: semver::Version, pipeline: SolcCodegen) { - let bytecode = get_bytecode(BTreeMap::new(), &version, pipeline); +fn library_not_passed_post_compile_time( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, +) { + let bytecode = get_bytecode(Libraries::default(), &version, codegen); let memory_buffer = inkwell::memory_buffer::MemoryBuffer::create_from_memory_range( bytecode.as_slice(), @@ -189,13 +232,15 @@ fn library_not_passed_post_compile_time(version: semver::Version, pipeline: Solc ); } -fn library_passed_compile_time(version: semver::Version, pipeline: SolcCodegen) { - let libraries = Libraries::into_standard_json(vec![ - "test.sol:GreaterHelper=0x1234567890abcdef1234567890abcdef12345678".to_owned(), - ]) - .expect("Always valid"); +fn library_passed_compile_time( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, +) { + let library_arguments = + vec!["test.sol:GreaterHelper=0x1234567890abcdef1234567890abcdef12345678".to_owned()]; + let libraries = Libraries::try_from(library_arguments.as_slice()).expect("Always valid"); - let bytecode = get_bytecode(libraries, &version, pipeline); + let bytecode = get_bytecode(libraries, &version, codegen); let memory_buffer = inkwell::memory_buffer::MemoryBuffer::create_from_memory_range( bytecode.as_slice(), @@ -205,13 +250,18 @@ fn library_passed_compile_time(version: semver::Version, pipeline: SolcCodegen) assert!(!memory_buffer.is_elf_eravm(), "The bytecode is an ELF file"); } -fn library_passed_post_compile_time(version: semver::Version, pipeline: SolcCodegen) { - let libraries = Libraries::into_linker(vec![ - "test.sol:GreaterHelper=0x1234567890abcdef1234567890abcdef12345678".to_owned(), - ]) - .expect("Always valid"); +fn library_passed_post_compile_time( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, +) { + let library_arguments = + vec!["test.sol:GreaterHelper=0x1234567890abcdef1234567890abcdef12345678".to_owned()]; + let linker_symbols = Libraries::try_from(library_arguments.as_slice()) + .expect("Always valid") + .as_linker_symbols() + .expect("Always valid"); - let bytecode = get_bytecode(BTreeMap::new(), &version, pipeline); + let bytecode = get_bytecode(Libraries::default(), &version, codegen); let memory_buffer = inkwell::memory_buffer::MemoryBuffer::create_from_memory_range( bytecode.as_slice(), @@ -219,7 +269,7 @@ fn library_passed_post_compile_time(version: semver::Version, pipeline: SolcCode false, ); let memory_buffer_linked = memory_buffer - .link_module_eravm(&libraries) + .link_module_eravm(&linker_symbols) .expect("Link failure"); assert!( !memory_buffer_linked.is_elf_eravm(), @@ -227,13 +277,18 @@ fn library_passed_post_compile_time(version: semver::Version, pipeline: SolcCode ); } -fn library_passed_post_compile_time_second_call(version: semver::Version, pipeline: SolcCodegen) { - let libraries = Libraries::into_linker(vec![ - "test.sol:GreaterHelper=0x1234567890abcdef1234567890abcdef12345678".to_owned(), - ]) - .expect("Always valid"); +fn library_passed_post_compile_time_second_call( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, +) { + let library_arguments = + vec!["test.sol:GreaterHelper=0x1234567890abcdef1234567890abcdef12345678".to_owned()]; + let linker_symbols = Libraries::try_from(library_arguments.as_slice()) + .expect("Always valid") + .as_linker_symbols() + .expect("Always valid"); - let bytecode = get_bytecode(BTreeMap::new(), &version, pipeline); + let bytecode = get_bytecode(Libraries::default(), &version, codegen); let memory_buffer = inkwell::memory_buffer::MemoryBuffer::create_from_memory_range( bytecode.as_slice(), @@ -244,7 +299,7 @@ fn library_passed_post_compile_time_second_call(version: semver::Version, pipeli .link_module_eravm(&BTreeMap::new()) .expect("Link failure"); let memory_buffer_linked = memory_buffer_linked_empty - .link_module_eravm(&libraries) + .link_module_eravm(&linker_symbols) .expect("Link failure"); assert!( !memory_buffer_linked.is_elf_eravm(), @@ -254,16 +309,19 @@ fn library_passed_post_compile_time_second_call(version: semver::Version, pipeli fn library_passed_post_compile_time_redundant_args( version: semver::Version, - pipeline: SolcCodegen, + codegen: SolcStandardJsonInputSettingsCodegen, ) { - let libraries = Libraries::into_linker(vec![ + let library_arguments = vec![ "fake.sol:Fake=0x0000000000000000000000000000000000000000".to_owned(), "scam.sol:Scam=0x0000000000000000000000000000000000000000".to_owned(), "test.sol:GreaterHelper=0x1234567890abcdef1234567890abcdef12345678".to_owned(), - ]) - .expect("Always valid"); + ]; + let linker_symbols = Libraries::try_from(library_arguments.as_slice()) + .expect("Always valid") + .as_linker_symbols() + .expect("Always valid"); - let bytecode = get_bytecode(BTreeMap::new(), &version, pipeline); + let bytecode = get_bytecode(Libraries::default(), &version, codegen); let memory_buffer = inkwell::memory_buffer::MemoryBuffer::create_from_memory_range( bytecode.as_slice(), @@ -271,7 +329,7 @@ fn library_passed_post_compile_time_redundant_args( false, ); let memory_buffer_linked = memory_buffer - .link_module_eravm(&libraries) + .link_module_eravm(&linker_symbols) .expect("Link failure"); assert!( !memory_buffer_linked.is_elf_eravm(), @@ -279,13 +337,18 @@ fn library_passed_post_compile_time_redundant_args( ); } -fn library_passed_post_compile_time_non_elf(version: semver::Version, pipeline: SolcCodegen) { - let libraries = Libraries::into_linker(vec![ - "test.sol:GreaterHelper=0x1234567890abcdef1234567890abcdef12345678".to_owned(), - ]) - .expect("Always valid"); +fn library_passed_post_compile_time_non_elf( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, +) { + let library_arguments = + vec!["test.sol:GreaterHelper=0x1234567890abcdef1234567890abcdef12345678".to_owned()]; + let libraries = Libraries::try_from(library_arguments.as_slice()) + .expect("Always valid") + .as_linker_symbols() + .expect("Always valid"); - let bytecode = get_bytecode(BTreeMap::new(), &version, pipeline); + let bytecode = get_bytecode(Libraries::default(), &version, codegen); let memory_buffer = inkwell::memory_buffer::MemoryBuffer::create_from_memory_range( bytecode.as_slice(), @@ -303,3 +366,40 @@ fn library_passed_post_compile_time_non_elf(version: semver::Version, pipeline: "The bytecode is an ELF file" ); } + +fn library_produce_equal_bytecode_in_both_cases( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, +) { + let library_arguments = + vec!["test.sol:GreaterHelper=0x1234567890abcdef1234567890abcdef12345678".to_owned()]; + let libraries = Libraries::try_from(library_arguments.as_slice()).expect("Always valid"); + let linker_symbols = libraries.as_linker_symbols().expect("Always valid"); + + let bytecode_compile_time = get_bytecode(libraries, &version, codegen); + let memory_buffer_compile_time = inkwell::memory_buffer::MemoryBuffer::create_from_memory_range( + bytecode_compile_time.as_slice(), + "bytecode_compile_time", + false, + ); + + let bytecode_post_compile_time = get_bytecode(Libraries::default(), &version, codegen); + let memory_buffer_post_compile_time = + inkwell::memory_buffer::MemoryBuffer::create_from_memory_range( + bytecode_post_compile_time.as_slice(), + "bytecode_post_compile_time", + false, + ); + let memory_buffer_linked_post_compile_time = memory_buffer_post_compile_time + .link_module_eravm(&linker_symbols) + .expect("Link failure"); + + dbg!( + hex::encode(memory_buffer_compile_time.as_slice()), + hex::encode(memory_buffer_linked_post_compile_time.as_slice()) + ); + assert!( + memory_buffer_compile_time.as_slice() == memory_buffer_linked_post_compile_time.as_slice(), + "The bytecodes are not equal" + ); +} diff --git a/era-compiler-solidity/tests/unit/messages.rs b/era-compiler-solidity/tests/unit/messages.rs index 55264a5c..73bb1f18 100644 --- a/era-compiler-solidity/tests/unit/messages.rs +++ b/era-compiler-solidity/tests/unit/messages.rs @@ -2,10 +2,9 @@ //! The Solidity compiler unit tests for messages. //! -use std::collections::BTreeMap; - use era_compiler_solidity::error_type::ErrorType; -use era_compiler_solidity::solc::codegen::Codegen as SolcCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::libraries::Libraries; use era_compiler_solidity::solc::Compiler as SolcCompiler; use era_compiler_solidity::warning_type::WarningType; @@ -16,7 +15,7 @@ use crate::common; fn send_04_evmla() { send( semver::Version::new(0, 4, 26), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SEND_TEST_SOURCE_04, ); } @@ -25,7 +24,7 @@ fn send_04_evmla() { fn send_05_evmla() { send( semver::Version::new(0, 5, 17), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SEND_TEST_SOURCE_05_07, ); } @@ -33,7 +32,7 @@ fn send_05_evmla() { fn send_06_evmla() { send( semver::Version::new(0, 6, 12), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SEND_TEST_SOURCE_05_07, ); } @@ -41,7 +40,7 @@ fn send_06_evmla() { fn send_07_evmla() { send( semver::Version::new(0, 7, 6), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SEND_TEST_SOURCE_05_07, ); } @@ -49,7 +48,7 @@ fn send_07_evmla() { fn send_08_evmla() { send( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SEND_TEST_SOURCE, ); } @@ -57,7 +56,7 @@ fn send_08_evmla() { fn send_08_yul() { send( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::Yul, + SolcStandardJsonInputSettingsCodegen::Yul, SEND_TEST_SOURCE, ); } @@ -67,7 +66,7 @@ fn send_08_yul() { fn send_suppressed_04_evmla() { send_suppressed( semver::Version::new(0, 4, 26), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SEND_TEST_SOURCE_04, ); } @@ -76,7 +75,7 @@ fn send_suppressed_04_evmla() { fn send_suppressed_05_evmla() { send_suppressed( semver::Version::new(0, 5, 17), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SEND_TEST_SOURCE_05_07, ); } @@ -84,7 +83,7 @@ fn send_suppressed_05_evmla() { fn send_suppressed_06_evmla() { send_suppressed( semver::Version::new(0, 6, 12), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SEND_TEST_SOURCE_05_07, ); } @@ -92,7 +91,7 @@ fn send_suppressed_06_evmla() { fn send_suppressed_07_evmla() { send_suppressed( semver::Version::new(0, 7, 6), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SEND_TEST_SOURCE_05_07, ); } @@ -100,7 +99,7 @@ fn send_suppressed_07_evmla() { fn send_suppressed_08_evmla() { send_suppressed( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SEND_TEST_SOURCE, ); } @@ -108,7 +107,7 @@ fn send_suppressed_08_evmla() { fn send_suppressed_08_yul() { send_suppressed( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::Yul, + SolcStandardJsonInputSettingsCodegen::Yul, SEND_TEST_SOURCE, ); } @@ -118,7 +117,7 @@ fn send_suppressed_08_yul() { fn transfer_04_evmla() { transfer( semver::Version::new(0, 4, 26), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, TRANSFER_TEST_SOURCE_04, ); } @@ -127,7 +126,7 @@ fn transfer_04_evmla() { fn transfer_05_evmla() { transfer( semver::Version::new(0, 5, 17), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, TRANSFER_TEST_SOURCE_05_07, ); } @@ -135,7 +134,7 @@ fn transfer_05_evmla() { fn transfer_06_evmla() { transfer( semver::Version::new(0, 6, 12), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, TRANSFER_TEST_SOURCE_05_07, ); } @@ -143,7 +142,7 @@ fn transfer_06_evmla() { fn transfer_07_evmla() { transfer( semver::Version::new(0, 7, 6), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, TRANSFER_TEST_SOURCE_05_07, ); } @@ -151,7 +150,7 @@ fn transfer_07_evmla() { fn transfer_08_evmla() { transfer( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, TRANSFER_TEST_SOURCE, ); } @@ -159,7 +158,7 @@ fn transfer_08_evmla() { fn transfer_08_yul() { transfer( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::Yul, + SolcStandardJsonInputSettingsCodegen::Yul, TRANSFER_TEST_SOURCE, ); } @@ -169,7 +168,7 @@ fn transfer_08_yul() { fn transfer_suppressed_04_evmla() { transfer_suppressed( semver::Version::new(0, 4, 26), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, TRANSFER_TEST_SOURCE_04, ); } @@ -178,7 +177,7 @@ fn transfer_suppressed_04_evmla() { fn transfer_suppressed_05_evmla() { transfer_suppressed( semver::Version::new(0, 5, 17), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, TRANSFER_TEST_SOURCE_05_07, ); } @@ -186,7 +185,7 @@ fn transfer_suppressed_05_evmla() { fn transfer_suppressed_06_evmla() { transfer_suppressed( semver::Version::new(0, 6, 12), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, TRANSFER_TEST_SOURCE_05_07, ); } @@ -194,7 +193,7 @@ fn transfer_suppressed_06_evmla() { fn transfer_suppressed_07_evmla() { transfer_suppressed( semver::Version::new(0, 7, 6), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, TRANSFER_TEST_SOURCE_05_07, ); } @@ -202,7 +201,7 @@ fn transfer_suppressed_07_evmla() { fn transfer_suppressed_08_evmla() { transfer_suppressed( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, TRANSFER_TEST_SOURCE, ); } @@ -210,7 +209,7 @@ fn transfer_suppressed_08_evmla() { fn transfer_suppressed_08_yul() { transfer_suppressed( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::Yul, + SolcStandardJsonInputSettingsCodegen::Yul, TRANSFER_TEST_SOURCE, ); } @@ -218,90 +217,168 @@ fn transfer_suppressed_08_yul() { #[test] #[cfg_attr(target_os = "windows", ignore)] fn runtime_code_05_evmla() { - runtime_code(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + runtime_code( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn runtime_code_06_evmla() { - runtime_code(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + runtime_code( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn runtime_code_07_evmla() { - runtime_code(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + runtime_code( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn runtime_code_08_evmla() { - runtime_code(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + runtime_code( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn runtime_code_08_yul() { - runtime_code(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + runtime_code( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] -#[cfg_attr(target_os = "windows", ignore)] +#[cfg_attr( + any( + target_os = "windows", + all(target_arch = "aarch64", target_os = "linux") + ), + ignore +)] fn internal_function_pointer_argument_04() { internal_function_pointer_argument(semver::Version::new(0, 4, 26)); } #[test] -#[cfg_attr(target_os = "windows", ignore)] +#[cfg_attr( + any( + target_os = "windows", + all(target_arch = "aarch64", target_os = "linux") + ), + ignore +)] fn internal_function_pointer_argument_05() { internal_function_pointer_argument(semver::Version::new(0, 5, 17)); } #[test] +#[cfg_attr( + any( + target_os = "windows", + all(target_arch = "aarch64", target_os = "linux") + ), + ignore +)] fn internal_function_pointer_argument_06() { internal_function_pointer_argument(semver::Version::new(0, 6, 12)); } #[test] +#[cfg_attr(all(target_arch = "aarch64", target_os = "linux"), ignore)] fn internal_function_pointer_argument_07() { internal_function_pointer_argument(semver::Version::new(0, 7, 6)); } #[test] +#[cfg_attr(all(target_arch = "aarch64", target_os = "linux"), ignore)] fn internal_function_pointer_argument_08() { internal_function_pointer_argument(SolcCompiler::LAST_SUPPORTED_VERSION); } #[test] -#[cfg_attr(target_os = "windows", ignore)] +#[cfg_attr( + any( + target_os = "windows", + all(target_arch = "aarch64", target_os = "linux") + ), + ignore +)] fn internal_function_pointer_stack_04() { internal_function_pointer_stack(semver::Version::new(0, 4, 26)); } #[test] -#[cfg_attr(target_os = "windows", ignore)] +#[cfg_attr( + any( + target_os = "windows", + all(target_arch = "aarch64", target_os = "linux") + ), + ignore +)] fn internal_function_pointer_stack_05() { internal_function_pointer_stack(semver::Version::new(0, 5, 17)); } #[test] +#[cfg_attr( + any( + target_os = "windows", + all(target_arch = "aarch64", target_os = "linux") + ), + ignore +)] fn internal_function_pointer_stack_06() { internal_function_pointer_stack(semver::Version::new(0, 6, 12)); } #[test] +#[cfg_attr(all(target_arch = "aarch64", target_os = "linux"), ignore)] fn internal_function_pointer_stack_07() { internal_function_pointer_stack(semver::Version::new(0, 7, 6)); } #[test] +#[cfg_attr(all(target_arch = "aarch64", target_os = "linux"), ignore)] fn internal_function_pointer_stack_08() { internal_function_pointer_stack(SolcCompiler::LAST_SUPPORTED_VERSION); } #[test] -#[cfg_attr(target_os = "windows", ignore)] +#[cfg_attr( + any( + target_os = "windows", + all(target_arch = "aarch64", target_os = "linux") + ), + ignore +)] fn internal_function_pointer_storage_04() { internal_function_pointer_storage(semver::Version::new(0, 4, 26)); } #[test] -#[cfg_attr(target_os = "windows", ignore)] +#[cfg_attr( + any( + target_os = "windows", + all(target_arch = "aarch64", target_os = "linux") + ), + ignore +)] fn internal_function_pointer_storage_05() { internal_function_pointer_storage(semver::Version::new(0, 5, 17)); } #[test] +#[cfg_attr( + any( + target_os = "windows", + all(target_arch = "aarch64", target_os = "linux") + ), + ignore +)] fn internal_function_pointer_storage_06() { internal_function_pointer_storage(semver::Version::new(0, 6, 12)); } #[test] +#[cfg_attr(all(target_arch = "aarch64", target_os = "linux"), ignore)] fn internal_function_pointer_storage_07() { internal_function_pointer_storage(semver::Version::new(0, 7, 6)); } #[test] +#[cfg_attr(all(target_arch = "aarch64", target_os = "linux"), ignore)] fn internal_function_pointer_storage_08() { internal_function_pointer_storage(SolcCompiler::LAST_SUPPORTED_VERSION); } @@ -309,109 +386,181 @@ fn internal_function_pointer_storage_08() { #[test] #[cfg_attr(target_os = "windows", ignore)] fn tx_origin_04_evmla() { - tx_origin(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + tx_origin( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn tx_origin_05_evmla() { - tx_origin(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + tx_origin( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_06_evmla() { - tx_origin(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + tx_origin( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_07_evmla() { - tx_origin(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + tx_origin( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_08_evmla() { - tx_origin(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + tx_origin( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_08_yul() { - tx_origin(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + tx_origin( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn tx_origin_suppressed_04_evmla() { - tx_origin_suppressed(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + tx_origin_suppressed( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn tx_origin_suppressed_05_evmla() { - tx_origin_suppressed(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + tx_origin_suppressed( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_suppressed_06_evmla() { - tx_origin_suppressed(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + tx_origin_suppressed( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_suppressed_07_evmla() { - tx_origin_suppressed(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + tx_origin_suppressed( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_suppressed_08_evmla() { - tx_origin_suppressed(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + tx_origin_suppressed( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_suppressed_08_yul() { - tx_origin_suppressed(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + tx_origin_suppressed( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn tx_origin_assembly_04_evmla() { - tx_origin_assembly(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + tx_origin_assembly( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn tx_origin_assembly_05_evmla() { - tx_origin_assembly(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + tx_origin_assembly( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_assembly_06_evmla() { - tx_origin_assembly(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + tx_origin_assembly( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_assembly_07_evmla() { - tx_origin_assembly(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + tx_origin_assembly( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_assembly_08_evmla() { - tx_origin_assembly(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + tx_origin_assembly( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_assembly_08_yul() { - tx_origin_assembly(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + tx_origin_assembly( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn tx_origin_assembly_suppressed_04_evmla() { - tx_origin_assembly_suppressed(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + tx_origin_assembly_suppressed( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn tx_origin_assembly_suppressed_05_evmla() { - tx_origin_assembly_suppressed(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + tx_origin_assembly_suppressed( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_assembly_suppressed_06_evmla() { - tx_origin_assembly_suppressed(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + tx_origin_assembly_suppressed( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_assembly_suppressed_07_evmla() { - tx_origin_assembly_suppressed(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + tx_origin_assembly_suppressed( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_assembly_suppressed_08_evmla() { - tx_origin_assembly_suppressed(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + tx_origin_assembly_suppressed( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn tx_origin_assembly_suppressed_08_yul() { - tx_origin_assembly_suppressed(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + tx_origin_assembly_suppressed( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } pub const SEND_TEST_SOURCE_04: &str = r#" @@ -441,13 +590,17 @@ contract SendExample { } "#; -fn send(version: semver::Version, pipeline: SolcCodegen, source_code: &str) { +fn send( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, + source_code: &str, +) { assert!(common::check_solidity_message( source_code, "You are using '
.send/transfer()' without providing", - BTreeMap::new(), + Libraries::default(), &version, - pipeline, + codegen, false, vec![], vec![], @@ -455,13 +608,17 @@ fn send(version: semver::Version, pipeline: SolcCodegen, source_code: &str) { .expect("Test failure")); } -fn send_suppressed(version: semver::Version, pipeline: SolcCodegen, source_code: &str) { +fn send_suppressed( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, + source_code: &str, +) { assert!(!common::check_solidity_message( source_code, "You are using '
.send/transfer()' without providing", - BTreeMap::new(), + Libraries::default(), &version, - pipeline, + codegen, false, vec![ErrorType::SendTransfer], vec![], @@ -496,13 +653,17 @@ contract TransferExample { } "#; -fn transfer(version: semver::Version, pipeline: SolcCodegen, source_code: &str) { +fn transfer( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, + source_code: &str, +) { assert!(common::check_solidity_message( source_code, "You are using '
.send/transfer()' without providing", - BTreeMap::new(), + Libraries::default(), &version, - pipeline, + codegen, false, vec![], vec![], @@ -510,13 +671,17 @@ fn transfer(version: semver::Version, pipeline: SolcCodegen, source_code: &str) .expect("Test failure")); } -fn transfer_suppressed(version: semver::Version, pipeline: SolcCodegen, source_code: &str) { +fn transfer_suppressed( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, + source_code: &str, +) { assert!(!common::check_solidity_message( source_code, "You are using '
.send/transfer()' without providing", - BTreeMap::new(), + Libraries::default(), &version, - pipeline, + codegen, false, vec![ErrorType::SendTransfer], vec![], @@ -537,13 +702,13 @@ contract Test { } "#; -fn runtime_code(version: semver::Version, pipeline: SolcCodegen) { +fn runtime_code(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { assert!(common::check_solidity_message( RUNTIME_CODE_SOURCE_CODE, "Deploy and runtime code are merged together on ZKsync", - BTreeMap::new(), + Libraries::default(), &version, - pipeline, + codegen, false, vec![], vec![], @@ -585,10 +750,10 @@ contract InternalFunctionPointerExample { assert!(common::check_solidity_message( source_code, - "Internal function pointers are not supported in the EVM assembly pipeline.", - BTreeMap::new(), + "Internal function pointers are not supported in the EVM assembly codegen.", + Libraries::default(), &version, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, true, vec![], vec![], @@ -624,10 +789,10 @@ contract StackFunctionPointerExample { assert!(common::check_solidity_message( source_code, - "Internal function pointers are not supported in the EVM assembly pipeline.", - BTreeMap::new(), + "Internal function pointers are not supported in the EVM assembly codegen.", + Libraries::default(), &version, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, true, vec![], vec![], @@ -670,10 +835,10 @@ contract StorageFunctionPointerExample { assert!(common::check_solidity_message( source_code, - "Internal function pointers are not supported in the EVM assembly pipeline.", - BTreeMap::new(), + "Internal function pointers are not supported in the EVM assembly codegen.", + Libraries::default(), &version, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, true, vec![], vec![], @@ -689,13 +854,13 @@ contract TxOriginExample { } "#; -fn tx_origin(version: semver::Version, pipeline: SolcCodegen) { +fn tx_origin(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { assert!(common::check_solidity_message( TX_ORIGIN_TEST_SOURCE, "You are checking for 'tx.origin', which might lead to", - BTreeMap::new(), + Libraries::default(), &version, - pipeline, + codegen, false, vec![], vec![], @@ -703,13 +868,13 @@ fn tx_origin(version: semver::Version, pipeline: SolcCodegen) { .expect("Test failure")); } -fn tx_origin_suppressed(version: semver::Version, pipeline: SolcCodegen) { +fn tx_origin_suppressed(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { assert!(!common::check_solidity_message( TX_ORIGIN_TEST_SOURCE, "You are checking for 'tx.origin', which might lead to", - BTreeMap::new(), + Libraries::default(), &version, - pipeline, + codegen, false, vec![], vec![WarningType::TxOrigin], @@ -727,13 +892,13 @@ contract TxOriginExample { } "#; -fn tx_origin_assembly(version: semver::Version, pipeline: SolcCodegen) { +fn tx_origin_assembly(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { assert!(common::check_solidity_message( TX_ORIGIN_ASSEMBLY_TEST_SOURCE, "You are checking for 'tx.origin', which might lead to", - BTreeMap::new(), + Libraries::default(), &version, - pipeline, + codegen, false, vec![], vec![], @@ -741,13 +906,16 @@ fn tx_origin_assembly(version: semver::Version, pipeline: SolcCodegen) { .expect("Test failure")); } -fn tx_origin_assembly_suppressed(version: semver::Version, pipeline: SolcCodegen) { +fn tx_origin_assembly_suppressed( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, +) { assert!(!common::check_solidity_message( TX_ORIGIN_ASSEMBLY_TEST_SOURCE, "You are checking for 'tx.origin' in your code, which might lead to", - BTreeMap::new(), + Libraries::default(), &version, - pipeline, + codegen, false, vec![], vec![WarningType::TxOrigin], diff --git a/era-compiler-solidity/tests/unit/optimizer.rs b/era-compiler-solidity/tests/unit/optimizer.rs index 2197eda1..2a78c554 100644 --- a/era-compiler-solidity/tests/unit/optimizer.rs +++ b/era-compiler-solidity/tests/unit/optimizer.rs @@ -5,7 +5,8 @@ use std::collections::BTreeMap; use std::collections::BTreeSet; -use era_compiler_solidity::solc::codegen::Codegen as SolcCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::libraries::Libraries; use era_compiler_solidity::solc::Compiler as SolcCompiler; use crate::common; @@ -13,28 +14,46 @@ use crate::common; #[test] #[cfg_attr(target_os = "windows", ignore)] fn default_04_evmla() { - default(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn default_05_evmla() { - default(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_06_evmla() { - default(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_07_evmla() { - default(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_08_evmla() { - default(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + default( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_08_yul() { - default(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + default( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } pub const SOURCE_CODE: &str = r#" @@ -76,42 +95,43 @@ contract Test { } "#; -fn default(version: semver::Version, pipeline: SolcCodegen) { +fn default(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { let mut sources = BTreeMap::new(); sources.insert("test.sol".to_owned(), SOURCE_CODE.to_owned()); let build_unoptimized = common::build_solidity( sources.clone(), - BTreeMap::new(), + Libraries::default(), + era_compiler_common::HashType::Keccak256, BTreeSet::new(), &version, - pipeline, + codegen, era_compiler_llvm_context::OptimizerSettings::none(), ) .expect("Build failure"); let build_optimized_for_cycles = common::build_solidity( sources.clone(), - BTreeMap::new(), + Libraries::default(), + era_compiler_common::HashType::Keccak256, BTreeSet::new(), &version, - pipeline, + codegen, era_compiler_llvm_context::OptimizerSettings::cycles(), ) .expect("Build failure"); let build_optimized_for_size = common::build_solidity( sources.clone(), - BTreeMap::new(), + Libraries::default(), + era_compiler_common::HashType::Keccak256, BTreeSet::new(), &version, - pipeline, + codegen, era_compiler_llvm_context::OptimizerSettings::size(), ) .expect("Build failure"); let size_when_unoptimized = build_unoptimized .contracts - .as_ref() - .expect("Missing field `contracts`") .get("test.sol") .expect("Missing file `test.sol`") .get("Test") @@ -126,8 +146,6 @@ fn default(version: semver::Version, pipeline: SolcCodegen) { .len(); let size_when_optimized_for_cycles = build_optimized_for_cycles .contracts - .as_ref() - .expect("Missing field `contracts`") .get("test.sol") .expect("Missing file `test.sol`") .get("Test") @@ -142,8 +160,6 @@ fn default(version: semver::Version, pipeline: SolcCodegen) { .len(); let size_when_optimized_for_size = build_optimized_for_size .contracts - .as_ref() - .expect("Missing field `contracts`") .get("test.sol") .expect("Missing file `test.sol`") .get("Test") diff --git a/era-compiler-solidity/tests/unit/remappings.rs b/era-compiler-solidity/tests/unit/remappings.rs index 307c5e98..a427ff28 100644 --- a/era-compiler-solidity/tests/unit/remappings.rs +++ b/era-compiler-solidity/tests/unit/remappings.rs @@ -5,7 +5,8 @@ use std::collections::BTreeMap; use std::collections::BTreeSet; -use era_compiler_solidity::solc::codegen::Codegen as SolcCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::libraries::Libraries; use era_compiler_solidity::solc::Compiler as SolcCompiler; use crate::common; @@ -13,28 +14,46 @@ use crate::common; #[test] #[cfg_attr(target_os = "windows", ignore)] fn default_04_evmla() { - default(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn default_05_evmla() { - default(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_06_evmla() { - default(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_07_evmla() { - default(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + default( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_08_evmla() { - default(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + default( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn default_08_yul() { - default(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + default( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } pub const CALLEE_TEST_SOURCE: &str = r#" @@ -63,7 +82,7 @@ contract Main { } "#; -fn default(version: semver::Version, pipeline: SolcCodegen) { +fn default(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { let mut sources = BTreeMap::new(); sources.insert("./test.sol".to_owned(), CALLER_TEST_SOURCE.to_owned()); sources.insert("./callable.sol".to_owned(), CALLEE_TEST_SOURCE.to_owned()); @@ -73,10 +92,11 @@ fn default(version: semver::Version, pipeline: SolcCodegen) { common::build_solidity( sources, - BTreeMap::new(), + Libraries::default(), + era_compiler_common::HashType::Keccak256, remappings, &version, - pipeline, + codegen, era_compiler_llvm_context::OptimizerSettings::cycles(), ) .expect("Test failure"); diff --git a/era-compiler-solidity/tests/unit/standard_json.rs b/era-compiler-solidity/tests/unit/standard_json.rs index ba6b7bd9..95a4cbe6 100644 --- a/era-compiler-solidity/tests/unit/standard_json.rs +++ b/era-compiler-solidity/tests/unit/standard_json.rs @@ -19,7 +19,6 @@ fn standard_json_yul_solc() { assert!(!solc_output .contracts - .expect("The `contracts` field is missing") .get("Test") .expect("The `Test` contract is missing") .get("Test") @@ -41,14 +40,13 @@ fn standard_json_yul_solc_validated() { )) .expect("Standard JSON reading error"); - let solc_compiler = common::get_solc_compiler(&SolcCompiler::LAST_SUPPORTED_VERSION) + let solc_compiler = common::get_solc_compiler(&SolcCompiler::LAST_SUPPORTED_VERSION, false) .expect("`solc` initialization error"); let solc_output = common::build_yul_standard_json(solc_input, Some(&solc_compiler)).expect("Test failure"); assert!(!solc_output .contracts - .expect("The `contracts` field is missing") .get("Test") .expect("The `Test` contract is missing") .get("Test") @@ -73,7 +71,6 @@ fn standard_json_yul_solc_urls() { assert!(!solc_output .contracts - .expect("The `contracts` field is missing") .get("Test") .expect("The `Test` contract is missing") .get("Test") @@ -95,14 +92,13 @@ fn standard_json_yul_solc_urls_validated() { )) .expect("Standard JSON reading error"); - let solc_compiler = common::get_solc_compiler(&SolcCompiler::LAST_SUPPORTED_VERSION) + let solc_compiler = common::get_solc_compiler(&SolcCompiler::LAST_SUPPORTED_VERSION, false) .expect("`solc` initialization error"); let solc_output = common::build_yul_standard_json(solc_input, Some(&solc_compiler)).expect("Test failure"); assert!(!solc_output .contracts - .expect("The `contracts` field is missing") .get("Test") .expect("The `Test` contract is missing") .get("Test") @@ -127,7 +123,6 @@ fn standard_json_yul_zksolc() { assert!(!solc_output .contracts - .expect("The `contracts` field is missing") .get("EventWriter.yul") .expect("The `EventWriter.yul` contract is missing") .get("EventWriter.yul") @@ -149,14 +144,13 @@ fn standard_json_yul_zksolc_validated() { )) .expect("Standard JSON reading error"); - let solc_compiler = common::get_solc_compiler(&SolcCompiler::LAST_SUPPORTED_VERSION) + let solc_compiler = common::get_solc_compiler(&SolcCompiler::LAST_SUPPORTED_VERSION, false) .expect("`solc` initialization error"); let solc_output = common::build_yul_standard_json(solc_input, Some(&solc_compiler)).expect("Test failure"); assert!(!solc_output .contracts - .expect("The `contracts` field is missing") .get("EventWriter.yul") .expect("The `EventWriter.yul` contract is missing") .get("EventWriter.yul") @@ -181,7 +175,6 @@ fn standard_json_yul_zksolc_urls() { assert!(!solc_output .contracts - .expect("The `contracts` field is missing") .get("EventWriter.yul") .expect("The `EventWriter.yul` contract is missing") .get("EventWriter.yul") @@ -202,14 +195,13 @@ fn standard_json_yul_zksolc_urls_validated() { PathBuf::from("tests/data/standard_json_input/yul_zksolc_urls.json").as_path(), )) .expect("Standard JSON reading error"); - let solc_compiler = common::get_solc_compiler(&SolcCompiler::LAST_SUPPORTED_VERSION) + let solc_compiler = common::get_solc_compiler(&SolcCompiler::LAST_SUPPORTED_VERSION, false) .expect("`solc` initialization error"); let solc_output = common::build_yul_standard_json(solc_input, Some(&solc_compiler)).expect("Test failure"); assert!(!solc_output .contracts - .expect("The `contracts` field is missing") .get("EventWriter.yul") .expect("The `EventWriter.yul` contract is missing") .get("EventWriter.yul") @@ -234,7 +226,6 @@ fn standard_json_llvm_ir_urls() { assert!(!solc_output .contracts - .expect("The `contracts` field is missing") .get("Test") .expect("The `Test` contract is missing") .get("Test") @@ -259,7 +250,6 @@ fn standard_json_eravm_assembly_urls() { assert!(!solc_output .contracts - .expect("The `contracts` field is missing") .get("Test") .expect("The `Test` contract is missing") .get("Test") diff --git a/era-compiler-solidity/tests/unit/unsupported_instructions.rs b/era-compiler-solidity/tests/unit/unsupported_instructions.rs index 126bac98..26ef3561 100644 --- a/era-compiler-solidity/tests/unit/unsupported_instructions.rs +++ b/era-compiler-solidity/tests/unit/unsupported_instructions.rs @@ -5,7 +5,8 @@ use std::collections::BTreeMap; use std::collections::BTreeSet; -use era_compiler_solidity::solc::codegen::Codegen as SolcCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::codegen::Codegen as SolcStandardJsonInputSettingsCodegen; +use era_compiler_solidity::solc::standard_json::input::settings::libraries::Libraries; use era_compiler_solidity::solc::Compiler as SolcCompiler; use crate::common; @@ -13,95 +14,149 @@ use crate::common; #[test] #[cfg_attr(target_os = "windows", ignore)] fn codecopy_runtime_04_evmla() { - codecopy_runtime(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + codecopy_runtime( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[cfg_attr(target_os = "windows", ignore)] fn codecopy_runtime_05_evmla() { - codecopy_runtime(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + codecopy_runtime( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn codecopy_runtime_06_evmla() { - codecopy_runtime(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + codecopy_runtime( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn codecopy_runtime_07_evmla() { - codecopy_runtime(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + codecopy_runtime( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] fn codecopy_runtime_08_evmla() { - codecopy_runtime(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + codecopy_runtime( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[should_panic(expected = "The `CODECOPY` instruction is not supported")] fn codecopy_runtime_08_yul() { - codecopy_runtime(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + codecopy_runtime( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] #[should_panic(expected = "The `CALLCODE` instruction is not supported")] #[cfg_attr(target_os = "windows", ignore)] fn callcode_04_evmla() { - callcode(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + callcode( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[should_panic(expected = "The `CALLCODE` instruction is not supported")] #[cfg_attr(target_os = "windows", ignore)] fn callcode_05_evmla() { - callcode(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + callcode( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[should_panic(expected = "The `CALLCODE` instruction is not supported")] fn callcode_06_evmla() { - callcode(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + callcode( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[should_panic(expected = "The `CALLCODE` instruction is not supported")] fn callcode_07_evmla() { - callcode(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + callcode( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[should_panic(expected = "The `CALLCODE` instruction is not supported")] fn callcode_08_evmla() { - callcode(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + callcode( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[should_panic(expected = "The `CALLCODE` instruction is not supported")] fn callcode_08_yul() { - callcode(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + callcode( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] #[should_panic(expected = "The `EXTCODECOPY` instruction is not supported")] #[cfg_attr(target_os = "windows", ignore)] fn extcodecopy_04_evmla() { - extcodecopy(semver::Version::new(0, 4, 26), SolcCodegen::EVMLA); + extcodecopy( + semver::Version::new(0, 4, 26), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[should_panic(expected = "The `EXTCODECOPY` instruction is not supported")] #[cfg_attr(target_os = "windows", ignore)] fn extcodecopy_05_evmla() { - extcodecopy(semver::Version::new(0, 5, 17), SolcCodegen::EVMLA); + extcodecopy( + semver::Version::new(0, 5, 17), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[should_panic(expected = "The `EXTCODECOPY` instruction is not supported")] fn extcodecopy_06_evmla() { - extcodecopy(semver::Version::new(0, 6, 12), SolcCodegen::EVMLA); + extcodecopy( + semver::Version::new(0, 6, 12), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[should_panic(expected = "The `EXTCODECOPY` instruction is not supported")] fn extcodecopy_07_evmla() { - extcodecopy(semver::Version::new(0, 7, 6), SolcCodegen::EVMLA); + extcodecopy( + semver::Version::new(0, 7, 6), + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[should_panic(expected = "The `EXTCODECOPY` instruction is not supported")] fn extcodecopy_08_evmla() { - extcodecopy(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::EVMLA); + extcodecopy( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::EVMLA, + ); } #[test] #[should_panic(expected = "The `EXTCODECOPY` instruction is not supported")] fn extcodecopy_08_yul() { - extcodecopy(SolcCompiler::LAST_SUPPORTED_VERSION, SolcCodegen::Yul); + extcodecopy( + SolcCompiler::LAST_SUPPORTED_VERSION, + SolcStandardJsonInputSettingsCodegen::Yul, + ); } #[test] @@ -110,7 +165,7 @@ fn extcodecopy_08_yul() { fn selfdestruct_04_evmla() { selfdestruct( semver::Version::new(0, 4, 26), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SELFDESTRUCT_TEST_SOURCE_04, ); } @@ -120,7 +175,7 @@ fn selfdestruct_04_evmla() { fn selfdestruct_05_evmla() { selfdestruct( semver::Version::new(0, 5, 17), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SELFDESTRUCT_TEST_SOURCE_05, ); } @@ -129,7 +184,7 @@ fn selfdestruct_05_evmla() { fn selfdestruct_06_evmla() { selfdestruct( semver::Version::new(0, 6, 12), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SELFDESTRUCT_TEST_SOURCE_06, ); } @@ -138,7 +193,7 @@ fn selfdestruct_06_evmla() { fn selfdestruct_07_evmla() { selfdestruct( semver::Version::new(0, 7, 6), - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SELFDESTRUCT_TEST_SOURCE, ); } @@ -147,7 +202,7 @@ fn selfdestruct_07_evmla() { fn selfdestruct_08_evmla() { selfdestruct( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::EVMLA, + SolcStandardJsonInputSettingsCodegen::EVMLA, SELFDESTRUCT_TEST_SOURCE, ); } @@ -156,7 +211,7 @@ fn selfdestruct_08_evmla() { fn selfdestruct_08_yul() { selfdestruct( SolcCompiler::LAST_SUPPORTED_VERSION, - SolcCodegen::Yul, + SolcStandardJsonInputSettingsCodegen::Yul, SELFDESTRUCT_TEST_SOURCE, ); } @@ -188,7 +243,7 @@ object "ProgramCounter" { common::build_yul(sources).expect("Test failure"); } -fn codecopy_runtime(version: semver::Version, pipeline: SolcCodegen) { +fn codecopy_runtime(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { let source_code = r#" // SPDX-License-Identifier: MIT pragma solidity >=0.4.12; @@ -212,10 +267,11 @@ contract FixedCodeCopy { common::build_solidity( sources.clone(), - BTreeMap::new(), + Libraries::default(), + era_compiler_common::HashType::Ipfs, BTreeSet::new(), &version, - pipeline, + codegen, era_compiler_llvm_context::OptimizerSettings::cycles(), ) .expect("Test failure"); @@ -244,16 +300,17 @@ contract CallcodeTest { } "#; -fn callcode(version: semver::Version, pipeline: SolcCodegen) { +fn callcode(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { let mut sources = BTreeMap::new(); sources.insert("test.sol".to_owned(), CALLCODE_TEST_SOURCE.to_owned()); common::build_solidity( sources.clone(), - BTreeMap::new(), + Libraries::default(), + era_compiler_common::HashType::Ipfs, BTreeSet::new(), &version, - pipeline, + codegen, era_compiler_llvm_context::OptimizerSettings::cycles(), ) .expect("Test failure"); @@ -276,16 +333,17 @@ contract ExternalCodeCopy { } "#; -fn extcodecopy(version: semver::Version, pipeline: SolcCodegen) { +fn extcodecopy(version: semver::Version, codegen: SolcStandardJsonInputSettingsCodegen) { let mut sources = BTreeMap::new(); sources.insert("test.sol".to_owned(), EXTCODECOPY_TEST_SOURCE.to_owned()); common::build_solidity( sources.clone(), - BTreeMap::new(), + Libraries::default(), + era_compiler_common::HashType::Ipfs, BTreeSet::new(), &version, - pipeline, + codegen, era_compiler_llvm_context::OptimizerSettings::cycles(), ) .expect("Test failure"); @@ -363,16 +421,21 @@ contract MinimalDestructible { } "#; -fn selfdestruct(version: semver::Version, pipeline: SolcCodegen, source: &str) { +fn selfdestruct( + version: semver::Version, + codegen: SolcStandardJsonInputSettingsCodegen, + source: &str, +) { let mut sources = BTreeMap::new(); sources.insert("test.sol".to_owned(), source.to_owned()); common::build_solidity( sources.clone(), - BTreeMap::new(), + Libraries::default(), + era_compiler_common::HashType::Ipfs, BTreeSet::new(), &version, - pipeline, + codegen, era_compiler_llvm_context::OptimizerSettings::cycles(), ) .expect("Test failure");