Deploy script is initialize with wrong flag
Description
Because of encoded addresses, hook developers must mine an address to a their particular pattern. Mine the address by finding a salt that produces a hook address with the desired flags, use the Foundry deterministic deployer when deploying via Foundry script.
Inside deployLaunchHool.s.sol wrong flag is initialized for the intended hook
function run() public {
uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_INITIALIZE_FLAG);
bytes memory constructorArgs = abi.encode(
poolManager,
PHASE1_DURATION,
PHASE2_DURATION,
PHASE1_LIMIT_BPS,
PHASE2_LIMIT_BPS,
PHASE1_COOLDOWN,
PHASE2_COOLDOWN,
PHASE1_PENALTY_BPS,
PHASE2_PENALTY_BPS
);
(address hookAddress, bytes32 salt) =
HookMiner.find(CREATE2_FACTORY, flags, type(TokenLaunchHook).creationCode, constructorArgs);
Risk
Failed to deploy to desired chain
Likelihood:
Impact:
Proof of Concept
Inside current test suite TokenLaunchHookUnit.t.sol change flag on lines 76.
Run test suite with forge test
contract TestTokenLaunchHook is Test, Deployers, ERC1155TokenReceiver {
MockERC20 token;
TokenLaunchHook public antiBotHook;
Currency ethCurrency = Currency.wrap(address(0));
Currency tokenCurrency;
address user1 = address(0x1);
address user2 = address(0x2);
address bot1 = address(0xB0B1);
address bot2 = address(0xB0B2);
uint160 constant SQRT_PRICE_1_1_s = 79228162514264337593543950336;
uint256 phase1Duration = 100;
uint256 phase2Duration = 100;
uint256 phase1LimitBps = 100;
uint256 phase2LimitBps = 500;
uint256 phase1Cooldown = 5;
uint256 phase2Cooldown = 2;
uint256 phase1PenaltyBps = 1000;
uint256 phase2PenaltyBps = 500;
function setUp() public {
deployFreshManagerAndRouters();
token = new MockERC20("TOKEN", "TKN", 18);
tokenCurrency = Currency.wrap(address(token));
token.mint(address(this), 1000 ether);
token.mint(user1, 1000 ether);
token.mint(user2, 1000 ether);
token.mint(bot1, 1000 ether);
token.mint(bot2, 1000 ether);
bytes memory creationCode = type(TokenLaunchHook).creationCode;
bytes memory constructorArgs = abi.encode(
manager,
phase1Duration,
phase2Duration,
phase1LimitBps,
phase2LimitBps,
phase1Cooldown,
phase2Cooldown,
phase1PenaltyBps,
phase2PenaltyBps
);
uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_INITIALIZE_FLAG);
(address hookAddress, bytes32 salt) = HookMiner.find(address(this), flags, creationCode, constructorArgs);
antiBotHook = new TokenLaunchHook{salt: salt}(
manager,
phase1Duration,
phase2Duration,
phase1LimitBps,
phase2LimitBps,
phase1Cooldown,
phase2Cooldown,
phase1PenaltyBps,
phase2PenaltyBps
);
require(address(antiBotHook) == hookAddress, "Hook address mismatch");
Log output
andrea@Andreas-MacBook-Pro 2026-01-vanguard % forge test
[⠊] Compiling...
[⠊] Compiling 1 files with Solc 0.8.26
[⠒] Solc 0.8.26 finished in 60.52s
Compiler run successful!
Ran 1 test for test/TokenLaunchHookUnit.t.sol:TestTokenLaunchHook
[FAIL: HookAddressNotValid(0x30c125944809F47AF300cDB99D9181731687a080)] setUp() (gas: 0)
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 262.44ms (0.00ns CPU time)
Ran 1 test suite in 371.93ms (262.44ms CPU time): 0 tests passed, 1 failed, 0 skipped (1 total tests)
Failing tests:
Encountered 1 failing test in test/TokenLaunchHookUnit.t.sol:TestTokenLaunchHook
[FAIL: HookAddressNotValid(0x30c125944809F47AF300cDB99D9181731687a080)] setUp() (gas: 0)
Encountered a total of 1 failing tests, 0 tests succeeded
Recommended Mitigation
Switch code to correct flag
function run() public {
// hook contracts must have specific flags encoded in the address
- uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_INITIALIZE_FLAG);
+ uint160 flags = uint160(Hooks.AFTER_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG);
// Mine a salt that will produce a hook address with the correct flags
bytes memory constructorArgs = abi.encode(
poolManager,
PHASE1_DURATION,
PHASE2_DURATION,
PHASE1_LIMIT_BPS,
PHASE2_LIMIT_BPS,
PHASE1_COOLDOWN,
PHASE2_COOLDOWN,
PHASE1_PENALTY_BPS,
PHASE2_PENALTY_BPS
);
(address hookAddress, bytes32 salt) =
HookMiner.find(CREATE2_FACTORY, flags, type(TokenLaunchHook).creationCode, constructorArgs);