Skip to content

Commit f75cd72

Browse files
authored
fix: Etherscan V2 API URLs from alloy-chains already contain chainid (#93)
Related: foundry-rs/foundry#10912 Latest `alloy-chains` update causes failures in Foundry: https://github.com/foundry-rs/foundry/actions/runs/16050452390/job/45291650366 due to `chainid` query parameter being set multiple times (once in `alloy-chains` and then again in `query`). We should avoid setting it twice if it already exists. before: ``` https://api.etherscan.io/v2/api?chainid=137&apikey=<API_KEY>&module=contract&action=getsourcecode&chainid=137&address=0x794a61358d6845594f94dc1db02a252b5b4814ad ``` after (avoid duplicate `chainid` / `chainId`): ``` https://api.etherscan.io/v2/api?chainid=137&apikey=<API_KEY>&module=contract&action=getsourcecode&address=0x794a61358d6845594f94dc1db02a252b5b4814ad ``` Failing without: https://github.com/foundry-rs/foundry/actions/runs/16050452390/job/45291650366 Passing with this change: https://github.com/foundry-rs/foundry/actions/runs/16053887189/job/45303239622
1 parent 561480b commit f75cd72

File tree

1 file changed

+16
-9
lines changed
  • crates/block-explorers/src

1 file changed

+16
-9
lines changed

crates/block-explorers/src/lib.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub struct Client {
9797
api_key: Option<String>,
9898
/// Etherscan API version
9999
etherscan_api_version: EtherscanApiVersion,
100-
/// Etherscan API endpoint like <https://api(-chain).etherscan.io/api>
100+
/// Etherscan API endpoint like <https://api.etherscan.io/v2/api?chainid=(chain_id)>
101101
etherscan_api_url: Url,
102102
/// Etherscan base endpoint like <https://etherscan.io>
103103
etherscan_url: Url,
@@ -262,12 +262,14 @@ impl Client {
262262
async fn post<F: Serialize>(&self, form: &F) -> Result<String> {
263263
trace!(target: "etherscan", "POST {}", self.etherscan_api_url);
264264

265-
let post_query = match self.chain_id {
266-
Some(chain_id) if self.etherscan_api_version == EtherscanApiVersion::V2 => {
267-
HashMap::from([("chainid", chain_id)])
268-
}
269-
_ => HashMap::new(),
270-
};
265+
let mut post_query = HashMap::new();
266+
267+
if self.etherscan_api_version == EtherscanApiVersion::V2
268+
&& self.chain_id.is_some()
269+
&& !self.url_contains_chainid()
270+
{
271+
post_query.insert("chainid", self.chain_id.unwrap());
272+
}
271273

272274
let response = self
273275
.client
@@ -278,6 +280,7 @@ impl Client {
278280
.await?
279281
.text()
280282
.await?;
283+
281284
Ok(response)
282285
}
283286

@@ -322,10 +325,14 @@ impl Client {
322325
apikey: self.api_key.as_deref().map(Cow::Borrowed),
323326
module: Cow::Borrowed(module),
324327
action: Cow::Borrowed(action),
325-
chain_id: self.chain_id,
328+
chain_id: if self.url_contains_chainid() { None } else { self.chain_id },
326329
other,
327330
}
328331
}
332+
333+
fn url_contains_chainid(&self) -> bool {
334+
self.etherscan_api_url.query_pairs().any(|(key, _)| key.eq_ignore_ascii_case("chainid"))
335+
}
329336
}
330337

331338
#[derive(Clone, Debug, Default)]
@@ -334,7 +341,7 @@ pub struct ClientBuilder {
334341
client: Option<reqwest::Client>,
335342
/// Etherscan API key
336343
api_key: Option<String>,
337-
/// Etherscan API endpoint like <https://api(-chain).etherscan.io/api>
344+
/// Etherscan API endpoint like <https://api.etherscan.io/v2/api?chainid=(chain_id)>
338345
etherscan_api_url: Option<Url>,
339346
/// Etherscan API version (v2 is new verifier version, v1 is the default)
340347
etherscan_api_version: EtherscanApiVersion,

0 commit comments

Comments
 (0)