Deploying a Hook to the Testnet

The following material is strictly for personal and testing purposes. This guide may not work for production deployments
  1. 1.
    Obtain testnet ETH by bridging from Sepolia
The testnet supports deploying hooks with forge script and CREATE2 salt mining. In production, not all networks will support this
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Script.sol";
import {Hooks} from "@uniswap/v4-core/contracts/libraries/Hooks.sol";
import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol";
import {Counter} from "../src/Counter.sol";
import {HookMiner} from "../test/utils/HookMiner.sol";
contract CounterScript is Script {
address constant CREATE2_DEPLOYER = address(0x4e59b44847b379578588920cA78FbF26c0B4956C);
function setUp() public {}
function run() public {
IPoolManager manager = IPoolManager(payable(0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9));
// hook contracts must have specific flags encoded in the address
uint160 flags = uint160(
Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_SWAP_FLAG | Hooks.BEFORE_MODIFY_POSITION_FLAG
| Hooks.AFTER_MODIFY_POSITION_FLAG
);
// Mine a salt that will produce a hook address with the correct flags
(address hookAddress, bytes32 salt) = HookMiner.find(CREATE2_DEPLOYER, flags, 1000, type(Counter).creationCode, abi.encode(address(manager)));
// Deploy the hook using CREATE2
vm.broadcast();
Counter counter = new Counter{salt: salt}(manager);
require(address(counter) == hookAddress, "CounterScript: hook address mismatch");
}
}
Deployment:
forge script script/Counter.s.sol \
--rpc-url https://l2-uniswap-v4-hook-sandbox-6tl5qq8i4d.t.conduit.xyz \
--private-key <private-key> \
--broadcast