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

# Multi-Depositor Vaults

> Operating multi-depositor vaults as a guardian -- order solving, price reporting, fee reporting, transfer hooks, and emergency procedures

Multi-depositor vaults extend the base guardian workflow with shared liquidity across multiple depositors, tokenized vault units (ERC-20), and an async order-solving model for deposits and redemptions. For background on how the guardian role works at the protocol level, see the [Guardian Model](/guides/concepts/supported-protocols/aera-v3/guardian-model). For base guardian operations like strategy execution and vault reads, see the [Single-Depositor Vaults](/guides/guardian/single-depositor-vaults) guide -- this page focuses on the operations unique to multi-depositor vaults.

<Info>
  Before starting, make sure you have:

  * A wallet with guardian permissions on the target vault
  * [viem](https://viem.sh) 2.x installed (`npm install viem`) or [Foundry](https://book.getfoundry.sh/) for the `cast` CLI
  * Familiarity with the [Aera V3 Guardian Model](/guides/concepts/supported-protocols/aera-v3/guardian-model)
  * Understanding of the [Provisioner](/contract-reference/provisioner) model for depositor interactions (see [Cross-Chain](/guides/concepts/supported-protocols/aera-v3/cross-chain) for conceptual overview)
</Info>

## Setup

Configure your environment for interacting with the vault, Provisioner, and PriceAndFeeCalculator contracts. Multi-depositor vaults require more contract addresses than single-depositor vaults because pricing and order fulfillment involve additional periphery contracts.

<CodeGroup>
  ```typescript viem theme={null}
  import {
    createPublicClient,
    createWalletClient,
    http,
  } from 'viem'
  import { privateKeyToAccount } from 'viem/accounts'
  import { mainnet } from 'viem/chains'

  const account = privateKeyToAccount('0xYOUR_PRIVATE_KEY')

  const publicClient = createPublicClient({
    chain: mainnet,
    transport: http(process.env.RPC_URL_ETHEREUM!),
  })

  const walletClient = createWalletClient({
    account,
    chain: mainnet,
    transport: http(process.env.RPC_URL_ETHEREUM!),
  })

  // Contract addresses -- see Contract Reference for deployed addresses
  // https://docs.gauntlet.xyz/contract-reference/addresses
  const VAULT_ADDRESS = '0x...' as const
  const PROVISIONER_ADDRESS = '0x...' as const
  const PRICE_FEE_CALCULATOR_ADDRESS = '0x...' as const
  const FEE_VAULT_ADDRESS = '0x...' as const
  ```

  ```bash cast theme={null}
  # Set environment variables for all subsequent commands
  export RPC_URL_ETHEREUM="https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY"
  export PRIVATE_KEY="0xYOUR_PRIVATE_KEY"

  # Contract addresses -- see Contract Reference for deployed addresses
  # https://docs.gauntlet.xyz/contract-reference/addresses
  export VAULT_ADDRESS="0x..."
  export PROVISIONER_ADDRESS="0x..."
  export PRICE_FEE_CALCULATOR_ADDRESS="0x..."
  export FEE_VAULT_ADDRESS="0x..."
  ```
</CodeGroup>

## Strategy Execution

Strategy execution in multi-depositor vaults uses the same `submit(Operation[])` pattern as single-depositor vaults -- the guardian submits batched operations that are validated against a Merkle tree. See the [Single-Depositor Vaults](/guides/guardian/single-depositor-vaults#strategy-execution) guide for full details on operation submission, vault state reads, and rebalancing.

<CodeGroup>
  ```typescript viem theme={null}
  // Minimal ABI fragment for submit -- see BaseVault Contract Reference for full ABI
  const baseVaultAbi = [
    {
      name: 'submit',
      type: 'function',
      stateMutability: 'nonpayable',
      inputs: [{
        name: 'operations',
        type: 'tuple[]',
        components: [
          { name: 'target', type: 'address' },
          { name: 'data', type: 'bytes' },
          { name: 'value', type: 'uint256' },
          { name: 'proof', type: 'bytes32[]' },
          { name: 'preHook', type: 'address' },
          { name: 'preHookData', type: 'bytes' },
          { name: 'postHook', type: 'address' },
          { name: 'postHookData', type: 'bytes' },
        ],
      }],
      outputs: [],
    },
  ] as const

  // Example: single operation in an MDV context
  const operations = [
    {
      target: '0x...' as `0x${string}`,   // Target protocol contract
      data: '0x...' as `0x${string}`,     // Encoded function call
      value: 0n,
      proof: [] as `0x${string}`[],       // Merkle proof for this operation
      preHook: '0x0000000000000000000000000000000000000000' as `0x${string}`,
      preHookData: '0x' as `0x${string}`,
      postHook: '0x0000000000000000000000000000000000000000' as `0x${string}`,
      postHookData: '0x' as `0x${string}`,
    },
  ]

  const { request } = await publicClient.simulateContract({
    address: VAULT_ADDRESS,
    abi: baseVaultAbi,
    functionName: 'submit',
    args: [operations],
    account,
  })

  const txHash = await walletClient.writeContract(request)
  await publicClient.waitForTransactionReceipt({ hash: txHash, confirmations: 2 })
  ```

  ```bash cast theme={null}
  # Submit a single operation -- complex struct submissions are typically scripted
  cast send $VAULT_ADDRESS \
    "submit((address,bytes,uint256,bytes32[],address,bytes,address,bytes)[])" \
    "[($TARGET,$CALLDATA,0,[],0x0000000000000000000000000000000000000000,0x,0x0000000000000000000000000000000000000000,0x)]" \
    --rpc-url $RPC_URL \
    --private-key $PRIVATE_KEY
  ```
</CodeGroup>

## Order Solving

Order solving is the primary difference between multi-depositor and single-depositor vault operations. Depositors interact with the vault through the [Provisioner](/contract-reference/provisioner) contract using an asynchronous request/fulfill lifecycle. The guardian (acting as solver) monitors pending requests and fulfills them through the vault's submit flow.

### How Orders Work

The async order lifecycle has three stages:

1. **Request** -- A depositor calls `requestDeposit` or `requestRedeem` on the Provisioner, locking their assets (for deposits) or vault units (for redemptions). Each request receives a unique `requestId`.
2. **Fulfill** -- The guardian processes the request through the vault's submit flow. For deposit requests, the guardian ensures assets are accounted for and vault units are allocated. For redemption requests, the guardian ensures exit positions are unwound and assets are available.
3. **Claim** -- The depositor (or receiver) calls `claimDeposit` or `claimRedeem` on the Provisioner to receive their vault units or underlying assets.

This async model is essential for cross-chain operations where CCTP bridging introduces latency between the request and fulfillment. See [Cross-Chain](/guides/concepts/supported-protocols/aera-v3/cross-chain) for the conceptual overview of cross-chain vault flows.

### Monitoring Pending Orders

Monitor the Provisioner for incoming deposit and redemption requests by watching for `DepositRequested` and `RedeemRequested` events. This lets the guardian detect new orders that need fulfillment.

<CodeGroup>
  ```typescript viem theme={null}
  const provisionerEventAbi = [
    {
      name: 'DepositRequested',
      type: 'event',
      inputs: [
        { name: 'requestId', type: 'uint256', indexed: true },
        { name: 'owner', type: 'address', indexed: true },
        { name: 'assets', type: 'uint256', indexed: false },
      ],
    },
    {
      name: 'RedeemRequested',
      type: 'event',
      inputs: [
        { name: 'requestId', type: 'uint256', indexed: true },
        { name: 'owner', type: 'address', indexed: true },
        { name: 'shares', type: 'uint256', indexed: false },
      ],
    },
  ] as const

  // Watch for new deposit requests
  const depositLogs = await publicClient.getLogs({
    address: PROVISIONER_ADDRESS,
    event: provisionerEventAbi[0],
    fromBlock: 'latest',
  })

  for (const log of depositLogs) {
    console.log('Pending deposit:', {
      requestId: log.args.requestId,
      owner: log.args.owner,
      assets: log.args.assets,
    })
  }

  // Watch for new redemption requests
  const redeemLogs = await publicClient.getLogs({
    address: PROVISIONER_ADDRESS,
    event: provisionerEventAbi[1],
    fromBlock: 'latest',
  })

  for (const log of redeemLogs) {
    console.log('Pending redemption:', {
      requestId: log.args.requestId,
      owner: log.args.owner,
      shares: log.args.shares,
    })
  }
  ```

  ```bash cast theme={null}
  # Query recent deposit request events
  cast logs --address $PROVISIONER_ADDRESS \
    "DepositRequested(uint256 indexed requestId, address indexed owner, uint256 assets)" \
    --from-block latest \
    --rpc-url $RPC_URL

  # Query recent redemption request events
  cast logs --address $PROVISIONER_ADDRESS \
    "RedeemRequested(uint256 indexed requestId, address indexed owner, uint256 shares)" \
    --from-block latest \
    --rpc-url $RPC_URL
  ```
</CodeGroup>

### Fulfilling Deposit Orders

When a depositor places a deposit request via `requestDeposit`, the guardian fulfills it by processing the request through the vault's submit flow. Once fulfilled, the depositor can claim their vault units by calling `claimDeposit` on the Provisioner.

<CodeGroup>
  ```typescript viem theme={null}
  const provisionerAbi = [
    {
      name: 'claimDeposit',
      type: 'function',
      stateMutability: 'nonpayable',
      inputs: [
        { name: 'requestId', type: 'uint256' },
        { name: 'receiver', type: 'address' },
      ],
      outputs: [{ type: 'uint256' }],
    },
  ] as const

  // After the guardian fulfills the request via submit, the depositor claims:
  const requestId = 1n // The request ID from DepositRequested event
  const receiver = '0x...' as `0x${string}` // Depositor's address

  const { request: claimReq } = await publicClient.simulateContract({
    address: PROVISIONER_ADDRESS,
    abi: provisionerAbi,
    functionName: 'claimDeposit',
    args: [requestId, receiver],
    account,
  })

  const claimTx = await walletClient.writeContract(claimReq)
  const receipt = await publicClient.waitForTransactionReceipt({ hash: claimTx, confirmations: 2 })

  console.log('Deposit claimed, vault units received:', receipt.transactionHash)
  ```

  ```bash cast theme={null}
  # Claim vault units from a fulfilled deposit request
  # requestId: the ID from the DepositRequested event
  cast send $PROVISIONER_ADDRESS \
    "claimDeposit(uint256,address)(uint256)" \
    1 \
    $RECEIVER_ADDRESS \
    --rpc-url $RPC_URL \
    --private-key $PRIVATE_KEY
  ```
</CodeGroup>

### Fulfilling Redemption Orders

Redemption requests follow the same async pattern. The depositor calls `requestRedeem` on the Provisioner, and after the guardian ensures the underlying assets are available (by unwinding positions if needed via submit), the depositor claims the assets with `claimRedeem`.

<CodeGroup>
  ```typescript viem theme={null}
  const redeemClaimAbi = [
    {
      name: 'claimRedeem',
      type: 'function',
      stateMutability: 'nonpayable',
      inputs: [
        { name: 'requestId', type: 'uint256' },
        { name: 'receiver', type: 'address' },
      ],
      outputs: [{ type: 'uint256' }],
    },
  ] as const

  // After the guardian fulfills the redemption via submit, the depositor claims:
  const redeemRequestId = 2n // The request ID from RedeemRequested event
  const assetReceiver = '0x...' as `0x${string}`

  const { request: redeemReq } = await publicClient.simulateContract({
    address: PROVISIONER_ADDRESS,
    abi: redeemClaimAbi,
    functionName: 'claimRedeem',
    args: [redeemRequestId, assetReceiver],
    account,
  })

  const redeemTx = await walletClient.writeContract(redeemReq)
  const redeemReceipt = await publicClient.waitForTransactionReceipt({ hash: redeemTx, confirmations: 2 })

  console.log('Redemption claimed, assets received:', redeemReceipt.transactionHash)
  ```

  ```bash cast theme={null}
  # Claim assets from a fulfilled redemption request
  cast send $PROVISIONER_ADDRESS \
    "claimRedeem(uint256,address)(uint256)" \
    2 \
    $RECEIVER_ADDRESS \
    --rpc-url $RPC_URL \
    --private-key $PRIVATE_KEY
  ```
</CodeGroup>

<Info>
  Order fulfillment is executed through the guardian's `submit` flow on the vault. The exact fulfillment mechanics depend on whether the deposit/redemption is same-chain or cross-chain. See the [Provisioner Contract Reference](/contract-reference/provisioner) for full function signatures and the [Cross-Chain](/guides/concepts/supported-protocols/aera-v3/cross-chain) page for how cross-chain bridging integrates with the order lifecycle.
</Info>

## Price Reporting

Price reporting is unique to multi-depositor vaults. Because multiple depositors share the same pool, accurate unit pricing is essential for fair minting and redemption of vault shares. The `PriceAndFeeCalculator` contract manages price snapshots and uses them for both share pricing and fee computation.

### Why Prices Matter

In a multi-depositor vault, each depositor's ownership is represented by ERC-20 vault units. The unit price determines how many shares a depositor receives on deposit and how many assets they receive on redemption. Accurate, timely price reporting ensures:

* Fair entry and exit prices for all depositors
* Correct NAV (Net Asset Value) calculation for the vault
* Accurate fee accrual based on vault performance

The `PriceAndFeeCalculator` uses managed accountant snapshots rather than real-time pricing to prevent fee manipulation through short-term vault value changes. See the [Periphery Contract Reference](/contract-reference/periphery) for full function signatures.

### Taking Snapshots

The guardian takes price snapshots by calling `snapshot` on the `PriceAndFeeCalculator`. This records the current unit price and total supply for fee calculation. Snapshots are typically taken as part of the submit flow via an `afterSubmit` hook, but can also be called directly.

<CodeGroup>
  ```typescript viem theme={null}
  const priceCalcAbi = [
    {
      name: 'snapshot',
      type: 'function',
      stateMutability: 'nonpayable',
      inputs: [
        { name: 'unitPrice', type: 'uint256' },
        { name: 'totalSupply', type: 'uint256' },
      ],
      outputs: [],
    },
  ] as const

  // Current unit price and total supply -- derived from vault state
  const unitPrice = 1050000000000000000n  // 1.05 in 18 decimals (vault has appreciated 5%)
  const totalSupply = 10000000000000000000000n // 10,000 vault units

  const { request: snapshotReq } = await publicClient.simulateContract({
    address: PRICE_FEE_CALCULATOR_ADDRESS,
    abi: priceCalcAbi,
    functionName: 'snapshot',
    args: [unitPrice, totalSupply],
    account,
  })

  const snapshotTx = await walletClient.writeContract(snapshotReq)
  await publicClient.waitForTransactionReceipt({ hash: snapshotTx, confirmations: 2 })

  console.log('Price snapshot taken:', snapshotTx)
  ```

  ```bash cast theme={null}
  # Take a price snapshot with current unit price and total supply
  # unitPrice: 1.05 in 18 decimals, totalSupply: 10,000 units in 18 decimals
  cast send $PRICE_FEE_CALCULATOR_ADDRESS \
    "snapshot(uint256,uint256)" \
    1050000000000000000 \
    10000000000000000000000 \
    --rpc-url $RPC_URL \
    --private-key $PRIVATE_KEY
  ```
</CodeGroup>

### Monitoring Prices

Read the current vault state to determine the unit price and total supply before taking a snapshot or verifying pricing accuracy.

<CodeGroup>
  ```typescript viem theme={null}
  const vaultPriceAbi = [
    {
      name: 'totalAssets',
      type: 'function',
      stateMutability: 'view',
      inputs: [],
      outputs: [{ type: 'uint256' }],
    },
    {
      name: 'totalSupply',
      type: 'function',
      stateMutability: 'view',
      inputs: [],
      outputs: [{ type: 'uint256' }],
    },
    {
      name: 'convertToShares',
      type: 'function',
      stateMutability: 'view',
      inputs: [{ name: 'assets', type: 'uint256' }],
      outputs: [{ type: 'uint256' }],
    },
    {
      name: 'convertToAssets',
      type: 'function',
      stateMutability: 'view',
      inputs: [{ name: 'shares', type: 'uint256' }],
      outputs: [{ type: 'uint256' }],
    },
  ] as const

  const [totalAssets, totalSupply] = await Promise.all([
    publicClient.readContract({
      address: VAULT_ADDRESS,
      abi: vaultPriceAbi,
      functionName: 'totalAssets',
    }),
    publicClient.readContract({
      address: VAULT_ADDRESS,
      abi: vaultPriceAbi,
      functionName: 'totalSupply',
    }),
  ])

  // Derive unit price: totalAssets / totalSupply
  const unitPrice = totalSupply > 0n
    ? (totalAssets * 10n ** 18n) / totalSupply
    : 10n ** 18n // Default 1:1 if no supply

  console.log('Total assets:', totalAssets.toString())
  console.log('Total supply:', totalSupply.toString())
  console.log('Unit price (18 decimals):', unitPrice.toString())

  // Convert between shares and assets at current rate
  const sharesFor1000 = await publicClient.readContract({
    address: VAULT_ADDRESS,
    abi: vaultPriceAbi,
    functionName: 'convertToShares',
    args: [1000n * 10n ** 18n],
  })

  console.log('Shares for 1000 assets:', sharesFor1000.toString())
  ```

  ```bash cast theme={null}
  # Read total assets and total supply
  cast call $VAULT_ADDRESS "totalAssets()(uint256)" --rpc-url $RPC_URL
  cast call $VAULT_ADDRESS "totalSupply()(uint256)" --rpc-url $RPC_URL

  # Convert between shares and assets
  cast call $VAULT_ADDRESS "convertToShares(uint256)(uint256)" 1000000000000000000000 --rpc-url $RPC_URL
  cast call $VAULT_ADDRESS "convertToAssets(uint256)(uint256)" 1000000000000000000000 --rpc-url $RPC_URL
  ```
</CodeGroup>

## Fee Reporting

Multi-depositor vaults use the `PriceAndFeeCalculator` for fee computation instead of the `DelayedFeeCalculator` used by single-depositor vaults. The same two fee types apply -- management fees (percentage of AUM over time) and performance fees (percentage of gains above a high-water mark). See the [Single-Depositor Vaults](/guides/guardian/single-depositor-vaults#fee-reporting) guide for the conceptual explanation of how these fee types work.

### Reporting Fees

Report fees by providing the current vault value to the fee vault. The `PriceAndFeeCalculator` uses its most recent snapshot to compute accrued fees.

<CodeGroup>
  ```typescript viem theme={null}
  const feeVaultAbi = [
    {
      name: 'reportFees',
      type: 'function',
      stateMutability: 'nonpayable',
      inputs: [{ name: 'vaultValue', type: 'uint256' }],
      outputs: [],
    },
  ] as const

  // Report current vault value for fee calculation
  const currentVaultValue = 10500000n * 10n ** 18n // Example: 10.5M in 18 decimals

  const { request: reportReq } = await publicClient.simulateContract({
    address: FEE_VAULT_ADDRESS,
    abi: feeVaultAbi,
    functionName: 'reportFees',
    args: [currentVaultValue],
    account,
  })

  const reportTx = await walletClient.writeContract(reportReq)
  await publicClient.waitForTransactionReceipt({ hash: reportTx, confirmations: 2 })

  console.log('Fees reported for vault value:', currentVaultValue.toString())
  ```

  ```bash cast theme={null}
  # Report fees with current vault value
  cast send $FEE_VAULT_ADDRESS \
    "reportFees(uint256)" \
    10500000000000000000000000 \
    --rpc-url $RPC_URL \
    --private-key $PRIVATE_KEY
  ```
</CodeGroup>

### Claiming Fees

The fee recipient claims accrued fees from the fee vault. Specify the token, amount, and recipient address. See the [FeeVault Contract Reference](/contract-reference/fee-vault) for full function details.

<CodeGroup>
  ```typescript viem theme={null}
  const claimFeesAbi = [
    {
      name: 'claimFees',
      type: 'function',
      stateMutability: 'nonpayable',
      inputs: [
        { name: 'token', type: 'address' },
        { name: 'amount', type: 'uint256' },
        { name: 'recipient', type: 'address' },
      ],
      outputs: [],
    },
    {
      name: 'accruedFees',
      type: 'function',
      stateMutability: 'view',
      inputs: [],
      outputs: [{ type: 'uint256' }],
    },
  ] as const

  // Check accrued fees first
  const accrued = await publicClient.readContract({
    address: FEE_VAULT_ADDRESS,
    abi: claimFeesAbi,
    functionName: 'accruedFees',
  })

  console.log('Accrued fees:', accrued.toString())

  // Claim fees
  const FEE_TOKEN = '0x...' as const       // Token to claim fees in
  const FEE_RECIPIENT = '0x...' as const   // Address to receive fees

  const { request: claimReq } = await publicClient.simulateContract({
    address: FEE_VAULT_ADDRESS,
    abi: claimFeesAbi,
    functionName: 'claimFees',
    args: [FEE_TOKEN, accrued, FEE_RECIPIENT],
    account,
  })

  const claimTx = await walletClient.writeContract(claimReq)
  await publicClient.waitForTransactionReceipt({ hash: claimTx, confirmations: 2 })

  console.log('Fees claimed:', claimTx)
  ```

  ```bash cast theme={null}
  # Check accrued fees
  cast call $FEE_VAULT_ADDRESS "accruedFees()(uint256)" --rpc-url $RPC_URL

  # Claim fees
  cast send $FEE_VAULT_ADDRESS \
    "claimFees(address,uint256,address)" \
    $FEE_TOKEN \
    $CLAIM_AMOUNT \
    $FEE_RECIPIENT \
    --rpc-url $RPC_URL \
    --private-key $PRIVATE_KEY
  ```
</CodeGroup>

## Transfer Hooks

Multi-depositor vault units are ERC-20 tokens that can be transferred between addresses. Transfer hooks allow the vault owner to enforce restrictions on these transfers -- for example, compliance blocklists, lock-up periods, or allowlists for approved recipients.

### Setting Transfer Hooks

Setting the transfer hook is an **owner operation** (not a guardian operation), but understanding the mechanism is important for guardians because transfer hooks affect how vault units flow between depositors.

<CodeGroup>
  ```typescript viem theme={null}
  // Owner-only: set the transfer hook contract on the vault
  const setHookAbi = [
    {
      name: 'setTransferHook',
      type: 'function',
      stateMutability: 'nonpayable',
      inputs: [{ name: 'hook', type: 'address' }],
      outputs: [],
    },
  ] as const

  const HOOK_ADDRESS = '0x...' as const // Contract implementing IBeforeTransferHook

  const { request: hookReq } = await publicClient.simulateContract({
    address: VAULT_ADDRESS,
    abi: setHookAbi,
    functionName: 'setTransferHook',
    args: [HOOK_ADDRESS],
    account, // Must be vault owner
  })

  const hookTx = await walletClient.writeContract(hookReq)
  await publicClient.waitForTransactionReceipt({ hash: hookTx, confirmations: 2 })

  console.log('Transfer hook set:', hookTx)
  ```

  ```bash cast theme={null}
  # Owner-only: set transfer hook on the vault
  cast send $VAULT_ADDRESS \
    "setTransferHook(address)" \
    $HOOK_ADDRESS \
    --rpc-url $RPC_URL \
    --private-key $OWNER_PRIVATE_KEY
  ```
</CodeGroup>

When a transfer hook is configured, every vault unit transfer calls `beforeTransfer(address from, address to, uint256 amount)` on the hook contract before executing. If the hook reverts, the transfer fails with `MultiDepositorVault__TransferHookFailed`. See [Custom Hooks](/guides/guardian/custom-hooks) for building custom transfer hook contracts and the [Hook Interfaces Contract Reference](/contract-reference/hooks) for the `IBeforeTransferHook` interface.

## Emergency Procedures

Emergency procedures for multi-depositor vaults follow the same pattern as single-depositor vaults. See the [Single-Depositor Vaults](/guides/guardian/single-depositor-vaults#emergency-procedures) guide for full details on when and why to use these. The key operations are summarized below.

### Pausing the Vault

Calling `pause` immediately halts all guardian operations. Both the guardian and the vault owner can pause.

<CodeGroup>
  ```typescript viem theme={null}
  const pauseAbi = [
    {
      name: 'pause',
      type: 'function',
      stateMutability: 'nonpayable',
      inputs: [],
      outputs: [],
    },
  ] as const

  const { request: pauseReq } = await publicClient.simulateContract({
    address: VAULT_ADDRESS,
    abi: pauseAbi,
    functionName: 'pause',
    account,
  })

  const pauseTx = await walletClient.writeContract(pauseReq)
  await publicClient.waitForTransactionReceipt({ hash: pauseTx, confirmations: 2 })

  console.log('Vault paused:', pauseTx)
  ```

  ```bash cast theme={null}
  cast send $VAULT_ADDRESS "pause()" \
    --rpc-url $RPC_URL \
    --private-key $PRIVATE_KEY
  ```
</CodeGroup>

<Warning>
  Only the vault **owner** can call `unpause` to resume operations. As a guardian, once you pause the vault, you cannot unpause it yourself. Coordinate with the vault owner before pausing in non-emergency situations.
</Warning>

### Checking Pause Status

Verify whether the vault is currently paused before attempting operations.

<CodeGroup>
  ```typescript viem theme={null}
  const pausedAbi = [
    {
      name: 'paused',
      type: 'function',
      stateMutability: 'view',
      inputs: [],
      outputs: [{ type: 'bool' }],
    },
  ] as const

  const isPaused = await publicClient.readContract({
    address: VAULT_ADDRESS,
    abi: pausedAbi,
    functionName: 'paused',
  })

  console.log('Vault paused:', isPaused)
  ```

  ```bash cast theme={null}
  cast call $VAULT_ADDRESS "paused()(bool)" --rpc-url $RPC_URL
  ```
</CodeGroup>

### Guardian Whitelist Check

Verify that the guardian is still authorized on the vault's whitelist.

<CodeGroup>
  ```typescript viem theme={null}
  const whitelistAbi = [
    {
      name: 'checkGuardianWhitelist',
      type: 'function',
      stateMutability: 'nonpayable',
      inputs: [],
      outputs: [],
    },
  ] as const

  const { request: whitelistReq } = await publicClient.simulateContract({
    address: VAULT_ADDRESS,
    abi: whitelistAbi,
    functionName: 'checkGuardianWhitelist',
    account,
  })

  const whitelistTx = await walletClient.writeContract(whitelistReq)
  await publicClient.waitForTransactionReceipt({ hash: whitelistTx, confirmations: 2 })

  console.log('Guardian whitelist check passed:', whitelistTx)
  ```

  ```bash cast theme={null}
  cast send $VAULT_ADDRESS "checkGuardianWhitelist()" \
    --rpc-url $RPC_URL \
    --private-key $PRIVATE_KEY
  ```
</CodeGroup>

## Related Pages

* [Single-Depositor Vaults](/guides/guardian/single-depositor-vaults) -- Base guardian operations for dedicated capital
* [Custom Hooks](/guides/guardian/custom-hooks) -- Building and deploying custom hooks for vault operations
* [Guardian Model](/guides/concepts/supported-protocols/aera-v3/guardian-model) -- How the guardian role works at the protocol level
* [Cross-Chain](/guides/concepts/supported-protocols/aera-v3/cross-chain) -- Cross-chain vault architecture and Provisioner model
* [Hooks](/guides/concepts/supported-protocols/aera-v3/hooks) -- How hooks validate and extend guardian operations
* [MultiDepositorVault Contract Reference](/contract-reference/multi-depositor-vault) -- Full ABI for vault unit operations
* [Provisioner Contract Reference](/contract-reference/provisioner) -- Deposit/redeem request and claim functions
* [FeeVault Contract Reference](/contract-reference/fee-vault) -- Fee reporting and claiming functions
* [Periphery Contract Reference](/contract-reference/periphery) -- PriceAndFeeCalculator and OracleRegistry
