Vanguard

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

Deployment Failure Due to Mismatched Hook Flags

Author Revealed upon completion

ROOT + IMPACT

## Description

The `deployLaunchHook.s.sol` script is responsible for mining a salt to generate a specific contract address that encodes the hook's permissions. Uniswap V4 requires the hook's address to contain specific "flags" (bits set to 1) that strictly match the permissions returned by the hook's `getHookPermissions()` function.

However, the deployment script requests the wrong flag:

  1. **The Script** uses `Hooks.BEFORE_INITIALIZE_FLAG`.

  2. **The Contract** (`TokenLaunchHook.sol`) implements logic for `afterInitialize` and sets `afterInitialize: true` in its permissions struct.

When the `PoolManager` (or the deployment verification) attempts to validate the hook, it will detect that the address claims to handle `beforeInitialize` (via the flag), but the contract logic explicitly states it does not (`beforeInitialize: false`). This mismatch causes the deployment or pool initialization transaction to revert.

```solidity

// deployLaunchHook.s.sol

function run() public {

// hook contracts must have specific flags encoded in the address

//@audit: This sets the bit for BEFORE_INITIALIZE

uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_INITIALIZE_FLAG);

// ... HookMiner finds an address starting with specific bits ...

}

```

## Risk

**Likelihood**: High (Certainty)

* This is a hard-coded configuration error.

* Every attempt to run the deployment script `forge script script/deployLaunchHook.s.sol` will result in a hook address that is incompatible with the contract code.

**Impact**: Critical

* **Deployment Blocked:** The protocol cannot be deployed or initialized.

* **Protocol Failure:** The `PoolManager` will reject the hook, preventing any liquidity pools from being created with this hook attached.

## Proof of Concept

  1. **Contract Code (`TokenLaunchHook.sol`)**:

The contract explicitly defines its permissions to use `afterInitialize`.

```solidity

function getHookPermissions() public pure override returns (Hooks.Permissions memory) {

return Hooks.Permissions({

beforeInitialize: false, // <--- Contract says FALSE

afterInitialize: true, // <--- Contract says TRUE

// ...

});

}

```

\

  1. **Deployment Script (`deployLaunchHook.s.sol`)**:

The script attempts to mine an address for `beforeInitialize`.

```solidity

// The script forces the address to have the BEFORE_INITIALIZE bit set

uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_INITIALIZE_FLAG);

```

\

  1. **The Failure**:

When `HookMiner` generates the address, it will look like `0x...` where the leading bits indicate `BEFORE_INITIALIZE`. When the `PoolManager` checks this address against `getHookPermissions`, the validation fails because the flags do not match the return struct.

\

  1. **Validating My Claim**:

In the run function of `TokenLaunchHookUnit.t.sol` there is the following line for the flag;

```solidity

uint160 flags = uint160(Hooks.AFTER_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG);

```

When it has `Hooks.AFTER_INITIALIZE_FLAG` the test suite runs. But when the I replaced it with `Hooks.BEFORE_INITIALIZE_FLAG` the test suite failed to run and I got the following error;

```bash

Failing tests:

Encountered 1 failing test in test/TokenLaunchHookUnit.t.sol:TestTokenLaunchHook

[FAIL: HookAddressNotValid(0xB68723B2b5E1Ef43e9a32dC5708d65A5234c6080)] setUp() (gas: 0)

Encountered a total of 1 failing tests, 0 tests succeeded

```

## Recommended Mitigation

Update the `flags` variable in `deployLaunchHook.s.sol` to use `Hooks.AFTER_INITIALIZE_FLAG`, matching the logic inside `TokenLaunchHook.sol`.

```diff

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.BEFORE_SWAP_FLAG | Hooks.AFTER_INITIALIZE_FLAG);

// Mine a salt that will produce a hook address with the correct flags

bytes memory constructorArgs = abi.encode(

```

---

Support

FAQs

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

Give us feedback!