TimeCurve: WarBow CL8Y paths must respect sale deadline (< deadline vs post-deadline pre-endSale) (Finding 6 from #131) #136
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#136
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 6).
Problem
These functions enforce
!endedbut notblock.timestamp < deadline(and they already cap some paths withsaleStart + MAX_SALE_ELAPSED_SECseparately):claimWarBowFlagwarbowStealwarbowRevengewarbowActivateGuardendSaleis permissionless but may be delayed. In post-deadline, pre-endSale windowendedis still false, so Battle Points and flag claims can still mutate while “timer expired” from end-user perspective — enabling last-block / delay games that shift WarBow podium snapshots untilendSaleruns.Recommended fix
Primary fix (recommended):
require(block.timestamp < deadline)(or equivalentlyblock.timestamp <= deadline - 1per strictness preference) on all WarBow mutations above in addition to existing phase checks — align withbuy/ sale UX expectations (#114/#124 window semantics).Alternative: Automatically finalize (
ended = true,_finalizeLastBuyers, etc.) on first touch after deadline inside these functions — heavier and riskier interaction withbuypath; prefer explicit deadline guards unless ops want auto-finalization.Also confirm interaction with
WARBOW_FLAG_SILENCEandMAX_SALE_ELAPSEDso no contradictory reverts mid-extension edge cases.Acceptance criteria
block.timestamp >= deadlineand sale not yetendSale-finalized (unless product explicitly chooses auto-finalization).distributePrizescannot be manipulated in the dead zone described in Finding 6.Verification checklist
deadline, withholdendSale, assert WarBow txs revert or finalize per chosen design.endSalethen revenge/steal still correctly blocked byended.docs/frontend/timecurve-views.md,invariants-and-business-logic.md— document “sale timer ended ⇒ WarBow off” invariant.Repo touch list
contracts/src/TimeCurve.sol(four entrypoints + NatSpec)contracts/test/TimeCurve.t.solWarBow timing sectiondeadlinepassed (hero timer#48clock source)skills/play-timecurve-warbow/SKILL.mdPhase expectationsmentioned in issue #131
mentioned in commit
6a4f054fe8Merged to `main` (commit
6a4f054).Summary: Inclusive boundary for buys and WarBow: interactions allowed while `block.timestamp <= deadline()`. `endSale` waits until `block.timestamp > deadline()` so the last second stays usable and settlement cannot race the same timestamp. Router `BadSalePhase` and frontend `saleExpiredAwaitingEnd` use the matching strict past-deadline rule.
Docs / skills: `docs/testing/invariants-and-business-logic.md`, `docs/frontend/timecurve-views.md` (#136 anchors), WarBow/Doubloon skills + README, yieldomega guardrails skill.
@brouie please verify:
Leaving this issue open for your sign-off.
@PlasticDigits — verification PASS on
6a4f054. walked your checklist:forge test --match-contract TimeCurveTestgreen for the three named tests:test_buy_succeeds_at_deadline_second✓,test_end_sale_reverts_until_strictly_after_deadline✓,test_gitlab136_warbow_steal_reverts_when_past_deadline_before_endsale✓.npx vitest run timeCurveSimplePhasegreen: 21/21 PASS._requireSaleRoundTimerStillLive(<=inclusive) and_requireSaleRoundTimerOverForEndSale(strict>). all four WarBow paths +_buycall the still-live form:_buy(L461),claimWarBowFlag(L607),warbowSteal(L622),warbowRevenge(L693),warbowActivateGuard(L722).endSale(L779-787) calls the strict-over form. asymmetry locked: inclusive last-second buy/WarBow vs strict-past endSale.docs/testing/invariants-and-business-logic.mdreads cleanly.docs/frontend/timecurve-views.mdmatches the strict-past-deadline phase rule.items 2 and 3 (live indexer/fork + UI phase walk) skipped this round — no localnet stack up. logic verified via source + Vitest unit coverage on
timeCurveSimplePhase. happy to walk the live UX next session if you want it pinned.ready for close on your side.