Hook Address Mining

Brute-forcing a CREATE2 salt so a Uniswap v4 hook's address bits encode the exact lifecycle permissions the contract implements.

Hook Address Mining is the process of computing a CREATE2 deployment salt that produces a Uniswap v4 hook contract address whose low-order bits encode the precise set of lifecycle callbacks the hook is allowed to run. Because v4 reads a hook's permissions directly from its address, the address is not an arbitrary identifier—it is a permission bitmap, and it must be mined to match the code.

Why permissions live in the address

The Pool Manager must decide, for every pool operation, whether to call a hook's beforeSwap, afterSwap, beforeAddLiquidity, and so on. Reading that decision from contract storage would cost gas on every single swap. Instead, v4 encodes each permission as a single bit in the least significant 14 bits of the hook's address and checks it with one bitwise AND:

1function hasPermission(IHooks self, uint160 flag) internal pure returns (bool) {
2 return uint160(address(self)) & flag != 0;
3}

Each bit maps to one callback:

  • Bit 13 → BEFORE_INITIALIZE_FLAG
  • Bit 12 → AFTER_INITIALIZE_FLAG
  • ...
  • Bit 1 → AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG
  • Bit 0 → AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG

If the bit is set, the Pool Manager calls that callback. If it is clear, it never does.

How mining works

Since you cannot pick a contract address freely, you brute-force the input that determines it. With CREATE2, the address is a deterministic hash of the deployer address, the contract bytecode, and a 32-byte salt. A mining tool iterates over candidate salts until it finds one whose resulting address has exactly the permission bits you need:

1// v4-periphery provides HookMiner for this.
2(address hookAddress, bytes32 salt) = HookMiner.find(
3 deployer,
4 flags, // the permission bitmap you want
5 type(MyHook).creationCode,
6 constructorArgs
7);

The hook is then deployed with that salt so its on-chain address matches the declared flags.

Security implications

A mismatch between the address bits and the implemented functions is its own bug class:

  • Flag set, function missing → the Pool Manager tries to call a callback that does not exist (or reverts), bricking every operation on the pool—a denial of service.
  • Function present, flag clear → critical hook logic (a fee, a penalty, an access check) silently never runs, leaking value over time.
  • No constructor validation → a hand-rolled hook that does not inherit BaseHook skips Hooks.validateHookPermissions, so a mismatched address can deploy unnoticed.

Inheriting the v4-periphery BaseHook (or OpenZeppelin's hardened equivalent) is the standard defense: its constructor validates the address bits against the getHookPermissions() struct and reverts on any mismatch.

Related Concepts

  • Hooks: The external contracts whose permissions are encoded in the mined address.
  • Pool Manager: The singleton that reads the address bits to decide which callbacks to invoke.
  • Singleton Architecture: The design that makes per-swap gas costs—and therefore the address-bit optimization—matter.
  • Reentrancy Attack: A separate hook bug class that mining does not protect against.

Need expert guidance on Hook Address Mining?

Our team at Zealynx has deep expertise in blockchain security and DeFi protocols. Whether you need an audit or consultation, we're here to help.

Get a Quote