Index / VerifierHook
pattern · MIT · last updated 2026-08-27
VerifierHook
Gate every pool action behind an off-chain AML proof checked in the callback.
PureFi's VerifierHook is a compliance gate wired into almost every callback v4 offers: beforeAddLiquidity, afterAddLiquidity, beforeRemoveLiquidity, afterRemoveLiquidity, beforeSwap, afterSwap and beforeDonate. Seven bits is a lot of surface, and the reason is that a compliance rule which only covers swaps is trivially sidestepped by moving liquidity instead.
The hook holds an immutable IPureFiVerifier and a PureFiHookWhitelist. Callers hand it a signed PureFi package — an off-chain AML/KYC attestation — which the callback decodes through PureFiDataLibrary and checks against a ruleId mapping before letting the action through. Roles are OpenZeppelin AccessControl: ISSUER, MARKET_MAKER, ROUTER and QUOTER, plus a routersWhitelist so only sanctioned routers can reach the pool at all.
That last part is the important structural detail. The proof travels as hookData, and the repo ships its own PureFiSwapRouter and PureFiModifyLiquidityRouter to carry it, so this is not a pool you can trade against with a stock router — the swap path is part of the product. Read the routers alongside the hook; the hook alone will not tell you how the proof gets there.
Copy the shape, not the dependency. Gating all four liquidity callbacks plus both swap callbacks is the transferable idea; swap IPureFiVerifier for whatever attestation source you actually trust and the rest of the structure still holds.
Unaudited in this repository.
Permission bits
These bits must match the deployed address. Confirm on-chain before you route.
beforeAddLiquidityafterAddLiquiditybeforeRemoveLiquidityafterRemoveLiquiditybeforeSwapafterSwapbeforeDonate
Solidity
Excerpt from src/VerifierHook.sol. Copy the full file to implement this. Not an audit.
// SPDX-License-Identifier: MIT
// purefiprotocol/purefi-verifier-hook — excerpt. Full file: source.url
contract VerifierHook is BaseHook, AccessControl {
IPureFiVerifier public immutable verifier;
PureFiHookWhitelist public immutable whitelist;
mapping(address => bool) private routersWhitelist;
mapping(uint32 => bool) public ruleId;
bytes32 public constant ISSUER = keccak256('ISSUER');
bytes32 public constant MARKET_MAKER = keccak256('MARKET_MAKER');
bytes32 public constant ROUTER = keccak256('ROUTER');
bytes32 public constant QUOTER = keccak256('QUOTER');
function getHookPermissions() public pure override returns (Hooks.Permissions memory) {
return Hooks.Permissions({
beforeInitialize: false,
afterInitialize: false,
beforeAddLiquidity: true,
afterAddLiquidity: true,
beforeRemoveLiquidity: true,
afterRemoveLiquidity: true,
beforeSwap: true,
afterSwap: true,
beforeDonate: true,
afterDonate: false,
beforeSwapReturnDelta: false,
afterSwapReturnDelta: false,
afterAddLiquidityReturnDelta: false,
afterRemoveLiquidityReturnDelta: false
});
}
// Every gated callback decodes a signed PureFi package out of hookData via
// PureFiDataLibrary and checks it against ruleId before allowing the action.
// The proof is delivered by the repo's own PureFiSwapRouter /
// PureFiModifyLiquidityRouter — a stock router cannot reach this pool.Spec
| Kind | pattern |
|---|---|
| Status | experimental |
| License | MIT |
| Source | https://github.com/purefiprotocol/purefi-verifier-hook |
| Categories | Compliance |
| Properties | Custom swap data |
| Chains | Ethereum |
| Website | https://purefi.io/ |
FAQ
Can I paste this into production? The snippet is an excerpt. Use the full file at the source URL, match flags to the address, and treat this page as a map, not a guarantee.
How do I build this safely? Start with secure v4 hooks and the OpenZeppelin hooks guide.