Description
Constructor doesn't validate that cooldown values meet a minimum threshold, allowing ineffective or zero cooldown configurations.
Location: src/TokenLaunchHook.sol:62-88
constructor(...) BaseHook(_poolManager) {
if (_phase1Duration == 0 || _phase2Duration == 0) revert InvalidConstructorParams();
if (_phase1LimitBps > 10000 || ...) revert InvalidConstructorParams();
@> phase1Cooldown = _phase1Cooldown;
@> phase2Cooldown = _phase2Cooldown;
}
When cooldown is 0, the check blocksSinceLastSwap < phaseCooldown is always false for uint256.
When cooldown is 1, bots only need to wait ~12 seconds between swaps, providing minimal protection.
Risk
Likelihood: Occurs during deployment with misconfigured parameters (cooldown set too low).
Impact:
-
Setting cooldown to 0 completely disables cooldown protection
-
Setting cooldown to 1 provides minimal protection (~12 seconds on Ethereum)
-
Misconfiguration during deployment leads to ineffective anti-bot protection
Proof of Concept
function test_PoC_L06_MissingMinCooldownValidation() public {
bytes memory creationCode = type(TokenLaunchHook).creationCode;
bytes memory constructorArgs = abi.encode(
manager,
phase1Duration,
phase2Duration,
phase1LimitBps,
phase2LimitBps,
0,
1,
phase1PenaltyBps,
phase2PenaltyBps
);
uint160 flags = uint160(Hooks.AFTER_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG);
(address hookAddress, bytes32 salt) = HookMiner.find(address(this), flags, creationCode, constructorArgs);
TokenLaunchHook weakHook = new TokenLaunchHook{salt: salt}(
manager, phase1Duration, phase2Duration,
phase1LimitBps, phase2LimitBps,
0, 1,
phase1PenaltyBps, phase2PenaltyBps
);
assertEq(weakHook.phase1Cooldown(), 0, "Zero cooldown accepted");
assertEq(weakHook.phase2Cooldown(), 1, "Cooldown of 1 block accepted");
}
Recommendations
Add minimum cooldown validation in constructor:
uint256 constant MIN_COOLDOWN = 5;
constructor(...) BaseHook(_poolManager) {
if (_phase1Duration == 0 || _phase2Duration == 0) revert InvalidConstructorParams();
+ if (_phase1Cooldown < MIN_COOLDOWN || _phase2Cooldown < MIN_COOLDOWN) revert InvalidConstructorParams();
}