diff --git a/crates/forge/bin/cmd/coverage.rs b/crates/forge/bin/cmd/coverage.rs index 56b2024e391b..7e60a5451efc 100644 --- a/crates/forge/bin/cmd/coverage.rs +++ b/crates/forge/bin/cmd/coverage.rs @@ -16,7 +16,7 @@ use forge::{ use foundry_cli::utils::{LoadConfig, STATIC_FUZZ_SEED}; use foundry_common::{compile::ProjectCompiler, fs}; use foundry_compilers::{ - artifacts::{sourcemap::SourceMap, CompactBytecode, CompactDeployedBytecode}, + artifacts::{sourcemap::SourceMap, CompactBytecode, CompactDeployedBytecode, SolcLanguage}, Artifact, ArtifactId, Project, ProjectCompileOutput, }; use foundry_config::{Config, SolcReq}; @@ -94,23 +94,12 @@ impl CoverageArgs { // Set up the project let mut project = config.create_project(false, false)?; if self.ir_minimum { - // TODO: How to detect solc version if the user does not specify a solc version in - // config case1: specify local installed solc ? - // case2: multiple solc versions used and auto_detect_solc == true - if let Some(SolcReq::Version(version)) = &config.solc { - if *version < Version::new(0, 8, 13) { - return Err(eyre::eyre!( - "viaIR with minimum optimization is only available in Solidity 0.8.13 and above." - )); - } - } - // print warning message sh_warn!("{}", concat!( - "Warning! \"--ir-minimum\" flag enables viaIR with minimum optimization, \ + "`--ir-minimum` enables viaIR with minimum optimization, \ which can result in inaccurate source mappings.\n", "Only use this flag as a workaround if you are experiencing \"stack too deep\" errors.\n", - "Note that \"viaIR\" is only available in Solidity 0.8.13 and above.\n", + "Note that \"viaIR\" is production ready since Solidity 0.8.13 and above.\n", "See more: https://github.com/foundry-rs/foundry/issues/3357", ))?; @@ -119,7 +108,15 @@ impl CoverageArgs { // And also in new releases of solidity: // https://github.com/ethereum/solidity/issues/13972#issuecomment-1628632202 project.settings.solc.settings = - project.settings.solc.settings.with_via_ir_minimum_optimization() + project.settings.solc.settings.with_via_ir_minimum_optimization(); + let version = if let Some(SolcReq::Version(version)) = &config.solc { + version + } else { + // Sanitize settings for solc 0.8.4 if version cannot be detected. + // See . + &Version::new(0, 8, 4) + }; + project.settings.solc.settings.sanitize(version, SolcLanguage::Solidity); } else { project.settings.solc.optimizer.disable(); project.settings.solc.optimizer.runs = None; diff --git a/crates/forge/tests/cli/coverage.rs b/crates/forge/tests/cli/coverage.rs index 0ed272ae2531..65900c592ba5 100644 --- a/crates/forge/tests/cli/coverage.rs +++ b/crates/forge/tests/cli/coverage.rs @@ -1413,3 +1413,37 @@ contract AContractTest is DSTest { "#]]); }); + +// +// Test coverage with `--ir-minimum` for solidity < 0.8.5. +forgetest!(test_ir_minimum_coverage, |prj, cmd| { + prj.insert_ds_test(); + prj.add_source( + "AContract.sol", + r#" +pragma solidity 0.8.4; + +contract AContract { + function isContract(address account) internal view returns (bool) { + bytes32 codehash; + bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; + assembly { + codehash := extcodehash(account) + } + return (codehash != accountHash && codehash != 0x0); + } +} + "#, + ) + .unwrap(); + + // Assert coverage doesn't fail with `Error: Unknown key "inliner"`. + cmd.arg("coverage").arg("--ir-minimum").assert_success().stdout_eq(str![[r#" +... +| File | % Lines | % Statements | % Branches | % Funcs | +|-------------------|-------------|--------------|---------------|-------------| +| src/AContract.sol | 0.00% (0/4) | 0.00% (0/4) | 100.00% (0/0) | 0.00% (0/1) | +| Total | 0.00% (0/4) | 0.00% (0/4) | 100.00% (0/0) | 0.00% (0/1) | + +"#]]); +});