Skip to main content
Hooks extend vault behavior at specific lifecycle points without modifying core contracts. For background on how the hook system works, see the Hooks concept page. This guide covers building hooks: understanding the interfaces, composing them, and implementing one end-to-end.
Before starting, make sure you have:
  • Foundry installed (forge, cast, anvil)
  • Familiarity with Solidity development and testing
  • Understanding of the Aera V3 Hooks concept page

Hook Interfaces

Aera V3 defines six hook interfaces that fire at different points in the vault lifecycle. Each interface is a single function that the hook contract must implement. For full function signatures, parameter types, and detailed documentation, see the Contract Reference: Hooks.

Hook Lifecycle

When a guardian submits a batch of operations, hooks execute in a deterministic order:
  1. beforeSubmit fires once for the entire batch
  2. For each operation in the batch:
    • beforeOperation fires with the operation’s target, calldata, and hook data
    • The operation executes against the target contract
    • afterOperation fires with the same parameters
  3. afterSubmit fires once after all operations complete
Transfer hooks and claim hooks fire independently of the submission flow:
  • beforeTransfer fires during ERC-20 transfer calls on multi-depositor vault units
  • beforeClaim fires during fee claim operations
If any hook reverts, the entire transaction reverts. Hooks act as hard constraints — the vault cannot bypass a failing hook. The Hooks concept page includes a detailed breakdown of execution flow with examples of common hook configurations.

Composition Patterns

Chaining hooks. A hook contract can internally delegate to other hook contracts, building a pipeline of validation logic. For example, a submit hook might first check aggregate position limits, then update a fee accounting snapshot, then emit events for off-chain monitoring — each concern implemented as a separate internal hook. The vault owner configures hooks via vault settings, and the vault calls the configured hook contract at each lifecycle point. Configurable hooks. Hook contracts can accept configuration parameters rather than having behavior hardcoded. Operation hooks receive hookData from the Merkle tree, which means the same hook contract can enforce different slippage bounds for different operations or different position limits for different assets. This is configured per-guardian through the Merkle tree leaves, not by modifying the hook contract itself. For more on composition patterns, see Hooks: Hook Composition.

Tutorial: Building a Transfer Restriction Hook

This tutorial builds a complete hook from scratch: a transfer restriction hook that only allows vault unit transfers to allowlisted addresses. This is a common compliance requirement for multi-depositor vaults where vault shares should only be held by approved counterparties.

Overview

The hook implements IBeforeTransferHook. When a vault unit transfer occurs, the hook checks whether the recipient is on an allowlist. If not, the transfer reverts. The hook owner can add and remove addresses from the allowlist at any time.

Step 1: Project Setup

Create a new Foundry project and set up the directory structure:
Create the hook interface file. This mirrors the IBeforeTransferHook interface from the Aera V3 protocol:

Step 2: Implement the Hook

Create the transfer restriction hook contract:
The contract is deliberately simple: an owner, an allowlist mapping, and the beforeTransfer function that reverts if the recipient is not allowlisted. In production, you might add batch operations, timelocks, or role-based access — but the core pattern stays the same.

Step 3: Write Tests

Create a test file that verifies the hook behaves correctly:

Step 4: Run Tests

Run the test suite with verbose output to see individual test results:
Expected output:
All four tests should pass: allowlisted transfers succeed, disallowed transfers revert with RecipientNotAllowlisted, the owner can add and remove addresses, and non-owners cannot modify the allowlist.

Step 5: Deploy

Create a deployment script:
Deploy with Forge:
After deploying, the vault owner must configure the hook on the target vault. Hook registration is an owner operation, not a guardian operation. The owner calls setBeforeTransferHook on the multi-depositor vault, passing the deployed hook’s address. See the Multi-Depositor Vault contract reference for details.