diff --git a/crates/cast/src/cmd/storage.rs b/crates/cast/src/cmd/storage.rs index 311b5df7a509d..7188b1410b65c 100644 --- a/crates/cast/src/cmd/storage.rs +++ b/crates/cast/src/cmd/storage.rs @@ -69,6 +69,10 @@ pub struct StorageArgs { #[command(flatten)] build: BuildOpts, + + /// Specify the solc version to compile with. Overrides detected version. + #[arg(long, value_parser = Version::parse)] + solc_version: Option, } impl_figment_convert_cast!(StorageArgs); @@ -160,11 +164,19 @@ impl StorageArgs { let mut project = etherscan_project(metadata, root_path)?; add_storage_layout_output(&mut project); - project.compiler = if auto_detect { - SolcCompiler::AutoDetect + // Override solc version if provided + if let Some(solc_req) = self.solc_version { + // Use user-specified version + let solc = Solc::find_or_install(&solc_req)?; + project.compiler = SolcCompiler::Specific(solc); } else { - SolcCompiler::Specific(Solc::find_or_install(&version)?) - }; + // Auto-detect or use metadata version + project.compiler = if auto_detect { + SolcCompiler::AutoDetect + } else { + SolcCompiler::Specific(Solc::find_or_install(&version)?) + }; + } // Compile let mut out = ProjectCompiler::new().quiet(true).compile(&project)?; @@ -377,4 +389,10 @@ mod tests { let key = config.get_etherscan_api_key(None).unwrap(); assert_eq!(key, "dummykey".to_string()); } + + #[test] + fn parse_solc_version_arg() { + let args = StorageArgs::parse_from(["foundry-cli", "addr.eth", "--solc-version", "0.8.10"]); + assert_eq!(args.solc_version, Some(Version::parse("0.8.10").unwrap())); + } } diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index c13727352251a..8831cbb2d2440 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -1905,6 +1905,52 @@ casttest!(storage, |_prj, cmd| { "#]]); }); +casttest!(storage_with_valid_solc_version_1, |_prj, cmd| { + cmd.args([ + "storage", + "0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2", + "--solc-version", + "0.8.10", + "--rpc-url", + next_http_archive_rpc_url().as_str(), + "--etherscan-api-key", + next_etherscan_api_key().as_str(), + ]) + .assert_success(); +}); + +casttest!(storage_with_valid_solc_version_2, |_prj, cmd| { + cmd.args([ + "storage", + "0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2", + "--solc-version", + "0.8.23", + "--rpc-url", + next_http_archive_rpc_url().as_str(), + "--etherscan-api-key", + next_etherscan_api_key().as_str(), + ]) + .assert_success(); +}); + +casttest!(storage_with_invalid_solc_version, |_prj, cmd| { + cmd.args([ + "storage", + "0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2", + "--solc-version", + "0.8.2", + "--rpc-url", + next_http_archive_rpc_url().as_str(), + "--etherscan-api-key", + next_etherscan_api_key().as_str(), + ]) + .assert_failure() + .stderr_eq(str![[r#" +Error: Encountered invalid solc version in contracts/Create2Deployer.sol: No solc version exists that matches the version requirement: ^0.8.9 + +"#]]); +}); + // casttest!(storage_layout_simple, |_prj, cmd| { cmd.args([