Skip to content

Commit f9ed928

Browse files
committed
cover solc version errors with scripts
1 parent d59ef94 commit f9ed928

12 files changed

+212
-43
lines changed

era-compiler-solidity/src/solc/mod.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ impl Compiler {
6969
let mut executables = Self::executables().write().expect("Sync");
7070

7171
if let Err(error) = which::which(executable) {
72-
anyhow::bail!("The `{executable}` executable not found in ${{PATH}}: {error}. Please add it to ${{PATH}} or provide it explicitly with the `--solc` option.");
72+
anyhow::bail!("The `{executable}` executable not found: {error}. Please add it to ${{PATH}} or provide it explicitly with the `--solc` option.");
7373
}
7474
let version = Self::parse_version(executable)?;
7575
let compiler = Self {
@@ -335,11 +335,10 @@ impl Compiler {
335335
command.arg("--version");
336336
let output = command
337337
.output()
338-
.map_err(|error| anyhow::anyhow!("{} subprocess: {:?}", executable, error))?;
338+
.map_err(|error| anyhow::anyhow!("`{executable}` subprocess: {error:?}."))?;
339339
if !output.status.success() {
340340
anyhow::bail!(
341-
"{} version getting: {}",
342-
executable,
341+
"`{executable}` version getting: {}",
343342
String::from_utf8_lossy(output.stderr.as_slice()).to_string()
344343
);
345344
}
@@ -348,22 +347,19 @@ impl Compiler {
348347
let long = stdout
349348
.lines()
350349
.nth(1)
351-
.ok_or_else(|| anyhow::anyhow!("{} version parsing: not enough lines", executable))?
350+
.ok_or_else(|| anyhow::anyhow!("`{executable}` version parsing: not enough lines."))?
352351
.split(' ')
353352
.nth(1)
354353
.ok_or_else(|| {
355-
anyhow::anyhow!(
356-
"{} version parsing: not enough words in the 2nd line",
357-
executable
358-
)
354+
anyhow::anyhow!("`{executable}` version parsing: not enough words in the 2nd line.")
359355
})?
360356
.to_owned();
361357
let default: semver::Version = long
362358
.split('+')
363359
.next()
364-
.ok_or_else(|| anyhow::anyhow!("{} version parsing: metadata dropping", executable))?
360+
.expect("Always exists")
365361
.parse()
366-
.map_err(|error| anyhow::anyhow!("{} version parsing: {}", executable, error))?;
362+
.map_err(|error| anyhow::anyhow!("`{executable}` version parsing: {error}."))?;
367363

368364
let l2_revision: Option<semver::Version> = stdout
369365
.lines()
@@ -375,14 +371,14 @@ impl Compiler {
375371
let version = Version::new(long, default, l2_revision);
376372
if version.default < Self::FIRST_SUPPORTED_VERSION {
377373
anyhow::bail!(
378-
"`solc` versions <{} are not supported, found {}",
374+
"`{executable}` versions older than {} are not supported, found {}. Please upgrade to the latest supported version.",
379375
Self::FIRST_SUPPORTED_VERSION,
380376
version.default
381377
);
382378
}
383379
if version.default > Self::LAST_SUPPORTED_VERSION {
384380
anyhow::bail!(
385-
"`solc` versions >{} are not supported, found {}",
381+
"`{executable}` versions newer than {} are not supported, found {}. Please check if you are using the latest version of zksolc.",
386382
Self::LAST_SUPPORTED_VERSION,
387383
version.default
388384
);

era-compiler-solidity/src/solc/standard_json/output/contract/eravm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
///
66
/// The `solc --standard-json` output contract EraVM data.
77
///
8-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
8+
#[derive(Debug, Clone, serde::Serialize)]
99
#[serde(rename_all = "camelCase")]
1010
pub struct EraVM {
1111
/// The contract bytecode.

era-compiler-solidity/src/solc/standard_json/output/contract/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub struct Contract {
3939
#[serde(default, skip_serializing_if = "Option::is_none")]
4040
pub ir_optimized: Option<String>,
4141
/// The EraVM data of the contract.
42-
#[serde(default, skip_serializing_if = "Option::is_none")]
42+
#[serde(default, skip_serializing_if = "Option::is_none", skip_deserializing)]
4343
pub eravm: Option<EraVM>,
4444
/// The EVM data of the contract.
4545
#[serde(default, skip_serializing_if = "Option::is_none")]

era-compiler-solidity/tests/cli/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,28 @@ pub const TEST_LINKER_BYTECODE_COPY_PATH: &str = "tests/data/bytecodes/linker_co
182182
/// The broken input file path.
183183
pub const TEST_BROKEN_INPUT_PATH: &str = "tests/data/broken.bad";
184184

185+
/// A test constant.
186+
pub const TEST_SCRIPT_SOLC_VERSION_OUTPUT_ERROR_PATH: &str =
187+
"tests/scripts/solc_version_output_error.sh";
188+
189+
/// A test constant.
190+
pub const TEST_SCRIPT_SOLC_VERSION_TOO_OLD_PATH: &str = "tests/scripts/solc_version_too_old.sh";
191+
192+
/// A test constant.
193+
pub const TEST_SCRIPT_SOLC_VERSION_TOO_NEW_PATH: &str = "tests/scripts/solc_version_too_new.sh";
194+
195+
/// A test constant.
196+
pub const TEST_SCRIPT_SOLC_VERSION_NOT_ENOUGH_LINES_PATH: &str =
197+
"tests/scripts/solc_version_not_enough_lines.sh";
198+
199+
/// A test constant.
200+
pub const TEST_SCRIPT_SOLC_VERSION_NOT_ENOUGH_WORDS_IN_2ND_LINE_PATH: &str =
201+
"tests/scripts/solc_version_not_enough_words_in_2nd_line.sh";
202+
203+
/// A test constant.
204+
pub const TEST_SCRIPT_SOLC_VERSION_PARSING_ERROR_PATH: &str =
205+
"tests/scripts/solc_version_parsing_error.sh";
206+
185207
/// A test constant.
186208
pub const LIBRARY_DEFAULT: &str = "tests/data/contracts/solidity/MiniMath.sol:MiniMath=0xF9702469Dfb84A9aC171E284F71615bd3D3f1EdC";
187209

era-compiler-solidity/tests/cli/solc.rs

Lines changed: 156 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@ use predicates::prelude::predicate;
77
fn with_solc() -> anyhow::Result<()> {
88
common::setup()?;
99

10-
let mut zksolc = Command::cargo_bin(era_compiler_solidity::DEFAULT_EXECUTABLE_NAME)?;
1110
let solc_compiler = common::get_solc_compiler(
1211
&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION,
1312
false,
1413
)?
1514
.executable;
1615

17-
let assert = zksolc
18-
.arg(cli::TEST_SOLIDITY_CONTRACT_PATH)
19-
.arg("--solc")
20-
.arg(solc_compiler)
21-
.assert();
16+
let args = &[
17+
cli::TEST_SOLIDITY_CONTRACT_PATH,
18+
"--solc",
19+
solc_compiler.as_str(),
20+
];
2221

23-
assert
22+
let result = cli::execute_zksolc(args)?;
23+
result
2424
.success()
2525
.stderr(predicate::str::contains("Compiler run successful"));
2626

@@ -33,12 +33,11 @@ fn without_solc() -> anyhow::Result<()> {
3333

3434
let mut zksolc = Command::cargo_bin(era_compiler_solidity::DEFAULT_EXECUTABLE_NAME)?;
3535

36-
let assert = zksolc
36+
let result = zksolc
3737
.arg(cli::TEST_SOLIDITY_CONTRACT_PATH)
3838
.env("PATH", "./solc-bin")
3939
.assert();
40-
41-
assert
40+
result
4241
.success()
4342
.stderr(predicate::str::contains("Compiler run successful"));
4443

@@ -49,21 +48,21 @@ fn without_solc() -> anyhow::Result<()> {
4948
fn with_solc_standard_json_mode() -> anyhow::Result<()> {
5049
common::setup()?;
5150

52-
let mut zksolc = Command::cargo_bin(era_compiler_solidity::DEFAULT_EXECUTABLE_NAME)?;
5351
let solc_compiler = common::get_solc_compiler(
5452
&era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION,
5553
false,
5654
)?
5755
.executable;
5856

59-
let assert = zksolc
60-
.arg("--solc")
61-
.arg(solc_compiler)
62-
.arg("--standard-json")
63-
.arg(cli::TEST_SOLIDITY_STANDARD_JSON_SOLC_PATH)
64-
.assert();
57+
let args = &[
58+
"--solc",
59+
solc_compiler.as_str(),
60+
"--standard-json",
61+
cli::TEST_SOLIDITY_STANDARD_JSON_SOLC_PATH,
62+
];
6563

66-
assert
64+
let result = cli::execute_zksolc(args)?;
65+
result
6766
.success()
6867
.stdout(predicate::str::contains("bytecode"));
6968

@@ -74,16 +73,15 @@ fn with_solc_standard_json_mode() -> anyhow::Result<()> {
7473
fn without_solc_standard_json_mode() -> anyhow::Result<()> {
7574
common::setup()?;
7675

77-
let mut zksolc = Command::cargo_bin(era_compiler_solidity::DEFAULT_EXECUTABLE_NAME)?;
78-
79-
let assert = zksolc
80-
.arg("--standard-json")
81-
.arg(cli::TEST_SOLIDITY_STANDARD_JSON_SOLC_PATH)
82-
.assert();
76+
let args = &[
77+
"--standard-json",
78+
cli::TEST_SOLIDITY_STANDARD_JSON_SOLC_PATH,
79+
];
8380

84-
assert.success().stdout(predicate::str::contains(
85-
"The `solc` executable not found in ${PATH}",
86-
));
81+
let result = cli::execute_zksolc(args)?;
82+
result
83+
.success()
84+
.stdout(predicate::str::contains("bytecode"));
8785

8886
Ok(())
8987
}
@@ -139,3 +137,134 @@ fn with_solc_eravm_assembly_mode() -> anyhow::Result<()> {
139137

140138
Ok(())
141139
}
140+
141+
#[test]
142+
fn with_solc_not_found() -> anyhow::Result<()> {
143+
common::setup()?;
144+
145+
let path = "solc-not-found";
146+
let args = &[cli::TEST_SOLIDITY_CONTRACT_PATH, "--solc", path];
147+
148+
let result = cli::execute_zksolc(args)?;
149+
result.failure().stderr(predicate::str::contains(
150+
format!("The `{path}` executable not found:").as_str(),
151+
));
152+
153+
Ok(())
154+
}
155+
156+
#[test]
157+
fn with_solc_version_output_error() -> anyhow::Result<()> {
158+
common::setup()?;
159+
160+
let args = &[
161+
cli::TEST_SOLIDITY_CONTRACT_PATH,
162+
"--solc",
163+
cli::TEST_SCRIPT_SOLC_VERSION_OUTPUT_ERROR_PATH,
164+
];
165+
166+
let result = cli::execute_zksolc(args)?;
167+
result
168+
.failure()
169+
.stderr(predicate::str::contains("version getting:"));
170+
171+
Ok(())
172+
}
173+
174+
#[test]
175+
fn with_solc_version_too_old() -> anyhow::Result<()> {
176+
common::setup()?;
177+
178+
let args = &[
179+
cli::TEST_SOLIDITY_CONTRACT_PATH,
180+
"--solc",
181+
cli::TEST_SCRIPT_SOLC_VERSION_TOO_OLD_PATH,
182+
];
183+
184+
let version_supported = era_compiler_solidity::SolcCompiler::FIRST_SUPPORTED_VERSION;
185+
let mut version_not_supported = version_supported.clone();
186+
version_not_supported.patch -= 1;
187+
188+
let result = cli::execute_zksolc(args)?;
189+
result
190+
.failure()
191+
.stderr(predicate::str::contains(format!("versions older than {version_supported} are not supported, found {version_not_supported}.").as_str()));
192+
193+
Ok(())
194+
}
195+
196+
#[test]
197+
fn with_solc_version_too_new() -> anyhow::Result<()> {
198+
common::setup()?;
199+
200+
let args = &[
201+
cli::TEST_SOLIDITY_CONTRACT_PATH,
202+
"--solc",
203+
cli::TEST_SCRIPT_SOLC_VERSION_TOO_NEW_PATH,
204+
];
205+
206+
let version_supported = era_compiler_solidity::SolcCompiler::LAST_SUPPORTED_VERSION;
207+
let mut version_not_supported = version_supported.clone();
208+
version_not_supported.patch += 1;
209+
210+
let result = cli::execute_zksolc(args)?;
211+
result
212+
.failure()
213+
.stderr(predicate::str::contains(format!("versions newer than {version_supported} are not supported, found {version_not_supported}.").as_str()));
214+
215+
Ok(())
216+
}
217+
218+
#[test]
219+
fn with_solc_version_not_enough_lines() -> anyhow::Result<()> {
220+
common::setup()?;
221+
222+
let args = &[
223+
cli::TEST_SOLIDITY_CONTRACT_PATH,
224+
"--solc",
225+
cli::TEST_SCRIPT_SOLC_VERSION_NOT_ENOUGH_LINES_PATH,
226+
];
227+
228+
let result = cli::execute_zksolc(args)?;
229+
result.failure().stderr(predicate::str::contains(
230+
"version parsing: not enough lines.",
231+
));
232+
233+
Ok(())
234+
}
235+
236+
#[test]
237+
fn with_solc_version_not_enough_words_in_2nd_line() -> anyhow::Result<()> {
238+
common::setup()?;
239+
240+
let args = &[
241+
cli::TEST_SOLIDITY_CONTRACT_PATH,
242+
"--solc",
243+
cli::TEST_SCRIPT_SOLC_VERSION_NOT_ENOUGH_WORDS_IN_2ND_LINE_PATH,
244+
];
245+
246+
let result = cli::execute_zksolc(args)?;
247+
result.failure().stderr(predicate::str::contains(
248+
"version parsing: not enough words in the 2nd line.",
249+
));
250+
251+
Ok(())
252+
}
253+
254+
#[test]
255+
fn with_solc_version_parsing_error() -> anyhow::Result<()> {
256+
common::setup()?;
257+
258+
let args = &[
259+
cli::TEST_SOLIDITY_CONTRACT_PATH,
260+
"--solc",
261+
cli::TEST_SCRIPT_SOLC_VERSION_PARSING_ERROR_PATH,
262+
];
263+
264+
let result = cli::execute_zksolc(args)?;
265+
result
266+
.failure()
267+
.stderr(predicate::str::contains("version parsing:"));
268+
269+
Ok(())
270+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
This is a broken file that must be rejected by the compiler.
1+
This is a broken file that must be rejected for various reasons.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
echo 'solc, the solidity compiler commandline interface'
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
3+
echo 'solc, the solidity compiler commandline interface'
4+
echo 'Version:'
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
exit 1
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
3+
echo 'solc, the solidity compiler commandline interface'
4+
echo 'Version: x.y.z+commit.deadbeef.platform.toolchain'
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
3+
echo 'solc, the solidity compiler commandline interface'
4+
echo 'Version: 0.8.29+commit.deadbeef.platform.toolchain'
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
3+
echo 'solc, the solidity compiler commandline interface'
4+
echo 'Version: 0.4.11+commit.deadbeef.platform.toolchain'

0 commit comments

Comments
 (0)