From 63c988d9c31b4c49ff9475800646c0a306b142ca Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Mon, 22 May 2023 17:19:34 -0400 Subject: [PATCH 1/5] fix(): make result an option to handle nulls gracefully --- ethers-etherscan/src/contract.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ethers-etherscan/src/contract.rs b/ethers-etherscan/src/contract.rs index 2942afa66..183a10404 100644 --- a/ethers-etherscan/src/contract.rs +++ b/ethers-etherscan/src/contract.rs @@ -9,6 +9,7 @@ use ethers_core::{ }; use semver::Version; use serde::{Deserialize, Serialize}; +use tracing::trace; use std::{collections::HashMap, path::Path}; #[cfg(feature = "ethers-solc")] @@ -331,17 +332,21 @@ impl Client { } let query = self.create_query("contract", "getabi", HashMap::from([("address", address)])); - let resp: Response = self.get_json(&query).await?; - if resp.result.starts_with("Max rate limit reached") { + let resp: Response> = self.get_json(&query).await?; + + let result = resp.result.unwrap_or("".to_string()); + + if result.starts_with("Max rate limit reached") { return Err(EtherscanError::RateLimitExceeded) } - if resp.result.starts_with("Contract source code not verified") { + + if result.starts_with("Contract source code not verified") || resp.message.starts_with("Contract source code not verified") { if let Some(ref cache) = self.cache { cache.set_abi(address, None); } return Err(EtherscanError::ContractCodeNotVerified(address)) } - let abi = serde_json::from_str(&resp.result)?; + let abi = serde_json::from_str(&result)?; if let Some(ref cache) = self.cache { cache.set_abi(address, Some(&abi)); From 385c9088a56fff129a8968dbfe4aaaae80f1b458 Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Mon, 22 May 2023 18:02:22 -0400 Subject: [PATCH 2/5] chore: fmt --- ethers-etherscan/src/contract.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ethers-etherscan/src/contract.rs b/ethers-etherscan/src/contract.rs index 183a10404..9995fe12a 100644 --- a/ethers-etherscan/src/contract.rs +++ b/ethers-etherscan/src/contract.rs @@ -9,8 +9,8 @@ use ethers_core::{ }; use semver::Version; use serde::{Deserialize, Serialize}; -use tracing::trace; use std::{collections::HashMap, path::Path}; +use tracing::trace; #[cfg(feature = "ethers-solc")] use ethers_solc::{artifacts::Settings, EvmVersion, Project, ProjectBuilder, SolcConfig}; @@ -340,7 +340,9 @@ impl Client { return Err(EtherscanError::RateLimitExceeded) } - if result.starts_with("Contract source code not verified") || resp.message.starts_with("Contract source code not verified") { + if result.starts_with("Contract source code not verified") || + resp.message.starts_with("Contract source code not verified") + { if let Some(ref cache) = self.cache { cache.set_abi(address, None); } From 03680fa897ff334f1c62068b01d8f4afce3fd4cc Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Mon, 22 May 2023 18:03:58 -0400 Subject: [PATCH 3/5] chore: clippy --- ethers-etherscan/src/contract.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/ethers-etherscan/src/contract.rs b/ethers-etherscan/src/contract.rs index 9995fe12a..b09048852 100644 --- a/ethers-etherscan/src/contract.rs +++ b/ethers-etherscan/src/contract.rs @@ -10,7 +10,6 @@ use ethers_core::{ use semver::Version; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, path::Path}; -use tracing::trace; #[cfg(feature = "ethers-solc")] use ethers_solc::{artifacts::Settings, EvmVersion, Project, ProjectBuilder, SolcConfig}; From 94ad922d9651ef3c1ff9cb5fc2acb0f5a43f5389 Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Mon, 22 May 2023 18:45:15 -0400 Subject: [PATCH 4/5] chore: error with EmptyResult instead of always letting serde error --- ethers-etherscan/src/contract.rs | 10 +++++++++- ethers-etherscan/src/errors.rs | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ethers-etherscan/src/contract.rs b/ethers-etherscan/src/contract.rs index b09048852..0cfff5cd9 100644 --- a/ethers-etherscan/src/contract.rs +++ b/ethers-etherscan/src/contract.rs @@ -333,7 +333,15 @@ impl Client { let query = self.create_query("contract", "getabi", HashMap::from([("address", address)])); let resp: Response> = self.get_json(&query).await?; - let result = resp.result.unwrap_or("".to_string()); + let result = match resp.result { + Some(result) => result, + None => { + return Err(EtherscanError::EmptyResult { + message: resp.message, + status: resp.status, + }) + } + }; if result.starts_with("Max rate limit reached") { return Err(EtherscanError::RateLimitExceeded) diff --git a/ethers-etherscan/src/errors.rs b/ethers-etherscan/src/errors.rs index 5f71f52d9..f5d4d7016 100644 --- a/ethers-etherscan/src/errors.rs +++ b/ethers-etherscan/src/errors.rs @@ -23,6 +23,8 @@ pub enum EtherscanError { Serde(#[from] serde_json::Error), #[error("Contract source code not verified: {0}")] ContractCodeNotVerified(Address), + #[error("Response result is unexpectedly empty")] + EmptyResult { status: String, message: String }, #[error("Rate limit exceeded")] RateLimitExceeded, #[error(transparent)] From fa5c243a40adbd4af7aa291cb90ea5f52594ae9b Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Tue, 23 May 2023 11:13:09 -0400 Subject: [PATCH 5/5] chore: include status/message on error --- ethers-etherscan/src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethers-etherscan/src/errors.rs b/ethers-etherscan/src/errors.rs index f5d4d7016..83b8b10a0 100644 --- a/ethers-etherscan/src/errors.rs +++ b/ethers-etherscan/src/errors.rs @@ -23,7 +23,7 @@ pub enum EtherscanError { Serde(#[from] serde_json::Error), #[error("Contract source code not verified: {0}")] ContractCodeNotVerified(Address), - #[error("Response result is unexpectedly empty")] + #[error("Response result is unexpectedly empty: status={status}, message={message}")] EmptyResult { status: String, message: String }, #[error("Rate limit exceeded")] RateLimitExceeded,