Description
-
The constructor validates that phase1Duration and phase2Duration cannot be 0, preventing a broken launch timeline.
-
However, phase1Cooldown and phase2Cooldown are not validated. Setting these to 0 would make the cooldown mechanism completely ineffective.
constructor(
IPoolManager _poolManager,
uint256 _phase1Duration,
uint256 _phase2Duration,
uint256 _phase1LimitBps,
uint256 _phase2LimitBps,
uint256 _phase1Cooldown,
uint256 _phase2Cooldown,
uint256 _phase1PenaltyBps,
uint256 _phase2PenaltyBps
) BaseHook(_poolManager) {
if (_phase1Duration == 0 || _phase2Duration == 0) revert InvalidConstructorParams();
if (_phase1LimitBps > 10000 || _phase2LimitBps > 10000 ||
_phase1PenaltyBps > 10000 || _phase2PenaltyBps > 10000
) revert InvalidConstructorParams();
}
Risk
Likelihood:
Impact:
-
Zero cooldown means bots can swap rapidly without penalty
-
Reduces effectiveness of anti-bot protection
-
Defeats one of the two primary protection mechanisms (cooldown + limits)
Proof of Concept
Deploy hook with 0 cooldown values - constructor accepts them without validation.
function test_ZeroCooldownAllowed() public {
bytes memory creationCode = type(TokenLaunchHook).creationCode;
bytes memory constructorArgs = abi.encode(
manager,
phase1Duration,
phase2Duration,
phase1LimitBps,
phase2LimitBps,
0,
0,
phase1PenaltyBps,
phase2PenaltyBps
);
uint160 flags = uint160(Hooks.AFTER_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG);
(, bytes32 salt) = HookMiner.find(address(this), flags, creationCode, constructorArgs);
TokenLaunchHook weakHook = new TokenLaunchHook{salt: salt}(
manager,
phase1Duration,
phase2Duration,
phase1LimitBps,
phase2LimitBps,
0,
0,
phase1PenaltyBps,
phase2PenaltyBps
);
assertEq(weakHook.phase1Cooldown(), 0, "Zero cooldown accepted");
}
Recommended Mitigation
Add zero-check for cooldown parameters in constructor.
constructor(
IPoolManager _poolManager,
uint256 _phase1Duration,
uint256 _phase2Duration,
uint256 _phase1LimitBps,
uint256 _phase2LimitBps,
uint256 _phase1Cooldown,
uint256 _phase2Cooldown,
uint256 _phase1PenaltyBps,
uint256 _phase2PenaltyBps
) BaseHook(_poolManager) {
if (_phase1Duration == 0 || _phase2Duration == 0) revert InvalidConstructorParams();
+ if (_phase1Cooldown == 0 || _phase2Cooldown == 0) revert InvalidConstructorParams();
if (
_phase1LimitBps > 10000 || _phase2LimitBps > 10000 ||
_phase1PenaltyBps > 10000 || _phase2PenaltyBps > 10000
) revert InvalidConstructorParams();
// ...
}