Arm podium settlement timers on first qualifying buy (#330) #504
No reviewers
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!504
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-330-podium-timer-arm-on-first-buy"
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?
Summary
Implements GitLab #330: per-category podium settlement timers stay unarmed after
startArena()androllPodiumEpoch(cat)until the first qualifying buy in that epoch (Option B — per-category, level-gated per #299).Contracts:
podiumTimerArmed[4],_armPodiumTimer,PodiumTimerArmedevent; autoroll androllPodiumEpochskip unarmed categories; Last Buydeadlinemirrors cat 0.Indexer:
GET /v1/arena/timersaddspodium_timer_armed(schema 2.17.0).Frontend: Play chips, hero carousel, and AUDIT show awaiting first buy when unarmed (indexer-first #301).
Verification checklist
cd contracts && forge test --match-contract TimeArenaTestbash scripts/verify-podium-timers-anvil.shcd indexer && cargo clippy --all-targets -- -D warningscd indexer && cargo testbash scripts/verify-podium-live-anvil.shcd frontend && npm run typecheckcd frontend && npm test -- --run src/pages/arena/arenaPodiumTimerDisplay.test.ts src/pages/arena/useArenaProtocolPodiumAudit.test.ts src/pages/arena/ArenaTimerChips.test.tsxcurl -s http://127.0.0.1:3100/v1/arena/timers | jq '.podium_timer_armed'(fresh arena, no buys)/and/arena/protocolThird-party verification
bash scripts/bootstrap-cloud-install.sh(or local toolchain per AGENTS.md).bash scripts/verify-podium-timers-anvil.sh— expect unarmed at start, arm after buy.bash scripts/start-qa-local-full-stack.sh --no-swarmor equivalent); before any buy:curl -s http://127.0.0.1:3100/v1/arena/timers | jq '{podium_timer_armed, podium_deadlines_sec}'→ allfalse/ zeros.cd contracts && forge test --match-contract TimeArenaTest— 118 tests pass.mentioned in issue #330
HIGH — UUPS storage layout collision on upgrade
Inserting
bool[4] podiumTimerArmedbetweenpodiumEpochandcharmWeightshifts every downstream storage slot (all mappings fromcharmWeightonward). Upgrading an existingTimeArenaERC-1967 proxy to this implementation corrupts live state.Attack path (post-upgrade): Operator performs a normal UUPS
upgradeTo→buyCount,charmWeight, WarBow BP, podium leaders, and CRED epoch mappings read/write wrong slots → e.g.buyCountappears zero soFIRST_BUY_CRED_BONUScan be re-triggered; podium settlement can pay wrong/zero winners.Evidence: Contract is
UUPSUpgradeable; repo already documents append-only storage discipline for prior vars (epochFixedCredBonus,_cachedLevel). Pre-change layout placescharmWeightat slot 50; this diff insertspodiumTimerArmedat slot 50 and movescharmWeightto slot 51.Fix: Append
podiumTimerArmedat the end of storage (with gap reduction / initializer), never before existing mappings. Fresh proxy deploys are safe; this blocks safe UUPS rollout on any proxy with the current layout.Security review — MR !504
Reviewed commit:
cc9a8489874bc886c1b4c2cada001801b9641075Scope:
TimeArenapodium timer arm model (#330), indexerpodium_timer_armed(schema 2.17.0), frontend/indexer display paths, tests and docs.Outcome:
FINDINGS: 1medium+Summary
Reviewed contract buy/arm/autoroll/roll paths,
TimeMathinteraction on first arm, indexer eth_call wiring, and frontend display helpers. Timer-arm logic itself is coherent: unarmed categories skip autoroll/rollPodiumEpoch,_willLastBuyHardResetcorrectly gates onpodiumTimerArmed, and_armPodiumTimerruns before deadline extension (avoiding false hard-reset ondeadline==0). Indexer/frontend changes are read-only reflections of chain state; no injection/XSS/auth bypass identified.One HIGH finding blocks safe UUPS upgrade of an existing
TimeArenaproxy — see inline thread oncontracts/src/arena/TimeArena.sol(insertion ofpodiumTimerArmedbeforecharmWeight).Fresh ERC-1967 proxy deploys are unaffected.
Inline threads
contracts/src/arena/TimeArena.sol:105We will be doing a fresh deploy, so this is not a concern.
resolved all threads
mentioned in commit
71d56404bc