WarBow steal daily-cap UX: UTC reset + inline cap warning (#361) #534

Merged
PlasticDigits merged 2 commits from issue-361-warbow-steal-quota-ux into main 2026-07-07 03:53:50 +00:00
PlasticDigits commented 2026-07-07 02:59:29 +00:00 (Migrated from gitlab.com)

Summary

Implements GitLab #361 (parent #360): WarBow play surface shows attacker steal quota and UTC-day reset in the viewer summary, and surfaces describeStealPreflight inline above the Steal button when daily caps apply — without waiting for a failed transaction.

  • STEAL QUOTA: line in warbow-hero-viewer-summary — X / 3 steals landed today + HH:MM:SS countdown to next UTC day; bypass hint when at cap.
  • Inline preflight — warbow-hero-steal-preflight warning/error above Steal; Steal disabled on error tone (mirrors protocol page).
  • Cap reads — useReadContract when indexer unset; one-shot readWarbowStealCapDisplay when VITE_INDEXER_URL is set (no recurring display RPC mirrors per #301).
  • UTC math — warbowUtcDayReset.ts matches onchain SECONDS_PER_DAY floor division.
  • Docs — INV-FRONTEND-361-WARBOW-STEAL-QUOTA-UX, arena-views §361, play skill update.

Acceptance checklist

Criterion Command / step Result
Viewer summary shows X/3 + UTC reset countdown cd frontend && npm test -- --run ArenaWarbowHeroPanel.test.ts PASS
Inline cap warning above Steal when victim/attacker capped cd frontend && npm test -- --run ArenaWarbowHeroPanel.test.ts timeArenaUx.test.ts PASS
Warning updates with victim/bypass/clock (hook tests + logic) cd frontend && npm test -- --run warbowUtcDayReset.test.ts PASS
Indexer-first: no recurring display RPC mirrors cd frontend && npm test -- --run indexerFirstDisplay.test.ts PASS
No contract changes (diff scope) PASS
Typecheck cd frontend && npm run typecheck PASS
Lint (changed files) npx eslint src/pages/arena/ArenaWarbowHeroPanel.tsx src/pages/arena/useArenaWarbowHero.ts src/lib/warbowUtcDayReset.ts src/lib/readWarbowStealCapDisplay.ts PASS
Full frontend unit tests cd frontend && npm test SKIP — 7 pre-existing failures in ArenaSimplePage.test.tsx (shouldShowLevelLock expectations) on main; unrelated to this MR
Manual Anvil play / bash scripts/start-qa-local-full-stack.sh --live-sale --no-swarm --no-frontend then cd frontend && npm run dev SKIP — not run in agent session
Manual Rabby signing path bash scripts/qa/build-frontend-for-rabby.sh + preview SKIP — optional

Verification for third parties

  1. git checkout issue-361-warbow-steal-quota-ux
  2. cd frontend && npm run typecheck && npx eslint src/pages/arena/ArenaWarbowHeroPanel.tsx src/pages/arena/useArenaWarbowHero.ts && npm test -- --run ArenaWarbowHeroPanel.test.tsx warbowUtcDayReset.test.ts timeArenaUx.test.ts indexerFirstDisplay.test.ts
  3. Start local stack with indexer + connect wallet on / at WarBow level ≥ 4.
  4. Confirm viewer summary STEAL QUOTA line shows usage and countdown.
  5. Select a victim at daily cap (or simulate 3 steals) — confirm Daily steal limit appears above Steal before submit; enable bypass checkbox and confirm warning clears to eligible/success tone.

Issue #361 left open for merge close.

## Summary Implements GitLab #361 (parent #360): WarBow play surface shows attacker steal quota and UTC-day reset in the viewer summary, and surfaces `describeStealPreflight` inline above the Steal button when daily caps apply — without waiting for a failed transaction. - **`STEAL QUOTA:`** line in `warbow-hero-viewer-summary` — `X / 3` steals landed today + `HH:MM:SS` countdown to next UTC day; bypass hint when at cap. - **Inline preflight** — `warbow-hero-steal-preflight` warning/error above Steal; Steal disabled on error tone (mirrors protocol page). - **Cap reads** — `useReadContract` when indexer unset; one-shot `readWarbowStealCapDisplay` when `VITE_INDEXER_URL` is set (no recurring display RPC mirrors per #301). - **UTC math** — `warbowUtcDayReset.ts` matches onchain `SECONDS_PER_DAY` floor division. - **Docs** — `INV-FRONTEND-361-WARBOW-STEAL-QUOTA-UX`, arena-views §361, play skill update. ## Acceptance checklist | Criterion | Command / step | Result | |-----------|----------------|--------| | Viewer summary shows `X/3` + UTC reset countdown | `cd frontend && npm test -- --run ArenaWarbowHeroPanel.test.ts` | PASS | | Inline cap warning above Steal when victim/attacker capped | `cd frontend && npm test -- --run ArenaWarbowHeroPanel.test.ts timeArenaUx.test.ts` | PASS | | Warning updates with victim/bypass/clock (hook tests + logic) | `cd frontend && npm test -- --run warbowUtcDayReset.test.ts` | PASS | | Indexer-first: no recurring display RPC mirrors | `cd frontend && npm test -- --run indexerFirstDisplay.test.ts` | PASS | | No contract changes | (diff scope) | PASS | | Typecheck | `cd frontend && npm run typecheck` | PASS | | Lint (changed files) | `npx eslint src/pages/arena/ArenaWarbowHeroPanel.tsx src/pages/arena/useArenaWarbowHero.ts src/lib/warbowUtcDayReset.ts src/lib/readWarbowStealCapDisplay.ts` | PASS | | Full frontend unit tests | `cd frontend && npm test` | SKIP — 7 pre-existing failures in `ArenaSimplePage.test.tsx` (`shouldShowLevelLock` expectations) on `main`; unrelated to this MR | | Manual Anvil play `/` | `bash scripts/start-qa-local-full-stack.sh --live-sale --no-swarm --no-frontend` then `cd frontend && npm run dev` | SKIP — not run in agent session | | Manual Rabby signing path | `bash scripts/qa/build-frontend-for-rabby.sh` + preview | SKIP — optional | ## Verification for third parties 1. `git checkout issue-361-warbow-steal-quota-ux` 2. `cd frontend && npm run typecheck && npx eslint src/pages/arena/ArenaWarbowHeroPanel.tsx src/pages/arena/useArenaWarbowHero.ts && npm test -- --run ArenaWarbowHeroPanel.test.tsx warbowUtcDayReset.test.ts timeArenaUx.test.ts indexerFirstDisplay.test.ts` 3. Start local stack with indexer + connect wallet on `/` at WarBow level ≥ 4. 4. Confirm viewer summary **STEAL QUOTA** line shows usage and countdown. 5. Select a victim at daily cap (or simulate 3 steals) — confirm **Daily steal limit** appears above Steal before submit; enable bypass checkbox and confirm warning clears to eligible/success tone. Issue #361 left open for merge close.
project_80561744_bot_5118c68a88bff95eacb6ab1c47c19cae commented 2026-07-07 02:59:33 +00:00 (Migrated from gitlab.com)

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the [Cursor dashboard](https://www.cursor.com/dashboard/bugbot) to get automatic reviews on future PRs.
PlasticDigits commented 2026-07-07 03:01:43 +00:00 (Migrated from gitlab.com)

Security review — MR !534

Commit reviewed: d363d40ff38b20afce23b4042c601ab363297abb

Scope: Frontend WarBow steal daily-cap UX (#361) — warbowUtcDayReset.ts, readWarbowStealCapDisplay.ts, useArenaWarbowHero.ts, ArenaWarbowHeroPanel.tsx, submit-preflight attacker-cap read, docs/tests/skills. No contract/indexer/API changes in this diff.

Method: Diff + sink tracing for injection, authz, XSS, cap-bypass, and EVM steal paths (warbowSteal onchain remains authoritative).

Outcome: FINDINGS: 0 medium+

Inline threads: none


Security review: no medium+ findings on this diff.

Notes (informational, below threshold)

  • Daily-cap enforcement is unchanged onchain (TimeArena.warbowSteal still gates stealsReceivedOnDay / stealsCommittedByAttackerOnDay and requires payBypassBurn when capped). New UI is display + pre-submit guidance only.
  • Submit path hardening: readFreshWarbowStealPreflight now includes attackerStealsToday (previously undefined at submit), closing a UX gap where attacker-side cap could be missed before signing — defense-in-depth, not a protocol bypass.
  • Steal button disables on error preflight only; warning (daily cap) still allows click, but runWarBowSteal re-reads chain state and onchain reverts without bypass — self-grief gas at worst.
  • XSS: describeStealPreflight strings render as React text via StatusMessage; victim input is isAddress-gated before contract reads.
  • Indexer-first caps: one-shot readWarbowStealCapDisplay on dependency change; stale/missing indexer RPC data affects display only, not signed tx args.

No block:security label applied.

## Security review — MR !534 **Commit reviewed:** `d363d40ff38b20afce23b4042c601ab363297abb` **Scope:** Frontend WarBow steal daily-cap UX (#361) — `warbowUtcDayReset.ts`, `readWarbowStealCapDisplay.ts`, `useArenaWarbowHero.ts`, `ArenaWarbowHeroPanel.tsx`, submit-preflight attacker-cap read, docs/tests/skills. No contract/indexer/API changes in this diff. **Method:** Diff + sink tracing for injection, authz, XSS, cap-bypass, and EVM steal paths (`warbowSteal` onchain remains authoritative). **Outcome:** `FINDINGS: 0` medium+ **Inline threads:** none --- Security review: no medium+ findings on this diff. ### Notes (informational, below threshold) - **Daily-cap enforcement** is unchanged onchain (`TimeArena.warbowSteal` still gates `stealsReceivedOnDay` / `stealsCommittedByAttackerOnDay` and requires `payBypassBurn` when capped). New UI is display + pre-submit guidance only. - **Submit path hardening:** `readFreshWarbowStealPreflight` now includes `attackerStealsToday` (previously `undefined` at submit), closing a UX gap where attacker-side cap could be missed before signing — defense-in-depth, not a protocol bypass. - **Steal button** disables on `error` preflight only; `warning` (daily cap) still allows click, but `runWarBowSteal` re-reads chain state and onchain reverts without bypass — self-grief gas at worst. - **XSS:** `describeStealPreflight` strings render as React text via `StatusMessage`; victim input is `isAddress`-gated before contract reads. - **Indexer-first caps:** one-shot `readWarbowStealCapDisplay` on dependency change; stale/missing indexer RPC data affects display only, not signed tx args. No `block:security` label applied.
PlasticDigits commented 2026-07-07 03:37:50 +00:00 (Migrated from gitlab.com)

added 4 commits

  • d363d40f...6550fe97 - 3 commits from branch main
  • 1459ead1 - Merge origin/main into issue-361-warbow-steal-quota-ux

Compare with previous version

added 4 commits <ul><li>d363d40f...6550fe97 - 3 commits from branch <code>main</code></li><li>1459ead1 - Merge origin/main into issue-361-warbow-steal-quota-ux</li></ul> [Compare with previous version](/PlasticDigits/yieldomega/-/merge_requests/164/diffs?diff_id=1889087235&start_sha=d363d40ff38b20afce23b4042c601ab363297abb)
project_80561744_bot_5118c68a88bff95eacb6ab1c47c19cae commented 2026-07-07 03:37:52 +00:00 (Migrated from gitlab.com)

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the [Cursor dashboard](https://www.cursor.com/dashboard/bugbot) to get automatic reviews on future PRs.
PlasticDigits commented 2026-07-07 03:37:55 +00:00 (Migrated from gitlab.com)

Resolved merge conflicts with origin/main.

  • Unified warbowUtcDayReset.ts (warbowUtcDayId, warbowSecondsUntilNextUtcDay, warbowUtcDayResetSec alias).
  • Kept indexer-first steal-cap reads (readWarbowStealCapDisplay one-shot when indexer on; useReadContract when off) per #301.
  • Adopted main’s viewer-summary steal-quota UI and inline describeStealPreflight above Steal.
  • Merged both victim- and attacker-cap preflight tests; updated indexerFirstDisplay.test.ts for the one-shot path.

Sanity: npm run typecheck PASS; targeted unit tests (53) PASS.

Resolved merge conflicts with `origin/main`. - Unified `warbowUtcDayReset.ts` (`warbowUtcDayId`, `warbowSecondsUntilNextUtcDay`, `warbowUtcDayResetSec` alias). - Kept indexer-first steal-cap reads (`readWarbowStealCapDisplay` one-shot when indexer on; `useReadContract` when off) per #301. - Adopted main’s viewer-summary steal-quota UI and inline `describeStealPreflight` above Steal. - Merged both victim- and attacker-cap preflight tests; updated `indexerFirstDisplay.test.ts` for the one-shot path. Sanity: `npm run typecheck` PASS; targeted unit tests (53) PASS.
PlasticDigits commented 2026-07-07 03:40:13 +00:00 (Migrated from gitlab.com)

Security review — MR !534

Commit reviewed: 1459ead164787976f9962610be3d4d156072efd3 (post-merge with origin/main)

Scope: Frontend WarBow steal daily-cap UX (#361) — readWarbowStealCapDisplay.ts, warbowUtcDayReset.ts, useArenaWarbowHero.ts, ArenaWarbowHeroPanel.tsx, readFreshWarbowStealPreflight attacker-cap read, docs/tests/skills. No contract, indexer, or API surface changes.

Method: Full diff review after merge-conflict resolution; traced attacker-controlled inputs (victim address, bypass checkbox, indexer clock) to sinks (RPC reads, preflight narrative, warbowSteal submit). Verified onchain TimeArena.warbowSteal remains authoritative for cap enforcement.

Outcome: FINDINGS: 0 medium+

Inline threads: none


Security review: no medium+ findings on this diff.

Notes (informational, below threshold)

  • Daily-cap enforcement is unchanged onchain (stealsReceivedOnDay / stealsCommittedByAttackerOnDay + require(payBypassBurn) when capped). New UI is display and pre-submit guidance only.
  • Submit path hardening: readFreshWarbowStealPreflight now includes attackerStealsToday, closing a UX gap where attacker-side cap could be missed before signing — defense-in-depth, not a protocol bypass.
  • Steal button disables on error preflight only; warning (daily cap) still allows click, but runWarBowSteal re-reads fresh onchain state and the contract reverts without bypass — self-grief gas at worst.
  • XSS: describeStealPreflight strings render as React text via StatusMessage; victim input is isAddress-gated before contract reads.
  • Indexer-first caps: one-shot readWarbowStealCapDisplay on dependency change; stale/missing RPC data affects display only, not signed tx args. Victim BP/guard now come from onchain one-shot reads instead of indexer target list — improves fidelity vs prior path.
  • UTC math: warbowUtcDayId / warbowSecondsUntilNextUtcDay mirror onchain block.timestamp / SECONDS_PER_DAY floor division; boundary skew between indexer chainNowSec and mined block.timestamp can affect display/preflight reads but not cap bypass onchain.

No block:security label applied.

## Security review — MR !534 **Commit reviewed:** `1459ead164787976f9962610be3d4d156072efd3` (post-merge with `origin/main`) **Scope:** Frontend WarBow steal daily-cap UX (#361) — `readWarbowStealCapDisplay.ts`, `warbowUtcDayReset.ts`, `useArenaWarbowHero.ts`, `ArenaWarbowHeroPanel.tsx`, `readFreshWarbowStealPreflight` attacker-cap read, docs/tests/skills. No contract, indexer, or API surface changes. **Method:** Full diff review after merge-conflict resolution; traced attacker-controlled inputs (victim address, bypass checkbox, indexer clock) to sinks (RPC reads, preflight narrative, `warbowSteal` submit). Verified onchain `TimeArena.warbowSteal` remains authoritative for cap enforcement. **Outcome:** `FINDINGS: 0` medium+ **Inline threads:** none --- Security review: no medium+ findings on this diff. ### Notes (informational, below threshold) - **Daily-cap enforcement** is unchanged onchain (`stealsReceivedOnDay` / `stealsCommittedByAttackerOnDay` + `require(payBypassBurn)` when capped). New UI is display and pre-submit guidance only. - **Submit path hardening:** `readFreshWarbowStealPreflight` now includes `attackerStealsToday`, closing a UX gap where attacker-side cap could be missed before signing — defense-in-depth, not a protocol bypass. - **Steal button** disables on `error` preflight only; `warning` (daily cap) still allows click, but `runWarBowSteal` re-reads fresh onchain state and the contract reverts without bypass — self-grief gas at worst. - **XSS:** `describeStealPreflight` strings render as React text via `StatusMessage`; victim input is `isAddress`-gated before contract reads. - **Indexer-first caps:** one-shot `readWarbowStealCapDisplay` on dependency change; stale/missing RPC data affects display only, not signed tx args. Victim BP/guard now come from onchain one-shot reads instead of indexer target list — improves fidelity vs prior path. - **UTC math:** `warbowUtcDayId` / `warbowSecondsUntilNextUtcDay` mirror onchain `block.timestamp / SECONDS_PER_DAY` floor division; boundary skew between indexer `chainNowSec` and mined `block.timestamp` can affect display/preflight reads but not cap bypass onchain. No `block:security` label applied.
PlasticDigits commented 2026-07-07 03:53:51 +00:00 (Migrated from gitlab.com)

mentioned in commit c4de872e05

mentioned in commit c4de872e05f7a9253596323ff893c1614a4e1a58
PlasticDigits (Migrated from gitlab.com) merged commit c4de872e05 into main 2026-07-07 03:53:51 +00:00
Sign in to join this conversation.
No reviewers
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!534
No description provided.