The getCurrentPhase() view function and _beforeSwap() internal function use different comparison operators for phase boundary checks, causing a one-block discrepancy where view functions report a different phase than what's actually applied during swaps.
In _beforeSwap() (actual swap logic):
In getCurrentPhase() (view function):
At exactly blocksSinceLaunch == phase1Duration:
_beforeSwap() evaluates <= → TRUE → returns Phase 1
getCurrentPhase() evaluates < → FALSE → returns Phase 2
Likelihood:
This mismatch occurs deterministically at every phase boundary block
Phase boundaries happen exactly twice per pool lifecycle (Phase 1→2, Phase 2→3)
Any user or frontend querying state at these blocks will see incorrect information
Impact:
getUserRemainingLimit() returns wrong limits at boundary blocks (uses getCurrentPhase())
getUserCooldownEnd() returns wrong cooldowns at boundary blocks
Frontends/DApps display Phase 2 while swaps execute with Phase 1 rules
Users may attempt larger swaps expecting Phase 2 limits but get penalized under Phase 1 rules
Align comparison operators - change getCurrentPhase() to use <=:
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.