From f98cfd9fd7b7611127ae9c47132da10693d7e8bf Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 29 Sep 2026 16:25:20 +0000 Subject: [PATCH 1/2] fix: fall back to Sourcify when an explorer refuses the submission MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Manual sol verify` on rain.math.float.deploy fails on 4663 every run and always will: Robinhood's Blockscout serves a Cloudflare challenge, forge reads the interstitial as a JSON error, and no retry count outlasts it. That is a workflow that cannot be green while a contract is fully verifiable — Sourcify carries 4663, as it does all nine of that repo's chains. A chain the explorer rejects now retries through Sourcify, and only counts as failed if that fails too. Generic: no chain is named, and any explorer that starts refusing gets the same treatment. Keys are blanked for the retry because forge picks the verifier from the `[etherscan]` entry and goes to Etherscan whenever the chain's key holds a value, `--verifier sourcify` notwithstanding. Blank rather than unset, because forge resolves the whole table before honouring `--verifier` and errors on a name with no value at all. Both were established against the live explorer. `--watch --retries 40 --delay 15` on the retry, matching the first attempt. Without `--watch` forge prints a job ID and exits 0, which would report a verification that had not happened — the failure the rest of this workflow is built to avoid. Confirmed `--watch` is honoured by the Sourcify path: polls, then `Status: match`. Verified end to end by hand on 0xEc632ea4D04A6D72F87E60FEb4C6B6813cda59bd at chain 4663, which Sourcify now records as `"match"`. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/rainix-manual-sol-verify.yaml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rainix-manual-sol-verify.yaml b/.github/workflows/rainix-manual-sol-verify.yaml index 19fa091..557f68f 100644 --- a/.github/workflows/rainix-manual-sol-verify.yaml +++ b/.github/workflows/rainix-manual-sol-verify.yaml @@ -132,13 +132,27 @@ jobs: exit 1 fi + # Sourcify takes the chains whose explorer refuses us — Robinhood's + # Blockscout serves a Cloudflare challenge no retry count outlasts. + # + # Keys are blanked for the retry because forge picks the verifier from + # the `[etherscan]` entry and goes to Etherscan whenever the chain's + # key holds a value. Blank, not unset: it resolves the whole table + # before honouring `--verifier` and errors on a name with no value. + mapfile -t blanked < <(compgen -e | grep -E '^CI_DEPLOY_[A-Z_]+_ETHERSCAN_API_KEY$' | sed 's/$/=/') + failed='' for network in $VERIFY_NETWORKS do echo "::group::$VERIFY_CONTRACT on $network" nix develop github:rainlanguage/rainix/${{ env.RAINIX_SHA }}#sol-shell -c \ forge verify-contract --chain "$network" "$VERIFY_ADDRESS" "$VERIFY_CONTRACT" --watch --retries 40 --delay 15 \ - || failed="$failed $network" + || { + echo "$network's explorer rejected the submission; retrying through Sourcify" + env "${blanked[@]}" nix develop github:rainlanguage/rainix/${{ env.RAINIX_SHA }}#sol-shell -c \ + forge verify-contract --verifier sourcify --chain "$network" "$VERIFY_ADDRESS" "$VERIFY_CONTRACT" --watch --retries 40 --delay 15 \ + || failed="$failed $network" + } echo '::endgroup::' sleep 15 done From f62f34b4b2dbfdc5718df289dc410afd15499177 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 29 Sep 2026 16:28:22 +0000 Subject: [PATCH 2/2] fix: trim the fallback comment Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/rainix-manual-sol-verify.yaml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rainix-manual-sol-verify.yaml b/.github/workflows/rainix-manual-sol-verify.yaml index 557f68f..2976007 100644 --- a/.github/workflows/rainix-manual-sol-verify.yaml +++ b/.github/workflows/rainix-manual-sol-verify.yaml @@ -132,13 +132,9 @@ jobs: exit 1 fi - # Sourcify takes the chains whose explorer refuses us — Robinhood's - # Blockscout serves a Cloudflare challenge no retry count outlasts. - # - # Keys are blanked for the retry because forge picks the verifier from - # the `[etherscan]` entry and goes to Etherscan whenever the chain's - # key holds a value. Blank, not unset: it resolves the whole table - # before honouring `--verifier` and errors on a name with no value. + # Blanked for the Sourcify retry below: forge goes to Etherscan + # whenever the chain's key holds a value. Blank, not unset — unset it + # errors resolving the table. mapfile -t blanked < <(compgen -e | grep -E '^CI_DEPLOY_[A-Z_]+_ETHERSCAN_API_KEY$' | sed 's/$/=/') failed=''