> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy the hook and test tokens

> On this page, you will deploy a Counter hook and two mock tokens on Monad Testnet.

## Prerequisites

Complete [Setup](/guides/uniswap-v4-hooks/setup) first. Run the commands from your `monad-hook` directory with the account, RPC, and contract addresses loaded in the same shell. The addresses come from [`shared-infrastructure.json`](https://github.com/monad-developers/uniswap-v4-hooks-example/blob/c3cc78a88f10e5ba141cd6fb632f31db83c0daf8/shared-infrastructure.json) in that directory. If you opened a new shell, restore the environment variables from Setup’s [account configuration](/guides/uniswap-v4-hooks/setup#prepare-a-testnet-account) and [address exports](/guides/uniswap-v4-hooks/setup#load-the-contract-addresses).

## Deploy the mock tokens

Create the manifest directory if you have not already done so:

```sh theme={null}
mkdir -p deployments
```

Run [`DeployMockTokens.s.sol`](https://github.com/monad-developers/uniswap-v4-hooks-example/blob/c3cc78a88f10e5ba141cd6fb632f31db83c0daf8/script/monad/DeployMockTokens.s.sol) in simulation mode first. It deploys two 18-decimal `MockERC20` contracts and writes `deployments/tokens.json` with `.tokenA` and `.tokenB`:

```sh theme={null}
FOUNDRY_PROFILE=monad_testnet forge script \
  script/monad/DeployMockTokens.s.sol:DeployMockTokens \
  --network monad --rpc-url "$MONAD_TESTNET_RPC_URL" \
  --account monad-hooks-testnet \
  --sender "$DEPLOYER"
```

Inspect the predicted addresses and gas estimate, then broadcast once:

```sh theme={null}
FOUNDRY_PROFILE=monad_testnet forge script \
  script/monad/DeployMockTokens.s.sol:DeployMockTokens \
  --network monad --rpc-url "$MONAD_TESTNET_RPC_URL" \
  --account monad-hooks-testnet \
  --sender "$DEPLOYER" \
  --broadcast --slow
```

After a successful broadcast, load the deployed token addresses:

```sh theme={null}
export TOKEN_A="$(jq -er .tokenA deployments/tokens.json)"
export TOKEN_B="$(jq -er .tokenB deployments/tokens.json)"
```

Both tokens have public `mint` and `burn` methods for testing.

## Mine and deploy the hook

`Counter` enables four callbacks: `beforeSwap`, `afterSwap`, `beforeAddLiquidity`, and `beforeRemoveLiquidity`. Uniswap encodes these permissions in the hook address; Counter’s permission bits are `0x0ac0`.

[`DeployHook.s.sol`](https://github.com/monad-developers/uniswap-v4-hooks-example/blob/c3cc78a88f10e5ba141cd6fb632f31db83c0daf8/script/monad/DeployHook.s.sol) finds a CREATE2 salt that produces an address with those bits, then deploys the hook through the factory at `0x4e59b44847b379578588920cA78FbF26c0B4956C`. It takes `POOL_MANAGER` as the constructor argument and writes the result to `deployments/hook.json`.

Simulate the deployment:

```sh theme={null}
FOUNDRY_PROFILE=monad_testnet forge script \
  script/monad/DeployHook.s.sol:DeployHook \
  --network monad --rpc-url "$MONAD_TESTNET_RPC_URL" \
  --account monad-hooks-testnet \
  --sender "$DEPLOYER"
```

Broadcast only after the simulation succeeds:

```sh theme={null}
FOUNDRY_PROFILE=monad_testnet forge script \
  script/monad/DeployHook.s.sol:DeployHook \
  --network monad --rpc-url "$MONAD_TESTNET_RPC_URL" \
  --account monad-hooks-testnet \
  --sender "$DEPLOYER" \
  --broadcast --slow
```

Read the hook address from the manifest and verify it:

```sh theme={null}
export HOOK_ADDRESS="$(jq -er .hook deployments/hook.json)"
cast code "$HOOK_ADDRESS" --rpc-url "$MONAD_TESTNET_RPC_URL"
cast call "$HOOK_ADDRESS" "poolManager()(address)" --rpc-url "$MONAD_TESTNET_RPC_URL"
```

The `poolManager()` result should match `POOL_MANAGER`.

## Next step

Continue to [Pool lifecycle](/guides/uniswap-v4-hooks/pool-lifecycle) to create a pool and trigger the hook’s callbacks.
