From d2dbe3edbcd0234a98364f9105adb75d53b18a0d Mon Sep 17 00:00:00 2001
From: Marquis Shanahan <29431502+9547@users.noreply.github.com>
Date: Tue, 7 Jan 2025 23:36:45 +0800
Subject: [PATCH 01/74] fix(ens): don't resolve addr if doesn't contain .
(#9635)
* fix(ens): don't resolve addr if doesn't contain .
Signed-off-by: 9547 <29431502+9547@users.noreply.github.com>
* fix invalid ens name
Signed-off-by: 9547 <29431502+9547@users.noreply.github.com>
---------
Signed-off-by: 9547 <29431502+9547@users.noreply.github.com>
---
crates/cast/bin/cmd/storage.rs | 2 +-
crates/common/src/ens.rs | 25 +++++++++++++++++++++----
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/crates/cast/bin/cmd/storage.rs b/crates/cast/bin/cmd/storage.rs
index 4499fea1c..360e5d871 100644
--- a/crates/cast/bin/cmd/storage.rs
+++ b/crates/cast/bin/cmd/storage.rs
@@ -350,7 +350,7 @@ mod tests {
#[test]
fn parse_storage_etherscan_api_key() {
let args =
- StorageArgs::parse_from(["foundry-cli", "addr", "--etherscan-api-key", "dummykey"]);
+ StorageArgs::parse_from(["foundry-cli", "addr.eth", "--etherscan-api-key", "dummykey"]);
assert_eq!(args.etherscan.key(), Some("dummykey".to_string()));
std::env::set_var("ETHERSCAN_API_KEY", "FXY");
diff --git a/crates/common/src/ens.rs b/crates/common/src/ens.rs
index 1c4eadeac..650cb068a 100644
--- a/crates/common/src/ens.rs
+++ b/crates/common/src/ens.rs
@@ -96,10 +96,15 @@ impl FromStr for NameOrAddress {
type Err =
::Err;
fn from_str(s: &str) -> Result {
- if let Ok(addr) = Address::from_str(s) {
- Ok(Self::Address(addr))
- } else {
- Ok(Self::Name(s.to_string()))
+ match Address::from_str(s) {
+ Ok(addr) => Ok(Self::Address(addr)),
+ Err(err) => {
+ if s.contains('.') {
+ Ok(Self::Name(s.to_string()))
+ } else {
+ Err(err)
+ }
+ }
}
}
}
@@ -236,4 +241,16 @@ mod test {
assert_eq!(reverse_address(&addr.parse().unwrap()), expected, "{addr}");
}
}
+
+ #[test]
+ fn test_invalid_address() {
+ for addr in [
+ "0x314618",
+ "0x000000000000000000000000000000000000000", // 41
+ "0x00000000000000000000000000000000000000000", // 43
+ "0x28679A1a632125fbBf7A68d850E50623194A709E123", // 44
+ ] {
+ assert!(NameOrAddress::from_str(addr).is_err());
+ }
+ }
}
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 02/74] 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 2b0bb6273..058390dce 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 60a794477..f4465834e 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 9c619239b..8b3c510b6 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 c2ac28770..695a243c6 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,
}
From ad09bbe96a4c7b7d8ff2ad7a11ba453404a01988 Mon Sep 17 00:00:00 2001
From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com>
Date: Wed, 8 Jan 2025 11:41:46 +0530
Subject: [PATCH 03/74] chore(`forge`): rm regex for --debug and
--decode-internal (#9572)
* chore(`forge`): rm regex for --debug and --decode-internal
* fix
* fix tests
---------
Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com>
---
crates/forge/bin/cmd/test/mod.rs | 48 ++++++++----------------------
crates/forge/tests/cli/test_cmd.rs | 15 ++--------
2 files changed, 16 insertions(+), 47 deletions(-)
diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs
index 9c8e3b4e7..43181a01d 100644
--- a/crates/forge/bin/cmd/test/mod.rs
+++ b/crates/forge/bin/cmd/test/mod.rs
@@ -79,8 +79,8 @@ pub struct TestArgs {
///
/// If the matching test is a fuzz test, then it will open the debugger on the first failure
/// case. If the fuzz test does not fail, it will open the debugger on the last fuzz case.
- #[arg(long, conflicts_with_all = ["flamegraph", "flamechart", "decode_internal", "rerun"], value_name = "DEPRECATED_TEST_FUNCTION_REGEX")]
- debug: Option