Concepts
Notes & Vaults
How private balances work inside Siphon.
A note is the unit of private balance inside a Siphon vault.
Note structure
Each note contains:
| Field | Role |
|---|---|
| Value | Token amount (wei for ETH, base units for ERC-20) |
| Nullifier | Secret scalar; its hash is revealed on spend |
| Secret | Additional entropy for commitment derivation |
The commitment inserted into the Merkle tree is:
commitment = Poseidon(value, Poseidon(nullifier, secret))Only the user who generated the note knows the nullifier and secret.
Deposits
When you deposit through the Entrypoint:
- Tokens move into the asset-specific Vault.
- A new commitment is inserted as a Merkle leaf.
- Note secrets are generated and stored locally (optionally encrypted and synced to the server).
Spends
Spending a note requires a Groth16 proof that:
- Proves Merkle membership of the input commitment(s)
- Reveals nullifier hash(es) to prevent double-spend
- Binds the recipient and any swap parameters in public signals
Observers see that some note was spent — not which deposit it came from.
Spendable balance
Your balance is not a single on-chain number. The dapp reconstructs it by:
- Matching local notes against indexed Merkle leaves
- Excluding notes whose nullifiers appear on-chain
- Summing remaining note values
The indexer (siphon-indexer) makes this a single HTTP query instead of thousands of eth_getLogs calls.
Vault operations
| Operation | What it does |
|---|---|
| Withdraw | Send value to a recipient; optional change note |
| Merge | Combine 2–6 notes into one (funds stay in vault) |
| Swap | Spend one note through Uniswap V3; mint change note |
| Split | Divide one note into up to eight slices |