Inconsistent comparison operators between hook logic and view functions create a critical discrepancy at the phase transition boundary. The _beforeSwap enforcement logic uses <= (inclusive) to determine Phase 1 eligibility, while getCurrentPhase() view function uses < (exclusive). At the exact boundary block (blocksSinceLaunch == phase1Duration), the UI displays Phase 2 status (higher 3% limit, 20% penalty, no cooldown) to users, but the hook executes Phase 1 constraints (1% limit, 50% penalty, cooldown enforced), causing unexpected penalties on "safe" trades.
Likelihood:
High - Every phase transition hits this boundary. Users will naturally check the UI before trading, and the off-by-one discrepancy guarantees misalignment at the exact transition block. For a 300-block Phase 1, this occurs at block 300.
Impact:
**Medium **- Functional inconsistency between expectation and execution:
User deception: UI reports "Phase 2 Active" (3% limit, no cooldown), user places "safe" 2.5% trade
Unexpected penalty: Hook applies Phase 1 rules (1% limit), imposing 50% penalty on trade user believed was within limits
Trust destruction: User blames protocol for "random" penalties or front-running, damaging reputation
Arbitrage griefing: Malicious actors can exploit this UI/data disconnect to manipulate trading behavior at boundary
Demonstrates that at the exact Phase 1 duration boundary, getCurrentPhase() returns Phase 2 while _beforeSwap enforces Phase 1 rules, causing a 2% trade (valid per UI) to incur 50% penalty (unexpected).
Standardize comparison operators across all phase-checking functions. Use strict < consistently so that Phase 1 spans [0, phase1Duration) and Phase 2 begins at phase1Duration.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.