WarBow: widen steal BP band from 2x-10x to 1x-50x (contract + frontend + docs/bots/sims) #366

Closed
opened 2026-07-07 12:41:26 +00:00 by PlasticDigits · 6 comments
PlasticDigits commented 2026-07-07 12:41:26 +00:00 (Migrated from gitlab.com)

Summary

Widen the WarBow steal victim BP eligibility band from 2×–10× attacker BP to 1×–50× attacker BP, across the contract (source of truth), frontend mirrors/UX copy, docs, bots, and simulations — one bundled change so every layer stays consistent.

Current codebase

The band is enforced onchain in TimeArena.warbowSteal as hardcoded literals with a single revert string:

// contracts/src/arena/TimeArena.sol (line ~559)
require(abp > 0 && vbp >= 2 * abp && vbp <= 10 * abp, "TimeArena: steal band");
  • TimeArena is UUPS upgradeable (Ownable2StepUpgradeable + _authorizeUpgrade gated onlyOwner); there is no owner setter for the band — all WARBOW_* economics are public constant and documented as Fixed in contracts/PARAMETERS.md (§ "WarBow steal BP bracket", originally #211).
  • Self-steal is already blocked (require(victim != address(0) && victim != msg.sender, "TimeArena: bad victim")), and daily caps (WARBOW_MAX_STEALS_PER_DAY = 3 per attacker and per victim, UTC day) plus the WARBOW_STEAL_LIMIT_BYPASS_DOUB = 50_000e18 bypass are independent of the band.
  • The frontend mirrors the band in frontend/src/lib/warbowStealBpBand.ts (WARBOW_STEAL_VICTIM_MIN_MULT = 2n, WARBOW_STEAL_VICTIM_MAX_MULT = 10n, isWarbowStealVictimBpInBand), but ArenaWarbowHeroPanel.tsx (isEligibleTarget) duplicates the literals (viewer * 2n / viewer * 10n) instead of using the shared helper, and timeArenaUx.ts describeStealPreflight uses * 2n directly for the lower bound while importing only WARBOW_STEAL_VICTIM_MAX_MULT for the upper bound.
  • "2×–10×" copy is spread across timeArenaUx.ts, revertMessage.ts, warbowHeroSubcardHelpCopy.ts, ArenaSections.tsx, docs (contracts/PARAMETERS.md, docs/product/arena-v2.md, docs/product/time-arena.md), skills (skills/play-time-arena-warbow/SKILL.md), bots (bots/timearena/src/timearena_bot/strategies/warbow_setup.py, pvp.py), and simulations (simulations/ecostrategy/warbow_pvp.py, constants.py).
  • Revert-matrix coverage: INV-TIME-ARENA-WARBOW-REVERT-MATRIX (#316) with test_warbow_steal_reverts_steal_band and helpers _seedWarbowStealBand / _boostWarbowVictim in contracts/test/TimeArena.t.sol.

Why the new implementation is needed

The 2× floor forbids attacking peers at or near your own BP, and the 10× cap keeps large leaders out of reach of most of the field. Widening to 1×–50×:

  • enables peer-vs-peer PvP (equal-BP rivals become valid targets at exactly 1×), and
  • lets underdogs pressure far larger leaders (up to 50×), increasing steal volume, guard demand, and DOUB routed to podium vaults via _routeWarbowDoubSpend.

Whale-griefing protection is preserved by construction: the victim must still hold at least 1× the attacker's BP, so high-BP attackers can never drain lower-BP wallets.

Constraints / guardrails

  • Onchain is the source of truth — the band must change in TimeArena.sol; a frontend-only change would just produce TimeArena: steal band reverts. Deployed instances need a UUPS implementation upgrade (no admin setter exists).
  • Append-only storage for UUPS: implement as constants (no new storage). Do not add owner setters in this issue unless separately decided — keep the "Fixed" convention from PARAMETERS.md.
  • Keep the revert string "TimeArena: steal band" unchanged so revertMessage.ts matching and the #316 revert matrix stay valid.
  • Boundary semantics stay inclusive with uint256 * semantics: vbp >= 1 * abp && vbp <= 50 * abp; abp > 0 requirement unchanged. At exactly 1×, equal-BP victims are eligible.
  • No changes to drain BPS (10% / 1% guarded), daily caps, bypass cost, guard, revenge, flag, or routing (#310/#300).
  • Frontend eligibility/preflight must consume the shared helper (warbowStealBpBand.ts) — remove the duplicated literals in ArenaWarbowHeroPanel.tsx and the hardcoded * 2n in timeArenaUx.ts so a future band change is single-sourced.
  • Indexer is unaffected (WarBowSteal event shape unchanged) — confirm, do not touch.
  • AGPL headers, keep game logic onchain (repo guardrails skill).

Relevant files

Layer Files
Contract contracts/src/arena/TimeArena.sol (warbowSteal band require, WARBOW_* constants block)
Contract tests contracts/test/TimeArena.t.sol (test_warbow_steal_reverts_steal_band, _seedWarbowStealBand, _boostWarbowVictim, band assertions at ~1810)
Frontend logic frontend/src/lib/warbowStealBpBand.ts (+ .test.ts), frontend/src/pages/arena/ArenaWarbowHeroPanel.tsx (isEligibleTarget), frontend/src/lib/timeArenaUx.ts (describeStealPreflight)
Frontend copy frontend/src/lib/revertMessage.ts, frontend/src/pages/arena/warbowHeroSubcardHelpCopy.ts, frontend/src/pages/arena/ArenaSections.tsx
Frontend tests warbowStealBpBand.test.ts, timeArenaUx.test.ts, revertMessage.test.ts, warbowHeroSubcardHelpCopy.test.ts, ArenaWarbowHeroPanel.test.tsx
Docs contracts/PARAMETERS.md (§ WarBow steal BP bracket), docs/product/arena-v2.md, docs/product/time-arena.md, docs/testing/invariants-and-business-logic.md, docs/frontend/design.md (2× BP rule copy)
Skills skills/play-time-arena-warbow/SKILL.md
Bots bots/timearena/src/timearena_bot/strategies/warbow_setup.py (band predicate), pvp.py (log copy)
Simulations simulations/ecostrategy/warbow_pvp.py, simulations/ecostrategy/constants.py, simulations/tests/test_ecostrategy.py
  1. Contract: add named constants next to the other WARBOW_* values and use them in the check:
    uint256 public constant WARBOW_STEAL_VICTIM_MIN_MULT = 1;
    uint256 public constant WARBOW_STEAL_VICTIM_MAX_MULT = 50;
    // in warbowSteal:
    require(
        abp > 0 && vbp >= WARBOW_STEAL_VICTIM_MIN_MULT * abp && vbp <= WARBOW_STEAL_VICTIM_MAX_MULT * abp,
        "TimeArena: steal band"
    );
    
    Expose them in the read ABI (frontend/src/lib/abis.ts) if the UI should read them onchain when the indexer is off, mirroring the WARBOW_STEAL_DOUB pattern.
  2. Frontend: set WARBOW_STEAL_VICTIM_MIN_MULT = 1n / WARBOW_STEAL_VICTIM_MAX_MULT = 50n in warbowStealBpBand.ts; route ArenaWarbowHeroPanel.isEligibleTarget and describeStealPreflight lower bound through the shared constants/helper; update all "2×–10×" strings to "1×–50×" (preflight titles like "2× minimum not met" → band-driven copy).
  3. Docs/skills/bots/sims: update the bracket everywhere listed above; bots warbow_setup.py predicate vbp >= 1 * abp and vbp <= 50 * abp; sims warbow_pvp.py thresholds + constants.py label.
  4. Invariants: update INV-TIME-ARENA-WARBOW-REVERT-MATRIX wording and add/refresh a band invariant row mapping to the new tests.
  5. Deployment: UUPS upgrade of the deployed TimeArena implementation (owner upgradeToAndCall); Anvil dev stack picks the new implementation up automatically via DeployDev.

Acceptance criteria

  • warbowSteal accepts victims with abp <= vbp <= 50 * abp (inclusive both ends) and reverts TimeArena: steal band outside it; abp == 0 still reverts.
  • Equal-BP steal (vbp == abp) succeeds; vbp == abp - 1 and vbp == 50 * abp + 1 revert.
  • Self-steal still reverts TimeArena: bad victim (regression).
  • Frontend target eligibility, steal preflight, help copy, protocol page copy, and friendly revert messages all reflect 1×–50× and are sourced from warbowStealBpBand.ts constants (no duplicated literals in ArenaWarbowHeroPanel.tsx / timeArenaUx.ts).
  • Docs (PARAMETERS.md, arena-v2.md, time-arena.md, invariants), skill, bots, and sims updated; no stale "2×–10×" references (rg -n '2×–10×|2x–10x|2 \* abp|10 \* abp' clean outside changelog/audit history).
  • Revert string and WarBowSteal event unchanged; indexer untouched.
  • Storage layout unchanged (constants only) — UUPS-safe.

Test plan — all paths

Contracts (cd contracts && forge test):

  • Band boundaries: success at vbp == abp, vbp == 2*abp (old floor still in band), vbp == 50*abp; revert at vbp == abp - 1, vbp == 50*abp + 1, and abp == 0.
  • Update _seedWarbowStealBand / _boostWarbowVictim and the assertGe/assertLe band assertions (~line 1810) to the new multiples.
  • Unchanged behavior: guarded drain 1% vs 10%; steal zero when take rounds to 0; daily cap + bypass (steal limit); revenge window opens for victim; ranking updates for both parties; DOUB routing and totalDoubRaised increment.
  • Fuzz: for random abp > 0, in-band vbp succeeds and out-of-band reverts; include large abp values to exercise 50 * abp uint256 multiplication (no overflow within realistic BP magnitudes; document the type(uint256).max / 50 bound).

Frontend (cd frontend && npm run typecheck && npm run lint && npm test):

  • warbowStealBpBand.test.ts: constants 1n/50n; inclusive boundaries (equal BP eligible, 50x+1 not, abp = 0 not).
  • timeArenaUx.test.ts: preflight grading at new boundaries; self-target, zero-BP, below-min, above-max, cap/bypass, guarded-success wording.
  • ArenaWarbowHeroPanel.test.tsx: target rows flag eligible/too-low/too-high per new band.
  • revertMessage.test.ts, warbowHeroSubcardHelpCopy.test.ts: updated copy.

Bots/sims: simulations/tests/test_ecostrategy.py band cases updated; bot warbow_setup.py predicate covered by its existing checks.

E2E (stack): bash scripts/verify-podium-live-anvil.sh smoke plus a manual steal at exactly 1× on the Anvil stack (bash scripts/start-qa-local-full-stack.sh).

Test plan — attack / hack / abuse vectors

  • Peer collusion ping-pong (new at 1×): two equal-BP colluding wallets steal from each other alternately. Assert: BP is only transferred (net conserved, no inflation), each hit costs WARBOW_STEAL_DOUB routed to podiums, per-attacker and per-victim UTC-day caps (3) bind, and bypass costs 50k DOUB — so the loop is strictly value-negative for the pair. Add a Forge test simulating N round-trips and asserting total BP conservation and cumulative DOUB spend.
  • Whale griefing floor: attacker with high BP vs victim below 1× — must revert steal band (replaces the old 2× griefing test's intent; keep a dedicated test).
  • Sybil BP laddering (wider at 50×): fresh low-BP wallet (one 250-BP buy) can now target victims up to 50× (12,500 BP), taking 10% = up to 5× its own BP per hit. Assert daily attacker cap limits this to 3 hits/day without bypass; extend simulations/ecostrategy/warbow_pvp.py scenario to quantify ladder speed under the new band and confirm guard (1% drain) neutralizes it economically.
  • Self-steal / zero victim: regression tests that bad victim still fires (1× would otherwise make self in-band).
  • Overflow probing: fuzz abp near type(uint256).max / 50 to confirm the multiplication reverts safely (Solidity 0.8 checked math) rather than wrapping into a false in-band pass.
  • Guard bypass economics: confirm a guarded 50× victim yields 1% drain (0.5× attacker BP) and steal zero still guards dust-BP victims.
  • Revenge asymmetry: victim revenge takes 10% of stealer's current BP — test that a 50× victim's revenge after being drained behaves as today (no band applies to revenge; regression only).
  • Steal-cap bypass spam: with the wider band there are more eligible victims per attacker; assert the attacker-side UTC-day counter (across victims) still caps at 3 before requiring the 50k bypass.

Verification criteria

Item Command Expected
Contracts cd contracts && forge test PASS (incl. new band boundary + abuse tests; doub.csv fork tests may skip)
Frontend cd frontend && npm run typecheck && npm run lint && npm test PASS
Sims cd simulations && python3 -m pytest tests/test_ecostrategy.py PASS with new band
Stale copy sweep `rg -n '2×–10× steal 2x rule
Live smoke Anvil stack steal at exactly 1× and at 50× boundary Succeeds; WarBowSteal indexed
Invariants doc INV-TIME-ARENA-WARBOW-REVERT-MATRIX + band rows updated Reviewed in MR

Related: #211 (band origin), #316 (revert matrix), #310 (spend routing), #361 (steal quota UX).

## Summary Widen the WarBow steal victim BP eligibility band from **2×–10×** attacker BP to **1×–50×** attacker BP, across the contract (source of truth), frontend mirrors/UX copy, docs, bots, and simulations — one bundled change so every layer stays consistent. ## Current codebase The band is enforced onchain in `TimeArena.warbowSteal` as hardcoded literals with a single revert string: ```solidity // contracts/src/arena/TimeArena.sol (line ~559) require(abp > 0 && vbp >= 2 * abp && vbp <= 10 * abp, "TimeArena: steal band"); ``` - `TimeArena` is **UUPS upgradeable** (`Ownable2StepUpgradeable` + `_authorizeUpgrade` gated `onlyOwner`); there is **no owner setter** for the band — all `WARBOW_*` economics are `public constant` and documented as **Fixed** in `contracts/PARAMETERS.md` (§ "WarBow steal BP bracket", originally #211). - Self-steal is already blocked (`require(victim != address(0) && victim != msg.sender, "TimeArena: bad victim")`), and daily caps (`WARBOW_MAX_STEALS_PER_DAY = 3` per attacker and per victim, UTC day) plus the `WARBOW_STEAL_LIMIT_BYPASS_DOUB = 50_000e18` bypass are independent of the band. - The frontend mirrors the band in `frontend/src/lib/warbowStealBpBand.ts` (`WARBOW_STEAL_VICTIM_MIN_MULT = 2n`, `WARBOW_STEAL_VICTIM_MAX_MULT = 10n`, `isWarbowStealVictimBpInBand`), but `ArenaWarbowHeroPanel.tsx` (`isEligibleTarget`) **duplicates the literals** (`viewer * 2n` / `viewer * 10n`) instead of using the shared helper, and `timeArenaUx.ts` `describeStealPreflight` uses `* 2n` directly for the lower bound while importing only `WARBOW_STEAL_VICTIM_MAX_MULT` for the upper bound. - "2×–10×" copy is spread across `timeArenaUx.ts`, `revertMessage.ts`, `warbowHeroSubcardHelpCopy.ts`, `ArenaSections.tsx`, docs (`contracts/PARAMETERS.md`, `docs/product/arena-v2.md`, `docs/product/time-arena.md`), skills (`skills/play-time-arena-warbow/SKILL.md`), bots (`bots/timearena/src/timearena_bot/strategies/warbow_setup.py`, `pvp.py`), and simulations (`simulations/ecostrategy/warbow_pvp.py`, `constants.py`). - Revert-matrix coverage: **`INV-TIME-ARENA-WARBOW-REVERT-MATRIX`** (#316) with `test_warbow_steal_reverts_steal_band` and helpers `_seedWarbowStealBand` / `_boostWarbowVictim` in `contracts/test/TimeArena.t.sol`. ## Why the new implementation is needed The 2× floor forbids attacking peers at or near your own BP, and the 10× cap keeps large leaders out of reach of most of the field. Widening to **1×–50×**: - enables **peer-vs-peer** PvP (equal-BP rivals become valid targets at exactly 1×), and - lets underdogs pressure **far larger leaders** (up to 50×), increasing steal volume, guard demand, and DOUB routed to podium vaults via `_routeWarbowDoubSpend`. Whale-griefing protection is preserved by construction: the victim must still hold **at least 1× the attacker's BP**, so high-BP attackers can never drain lower-BP wallets. ## Constraints / guardrails - **Onchain is the source of truth** — the band must change in `TimeArena.sol`; a frontend-only change would just produce `TimeArena: steal band` reverts. Deployed instances need a **UUPS implementation upgrade** (no admin setter exists). - **Append-only storage** for UUPS: implement as `constant`s (no new storage). Do **not** add owner setters in this issue unless separately decided — keep the "Fixed" convention from `PARAMETERS.md`. - Keep the revert string **`"TimeArena: steal band"`** unchanged so `revertMessage.ts` matching and the #316 revert matrix stay valid. - Boundary semantics stay **inclusive** with uint256 `*` semantics: `vbp >= 1 * abp && vbp <= 50 * abp`; `abp > 0` requirement unchanged. At exactly 1×, equal-BP victims are eligible. - No changes to drain BPS (10% / 1% guarded), daily caps, bypass cost, guard, revenge, flag, or routing (#310/#300). - Frontend eligibility/preflight must consume the **shared helper** (`warbowStealBpBand.ts`) — remove the duplicated literals in `ArenaWarbowHeroPanel.tsx` and the hardcoded `* 2n` in `timeArenaUx.ts` so a future band change is single-sourced. - Indexer is unaffected (`WarBowSteal` event shape unchanged) — confirm, do not touch. - AGPL headers, keep game logic onchain (repo guardrails skill). ## Relevant files | Layer | Files | |---|---| | Contract | `contracts/src/arena/TimeArena.sol` (warbowSteal band require, `WARBOW_*` constants block) | | Contract tests | `contracts/test/TimeArena.t.sol` (`test_warbow_steal_reverts_steal_band`, `_seedWarbowStealBand`, `_boostWarbowVictim`, band assertions at ~1810) | | Frontend logic | `frontend/src/lib/warbowStealBpBand.ts` (+ `.test.ts`), `frontend/src/pages/arena/ArenaWarbowHeroPanel.tsx` (`isEligibleTarget`), `frontend/src/lib/timeArenaUx.ts` (`describeStealPreflight`) | | Frontend copy | `frontend/src/lib/revertMessage.ts`, `frontend/src/pages/arena/warbowHeroSubcardHelpCopy.ts`, `frontend/src/pages/arena/ArenaSections.tsx` | | Frontend tests | `warbowStealBpBand.test.ts`, `timeArenaUx.test.ts`, `revertMessage.test.ts`, `warbowHeroSubcardHelpCopy.test.ts`, `ArenaWarbowHeroPanel.test.tsx` | | Docs | `contracts/PARAMETERS.md` (§ WarBow steal BP bracket), `docs/product/arena-v2.md`, `docs/product/time-arena.md`, `docs/testing/invariants-and-business-logic.md`, `docs/frontend/design.md` (2× BP rule copy) | | Skills | `skills/play-time-arena-warbow/SKILL.md` | | Bots | `bots/timearena/src/timearena_bot/strategies/warbow_setup.py` (band predicate), `pvp.py` (log copy) | | Simulations | `simulations/ecostrategy/warbow_pvp.py`, `simulations/ecostrategy/constants.py`, `simulations/tests/test_ecostrategy.py` | ## Recommended direction 1. **Contract:** add named constants next to the other `WARBOW_*` values and use them in the check: ```solidity uint256 public constant WARBOW_STEAL_VICTIM_MIN_MULT = 1; uint256 public constant WARBOW_STEAL_VICTIM_MAX_MULT = 50; // in warbowSteal: require( abp > 0 && vbp >= WARBOW_STEAL_VICTIM_MIN_MULT * abp && vbp <= WARBOW_STEAL_VICTIM_MAX_MULT * abp, "TimeArena: steal band" ); ``` Expose them in the read ABI (`frontend/src/lib/abis.ts`) if the UI should read them onchain when the indexer is off, mirroring the `WARBOW_STEAL_DOUB` pattern. 2. **Frontend:** set `WARBOW_STEAL_VICTIM_MIN_MULT = 1n` / `WARBOW_STEAL_VICTIM_MAX_MULT = 50n` in `warbowStealBpBand.ts`; route `ArenaWarbowHeroPanel.isEligibleTarget` and `describeStealPreflight` lower bound through the shared constants/helper; update all "2×–10×" strings to "1×–50×" (preflight titles like "2× minimum not met" → band-driven copy). 3. **Docs/skills/bots/sims:** update the bracket everywhere listed above; bots `warbow_setup.py` predicate `vbp >= 1 * abp and vbp <= 50 * abp`; sims `warbow_pvp.py` thresholds + `constants.py` label. 4. **Invariants:** update `INV-TIME-ARENA-WARBOW-REVERT-MATRIX` wording and add/refresh a band invariant row mapping to the new tests. 5. **Deployment:** UUPS upgrade of the deployed `TimeArena` implementation (owner `upgradeToAndCall`); Anvil dev stack picks the new implementation up automatically via `DeployDev`. ## Acceptance criteria - [ ] `warbowSteal` accepts victims with `abp <= vbp <= 50 * abp` (inclusive both ends) and reverts `TimeArena: steal band` outside it; `abp == 0` still reverts. - [ ] Equal-BP steal (vbp == abp) succeeds; `vbp == abp - 1` and `vbp == 50 * abp + 1` revert. - [ ] Self-steal still reverts `TimeArena: bad victim` (regression). - [ ] Frontend target eligibility, steal preflight, help copy, protocol page copy, and friendly revert messages all reflect 1×–50× and are sourced from `warbowStealBpBand.ts` constants (no duplicated literals in `ArenaWarbowHeroPanel.tsx` / `timeArenaUx.ts`). - [ ] Docs (`PARAMETERS.md`, `arena-v2.md`, `time-arena.md`, invariants), skill, bots, and sims updated; no stale "2×–10×" references (`rg -n '2×–10×|2x–10x|2 \* abp|10 \* abp'` clean outside changelog/audit history). - [ ] Revert string and `WarBowSteal` event unchanged; indexer untouched. - [ ] Storage layout unchanged (constants only) — UUPS-safe. ## Test plan — all paths **Contracts (`cd contracts && forge test`):** - Band boundaries: success at `vbp == abp`, `vbp == 2*abp` (old floor still in band), `vbp == 50*abp`; revert at `vbp == abp - 1`, `vbp == 50*abp + 1`, and `abp == 0`. - Update `_seedWarbowStealBand` / `_boostWarbowVictim` and the `assertGe/assertLe` band assertions (~line 1810) to the new multiples. - Unchanged behavior: guarded drain 1% vs 10%; `steal zero` when take rounds to 0; daily cap + bypass (`steal limit`); revenge window opens for victim; ranking updates for both parties; DOUB routing and `totalDoubRaised` increment. - Fuzz: for random `abp > 0`, in-band `vbp` succeeds and out-of-band reverts; include large `abp` values to exercise `50 * abp` uint256 multiplication (no overflow within realistic BP magnitudes; document the `type(uint256).max / 50` bound). **Frontend (`cd frontend && npm run typecheck && npm run lint && npm test`):** - `warbowStealBpBand.test.ts`: constants `1n`/`50n`; inclusive boundaries (equal BP eligible, `50x+1` not, `abp = 0` not). - `timeArenaUx.test.ts`: preflight grading at new boundaries; self-target, zero-BP, below-min, above-max, cap/bypass, guarded-success wording. - `ArenaWarbowHeroPanel.test.tsx`: target rows flag eligible/too-low/too-high per new band. - `revertMessage.test.ts`, `warbowHeroSubcardHelpCopy.test.ts`: updated copy. **Bots/sims:** `simulations/tests/test_ecostrategy.py` band cases updated; bot `warbow_setup.py` predicate covered by its existing checks. **E2E (stack):** `bash scripts/verify-podium-live-anvil.sh` smoke plus a manual steal at exactly 1× on the Anvil stack (`bash scripts/start-qa-local-full-stack.sh`). ## Test plan — attack / hack / abuse vectors - **Peer collusion ping-pong (new at 1×):** two equal-BP colluding wallets steal from each other alternately. Assert: BP is only transferred (net conserved, no inflation), each hit costs `WARBOW_STEAL_DOUB` routed to podiums, per-attacker and per-victim UTC-day caps (3) bind, and bypass costs 50k DOUB — so the loop is strictly value-negative for the pair. Add a Forge test simulating N round-trips and asserting total BP conservation and cumulative DOUB spend. - **Whale griefing floor:** attacker with high BP vs victim below 1× — must revert `steal band` (replaces the old 2× griefing test's intent; keep a dedicated test). - **Sybil BP laddering (wider at 50×):** fresh low-BP wallet (one 250-BP buy) can now target victims up to 50× (12,500 BP), taking 10% = up to 5× its own BP per hit. Assert daily attacker cap limits this to 3 hits/day without bypass; extend `simulations/ecostrategy/warbow_pvp.py` scenario to quantify ladder speed under the new band and confirm guard (1% drain) neutralizes it economically. - **Self-steal / zero victim:** regression tests that `bad victim` still fires (1× would otherwise make self in-band). - **Overflow probing:** fuzz `abp` near `type(uint256).max / 50` to confirm the multiplication reverts safely (Solidity 0.8 checked math) rather than wrapping into a false in-band pass. - **Guard bypass economics:** confirm a guarded 50× victim yields 1% drain (0.5× attacker BP) and `steal zero` still guards dust-BP victims. - **Revenge asymmetry:** victim revenge takes 10% of stealer's current BP — test that a 50× victim's revenge after being drained behaves as today (no band applies to revenge; regression only). - **Steal-cap bypass spam:** with the wider band there are more eligible victims per attacker; assert the attacker-side UTC-day counter (across victims) still caps at 3 before requiring the 50k bypass. ## Verification criteria | Item | Command | Expected | |---|---|---| | Contracts | `cd contracts && forge test` | PASS (incl. new band boundary + abuse tests; `doub.csv` fork tests may skip) | | Frontend | `cd frontend && npm run typecheck && npm run lint && npm test` | PASS | | Sims | `cd simulations && python3 -m pytest tests/test_ecostrategy.py` | PASS with new band | | Stale copy sweep | `rg -n '2×–10×|steal 2x rule|steal 10x cap' --glob '!audits/**' --glob '!**/out*/**'` | No live-code/doc hits (audit history exempt) | | Live smoke | Anvil stack steal at exactly 1× and at 50× boundary | Succeeds; `WarBowSteal` indexed | | Invariants doc | `INV-TIME-ARENA-WARBOW-REVERT-MATRIX` + band rows updated | Reviewed in MR | Related: #211 (band origin), #316 (revert matrix), #310 (spend routing), #361 (steal quota UX).
PlasticDigits commented 2026-07-08 12:25:41 +00:00 (Migrated from gitlab.com)

mentioned in commit 23aa74d1fe

mentioned in commit 23aa74d1fe0b96ca7125b4ae1386bdad51965935
PlasticDigits commented 2026-07-08 13:10:27 +00:00 (Migrated from gitlab.com)

mentioned in commit e20072c565

mentioned in commit e20072c565875df7f13514335e6f7bf5080a6d44
PlasticDigits commented 2026-07-08 14:06:48 +00:00 (Migrated from gitlab.com)

mentioned in commit 0aa5658521

mentioned in commit 0aa565852186199af2eabbc76cf79403a63949fa
PlasticDigits commented 2026-07-11 01:54:50 +00:00 (Migrated from gitlab.com)

mentioned in commit a55964fa25

mentioned in commit a55964fa25f436733be6e01cd6e209ccc76611f6
PlasticDigits commented 2026-07-11 01:54:57 +00:00 (Migrated from gitlab.com)

mentioned in merge request !542

mentioned in merge request !542
PlasticDigits commented 2026-07-13 09:24:04 +00:00 (Migrated from gitlab.com)

mentioned in commit 8cc66b98d3

mentioned in commit 8cc66b98d3c1af029084b76605aa0070fcf9d4c2
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-07-13 09:24:05 +00:00
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#366
No description provided.