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

# How a Nullark note moves

Follow one Nullark bundle from deposit and recovery through a private proof and a public child-note withdrawal.

A deposit creates one bundle commitment containing up to two spendable child notes. The pool stores the bundle commitment once. Later, each child can be withdrawn once without creating another commitment.

## One complete flow

```mermaid
flowchart TB
  subgraph Client["Client — secrets stay here"]
    PREP["Prepare bundle, two child slots, and recovery envelope"]
    RESTORE["Restore the bundle locally"]
    SELECT["Select one unspent child"]
    PROVE["Prove child ownership and bundle membership locally"]
    RESTORE -->|available children| SELECT
    SELECT -->|private witness| PROVE
  end

  subgraph Chain["Pool — public settlement"]
    DEPOSIT["Deposit ETH and bundle commitment"]
    TREE["Insert one leaf and accept a new root"]
    CHECK{"Proof valid and nullifier unused?"}
    PAY["Record nullifier and send net ETH"]
    KEEP["Any sibling remains available"]
    STOP["Revert with no state change"]
    DEPOSIT -->|insert commitment| TREE
    CHECK -->|yes| PAY --> KEEP
    CHECK -->|no| STOP
  end

  PREP -->|wallet deposit| DEPOSIT
  TREE -->|membership data| RESTORE
  PROVE -->|proof and public inputs| CHECK
```

## Bundle commitment

The client chooses a supported template before deposit. That template fixes the parent amount and two child slots. Their amounts add up to the deposited amount; a zero second slot represents a standalone note.

The pool sees one bundle commitment, the deposit amount, timing, sender, and encrypted payload. Child secrets remain in the recovery envelope.

## Accepted root

Each inserted bundle commitment changes the Merkle root. A withdrawal witness proves two things together: the selected child belongs to the bundle, and the bundle commitment belongs to an accepted tree root.

The private Merkle path and child secret stay in the client. The accepted root is public.

## Nullifier and sibling

Each active child has its own nullifier. A successful withdrawal records it and blocks a second spend of that child.

The sibling was already committed at deposit and remains usable until its own nullifier is recorded.

## Public statement

The withdrawal proof fixes nine values in order:

1. Accepted root
2. Child nullifier
3. Public destination
4. Gross child amount
5. Fee
6. Chain ID
7. Verifying pool
8. Proof context hash
9. Encrypted payload hash

See [Withdrawal proof inputs](/reference/public-inputs.md) for exact integration rules.

## Scope of proof acceptance

An accepted proof shows that a private witness satisfies the selected circuit and public statement. Anonymity, setup integrity, source-to-circuit equivalence, frontend safety, wallet safety, RPC honesty, and deployment operations each rely on separate evidence.

Read [Security status](/security/status.md) for the current security and privacy scope.
