Frontend: CRED as buy payment option (balance, burn check, buyWithCred) #269

Closed
opened 2026-05-29 08:15:03 +00:00 by PlasticDigits · 6 comments
PlasticDigits commented 2026-05-29 08:15:03 +00:00 (Migrated from gitlab.com)

Summary

Add Play CRED as a payment option in the arena buy charm UI alongside CL8Y/ETH/USDM: read wallet CRED balance, compute required burn from selected CHARM, gate submit when insufficient, and call TimeArena.buyWithCred(charmWad) on the correct chain.

Bundled with onchain work in #268 (100 CRED per CHARM burn + first-buy bonus). This issue is frontend-only but must not ship burn math that disagrees with deployed TimeArena.

Parent: Arena v2 #238, arena mount #256, buy router #251 / #264.


Current codebase

Area Behavior
Pay asset type PayWithAsset = "cl8y" | "eth" | "usdm" only (frontend/src/lib/kumbayaRoutes.ts).
Buy UI TimeCurveSimplePage / useTimeCurveSaleSession — token picker SIMPLE_AMOUNT_PAY_TOKEN_OPTIONS (CL8Y, ETH, USDM).
Arena v2 submit When isArenaV2, only payWith === "cl8y" allowed; approves DOUB (acceptedAsset) and calls buy().
buyWithCred In timeArenaReadAbi but never called from frontend.
CRED UX today ArenaCharmCredCard — epoch CHARM, pendingCred, claimCred only (read/claim, not pay).
PlayCred address Not in frontend/src/lib/addresses.ts; available onchain as TimeArena.playCred().
Wallet profile Indexer field cred_claimed in WalletProfileModal; no live CRED balance.

Relevant files

  • frontend/src/lib/kumbayaRoutes.ts — extend pay type or parallel payMode
  • frontend/src/pages/TimeCurveSimplePage.tsx — token picker options, labels, slider copy
  • frontend/src/pages/timecurve/useTimeCurveSaleSession.ts — submit path, gates, sizing
  • frontend/src/lib/abis.ts — buyWithCred, ERC20 balanceOf on PlayCred
  • frontend/src/lib/addresses.ts — optional playCred from env or derived read
  • frontend/src/pages/arena/ArenaCharmCredCard.tsx — may share CRED balance hook
  • frontend/src/components/ChainMismatchWriteBarrier.tsx — wrap writes
  • frontend/e2e/arenaE2eHelpers.ts — selectPayWith helper
  • docs/frontend/arena-views.md (if present) — UX spec
  • docs/testing/manual-qa-checklists.md — Arena v2 QA section

Why this is needed

  • buyWithCred exists onchain but is unreachable for normal users without wallet/script calls.
  • Participants who earned CRED via DOUB epoch claims cannot spend it in-product.
  • Burn is CHARM-scaled (100 CRED per 1e18 CHARM after onchain issue); UI must show exact required CRED before sign.

