From 95442fa522e338a0f7685ce90a1839c36c84b52e Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Tue, 7 Jan 2025 22:55:54 +0530 Subject: [PATCH] feat(`verify`): default to sourcify if etherscan key not provided (#9630) * feat(`verify`): default to sourcify if etherscan key not provided * clippy * nit Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> --- crates/forge/tests/cli/utils.rs | 10 ++++ crates/forge/tests/cli/verify.rs | 91 ++++++++++++++++++++++---------- crates/verify/src/provider.rs | 12 ++++- crates/verify/src/verify.rs | 4 +- 4 files changed, 86 insertions(+), 31 deletions(-) diff --git a/crates/forge/tests/cli/utils.rs b/crates/forge/tests/cli/utils.rs index 2b0bb627314a..058390dceb7b 100644 --- a/crates/forge/tests/cli/utils.rs +++ b/crates/forge/tests/cli/utils.rs @@ -109,6 +109,16 @@ impl EnvExternalities { }) } + pub fn sepolia_empty_verifier() -> Option { + Some(Self { + chain: NamedChain::Sepolia, + rpc: network_rpc_key("sepolia")?, + pk: network_private_key("sepolia")?, + etherscan: String::new(), + verifier: String::new(), + }) + } + /// Returns the arguments required to deploy the contract pub fn create_args(&self) -> Vec { vec![ diff --git a/crates/forge/tests/cli/verify.rs b/crates/forge/tests/cli/verify.rs index 60a794477314..f4465834eb2d 100644 --- a/crates/forge/tests/cli/verify.rs +++ b/crates/forge/tests/cli/verify.rs @@ -91,6 +91,29 @@ fn parse_verification_result(cmd: &mut TestCommand, retries: u32) -> eyre::Resul }) } +fn verify_check( + guid: String, + chain: String, + etherscan_api_key: Option, + verifier: Option, + mut cmd: TestCommand, +) { + let mut args = vec!["verify-check", &guid, "--chain-id", &chain]; + + if let Some(etherscan_api_key) = ðerscan_api_key { + args.push("--etherscan-api-key"); + args.push(etherscan_api_key); + } + + if let Some(verifier) = &verifier { + args.push("--verifier"); + args.push(verifier); + } + cmd.forge_fuse().args(args); + + parse_verification_result(&mut cmd, 6).expect("Failed to verify check") +} + fn await_verification_response(info: EnvExternalities, mut cmd: TestCommand) { let guid = { // Give Etherscan some time to detect the transaction. @@ -110,17 +133,29 @@ fn await_verification_response(info: EnvExternalities, mut cmd: TestCommand) { }; // verify-check - cmd.forge_fuse() - .arg("verify-check") - .arg(guid) - .arg("--chain-id") - .arg(info.chain.to_string()) - .arg("--etherscan-api-key") - .arg(info.etherscan) - .arg("--verifier") - .arg(info.verifier); + let etherscan = (!info.etherscan.is_empty()).then_some(info.etherscan.clone()); + let verifier = (!info.verifier.is_empty()).then_some(info.verifier.clone()); + verify_check(guid, info.chain.to_string(), etherscan, verifier, cmd); +} - parse_verification_result(&mut cmd, 6).expect("Failed to verify check") +fn deploy_contract( + info: &EnvExternalities, + contract_path: &str, + prj: TestProject, + cmd: &mut TestCommand, +) -> String { + add_unique(&prj); + add_verify_target(&prj); + let output = cmd + .forge_fuse() + .arg("create") + .args(info.create_args()) + .arg(contract_path) + .assert_success() + .get_output() + .stdout_lossy(); + utils::parse_deployed_address(output.as_str()) + .unwrap_or_else(|| panic!("Failed to parse deployer {output}")) } #[allow(clippy::disallowed_macros)] @@ -128,30 +163,27 @@ fn verify_on_chain(info: Option, prj: TestProject, mut cmd: Te // only execute if keys present if let Some(info) = info { println!("verifying on {}", info.chain); - add_unique(&prj); - add_verify_target(&prj); let contract_path = "src/Verify.sol:Verify"; - let output = cmd - .arg("create") - .args(info.create_args()) - .arg(contract_path) - .assert_success() - .get_output() - .stdout_lossy(); - let address = utils::parse_deployed_address(output.as_str()) - .unwrap_or_else(|| panic!("Failed to parse deployer {output}")); + let address = deploy_contract(&info, contract_path, prj, &mut cmd); - cmd.forge_fuse().arg("verify-contract").root_arg().args([ + let mut args = vec![ "--chain-id".to_string(), info.chain.to_string(), address, contract_path.to_string(), - "--etherscan-api-key".to_string(), - info.etherscan.to_string(), - "--verifier".to_string(), - info.verifier.to_string(), - ]); + ]; + + if !info.etherscan.is_empty() { + args.push("--etherscan-api-key".to_string()); + args.push(info.etherscan.clone()); + } + + if !info.verifier.is_empty() { + args.push("--verifier".to_string()); + args.push(info.verifier.clone()); + } + cmd.forge_fuse().arg("verify-contract").root_arg().args(args); await_verification_response(info, cmd) } @@ -247,3 +279,8 @@ forgetest!(can_create_verify_random_contract_sepolia, |prj, cmd| { forgetest!(can_guess_constructor_args, |prj, cmd| { guess_constructor_args(EnvExternalities::goerli(), prj, cmd); }); + +// tests `create && verify-contract && verify-check` on sepolia with default sourcify verifier +forgetest!(can_verify_random_contract_sepolia_default_sourcify, |prj, cmd| { + verify_on_chain(EnvExternalities::sepolia_empty_verifier(), prj, cmd); +}); diff --git a/crates/verify/src/provider.rs b/crates/verify/src/provider.rs index 9c619239b6d6..8b3c510b64a9 100644 --- a/crates/verify/src/provider.rs +++ b/crates/verify/src/provider.rs @@ -158,8 +158,8 @@ impl fmt::Display for VerificationProviderType { #[derive(Clone, Debug, Default, PartialEq, Eq, clap::ValueEnum)] pub enum VerificationProviderType { - #[default] Etherscan, + #[default] Sourcify, Blockscout, Oklink, @@ -170,6 +170,9 @@ pub enum VerificationProviderType { impl VerificationProviderType { /// Returns the corresponding `VerificationProvider` for the key pub fn client(&self, key: &Option) -> Result> { + if key.as_ref().is_some_and(|k| !k.is_empty()) && matches!(self, Self::Sourcify) { + return Ok(Box::::default()); + } match self { Self::Etherscan => { if key.as_ref().is_none_or(|key| key.is_empty()) { @@ -177,7 +180,12 @@ impl VerificationProviderType { } Ok(Box::::default()) } - Self::Sourcify => Ok(Box::::default()), + Self::Sourcify => { + sh_println!( + "Attempting to verify on Sourcify, pass the --etherscan-api-key to verify on Etherscan OR use the --verifier flag to verify on any other provider" + )?; + Ok(Box::::default()) + } Self::Blockscout => Ok(Box::::default()), Self::Oklink => Ok(Box::::default()), Self::Custom => Ok(Box::::default()), diff --git a/crates/verify/src/verify.rs b/crates/verify/src/verify.rs index c2ac287703bd..695a243c6afd 100644 --- a/crates/verify/src/verify.rs +++ b/crates/verify/src/verify.rs @@ -29,7 +29,7 @@ use crate::provider::VerificationContext; #[derive(Clone, Debug, Parser)] pub struct VerifierArgs { /// The contract verification provider to use. - #[arg(long, help_heading = "Verifier options", default_value = "etherscan", value_enum)] + #[arg(long, help_heading = "Verifier options", default_value = "sourcify", value_enum)] pub verifier: VerificationProviderType, /// The verifier API KEY, if using a custom provider. @@ -44,7 +44,7 @@ pub struct VerifierArgs { impl Default for VerifierArgs { fn default() -> Self { Self { - verifier: VerificationProviderType::Etherscan, + verifier: VerificationProviderType::Sourcify, verifier_api_key: None, verifier_url: None, }