From cf7eb7568d41fe2c1ceac11d6d0b3f167d43ec4e Mon Sep 17 00:00:00 2001 From: Florent Tapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Sun, 26 Jul 2026 15:54:31 +0200 Subject: [PATCH] gas bench: relax Etherscan rate-gate to 250ms when API key present (was causing httpTimeout on chain4) --- .../gas-estimation/cmd/script/oracles.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/harnesses/gas-estimation/cmd/script/oracles.go b/harnesses/gas-estimation/cmd/script/oracles.go index 8fa1b0e3..14353a0e 100644 --- a/harnesses/gas-estimation/cmd/script/oracles.go +++ b/harnesses/gas-estimation/cmd/script/oracles.go @@ -341,17 +341,24 @@ type etherscanResp struct { } // etherscanGate serialises Etherscan calls across ALL chains. The -// free-tier limit is 1 req/5s per IP, shared. With multiple chains -// each polling on its own ticker, two unlucky jitter offsets can -// land within a 5 s window and trip the throttle. The gate ensures -// at least etherscanMinGap between any two Etherscan requests -// regardless of which (oracle, chain) goroutine made them. +// free-tier no-key limit is 1 req/5s per IP shared, so without a +// key we enforce ≥6s between any two Etherscan requests regardless +// of which (oracle, chain) goroutine made them. With ETHERSCAN_API_KEY +// set, the limit rises to 5 req/s across all chains, so we drop the +// gap to 250ms — enough to serialise bursts but not enough to make +// chain4 wait past our httpTimeout (which caused visible `timeout` +// counters on Polygon and Arbitrum before the key was wired). var ( etherscanMu sync.Mutex etherscanLast time.Time ) -const etherscanMinGap = 6 * time.Second +var etherscanMinGap = func() time.Duration { + if os.Getenv("ETHERSCAN_API_KEY") != "" { + return 250 * time.Millisecond + } + return 6 * time.Second +}() func etherscanGate(ctx context.Context) error { etherscanMu.Lock()