> For the complete documentation index, see [llms.txt](https://docs.zama.org/protocol/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zama.org/protocol/confidential-vault/concepts/multi-vault-router.md).

# Multi-Vault Router

How one transaction joins several vault batchers, with encrypted-zero legs hiding which vault received the money.

Each vault has its own deposit batcher and redeem batcher. A batch hides how much each participant sent, but joining a batcher is public, so joining one batcher tells everyone which vault you chose.

The router (`VaultBatcherConfidentialRouter`) is one contract per chain that joins several batchers in one transaction. You send it one encrypted amount and a list of **legs**. Each leg names a batcher and carries an encrypted amount. The router joins every batcher on the list, including the legs whose amount is zero. An observer sees the list of batchers and cannot tell which legs carried money and which were decoys. When every user of an app sends the same list, they all share one anonymity set instead of one per vault.

```mermaid
flowchart LR
    User["User<br/>(one encrypted amount)"]
    Router["VaultBatcherConfidentialRouter"]
    B1["Deposit batcher<br/>vault A"]
    B2["Deposit batcher<br/>vault B"]
    B3["Deposit batcher<br/>vault C"]

    User -- "one transaction<br/>encrypted legs" --> Router
    Router -- "join e(a)" --> B1
    Router -- "join e(b)" --> B2
    Router -- "join e(0)" --> B3
    Router -- "sweep remainder" --> User
```

Everything after the join is unchanged. Each leg is an ordinary position in its batcher: it settles, finalizes, and is claimed there, as described in [Batch Lifecycle](/protocol/confidential-vault/concepts/batch-lifecycle.md). The router keeps no funds and has no claim function.

## Two entry points

**Push, for deposits.** Send one confidential transfer to the router with the legs in the call data. Vaults with the same underlying accept the same confidential token, so one cUSDC transfer funds every leg. No approval is needed. Only tokens listed in the Zama token wrapper registry can use this entry point.

**Pull, for redemptions.** Each vault has its own confidential share token, so an exit touches several tokens. Grant the router ERC-7984 operator rights on each share token, then call `join` with the legs. The router pulls each leg's amount itself. The grants are safe to leave standing, so only the first exit costs more than one transaction.

## Leg limits

FHE work per transaction is capped. A push fits about 18 legs and a pull about 10, because a pull leg does three times the work. Nothing enforces this on-chain. A call over the limit fails when it runs out of FHE budget, so the client must cap the count.

Use 10 in both directions. A user must be able to exit every vault they entered in one transaction. An exit split over several transactions is visible on-chain and shrinks the anonymity set.

{% hint style="info" %}
These limits are measured against current FHEVM limits, which can change.
{% endhint %}

## Rules for clients

* **Send the same leg list for every user.** The list is public. Decoys work only when everyone sends the same one.
* **Exit through the same list you entered with.** An exit that names fewer vaults shows which vaults the deposit could not have gone to, and weakens the anonymity of everyone who shared those deposit batches.
* **Bundle the first exit when the wallet allows it.** A wallet with [EIP-5792](https://eips.ethereum.org/EIPS/eip-5792) (`wallet_sendCalls`) can put the operator grants and the `join` in one confirmation. Detect support with `wallet_getCapabilities`.

## What stays public

Everything in [Confidentiality](/protocol/confidential-vault/concepts/confidentiality.md) still applies. Aggregates become public, participation is visible, and a batch with one real participant reveals them. The entry point used shows the direction, deposit or redeem.

## Next steps

* [Router Interface](/protocol/confidential-vault/reference/router-interface.md) — the `Allocation` struct, both entry points, and the errors.
* [Deposit into a Vault](/protocol/confidential-vault/guides/deposit.md) — the push path, with code.
* [Withdraw from a Vault](/protocol/confidential-vault/guides/withdraw.md) — the pull path, with code.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.zama.org/protocol/confidential-vault/concepts/multi-vault-router.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