Constraints and guardrails

  • No offchain pricing authority — Burn formula must mirror TimeArena (read CRED_PER_CHARM_WAD constant or credBurnForCharm(charmWad) view if added onchain).
  • Wrong-network gating — Use existing ChainMismatchWriteBarrier / chainMismatchWriteMessage (#95).
  • Single-chain wagmi (#81).
  • Arena v2 only — CRED pay applies when TimeArena / isArenaV2; do not break legacy TimeCurve paths if still mounted (#266).
  • CRED non-transferable — No approve step; only balanceOf + buyWithCred (no ERC20 allowance UX).
  • Cooldown — Same nextBuyAllowedAt / buy cooldown UX as DOUB buys.
  • CHARM band — Reuse existing min/max CHARM validation before submit.
  • Referral / WarBow flags — CRED path onchain does not take referral today; UI must not send referral args on CRED buys (or file follow-up if product wants parity).
  • Accessibility — CRED option in same picker pattern as other tokens; aria-label includes CRED.

  1. Resolve PlayCred address — useReadContract timeArena.playCred() when env unset; cache in session context.
  2. Extend pay model — Add "cred" to pay union (or payWith + payAsset split). Picker shows CRED with distinct label/logo.
  3. Balance read — balanceOf(user) on PlayCred; poll/refetch after buy and on claim.
  4. Burn preview — requiredCred = charmWad * 100n / WAD (or read onchain helper post-deploy). Show in checkout summary and insufficient-CRED gate (mirror CL8Y insufficient pattern in TimeCurveSimplePage).
  5. Submit — writeContract buyWithCred(charmWad) with gas buffer helper used elsewhere; no DOUB approve.
  6. Slider / amount input — When CRED selected, slider still targets CHARM band; suffix shows “CRED cost” not DOUB/CL8Y.
  7. E2E — Anvil dev deploy mints CRED to test wallet; one spec selects CRED and buys (or mocks read if fork unavailable).
  8. First-buy bonus — No extra UI required if onchain schedules; optional tooltip “First buy grants 150 CRED next epoch” once onchain lands.

Acceptance criteria

  • Connected wallet on MegaETH (configured chain) sees CRED in buy payment picker on /arena (or unified simple buy surface).
  • UI displays wallet CRED balance and required burn for selected CHARM.
  • Buy button disabled with clear message when balance < requiredCred or CHARM out of band.
  • Successful submit calls buyWithCred with correct charmWad (fresh sizing read before tx).
  • Wrong chain: writes blocked; message matches existing pattern.
  • After tx, balance and ArenaCharmCredCard data refresh.
  • ETH/USDM modes unchanged; CRED mode does not require DOUB allowance.
  • Unit/integration tests for burn math helper (if extracted).
  • E2E or component test covers CRED selection path (Anvil/dev).

Test plan — functional paths

# Scenario Expected
1 Select CRED, sufficient balance buyWithCred tx succeeds
2 Select CRED, insufficient balance Disabled submit + error copy
3 Switch CRED → CL8Y DOUB approve path restored
4 CHARM at min/max band Burn preview matches onchain
5 Cooldown active Same error as DOUB buy
6 Not connected Connect prompt
7 Wrong chain Write barrier
8 playCred == address(0) CRED option hidden or disabled with copy
9 Post-buy CRED balance decreases by burn amount
10 Arena paused Buy disabled consistent with DOUB

Test plan — attack vectors / UX failure modes

Vector Mitigation / test
Stale balance Re-read balanceOf immediately before submit; show revert message on failure
Stale CHARM bounds Reuse readFreshTimeCurveBuySizing or arena equivalent
Wrong burn constant in UI Prefer onchain view/constant read; single shared credBurnForCharmWad() util tested against Forge expectations
User selects CRED but session sends buy() E2E asserts function name / calldata
Phishing wrong PlayCred Address only from TimeArena.playCred() on configured arena proxy
Double-submit Disable button while isPending
Scientific notation input Parse errors don’t submit tx

Verification criteria

  • npm test / vitest for any new burn helper.
  • npx playwright test arena spec with CRED path (5 workers per repo convention).
  • Manual QA checklist updated under “Arena v2 — CRED pay”.
  • No new secrets in env; optional VITE_PLAY_CRED_ADDRESS only as override if read fails.
  • Lighthouse/a11y: picker keyboard navigable.

Depends on

  • #268: 100 CRED per CHARM (and ideally public view for burn). Merge order: contracts first, then frontend (or feature-flag until deployed).

Out of scope

  • Implementing first-buy 150 CRED bonus (onchain issue).
  • Indexer API for CRED balance (wallet can read RPC).
  • Kumbaya / ETH / USDM → CRED swaps.
## Summary Add **Play CRED** as a payment option in the arena **buy charm** UI alongside CL8Y/ETH/USDM: read wallet CRED balance, compute required burn from selected CHARM, gate submit when insufficient, and call **`TimeArena.buyWithCred(charmWad)`** on the correct chain. Bundled with onchain work in [#268](https://gitlab.com/PlasticDigits/yieldomega/-/issues/268) (100 CRED per CHARM burn + first-buy bonus). This issue is **frontend-only** but must not ship burn math that disagrees with deployed `TimeArena`. Parent: Arena v2 [#238](https://gitlab.com/PlasticDigits/yieldomega/-/issues/238), arena mount [#256](https://gitlab.com/PlasticDigits/yieldomega/-/issues/256), buy router [#251](https://gitlab.com/PlasticDigits/yieldomega/-/issues/251) / [#264](https://gitlab.com/PlasticDigits/yieldomega/-/issues/264). --- ## Current codebase | Area | Behavior | |------|----------| | **Pay asset type** | `PayWithAsset = "cl8y" \| "eth" \| "usdm"` only (`frontend/src/lib/kumbayaRoutes.ts`). | | **Buy UI** | `TimeCurveSimplePage` / `useTimeCurveSaleSession` — token picker `SIMPLE_AMOUNT_PAY_TOKEN_OPTIONS` (CL8Y, ETH, USDM). | | **Arena v2 submit** | When `isArenaV2`, only `payWith === "cl8y"` allowed; approves DOUB (`acceptedAsset`) and calls `buy()`. | | **`buyWithCred`** | In `timeArenaReadAbi` but **never called** from frontend. | | **CRED UX today** | `ArenaCharmCredCard` — epoch CHARM, `pendingCred`, `claimCred` only (read/claim, not pay). | | **PlayCred address** | Not in `frontend/src/lib/addresses.ts`; available onchain as `TimeArena.playCred()`. | | **Wallet profile** | Indexer field `cred_claimed` in `WalletProfileModal`; no live CRED balance. | **Relevant files** - `frontend/src/lib/kumbayaRoutes.ts` — extend pay type or parallel `payMode` - `frontend/src/pages/TimeCurveSimplePage.tsx` — token picker options, labels, slider copy - `frontend/src/pages/timecurve/useTimeCurveSaleSession.ts` — submit path, gates, sizing - `frontend/src/lib/abis.ts` — `buyWithCred`, ERC20 `balanceOf` on PlayCred - `frontend/src/lib/addresses.ts` — optional `playCred` from env or derived read - `frontend/src/pages/arena/ArenaCharmCredCard.tsx` — may share CRED balance hook - `frontend/src/components/ChainMismatchWriteBarrier.tsx` — wrap writes - `frontend/e2e/arenaE2eHelpers.ts` — `selectPayWith` helper - `docs/frontend/arena-views.md` (if present) — UX spec - `docs/testing/manual-qa-checklists.md` — Arena v2 QA section --- ## Why this is needed - **`buyWithCred` exists onchain** but is unreachable for normal users without wallet/script calls. - Participants who earned CRED via DOUB epoch claims cannot spend it in-product. - Burn is **CHARM-scaled** (100 CRED per 1e18 CHARM after onchain issue); UI must show exact required CRED before sign. --- ## Constraints and guardrails - **No offchain pricing authority** — Burn formula must mirror `TimeArena` (read `CRED_PER_CHARM_WAD` constant or `credBurnForCharm(charmWad)` view if added onchain). - **Wrong-network gating** — Use existing `ChainMismatchWriteBarrier` / `chainMismatchWriteMessage` ([#95](https://gitlab.com/PlasticDigits/yieldomega/-/issues/95)). - **Single-chain wagmi** ([#81](https://gitlab.com/PlasticDigits/yieldomega/-/issues/81)). - **Arena v2 only** — CRED pay applies when `TimeArena` / `isArenaV2`; do not break legacy TimeCurve paths if still mounted ([#266](https://gitlab.com/PlasticDigits/yieldomega/-/issues/266)). - **CRED non-transferable** — No approve step; only `balanceOf` + `buyWithCred` (no ERC20 allowance UX). - **Cooldown** — Same `nextBuyAllowedAt` / buy cooldown UX as DOUB buys. - **CHARM band** — Reuse existing min/max CHARM validation before submit. - **Referral / WarBow flags** — CRED path onchain does not take referral today; UI must not send referral args on CRED buys (or file follow-up if product wants parity). - **Accessibility** — CRED option in same picker pattern as other tokens; `aria-label` includes CRED. --- ## Recommended direction 1. **Resolve PlayCred address** — `useReadContract` `timeArena.playCred()` when env unset; cache in session context. 2. **Extend pay model** — Add `"cred"` to pay union (or `payWith` + `payAsset` split). Picker shows CRED with distinct label/logo. 3. **Balance read** — `balanceOf(user)` on PlayCred; poll/refetch after buy and on claim. 4. **Burn preview** — `requiredCred = charmWad * 100n / WAD` (or read onchain helper post-deploy). Show in checkout summary and insufficient-CRED gate (mirror CL8Y insufficient pattern in `TimeCurveSimplePage`). 5. **Submit** — `writeContract` `buyWithCred(charmWad)` with gas buffer helper used elsewhere; no DOUB approve. 6. **Slider / amount input** — When CRED selected, slider still targets CHARM band; suffix shows “CRED cost” not DOUB/CL8Y. 7. **E2E** — Anvil dev deploy mints CRED to test wallet; one spec selects CRED and buys (or mocks read if fork unavailable). 8. **First-buy bonus** — No extra UI required if onchain schedules; optional tooltip “First buy grants 150 CRED next epoch” once onchain lands. --- ## Acceptance criteria - [ ] Connected wallet on MegaETH (configured chain) sees **CRED** in buy payment picker on `/arena` (or unified simple buy surface). - [ ] UI displays wallet **CRED balance** and **required burn** for selected CHARM. - [ ] Buy button disabled with clear message when `balance < requiredCred` or CHARM out of band. - [ ] Successful submit calls **`buyWithCred`** with correct `charmWad` (fresh sizing read before tx). - [ ] Wrong chain: writes blocked; message matches existing pattern. - [ ] After tx, balance and `ArenaCharmCredCard` data refresh. - [ ] ETH/USDM modes unchanged; CRED mode does not require DOUB allowance. - [ ] Unit/integration tests for burn math helper (if extracted). - [ ] E2E or component test covers CRED selection path (Anvil/dev). --- ## Test plan — functional paths | # | Scenario | Expected | |---|----------|----------| | 1 | Select CRED, sufficient balance | `buyWithCred` tx succeeds | | 2 | Select CRED, insufficient balance | Disabled submit + error copy | | 3 | Switch CRED → CL8Y | DOUB approve path restored | | 4 | CHARM at min/max band | Burn preview matches onchain | | 5 | Cooldown active | Same error as DOUB buy | | 6 | Not connected | Connect prompt | | 7 | Wrong chain | Write barrier | | 8 | `playCred == address(0)` | CRED option hidden or disabled with copy | | 9 | Post-buy | CRED balance decreases by burn amount | | 10 | Arena paused | Buy disabled consistent with DOUB | --- ## Test plan — attack vectors / UX failure modes | Vector | Mitigation / test | |--------|-------------------| | **Stale balance** | Re-read `balanceOf` immediately before submit; show revert message on failure | | **Stale CHARM bounds** | Reuse `readFreshTimeCurveBuySizing` or arena equivalent | | **Wrong burn constant in UI** | Prefer onchain view/constant read; single shared `credBurnForCharmWad()` util tested against Forge expectations | | **User selects CRED but session sends `buy()`** | E2E asserts function name / calldata | | **Phishing wrong PlayCred** | Address only from `TimeArena.playCred()` on configured arena proxy | | **Double-submit** | Disable button while `isPending` | | **Scientific notation input** | Parse errors don’t submit tx | --- ## Verification criteria - [ ] `npm test` / `vitest` for any new burn helper. - [ ] `npx playwright test` arena spec with CRED path (5 workers per repo convention). - [ ] Manual QA checklist updated under “Arena v2 — CRED pay”. - [ ] No new secrets in env; optional `VITE_PLAY_CRED_ADDRESS` only as override if read fails. - [ ] Lighthouse/a11y: picker keyboard navigable. --- ## Depends on - [#268](https://gitlab.com/PlasticDigits/yieldomega/-/issues/268): **100 CRED per CHARM** (and ideally public view for burn). Merge order: contracts first, then frontend (or feature-flag until deployed). ## Out of scope - Implementing first-buy **150 CRED** bonus (onchain issue). - Indexer API for CRED balance (wallet can read RPC). - Kumbaya / ETH / USDM → CRED swaps.
PlasticDigits commented 2026-05-29 08:15:04 +00:00 (Migrated from gitlab.com)

marked as related to #268

marked as related to #268
PlasticDigits commented 2026-05-29 08:58:58 +00:00 (Migrated from gitlab.com)

mentioned in commit faa36f0b22

mentioned in commit faa36f0b22745305dd96ec449ab0133b78601067
PlasticDigits commented 2026-05-29 08:59:07 +00:00 (Migrated from gitlab.com)

Implementation summary (#269)

Merged to main at faa36f0.

What changed

  • CRED pay mode on /arena buy panel: arena-paywith-cred, wallet balance + burn preview, buyWithCred(charmWad) submit (no DOUB approve).
  • Onchain-aligned burn via arenaCredBurn.ts + useArenaPlayCred (playCred(), CRED_BUY_BURN; ready for CRED_PER_CHARM_WAD when #268 lands).
  • E2E: e2e/anvil-arena-cred-buy.spec.ts; DeployDev mints 1000 CRED to Anvil account #0.
  • Docs/skills: INV-FRONTEND-269-CRED-BUY, arena-views, manual QA, guardrails, play-time-arena-doub.

Verification checklist

  • On configured chain, /arena shows CRED in pay toggles (arena-paywith-cred).
  • Connected wallet sees CRED balance and burn for selected CHARM before buy.
  • Insufficient CRED disables buy with clear copy.
  • Successful buy calls buyWithCred (explorer / receipt).
  • Wrong network: writes blocked (existing barrier).
  • After buy, CRED balance and CHARM/CRED card refresh.
  • CL8Y / ETH / USDM paths unchanged when not on CRED.
  • npm test — arenaCredBurn.test.ts
  • bash scripts/e2e-anvil.sh — includes anvil-arena-cred-buy.spec.ts

@brouie — please verify on Anvil or staging when you have a moment. Leaving issue open until sign-off.

## Implementation summary (#269) Merged to `main` at `faa36f0`. ### What changed - **CRED pay mode** on `/arena` buy panel: `arena-paywith-cred`, wallet balance + burn preview, `buyWithCred(charmWad)` submit (no DOUB approve). - **Onchain-aligned burn** via `arenaCredBurn.ts` + `useArenaPlayCred` (`playCred()`, `CRED_BUY_BURN`; ready for `CRED_PER_CHARM_WAD` when [#268](https://gitlab.com/PlasticDigits/yieldomega/-/issues/268) lands). - **E2E:** `e2e/anvil-arena-cred-buy.spec.ts`; DeployDev mints 1000 CRED to Anvil account #0. - **Docs/skills:** `INV-FRONTEND-269-CRED-BUY`, arena-views, manual QA, guardrails, `play-time-arena-doub`. ### Verification checklist - [ ] On configured chain, `/arena` shows **CRED** in pay toggles (`arena-paywith-cred`). - [ ] Connected wallet sees **CRED balance** and **burn for selected CHARM** before buy. - [ ] Insufficient CRED disables buy with clear copy. - [ ] Successful buy calls **`buyWithCred`** (explorer / receipt). - [ ] Wrong network: writes blocked (existing barrier). - [ ] After buy, CRED balance and CHARM/CRED card refresh. - [ ] CL8Y / ETH / USDM paths unchanged when not on CRED. - [ ] `npm test` — `arenaCredBurn.test.ts` - [ ] `bash scripts/e2e-anvil.sh` — includes `anvil-arena-cred-buy.spec.ts` @brouie — please verify on Anvil or staging when you have a moment. Leaving issue **open** until sign-off.
PlasticDigits commented 2026-05-29 09:06:34 +00:00 (Migrated from gitlab.com)

mentioned in commit 84ba60048a

mentioned in commit 84ba60048a6603a3f7f63d57bbb93f5d79d1cfbf
PlasticDigits commented 2026-06-01 11:25:10 +00:00 (Migrated from gitlab.com)

QA verification (#269) — issue/269-verify worktree @ 9831bd6

Verified the frontend CRED buy path already on main. No code changes were required; verification loop completed green on first pass.

Worktree & sync

  • Worktree: ../yieldomega-issue-269-verify branch issue/269-verify (same HEAD as origin/main).
  • Fetched origin/main; no new commits to merge. Worktree had no local diffs → nothing to merge beyond existing main.

Automated verification (all pass)

Check Result
npm test -- --run src/lib/arenaCredBurn.test.ts 5/5 pass
npm test -- --run (full Vitest) 531/531 pass
bash scripts/e2e-anvil.sh 6/6 Anvil specs pass, incl. e2e/anvil-arena-04-cred-buy.spec.ts (buyWithCred on /arena)

Implementation cross-check (acceptance criteria)

  • CRED in pay picker on /arena — payTokenOptionsForSimpleBuy, arena-paywith-cred, amount picker arena-simple-rate-pay-option-cred.
  • Balance + burn preview — useArenaPlayCred reads playCred(), CRED_PER_CHARM_WAD, balanceOf; preview test ids arena-simple-buy-preview-cred / arena-simple-buy-preview-insufficient-cred.
  • Insufficient CRED gate — resolveCredCheckoutBoundsGate + disabled buy button + copy.
  • Submit buyWithCred(charmWad) — useArenaSaleSession.submitBuy with fresh balanceOf re-read before tx; no DOUB approve on CRED path.
  • Wrong chain — ChainMismatchWriteBarrier + chainMismatchWriteMessage on buy panel.
  • Post-buy refresh — refetchCred() in refetchAll after successful buy.
  • ETH/USDM unchanged — Kumbaya path only for eth/usdm; CRED bypasses router.
  • Burn math onchain-aligned — arenaCredBurn.credBurnForCharmWad + onchain CRED_PER_CHARM_WAD read (#268 constant present in TimeArena.sol).
  • playCred == 0 — auto-fallback to DOUB via useEffect in session hook.
  • Docs / invariants / skills — INV-FRONTEND-269-CRED-BUY, arena-views.md, manual-qa-checklists.md CRED pay row, guardrails §9b, play-time-arena-doub skill.

Manual sign-off checklist (for staging / MegaETH)

  • Connect wallet on configured chain → /arena → select CRED (arena-paywith-cred).
  • Confirm wallet CRED balance and burn preview update with CHARM slider.
  • With insufficient CRED, buy stays disabled and blocked copy appears.
  • Successful buy: explorer shows buyWithCred; CRED balance drops by burn amount.
  • Switch CRED → DOUB: approve + buy() path works.
  • Wrong network: write barrier blocks buy (no tx prompt).
  • After buy: CRED balance + ArenaCharmCredCard epoch data refresh.
  • ETH/USDM buys still route via Kumbaya when router configured.
  • Keyboard: pay picker listbox navigable (aria-label includes token name, e.g. CRED).

Closing as verified — all issue-body acceptance + verification criteria satisfied on main. Dependency #268 onchain constant is present; that issue may remain open for separate contract QA.

## QA verification (#269) — issue/269-verify worktree @ `9831bd6` Verified the **frontend CRED buy path** already on `main`. No code changes were required; verification loop completed green on first pass. ### Worktree & sync - Worktree: `../yieldomega-issue-269-verify` branch `issue/269-verify` (same HEAD as `origin/main`). - Fetched `origin/main`; no new commits to merge. Worktree had no local diffs → nothing to merge beyond existing `main`. ### Automated verification (all pass) | Check | Result | |-------|--------| | `npm test -- --run src/lib/arenaCredBurn.test.ts` | **5/5** pass | | `npm test -- --run` (full Vitest) | **531/531** pass | | `bash scripts/e2e-anvil.sh` | **6/6** Anvil specs pass, incl. `e2e/anvil-arena-04-cred-buy.spec.ts` (`buyWithCred` on `/arena`) | ### Implementation cross-check (acceptance criteria) - [x] **CRED in pay picker** on `/arena` — `payTokenOptionsForSimpleBuy`, `arena-paywith-cred`, amount picker `arena-simple-rate-pay-option-cred`. - [x] **Balance + burn preview** — `useArenaPlayCred` reads `playCred()`, `CRED_PER_CHARM_WAD`, `balanceOf`; preview test ids `arena-simple-buy-preview-cred` / `arena-simple-buy-preview-insufficient-cred`. - [x] **Insufficient CRED gate** — `resolveCredCheckoutBoundsGate` + disabled buy button + copy. - [x] **Submit `buyWithCred(charmWad)`** — `useArenaSaleSession.submitBuy` with fresh `balanceOf` re-read before tx; no DOUB approve on CRED path. - [x] **Wrong chain** — `ChainMismatchWriteBarrier` + `chainMismatchWriteMessage` on buy panel. - [x] **Post-buy refresh** — `refetchCred()` in `refetchAll` after successful buy. - [x] **ETH/USDM unchanged** — Kumbaya path only for `eth`/`usdm`; CRED bypasses router. - [x] **Burn math onchain-aligned** — `arenaCredBurn.credBurnForCharmWad` + onchain `CRED_PER_CHARM_WAD` read ([#268](https://gitlab.com/PlasticDigits/yieldomega/-/issues/268) constant present in `TimeArena.sol`). - [x] **`playCred == 0`** — auto-fallback to DOUB via `useEffect` in session hook. - [x] **Docs / invariants / skills** — `INV-FRONTEND-269-CRED-BUY`, `arena-views.md`, `manual-qa-checklists.md` CRED pay row, guardrails §9b, `play-time-arena-doub` skill. ### Manual sign-off checklist (for staging / MegaETH) - [ ] Connect wallet on configured chain → `/arena` → select **CRED** (`arena-paywith-cred`). - [ ] Confirm wallet CRED balance and burn preview update with CHARM slider. - [ ] With insufficient CRED, buy stays disabled and blocked copy appears. - [ ] Successful buy: explorer shows **`buyWithCred`**; CRED balance drops by burn amount. - [ ] Switch CRED → DOUB: approve + `buy()` path works. - [ ] Wrong network: write barrier blocks buy (no tx prompt). - [ ] After buy: CRED balance + `ArenaCharmCredCard` epoch data refresh. - [ ] ETH/USDM buys still route via Kumbaya when router configured. - [ ] Keyboard: pay picker listbox navigable (`aria-label` includes token name, e.g. CRED). Closing as **verified** — all issue-body acceptance + verification criteria satisfied on `main`. Dependency [#268](https://gitlab.com/PlasticDigits/yieldomega/-/issues/268) onchain constant is present; that issue may remain open for separate contract QA.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-01 11:25:15 +00:00
PlasticDigits commented 2026-06-01 11:28:54 +00:00 (Migrated from gitlab.com)

mentioned in issue #268

mentioned in issue #268
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/yieldomega#269
No description provided.