Vanguard

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

Zero phaseCooldown Allows Unlimited Consecutive Swaps - Anti-Bot Bypass

Author Revealed upon completion

Root + Impact

Description

Normal Behavior: The anti-bot protection should enforce cooldown periods between swaps to prevent rapid-fire trading by bots during token launches.

Issue: The constructor does NOT validate that phase1Cooldown and phase2Cooldown are greater than zero. Setting phaseCooldown = 0 causes the cooldown check to always pass, completely bypassing the time-based anti-bot protection:

// In _beforeSwap:
if (addressLastSwapBlock[sender] > 0) {
uint256 blocksSinceLastSwap = block.number - addressLastSwapBlock[sender];
if (blocksSinceLastSwap < phaseCooldown) { // if phaseCooldown = 0, this is always FALSE
applyPenalty = true;
}
}

When phaseCooldown = 0, the condition blocksSinceLastSwap < 0 is always false (since blocksSinceLastSwap >= 0), so the cooldown penalty is NEVER applied.

Root Cause: Missing validation in constructor:

// Constructor only validates durations and BPS values, NOT cooldowns
if (_phase1Duration == 0 || _phase2Duration == 0) revert InvalidConstructorParams();
// Missing: if (_phase1Cooldown == 0 || _phase2Cooldown == 0) revert InvalidConstructorParams();

Impact:

  • Bots can execute unlimited consecutive swaps in the same block with no cooldown penalty

  • The entire anti-bot protection mechanism is defeated

  • MEV bots and sandwich attackers can freely exploit the launch phase

  • Legitimate users face unfair competition from high-frequency traders

Proof of Concept

// Deploy with zero cooldown
TokenLaunchHook hook = new TokenLaunchHook(
poolManager,
100, // phase1Duration
100, // phase2Duration
500, // phase1LimitBps
1000, // phase2LimitBps
0, // phase1Cooldown = 0 (VULNERABLE - no cooldown!)
0, // phase2Cooldown = 0 (VULNERABLE)
5000, // phase1PenaltyBps
2500 // phase2PenaltyBps
);
// Bot can now swap multiple times in rapid succession:
// Block N: swap 1 - no penalty (first swap)
// Block N: swap 2 - no penalty (0 < 0 is false)
// Block N: swap 3 - no penalty (0 < 0 is false)
// ... unlimited swaps with no cooldown enforcement

Recommended Mitigation

constructor(...) {
if (_phase1Duration == 0 || _phase2Duration == 0) revert InvalidConstructorParams();
+ if (_phase1Cooldown == 0 || _phase2Cooldown == 0) revert InvalidConstructorParams();
if (_phase1LimitBps > 10000 || _phase2LimitBps > 10000 || ...) revert InvalidConstructorParams();
...
}

Support

FAQs

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

Give us feedback!