Hook Development - Interacting With The Vault

The Balancer Router is typically the interface Externally Owned Accounts (EOAs) use to interact with the V3 Vault. While the Router uses Permit2 for token permissions, Hooks—being separate smart contracts—cannot sign these permissions. Instead, Hooks interact directly with the Vault. This section covers some common scenarios and usage patterns for Hooks.

Making A Swap

It is possible for a Hook to make a swapopen in new window by following the following steps:

  1. Send the tokens you are swapping to the Vault:
token.transfer(_vault, amount)
  1. Inform the Vault you have sent it tokens. This will update the Vaults transient accounting with the correct balances:
_vault.settle(token, amount)
  1. Perform the swap:
(amountCalculated, amountIn, amountOut) = _vault.swap(
    VaultSwapParams({
        kind: kind,
        pool: pool,
        tokenIn: tokenIn,
        tokenOut: tokenOut,
        amountGivenRaw: amount,
        limitRaw: limit,
        userData: userData
    })
);

AddingLiquidity - Donating To Pool LPs

Hooks can addopen in new window/removeopen in new window liquidity to pools. The following snippet shows how the DONATIONopen in new window kind can be used to add collected fees to a pool. This effectively donates the fees to the pool LPs and can be seen in action in the ExitFeeHookExampleopen in new window.

_vault.addLiquidity(
    AddLiquidityParams({
        pool: pool,
        to: msg.sender, // It would mint BPTs to router, but it's a donation so no BPT is minted
        maxAmountsIn: accruedFees, // Donate all accrued fees back to the pool (i.e. to the LPs)
        minBptAmountOut: 0, // Donation does not return BPTs, any number above 0 will revert
        kind: AddLiquidityKind.DONATION,
        userData: bytes("") // User data is not used by donation, so we can set it to an empty string
    })
);

Collecting Fees

The Vault sendToopen in new window function can be used to collect fees to a hook.

_vault.sendTo(feeToken, address(this), hookFee);

where address(this) would be the hook itself.

This is used in the FeeTakingHookExampleopen in new window and the LotteryHookExampleopen in new window to collect a fee after swapping.