Vanguard

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

Constructor Allows Zero phaseLimitBps - Forces Penalty on ALL Swaps

Author Revealed upon completion

Root + Impact

Description

Normal Behavior: The constructor should validate that all configuration parameters are within valid ranges to ensure the anti-bot protection mechanism works as intended.

Issue: The constructor validates that phase1LimitBps <= 10000 and phase2LimitBps <= 10000 (upper bound check), but does NOT validate that these values are greater than zero. Setting phaseLimitBps = 0 causes maxSwapAmount = (initialLiquidity * 0) / 10000 = 0, which means ALL swaps will trigger penalty fees regardless of their size.

Root Cause: Missing lower bound validation in constructor:

// Current code only checks upper bound:
if (_phase1LimitBps > 10000 || _phase2LimitBps > 10000 || ...) revert InvalidConstructorParams();
// Missing check:
if (_phase1LimitBps == 0 || _phase2LimitBps == 0) revert InvalidConstructorParams();

Impact:

  • Griefing attack: A malicious deployer can initialize the hook with phase1LimitBps = 0 to penalize ALL early swaps during the critical launch phase

  • Legitimate users are charged excessive penalty fees on every single swap

  • Breaks the intended tiered launch mechanism completely

  • Could be used to extract maximum fees from unsuspecting users

Proof of Concept

// Deploy with zero limit
TokenLaunchHook hook = new TokenLaunchHook(
poolManager,
100, // phase1Duration
100, // phase2Duration
0, // phase1LimitBps = 0 (VULNERABLE)
5000, // phase2LimitBps
5, // phase1Cooldown
3, // phase2Cooldown
5000, // phase1PenaltyBps (50% fee!)
2500 // phase2PenaltyBps
);
// In _beforeSwap:
uint256 maxSwapAmount = (initialLiquidity * 0) / 10000; // = 0
// ANY swap triggers penalty:
if (addressSwappedAmount[sender] + swapAmount > 0) {
applyPenalty = true; // ALWAYS TRUE for any swap > 0
}

Recommended Mitigation

constructor(...) {
if (_phase1Duration == 0 || _phase2Duration == 0) revert InvalidConstructorParams();
+ if (_phase1LimitBps == 0 || _phase2LimitBps == 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!