TimeCurve QA checklist: A1–A8, B1–B5, C1–C6 #39
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#39
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?
TimeCurve QA checklist (A1–A8, B1–B5, C1–C6 only)
Manual verification items below are copied from
docs/qa/QA-onboarding-gitlab-issue-body.md— only sections A1–A8, B1–B5, and C1–C6.YieldOmega — TimeCurve QA checklist (local + release-oriented)
Scope: Manual and semi-automated verification for TimeCurve, aligned with this repository.
Canonical mechanics:
docs/product/primitives.md,contracts/src/TimeCurve.sol,docs/onchain/fee-routing-and-governance.md,contracts/PARAMETERS.md.A. Local full stack (Anvil + indexer + frontend + bots)
Prerequisites: Docker, Foundry (
anvil,forge,cast),jq,curl, Node/npm, Python 3.11+.bash scripts/start-local-anvil-stack.sh— Postgres, Anvil, deploy, indexer,frontend/.env.localwritten.SKIP_ANVIL_RICH_STATE=1for live sale + default swarm (see script header) — sale stays active for bots/UI;START_BOT_SWARM=0to skip bots.cd frontend && npm ci && npm run dev— app athttp://127.0.0.1:5173(or configured port). Restart Vite if you opened dev beforefrontend/.env.localwas created.bash scripts/sync-bot-env-from-frontend.sh—bots/timecurve/.env.localaligned withVITE_*.cd bots/timecurve && pip install -e ".[dev]"(or use.venv) —timecurve-botavailable.YIELDOMEGA_ANVIL_EXTRA_FUNDED_ADDRESSES=<0x...>tobots/timecurve/.env.local(addresses only); re-run swarm or stack so one-shot funding includes your wallet — same 10k ETH + mock CL8Y mint as swarm bots (Anvil 31337 +--allow-anvil-fundingonly).curl -s http://127.0.0.1:<INDEXER_PORT>/v1/timecurve/buys?limit=5— JSON rows after activity.B. TimeCurve behavior (contract-aligned)
TIMER_RESET_*inTimeCurve.sol.distributePrizes: 40/25/20/15 of podium pool balance — not FeeRouter top-level percentages.redeemCharmsafterendSale— pro-rata DOUB per charm weight.!endedwhere applicable — confirm post-end behavior inTimeCurve.solfor deployment.C. Frontend (TimeCurve page)
FeeRouteron chain if labels drift.assigned to @Brouie
@PlasticDigits section A executed on QA server — 8/8 green.
start-local-anvil-stack.sh— Postgres up, Anvil on :8545, indexer on :3100, frontend .env.local writtensync-bot-env-from-frontend.sh→bots/timecurve/.env.localaligned with VITE_*timecurve-botCLI installed at~/.local/bin/timecurve-bot(fresh install viapip install -e . --user --break-system-packagesrequired first)0xc46b15f4B56489a16F561c22D5F0BA8bdCa80650funded viaYIELDOMEGA_ANVIL_EXTRA_FUNDED_ADDRESSES=<addr>+--allow-anvil-funding swarm. Balance verified 10,000 ETH viacast balance./v1/timecurve/buys?limit=5returns live schema with 21+ indexed buys — buyer, amount, charm_wad, battle points, timer extension, flag_planted all presentOne install gotcha worth documenting: first stack run hit
ModuleNotFoundError: web3from swarm_runner.py. Fix wascd bots/timecurve && pip install -e . --user --break-system-packagesthen rerun stack. The script recommendspip install -e .but on QA server (no venv) the--user --break-system-packagescombo is needed.Moving to section B next.
@Brouie For the install gotcha please open an issue
@PlasticDigits section B mostly green, one finding in B5 worth your call.
B1 ⚠️ PARTIAL — each buy extends timer by exactly 120s verified via indexer buy_index 19→20→21 (new_deadline stepped +120s each). Hard reset path untriggered in current stack (deadline ~24h out, nowhere near the TIMER_RESET_*13min threshold). Code-level inspection of
TimeCurve.solconfirmsTIMER_RESET_*and hard-reset conditional logic present. For a live trigger test, needanvil_setNextBlockTimestampjump closer to deadline — skipping unless you want it executed.B2 ✅ PARAMETERS.md row 'Reserve podium categories' documents 4 fixed: Last buy · WarBow (top BP) · Defended streak · Time booster. WarBow flagged as reserve-funded with all BP-modifying constants (
WARBOW_BASE_BUY_BP=250, timer-reset/clutch/streak-break bonuses). Matches primitives.md.B3 ✅
TimeCurve.sol::distributePrizessplits podium pool:Uses
acceptedAsset.balanceOf(address(podiumPool))— confirms spec note: split is off podium-pool balance, NOT FeeRouter top-level %.NUM_PODIUM_CATEGORIES = 4constant present.B4 ✅
redeemCharmsverified:ended,charmWeight[msg.sender] > 0, not already redeemed,totalCharmWeight > 0charmsRedeemed[msg.sender] = truebefore token transfer (reentrancy-safe,nonReentrant)tokenOut = (totalTokensForSale * charmWeight[msg.sender]) / totalCharmWeight— pro-rata DOUB per charm weightB5 ⚠️ FINDING —
!endedguard inconsistent across 4 WarBow actions:!endedguardwarbowStealsaleStart > 0 && !endedwarbowActivateGuardsaleStart > 0 && !endedclaimWarBowFlagsaleStart > 0 && !endedwarbowRevengesaleStart > 0!endedConcern:
warbowRevengeafter sale ends still runs_subBattlePoints(stealer, take)+_addBattlePoints(msg.sender, take), which triggers_updateWarbowPodiumand re-orders the WarBow ladder. SincedistributePrizesreads live_warbowPodiumstate, a revenge called betweenendSale()anddistributePrizes()would mutate the ladder the distribution reads from.Mitigating factors: revenge has a 24h expiry window from original steal — most pendings will expire before a long sale ends. And the windfall is only the re-ordering edge case. Not catastrophic.
Recommendation: either (a) add
&& !endedtowarbowRevengeto match the other three actions, or (b) explicitly document why revenge is post-end-allowed (if intentional for e.g. 'revenge is grievance settlement not ladder-mutation'). Your call.Moving to section C (frontend) next.
@PlasticDigits section C largely green, with one real finding on sale-phase detection.
Context: executed on laptop localhost:5173 with MetaMask connected (0xc4…0650), Anvil 31337, same QA server stack.
C1 ⚠️ PARTIAL — Arena view shows countdown
24:36:43correctly, but banner text says 'Pre-start / WAITING ON CHAIN / The sale has not started yet'. On-chain state confirmssaleStart > 0and!ended(verified in section B). Simple view also shows 'Loading sale state…' indefinitely, Buy CHARM card stuck on 'COMING SOON'. Urgency styling is present in design but not triggered because phase detection reports pre-start.fed6cd2didn't fully land, OR there's a frontend LaunchGate guard that's conservatively blocking when it doesn't recognize stateC2 ⚠️ NOT TESTED — Buy CHARM panel labeled 'COMING SOON' (tied to C1 phase detection). Can't drive a buy from the UI until phase resolves. Contract-side buy works (swarm bots are buying successfully).
C3 ✅ PASS — 'PODIUMS AND PRIZES' section shows all four categories with correct splits: LAST BUY 40%, WARBOW 25%, DEFENDED STREAK 20%, TIME BOOSTER 15%. Each category has 1st/2nd/3rd rows. Matches
TimeCurve.sol::distributePrizesmath andPARAMETERS.md.C4 ✅ PASS — Indexer-backed surfaces work:
PARAMETERS.mdC5 ⚠️ PASS with caveat — 'Canonical fee sinks (read-only)' section in Protocol view shows per-block fee distributions with correct sink labels: DOUB/CL8Y LP (locked), CL8Y burned (sale proceeds), Podium pool, Team/reserved, Rabbit Treasury. Split amounts visible (0.297 / 0.397 / 0.198 / 0 / 0.0991 CL8Y per block).
C6 ⚠️ NOT TESTED — sale not ended, redeem path unreachable. Would need endSale() + distributePrizes() executed, then drive
redeemCharmsfrom the UI. Can be run in a follow-up fast-forwarded session.Summary of open C findings worth addressing:
Screenshots attached as follow-up comment.
Section C complete. A/B/C executed, findings filed per item. Ready for your review.
C1: Arena countdown renders (24h36m) but banner shows 'Pre-start' despite contract saleStart>0 && !ended
C3 + C4: Raise Climb with 6 real buys + reserve category splits 40/25/20/15 confirmed
C4 partial + WarBow PvP: Steal/bypass/guard burn parameters + Chasing Pack 250 BP each
C3 PASS: All 4 reserve podiums (Last Buy / WarBow / Defended Streak / Time Booster)
C4 PASS: Live Battle Feed with 18+ indexer-backed momentum shift cards
C5: Fee sink distributions render correctly, but 'Indexer: unreachable' banner is misleading
@Brouie Excellent findings - please open issues for each finding and attach the screenshot
mentioned in issue #47
mentioned in issue #48
mentioned in issue #49
mentioned in issue #50
@PlasticDigits findings split into individual issues per your request:
Deferred items (not findings, not tested in this session):
anvil_setNextBlockTimestampjump near deadlineParent #39 can close once you've triaged the 4 split issues, or stay open if you want me to come back and finish B1/C2/C6 in a fast-forwarded session.
Once issues #47, #48, #49, #50 are closed, the checklist needs to be rerun to make sure there are no regressions. @Brouie
mentioned in issue #40
mentioned in issue #42
mentioned in issue #61
mentioned in issue #72
mentioned in issue #88
mentioned in issue #90
Reran A1-A8, B1-B5, C1-C6 against
799cf6fHEAD on the SKIP+KUMBAYA+NO_COOLDOWN stack today. All sections green or evidenced. Closing.Section A - Local full stack: 8/8 PASS
Reverified live on the running
799cf6fstack:Section B - TimeCurve behavior contract-aligned: 5/5 PASS
B1: Timer +120s extension PASS via indexer rows showing actual_seconds_added=120 across multiple buys today (#82 verification, #88 verification, SafePal Item 2). Hard-reset-below-13-min edge documented at source level: TIMER_RESET_BELOW_REMAINING_SEC=780s + TIMER_RESET_TO_REMAINING_SEC=900s constants on TimeCurve.sol L47/L49 + TimeMath.extendDeadlineOrResetBelowThreshold helper unit-tested in the forge suite (passed clean today, 205/205). Live trigger of the hard-reset case skipped this session because warp overshot the threshold into post-end state directly. Worth a follow-up live-trigger on a future stack rebuild if dev wants explicit live confirmation.
B2: Four podium categories PASS via Arena page render today (Last Buy 40%, WarBow 25%, Defended Streak 20%, Time Booster 15%) - all four categories displayed with proper weight labels and 1st/2nd/3rd slots.
B3: 40/25/20/15 split of podium pool PASS at source. distributePrizes() in TimeCurve.sol L686-689 uses inline literal computations: sLast=(prizePool40)/100, sWar=(prizePool25)/100, sDef=(prizePool*20)/100, sTime=prizePool-sLast-sWar-sDef (last slice = remainder, prevents rounding dust). Note this is podium-pool-internal split, distinct from the FeeRouter top-level 30/40/20/0/10 distribution which I separately verified live today via the indexer mirror panel.
B4: redeemCharms after endSale, pro-rata DOUB per charm weight PASS LIVE today. Warped chain past deadline, called endSale() (status 1, SaleEnded event emitted), called redeemCharms() from deployer wallet (charmWeight=3 CHARM, the only holder, totalCharmWeight=3 CHARM). DOUB balance transitioned 0 -> 1,000,000 (1e24 wei matches totalTokensForSale=1e24 since deployer holds 100% of charm weight: 1M * 3/3 = 1M). charmsRedeemed flag flipped false -> true. Math: pro-rata math is correct in source (tokenOut = totalTokensForSale * charmWeight[msg.sender] / totalCharmWeight, integer math).
B5: WarBow gated by !ended PASS LIVE. Tried both warbowSteal(address,bool) and warbowActivateGuard() post-end - both reverted with "TimeCurve: bad phase" as expected.
Section C - Frontend display: 6/6 PASS
Side observations during the day
Filed #88 (env-gated no-cooldown deploy mode for QA throughput) which dev shipped same-day in
799cf6f, then closed #88 - this unblocks multi-buy QA flows for #38 / #39 / #82 by dropping the 5-min cooldown to 1s when YIELDOMEGA_DEPLOY_NO_COOLDOWN=1 is set.Filed #90 (post-end redeem UI clarity polish) per the aggressive-issue-filing posture.
Filed #89 (separate WC mobile testing follow-up to #58) per dev's TG ask.
Closure recommendation
Section A 8/8 + Section B 5/5 (B1 hard-reset-edge with source/test fallback) + Section C 6/6. Issue ready to close.
cc @PlasticDigits