Vanguard

First Flight #56
Beginner FriendlyDeFiFoundry
0 EXP
Submission Details
Impact: low
Likelihood: low

When determining which phase , the equal case was missed, which can produce an incorrect phase value and affect subsequent progress

Author Revealed upon completion

Root + Impact

Description

There is a logic discrepancy between the view function getCurrentPhase() and the core enforcement logic in _beforeSwap()

if (blocksSinceLaunch < phase1Duration) {
return 1;
} else if (blocksSinceLaunch < phase1Duration + phase2Duration) {
return 2;
} else {
return 3;
}

Risk

Likelihood:

The logical inconsistency occurs specifically at two transition points: when blocksSinceLaunch == phase1Duration and when blocksSinceLaunch == phase1Duration + phase2Duration.

Crucially, this error propagates beyond just the phase display. Since both getUserRemainingLimit and getUserCooldownEnd internally call getCurrentPhase(), these functions will also return incorrect data to the frontend or external callers during those specific blocks.

Impact:

During transition blocks, getCurrentPhase and dependent functions (getUserRemainingLimit, getUserCooldownEnd) incorrectly report relaxed restrictions. Users acting on this misleading data face unexpected reverts or higher fees, as the contract strictly enforces the previous phase's tighter limits.

Proof of Concept

  1. Advance the blockchain to the exact block where block.number == launchStartBlock + phase1Duration.

  2. Call getCurrentPhase(). It returns 2, indicating Phase 2 has started.

  3. Observe that _beforeSwap still enforces Phase

function test_Poc_GetCurrentPhaseError() public {
uint256 startBlock = antiBotHook.launchStartBlock();
uint256 p1Duration = antiBotHook.phase1Duration();
vm.roll(startBlock + p1Duration);
uint256 reportedPhase = antiBotHook.getCurrentPhase();
assertEq(reportedPhase, 2, "Reported phase should be 2 after phase 1 duration");
}

Recommended Mitigation

Simply changing the comparison operator in the getCurrentPhase function's conditional statement from < to <= will suffice.

function getCurrentPhase() public view returns (uint256) {
- blocksSinceLaunch < phase1Duration
+ blocksSinceLaunch <= phase1Duration
- blocksSinceLaunch < phase1Duration + phase2Duration
+ blocksSinceLaunch <= phase1Duration + phase2Duration
}

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!