diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 32c713230492..033a6789c17a 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -580,12 +580,13 @@ impl Config { self.evm_version = self.get_normalized_evm_version(); } - /// Returns the normalized [EvmVersion] if a [SolcReq] is set to a valid version. + /// Returns the normalized [EvmVersion] if a [SolcReq] is set to a valid version or if the solc + /// path is a valid solc binary. /// /// Otherwise it returns the configured [EvmVersion]. pub fn get_normalized_evm_version(&self) -> EvmVersion { - if let Some(SolcReq::Version(version)) = &self.solc { - if let Some(evm_version) = self.evm_version.normalize_version(version) { + if let Some(version) = self.solc.as_ref().and_then(|solc| solc.try_version().ok()) { + if let Some(evm_version) = self.evm_version.normalize_version(&version) { return evm_version; } } @@ -1602,11 +1603,15 @@ impl Config { /// /// See also fn normalize_defaults(&mut self, figment: Figment) -> Figment { - if let Ok(version) = figment.extract_inner::("solc") { + if let Ok(solc) = figment.extract_inner::("solc") { // check if evm_version is set // TODO: add a warning if evm_version is provided but incompatible if figment.find_value("evm_version").is_err() { - if let Some(version) = self.evm_version.normalize_version(&version) { + if let Some(version) = solc + .try_version() + .ok() + .and_then(|version| self.evm_version.normalize_version(&version)) + { // normalize evm_version based on the provided solc version self.evm_version = version; } @@ -1999,6 +2004,22 @@ pub enum SolcReq { Local(PathBuf), } +impl SolcReq { + /// Tries to get the solc version from the `SolcReq` + /// + /// If the `SolcReq` is a `Version` it will return the version, if it's a path to a binary it + /// will try to get the version from the binary. + fn try_version(&self) -> Result { + match self { + SolcReq::Version(version) => Ok(version.clone()), + SolcReq::Local(path) => Solc::new(path).version().map_err(|err| { + warn!("failed to get solc version from {}: {}", path.display(), err); + err + }), + } + } +} + impl> From for SolcReq { fn from(s: T) -> Self { let s = s.as_ref(); diff --git a/crates/forge/bin/cmd/config.rs b/crates/forge/bin/cmd/config.rs index 731a545e4610..0758ddf5028b 100644 --- a/crates/forge/bin/cmd/config.rs +++ b/crates/forge/bin/cmd/config.rs @@ -39,7 +39,10 @@ impl ConfigArgs { return Ok(()) } - let config = self.try_load_config_unsanitized_emit_warnings()?; + let config = self + .try_load_config_unsanitized_emit_warnings()? + // we explicitly normalize the version, so mimic the behavior when invoking solc + .normalized_evm_version(); let s = if self.basic { let config = config.into_basic(); diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index d8f9db3106d9..f2dbf22c7aac 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -673,3 +673,11 @@ forgetest_init!(can_resolve_symlink_fs_permissions, |prj, cmd| { let permission = fs_permissions.find_permission(&config_path.join("config.json")).unwrap(); assert_eq!(permission, FsAccessPermission::Read); }); + +// tests if evm version is normalized for config output +forgetest!(normalize_config_evm_version, |_prj, cmd| { + cmd.args(["config", "--use", "0.8.0", "--json"]); + let output = cmd.stdout_lossy(); + let config: Config = serde_json::from_str(&output).unwrap(); + assert_eq!(config.evm_version, EvmVersion::Istanbul); +});