TimeCurve: WarBow steal 2x rule + per-wallet bypass + 10% victim floor (Finding 4 from #131 + Product notes) #134
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#134
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?
Parent
Split from #131 (Finding 4).
Maintainer notes (from #131 discussion)
Per PlasticDigits on #131:
+50 CL8Y) counters should be per attacker wallet, not global — document as an invariant.Problem
warbowStealenforces:When
abp == 0(fresh wallet), condition reduces tovbp > 0, so the “must outrank attacker by 2×” rule does not constrain sybil entrants. Combines poorly withWARBOW_MAX_STEALS_PER_VICTIM_PER_DAY+ cheap bypass (WARBOW_STEAL_LIMIT_BYPASS_BURN_WAD) economics called out in the review.Also verify whether daily bypass burn is globally shared vs per stealer wallet relative to Product note.
Recommended fix
abp > 0ANDvbp >= 2 * abp, or use lifetime / cumulative BP if that better matches podium fairness (needs game-design signoff vs podium snapshots).take/edge cases (guard, rounding) — ensure consistent withWARBOW_STEAL_DRAIN_GUARDED_BPSpath.mapping(address stealer => uint8 count)keyed by(victim, day)tiers) as needed so each distinct attacker wallet pays / exhausts bypass independently — document invariant indocs/testing/invariants-and-business-logic.md+ WarBow UX copy if surfaced.Acceptance criteria
Verification checklist
forge test— extendtest_warbow_steal_revert_2x_ruleand daily-limit / bypass matrices; property or fuzz-friendly cases for rotating fresh wallets if feasible.friendlyRevert*messages for new reverts (skills/play-timecurve-warbow/docs/frontend/timecurve-views.mdcross-links).docs/testing/invariants-and-business-logic.mdnew rows (steal rule, bypass per wallet, victim floor).docs/product/primitives.mdor WarBow subsection if authoritative for PvP rules.Repo touch list
contracts/src/TimeCurve.sol(steal + storage for per-wallet caps)contracts/test/TimeCurve.t.solinvariants-and-business-logic.md, product + frontend WarBow docsmentioned in issue #131
mentioned in commit
fc6ba68fccmentioned in commit
a9e8d1b046Agent follow-up (pushed
main@a9e8d1b)Contract logic: Already on
mainfrom earlier work (#134 steal ranking:abp > 0, victim BP ≥ 2× attacker BP, per-victim and per-attacker UTC-day caps, shared bypass burn,_warbowStealDrainBp). This commit finishes alignment for fuzz + docs:contracts/test/TimeCurveWarBowCl8yBurns.t.sol: steal/revenge burn fuzz setups — stealer one qualifying buy, victim two buys (+ cooldown), matching INV-WARBOW-134-RANK.docs/testing/invariants-and-business-logic.md§134: removed duplicate §134 section; Forge row describes fuzz BP geometry.skills/play-timecurve-warbow/SKILL.md+skills/README.md: participant/agent cross-links for #134 (stealsCommittedByAttackerOnDay, dual UTC caps).Verification checklist for @brouie
cd contracts && forge test --match-path test/TimeCurve.t.sol && forge test --match-path test/TimeCurveWarBowCl8yBurns.t.sol— all green (WarBow fuzz uses 256+ runs locally).warbowStealreverts steal 2x rule when attacker BP is 0 or victim BP < 2× attacker BP.Leaving issue open per request.
@PlasticDigits — verification PASS on
a9e8d1b. walked your checklist:forge test --match-test 'warbow_steal'green: 9/9 PASS across both files. key tests:test_warbow_steal_revert_2x_rule✓test_warbow_steal_revert_zero_attacker_bp✓ (fresh-wallet bypass closed)test_warbow_steal_attacker_daily_limit_fourth_needs_bypass✓ (per-attacker UTC day cap binds)test_warbow_steal_drains_ten_percent_and_burns_one_reserve✓ (10% floor)test_warbow_steal_fresh_wallet_drains_high_bp_victim_for_one_cl8y✓ (regression test for yesterday's documented attack)testFuzz_warbow_steal_burn_exact_to_sink✓ (256 runs)abp > 0 && vbp >= 2 * abpranking (TimeCurve.sol L654),stealsCommittedByAttackerOnDayper-attacker counter alongside per-victim, both checked at L627-631, both incremented at L664-669. bypass burn (WARBOW_STEAL_LIMIT_BYPASS_BURN_WAD) charged when EITHER limit binds (L642-648) — override is per-wallet on each side, not a global gate. 10% drain floor matchesfloor(victimBP × 1000 / 10_000)at_warbowStealDrainBp(L1052) gated byrequire(take > 0, "TimeCurve: steal zero").#timecurve-warbow-steal-rules-gitlab-134anchor reads cleanly — both counters mentioned, single section (no duplicate §134), play skill cross-links match.small follow-up worth flagging: there's no explicit fuzz over
payBypassBurn=falsewith attacker-cap-only-binding state machine — the four-victim test covers attacker-cap-binding via the same flow, but no dedicated revert-message fuzz onattackerLimitBefore && !victimLimitBefore && !payBypassBurn. low priority, gap relative to spec coverage rather than a correctness issue.also: the constant name
WARBOW_MAX_STEALS_PER_VICTIM_PER_DAYis now reused for the per-attacker daily cap (both share threshold of 3, so behaviorally correct), and the event fieldbypassedVictimDailyLimitis set on either limit kind binding now. cosmetic / observability only — could rename in a v2 event or alias for clarity.ready for close on your side.
mentioned in issue #148
mentioned in issue #211
mentioned in issue #217