> 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/batch-lifecycle.md).

# Batch Lifecycle

The four batch states, what triggers each transition, and what users can do in each state.

Every batcher runs one batch at a time. Users join the open batch with encrypted amounts. Once the batch is old enough, anyone dispatches it: the aggregate is decrypted, settled against the vault, and each participant claims their share at a single frozen exchange rate. The moment a batch is dispatched, the next one opens.

Batch ids start at 1 and increase by one per dispatch. Exactly one batch is pending at any time.

## The four states

```mermaid
stateDiagram-v2
    [*] --> Pending: previous batch dispatched
    Pending --> Dispatched: dispatchBatch()
    Dispatched --> Finalized: callback — vault settlement succeeds
    Dispatched --> Canceled: callback — empty batch, paused, or deadline passed
    Dispatched --> Dispatched: callback — vault call reverts (retry)
    Finalized --> [*]
    Canceled --> [*]
```

| State        | Meaning                                                                 | Join | `quit` | `claim` |
| ------------ | ----------------------------------------------------------------------- | ---- | ------ | ------- |
| `Pending`    | The batch is open.                                                      | Yes  | Yes    | No      |
| `Dispatched` | The aggregate is awaiting decryption and settlement — funds mid-flight. | No   | No     | No      |
| `Finalized`  | Settlement succeeded; the exchange rate is frozen forever.              | No   | No     | Yes     |
| `Canceled`   | Settlement did not happen; users quit for a full refund.                | No   | Yes    | No      |

Transitions are irreversible. A batch cannot dispatch twice, finalize twice, or cancel after it finalized. A join sent while a batch is `Dispatched` lands in the next batch, and joins are blocked while the batcher is paused.

Three properties hold throughout:

* **Quit is exact.** A quit returns the precise encrypted amount the user joined with, no fee.
* **Claim is ungated.** Anyone can call `claim` for any account; the tokens always go to that account.
* **Repeat calls are idempotent.** A second claim or quit on the same batch transfers zero.

## Join

A user joins by calling `confidentialTransferAndCall` on the input token (cUSDC for deposits, cShare for redemptions), targeting the batcher. The token invokes the batcher's receive hook, which adds the encrypted amount to the user's position in the pending batch. Repeated joins accumulate into one position, and the batcher grants the user FHE permission to decrypt their own position handle.

The [router](/protocol/confidential-vault/concepts/multi-vault-router.md) joins on the user's behalf through `join(beneficiary, amount, proof)`. The position belongs to the user and is claimed or quit on the batcher.

Two joins succeed on-chain while adding nothing: one that would overflow the batch's `uint64` total (clamped to zero and refunded in the same transaction), and a transfer larger than the sender's balance (clamped to a zero transfer by current wrappers). Integrators confirm a join through the `Joined` event or by decrypting the position.

## Dispatch

After the batch reaches its **minimum batch age**, anyone can call `dispatchBatch()`. Dispatch closes the batch, opens the next one, and asks the input token to unwrap the batch's encrypted aggregate. The unwrap marks the aggregate — and only the aggregate — for public decryption by the Zama Protocol.

Dispatch is gated by age alone, with no minimum participant count; [Confidentiality](/protocol/confidential-vault/concepts/confidentiality.md) explains the reasoning and the consequences.

## Finalize or cancel

Once the Zama Protocol produces the cleartext aggregate and its proof, anyone calls `dispatchBatchCallback(batchId, cleartextAmount, proof)`. The callback verifies the proof, then settles:

* **Finalize.** The batcher moves the aggregate through the vault (deposit or redeem), wraps the proceeds back into the output confidential token, and freezes the batch's `exchangeRate` — output units per input unit, with 6 decimals. It emits `BatchFinalized(batchId, exchangeRate)`.
* **Cancel.** Three conditions cancel instead: the aggregate decrypted to zero, the batcher is paused, or the **callback deadline** passed since dispatch. A canceled batch never touches the vault. It emits `BatchCanceled(batchId)`.
* **Retry.** If the vault call reverts inside the deadline — including a deposit settlement that breaches the batch's slippage bound — the batch stays `Dispatched` and the callback can be retried with the same arguments until it succeeds or the deadline cancels the batch.

The callback's gas cost is flat regardless of participant count, so a large batch can always be finalized.

## Claim

On a finalized batch, `claim(batchId, account)` computes the account's share — encrypted deposit times the public exchange rate, rounded down — and transfers the output tokens confidentially. The claimed amount stays encrypted; only the account can decrypt it.

Claims never expire — a finalized batch's rate is frozen forever.

## Timing policy is pinned per batch

Each batcher has three owner-tunable parameters: minimum batch age, callback deadline, and slippage tolerance (deposits only). Their values are **pinned into each batch at creation** — a parameter change affects only future batches.

## The daily cadence on mainnet

Every mainnet batcher has a minimum batch age of 23 hours 58 minutes and a callback deadline of 12 hours. The operator dispatches each batch as soon as it is old enough. The two minutes absorb the dispatch delay, so dispatch happens at the same time each day.

| Side    | Dispatch, every day | Funds claimable        |
| ------- | ------------------- | ---------------------- |
| Redeem  | about 11:00 UTC     | minutes after dispatch |
| Deposit | about 15:00 UTC     | minutes after dispatch |

Redemptions settle four hours before deposits dispatch, so a user can exit one vault, receive cUSDC, and join another vault's deposit batch the same day. A join sent after the dispatch time settles the next day. Read a batch's exact time from `batchCreatedAt` plus `batchMinBatchAge`, as shown in [Track Batch State](/protocol/confidential-vault/guides/track-batches.md). Sepolia batchers use a 58-minute minimum age.

## Next steps

* [Deposit into a Vault](/protocol/confidential-vault/guides/deposit.md) — the client-side call sequence for joining.
* [Track Batch State](/protocol/confidential-vault/guides/track-batches.md) — view functions and events for each state.
* [Trust Model](/protocol/confidential-vault/concepts/trust-model.md) — why every lifecycle step is permissionless.


---

# 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/batch-lifecycle.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.
