# Hook Deployment (/docs/protocols/v4/guides/hooks/hook-deployment)

Deploy Uniswap v4 hooks by encoding permissions in addresses and using HookMiner patterns.

## Hook Flags
As mentioned in [Concept of Hooks](/docs/protocols/v4/concepts/hooks), hook contracts indicate their implemented functions by **encoding their behavior in the address of the contract**. The `PoolManager` uses these permissions to determine which hook functions to call for a given pool. See `PoolManager` deployment addresses [here](/docs/protocols/v4/deployments).

Each hook function e.g. `beforeSwap` - corresponds to a certain *flag*. For example, the `beforeSwap` function is correlated to the [`BEFORE_SWAP_FLAG`](https://github.com/Uniswap/v4-core/blob/main/src/libraries/Hooks.sol#L37) which has a value of `1 << 7`.

These flags represent specific bits in the address of the hook smart contract - and the value of the bit (a one or a zero) represents whether that flag is true or false. An example:

Addresses on Ethereum are 20 bytes long (160 bits). So for example the address:

```
0x00000000000000000000000000000000000000C0
```

represented in binary is:

```solidity
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 0000 1100 0000
```

In binary it goes from right-to-left - so the trailing 8 bits of this address are `1100 0000` where:

1st Bit to 6th Bit = `0`

7th Bit and 8th Bit = `1`

The `AFTER_SWAP` flag is represented by the 7th bit - which is set to `1` for the example contract address. In the `PoolManager` swap execution flow, it will observe the flag and make a call to the hook's `afterSwap` function.

Similarly, the 8th bit which is also a `1`, actually corresponds to the `BEFORE_SWAP` i.e. the `beforeSwap` hook function - which will also be called by the `PoolManager` during a `swap` workflow.

A full list of all flags can be found [here](https://github.com/Uniswap/v4-core/blob/main/src/libraries/Hooks.sol).

## Hook Miner
Because of encoded addresses, hook developers must *mine* an address to a their particular pattern.

For local testing, `deployCodeTo` cheatcode in Foundry can be used to deploy hook contract to any address.

But when deploying hooks to an actual network, address mining is required to find the proper deployment address
There is a helper library [`HookMiner.sol`](https://github.com/Uniswap/v4-periphery/blob/main/src/utils/HookMiner.sol) that can be used to mine for correct addresses.

Let's see it in action for a Foundry script. We will make use of the example Points Hook from [Building Your First Hook](/docs/protocols/v4/guides/hooks/your-first-hook).

First we set up the contract for Foundry script and import the relevant dependencies:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "forge-std/Script.sol";
import {Hooks} from "v4-core/src/libraries/Hooks.sol";
import {IPoolManager} from "v4-core/src/interfaces/IPoolManager.sol";
import {HookMiner} from "v4-periphery/src/utils/HookMiner.sol";

import {Constants} from "./base/Constants.sol";
import {PointsHook} from "../src/PointsHook.sol";

/// @notice Mines the address and deploys the PointsHook.sol Hook contract
contract PointsHookScript is Script, Constants {
    function setUp() public {}

    function run() public {
```

Specify the flags needed to be encoded in the address:

```solidity
uint160 flags = uint160(
    Hooks.AFTER_ADD_LIQUIDITY_FLAG | Hooks.AFTER_SWAP_FLAG
);
```

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. For most chains, CREATE2\_DEPLOYER contract address is [0x4e59b44847b379578588920ca78fbf26c0b4956c](https://book.getfoundry.sh/guides/deterministic-deployments-using-create2#getting-started).

```solidity
bytes memory constructorArgs = abi.encode(POOLMANAGER);
(address hookAddress, bytes32 salt) =
    HookMiner.find(CREATE2_DEPLOYER, flags, type(PointsHook).creationCode, constructorArgs);
```

> [!NOTE]
> **CREATE2_DEPLOYER**
>
> * `CREATE2_DEPLOYER` is the address that will deploy the hook. In `forge test`, this will be the test contract `address(this)` or the pranking address.
>   * In `forge script`, this should be `0x4e59b44847b379578588920cA78FbF26c0B4956C` (CREATE2 Deployer Proxy)

Refer to this for more details on deploying contracts with CREATE2: [Deploying Contracts with CREATE2](https://docs.openzeppelin.com/cli/2.8/deploying-with-create2)

Deploy the hook using CREATE2 with the `salt`, and compare the deployed address with the address mined:

```solidity
vm.broadcast();
PointsHook pointsHook = new PointsHook{salt: salt}(IPoolManager(POOLMANAGER));
require(address(pointsHook) == hookAddress, "PointsHookScript: hook address mismatch");
```

## A Complete Foundry Script Contract
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "forge-std/Script.sol";
import {Hooks} from "v4-core/src/libraries/Hooks.sol";
import {IPoolManager} from "v4-core/src/interfaces/IPoolManager.sol";
import {HookMiner} from "v4-periphery/src/utils/HookMiner.sol";

import {Constants} from "./base/Constants.sol";
import {PointsHook} from "../src/PointsHook.sol";

/// @notice Mines the address and deploys the PointsHook.sol Hook contract
contract PointsHookScript is Script, Constants {
    function setUp() public {}

    function run() public {
        // hook contracts must have specific flags encoded in the address
        uint160 flags = uint160(Hooks.AFTER_ADD_LIQUIDITY_FLAG | Hooks.AFTER_SWAP_FLAG);

        // Mine a salt that will produce a hook address with the correct flags
        bytes memory constructorArgs = abi.encode(POOLMANAGER);
        (address hookAddress, bytes32 salt) =
            HookMiner.find(CREATE2_DEPLOYER, flags, type(PointsHook).creationCode, constructorArgs);

        // Deploy the hook using CREATE2
        vm.broadcast();
        PointsHook pointsHook = new PointsHook{salt: salt}(IPoolManager(POOLMANAGER));
        require(address(pointsHook) == hookAddress, "PointsHookScript: hook address mismatch");
    }
}
```
