From 157927029b39ccd773d82414956dbaedff3ccf84 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 29 Sep 2026 11:46:59 +0000 Subject: [PATCH 1/2] docs: the Sourcify fallback as it actually works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The note said `forge verify-contract --verifier sourcify --chain 4663 ...`. That command does not work, which only showed up when `DecimalFloat` needed it on 2026-09-29. Two things it omits. Unset the etherscan keys and forge refuses to start: it resolves every entry in `[etherscan]` before honouring `--verifier`, and errors on the first name with no value. Set the Robinhood key to anything and forge announces `ETHERSCAN_API_KEY is set, defaulting to Etherscan verifier` and goes to Blockscout regardless of `--verifier sourcify`. Only an EMPTY value reaches Sourcify, with the other keys set to a placeholder so the table resolves. Also records what "failure" looks like when it worked: Sourcify forwards the result to Blockscout (403, Cloudflare) and Etherscan (rate limit) and both fail. Its own record is the verification — `GET /v2/contract/4663/
` returned `"match"` for 0xEc632ea4D04A6D72F87E60FEb4C6B6813cda59bd at 11:45:47Z. The Blockscout description is corrected too: it has not merely "rejected non-browser clients", it serves a Cloudflare challenge page, which is why forge reports a JSON deserialization error rather than a refusal. Co-Authored-By: Claude Opus 5 (1M context) --- foundry.toml | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/foundry.toml b/foundry.toml index 1911cb1..eed3f6a 100644 --- a/foundry.toml +++ b/foundry.toml @@ -126,9 +126,25 @@ flare = { key = "${CI_DEPLOY_FLARE_ETHERSCAN_API_KEY}", chain = 14 } hyperevm = { key = "${CI_DEPLOY_HYPEREVM_ETHERSCAN_API_KEY}", chain = 999 } # Robinhood Chain (4663) is not indexed by Etherscan V2. Its Blockscout speaks # the Etherscan API, so the entry points there (the key is ignored). That -# explorer has rejected non-browser clients, so if `--verify` fails there, -# verify afterwards through Sourcify: `forge verify-contract --verifier -# sourcify --chain 4663 ...`. +# explorer sits behind a Cloudflare challenge and answers forge with a 403 +# interstitial, so `--verify` fails here and the repair is Sourcify, which does +# support 4663. +# +# The key must be set and EMPTY. Unset, forge refuses to start — it resolves +# every entry in this table before it honours `--verifier`, and errors on the +# first name with no value. Set to anything, forge reports `ETHERSCAN_API_KEY +# is set, defaulting to Etherscan verifier` and goes to Blockscout anyway, +# `--verifier sourcify` notwithstanding. Empty is the only value that reaches +# Sourcify: +# +# CI_DEPLOY_ROBINHOOD_ETHERSCAN_API_KEY= \ +# CI_DEPLOY_ARBITRUM_ETHERSCAN_API_KEY=x ...every other key in this table... \ +# forge verify-contract --verifier sourcify --chain 4663
+# +# Sourcify then tries to forward the result to Blockscout and Etherscan itself, +# and both fail — 403 and a rate limit. That is cosmetic: its own record is the +# verification, and `GET /v2/contract/4663/
` reporting `"match"` is +# what to check afterwards. robinhood = { key = "${CI_DEPLOY_ROBINHOOD_ETHERSCAN_API_KEY}", chain = 4663, url = "https://robinhoodchain.blockscout.com/api" } bsc = { key = "${CI_DEPLOY_BSC_ETHERSCAN_API_KEY}", chain = 56 } polygon = { key = "${CI_DEPLOY_POLYGON_ETHERSCAN_API_KEY}", chain = 137 } From 368b2e734f2ff5a52077c6b8ed4e316974545c3b Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 29 Sep 2026 14:06:05 +0000 Subject: [PATCH 2/2] docs: cut the Sourcify note to the two facts The empty key, and that Sourcify's own record is the verification. The rest was explanation of forge's internals that a reader does not need to act. Co-Authored-By: Claude Opus 5 (1M context) --- foundry.toml | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/foundry.toml b/foundry.toml index eed3f6a..346a997 100644 --- a/foundry.toml +++ b/foundry.toml @@ -125,26 +125,11 @@ ethereum = { key = "${CI_DEPLOY_ETHEREUM_ETHERSCAN_API_KEY}", chain = 1 } flare = { key = "${CI_DEPLOY_FLARE_ETHERSCAN_API_KEY}", chain = 14 } hyperevm = { key = "${CI_DEPLOY_HYPEREVM_ETHERSCAN_API_KEY}", chain = 999 } # Robinhood Chain (4663) is not indexed by Etherscan V2. Its Blockscout speaks -# the Etherscan API, so the entry points there (the key is ignored). That -# explorer sits behind a Cloudflare challenge and answers forge with a 403 -# interstitial, so `--verify` fails here and the repair is Sourcify, which does -# support 4663. -# -# The key must be set and EMPTY. Unset, forge refuses to start — it resolves -# every entry in this table before it honours `--verifier`, and errors on the -# first name with no value. Set to anything, forge reports `ETHERSCAN_API_KEY -# is set, defaulting to Etherscan verifier` and goes to Blockscout anyway, -# `--verifier sourcify` notwithstanding. Empty is the only value that reaches -# Sourcify: -# -# CI_DEPLOY_ROBINHOOD_ETHERSCAN_API_KEY= \ -# CI_DEPLOY_ARBITRUM_ETHERSCAN_API_KEY=x ...every other key in this table... \ -# forge verify-contract --verifier sourcify --chain 4663
-# -# Sourcify then tries to forward the result to Blockscout and Etherscan itself, -# and both fail — 403 and a rate limit. That is cosmetic: its own record is the -# verification, and `GET /v2/contract/4663/
` reporting `"match"` is -# what to check afterwards. +# the Etherscan API, so the entry points there (the key is ignored), but sits +# behind a Cloudflare challenge that fails `--verify`. Repair through Sourcify +# with this key set and EMPTY — unset, forge will not start; set, it ignores +# `--verifier sourcify`. Sourcify's onward pushes then fail and do not matter; +# `GET /v2/contract/4663/
` reporting `"match"` is the verification. robinhood = { key = "${CI_DEPLOY_ROBINHOOD_ETHERSCAN_API_KEY}", chain = 4663, url = "https://robinhoodchain.blockscout.com/api" } bsc = { key = "${CI_DEPLOY_BSC_ETHERSCAN_API_KEY}", chain = 56 } polygon = { key = "${CI_DEPLOY_POLYGON_ETHERSCAN_API_KEY}", chain = 137 }