Arena page generates uncontrolled RPC retry storm under any RPC degradation (post-#216) #221
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:open_issues
agents
agent:security_audit
agent:verify
area
timecurve
arena
arena-v2
audit
block:feature_review
block:security
bug
contracts
design
devops
docs
documentation
enhancement
epic
feature
frontend
indexer
low priority
megaeth
operations
ops
performance
QA
qa checklist
referrals
removal
security
smart-contracts
tech-debt
testing
time-arena
timecurve
visual-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
code/yieldomega#221
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found while running the #216 verification checklist. Arena (/timecurve/arena) is generating an uncontrolled retry storm against RPC endpoints. This appears to be a regression class separate from the polling-cadence work that #216 addresses — the retry layer never backs off.
Numbers from a fresh 60s observation
Arena is firing ~2,100 requests per second under load. Tested in Incognito so wallet extensions are ruled out as the cause.
What I see in the network panel
Every visible request on Arena is one of:
Both states across all RPC endpoints in the fallback list:
Hypothesis
Chrome enforces a per-origin parallel connection cap. When the page generates many simultaneous outgoing requests faster than the network can drain them, Chrome starts dropping or queueing. The (pending) rows look like requests sitting in Chrome's queue. The (failed) rows look like requests Chrome killed for backpressure.
Once requests start failing, the existing retry/fallback path appears to fire more requests immediately rather than backing off. That's the retry loop.
I confirmed mainnet.megaeth.com/rpc is alive globally with:
curl -X POST https://mainnet.megaeth.com/rpc -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
returned 0xfae6cc — block 16,443,084
So the underlying transport works. The failures are happening at the browser layer under load.
Possibly related to the #216 known follow-up
The shipped notes say:
Marked non-blocking, but this observation suggests it IS blocking — when RPC is even slightly degraded, the mergedArenaTc multicall doesn't drop in volume, the retry layer doesn't engage useRpcQueryHealthForRefetch (or it does but the multicall doesn't subscribe), and the page generates 100k+ requests/min.
Repro
Comparison data
Simple page (/timecurve) under the same conditions in the same session: 5,906 req/60s. So the storm is specific to Arena.
Severity
Launch-impact class. The Arena page is the WarBow leaderboard / steal / guard surface. If it's unusable when any RPC endpoint degrades (and one of them — globalstake — is the same one that was flagged in #216 as dead, still in position 1 of VITE_RPC_URL), most users hitting Arena during a partial RPC outage will see a broken page.
Related
Asks of dev
@PlasticDigits — couple things:
mentioned in issue #216
Keep here in 221
mentioned in commit
8f69b7b159Fix landed on
main(8f69b7b)Root cause: With
VITE_INDEXER_URLset, Arena disabled the #216 sale-state RPC multicalls — so nothing was feedingreportRpcFetchAttempt, while sixuseWatchContractEventlog pollers + uncappeduseBlockhead reads kept hammering JSON-RPC. Under a degraded endpoint, viem fallback (4 URLs) × react-query retry amplified into ~100k+ req/min (per repro in this issue).What changed:
LatestBlockProvider—useBlockreports into shared RPC health; MegaETH head poll usesuseRpcBackoffPollInterval(5s → 15s → 30s).useWarbowBpMovingEventWatch— off when indexer is configured (indexer WarBow ~1.5s polls cover live BP); off during RPC offline-tier backoff.useRpcConnectivity/rpcBackedReadQueryOptions— reactive poll intervals +retry: 0while offline-tier (Arena no-indexer multicalls).arenaWarbowPolicyRpcsupplement multicall now reports RPC health.Docs / invariants:
INV-FRONTEND-221-ARENA-RPC· invariants §221 · timecurve-views §221 · manual QA #221 · guardrails +skills/play-timecurve-warbow/SKILL.md.Automated:
rpcConnectivity.test.ts,rpcReadQueryOptions.test.ts,tsc -b.@brouie — please verify on production/staging when you have a moment:
/timecurve/arena(Incognito), Network → Fetch/XHR, wait 60s — request count should stay well below Simple/timecurve(not 50k+).VITE_RPC_URL— within ~3s of failures, polls should slow (5s tier), not stay at ~1 Hz with endless(pending)/(failed)rows.eth_getLogs/ filter traffic for WarBow events on Arena.readFreshWarbowStealPreflight).Leaving this issue open until your sign-off. Re: #216 follow-up item 2 (globalstake position in prod
VITE_RPC_URL) — that is a deploy/env change, not covered by this frontend commit; happy to track separately if still desired.Walked verification on production with the fix landed. Strong PASS on the core fix, two items needed additional testing I haven't done yet.
Re: globalstake position in prod VITE_RPC_URL — acknowledged separate concern, will not track here.
Bottom line: the storm is gone. The fix landed and the macro behavior is dramatically better. Items 2 + 4 + 5 still to walk, but the core regression is closed in my book.
@PlasticDigits
Follow-up — also walked item 5 (steal submit fresh RPC preflight).
Switched to cl8y bot w2 (rank #4) to attempt a steal against a wallet in the 2×–10× band. Clicked STEAL on #1, MetaMask popup fired with warbowSteal selector 0x23df5215 on TimeCurve proxy. Cancelled before signing.
Item 5 of your verification checklist verified — fresh RPC preflight (readFreshWarbowStealPreflight) appears to be firing on click since the popup populates with correct contract + selector + victim address. Steal CTA path is intact post-fix.
Updated status of your checklist:
mentioned in issue #215
Walked items 2 + 4 via DevTools URL block on indexer.yieldomega.com.
Item 2 (throttle backoff): PASS
Blocked
indexer.yieldomega.compattern. Page went quiet on indexer side as expected — no retry storm visible, no cascading failures, no pending/failed queue buildup. Sale clock kept counting client-side, on-screen WarBow data stayed at last-known-good state.The offline-tier
retry: 0behavior is working — pre-fix this would have been a storm, post-fix the page just stops asking.Item 4 (recovery within ~3s): PASS
Removed the block. Indexer requests resumed cleanly, normal cadence (~25 req/s), healthy 200 OK responses, response times 70-140ms range. No recovery delay, no burst pattern. WarBow data refreshed on the next poll interval as expected.
Full checklist now PASS from QA side:
#221 verified clean.
mentioned in issue #301