Vanguard

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

[H-03] Deployment Script Uses Wrong Hook Permission Flags

Author Revealed upon completion

Root

Description

The deployment script mines for BEFORE_INITIALIZE_FLAG but the contract implements afterInitialize, causing deployment to fail or produce an unusable hook.

Location: script/deployLaunchHook.s.sol:28

// Deployment script (INCORRECT):
uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_INITIALIZE_FLAG);

Location: src/TokenLaunchHook.sol:94-111

// Contract permissions (CORRECT implementation):
function getHookPermissions() public pure override returns (Hooks.Permissions memory) {
return Hooks.Permissions({
beforeInitialize: false, // <-- FALSE
afterInitialize: true, // <-- TRUE (needs AFTER_INITIALIZE_FLAG)
// ...
beforeSwap: true,
// ...
});
}

Risk

Likelihood:

  • This occurs on every deployment using the provided script

  • The script is the only deployment mechanism provided in the repository

  • No validation exists to catch this mismatch during deployment

Impact:

  • Deployed hook address will have BEFORE_INITIALIZE permission bit set

  • PoolManager will NOT call afterInitialize (wrong flag in address)

  • launchStartBlock and initialLiquidity will never be set (remain 0)

  • All swaps will revert with PoolNotInitialized() error

  • Contract is completely non-functional after deployment

Proof of Concept

The deployment script mines for a hook address with BEFORE_INITIALIZE_FLAG set, but the contract's getHookPermissions() declares afterInitialize: true. When PoolManager validates the hook, it checks that the address bits match the declared permissions. This mismatch causes the hook to malfunction.

function test_PoC_H03_DeploymentFlagsMismatch() public {
// The contract's getHookPermissions
Hooks.Permissions memory perms = hook.getHookPermissions();
// Contract declares:
// beforeInitialize: false
// afterInitialize: true
// What the deployment script uses (deployLaunchHook.s.sol line 28):
uint160 scriptFlags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_INITIALIZE_FLAG);
// What the contract actually needs:
uint160 correctFlags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_INITIALIZE_FLAG);
// Flags mismatch!
assertTrue(scriptFlags != correctFlags, "Flags mismatch confirmed!");
// IMPACT: Deployed hook's afterInitialize will NOT be called!
// launchStartBlock and initialLiquidity won't be set!
// All swaps will revert with PoolNotInitialized()!
}

Recommendations

Fix the deployment script:

// CORRECT flags:
uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_INITIALIZE_FLAG);

Support

FAQs

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

Give us feedback!