How it works

Merkle note system

All commitments are stored in a depth-20 Poseidon2 Merkle tree on-chain. The tree supports up to 2²⁰ (≈ 1 million) commitments. The SDK mirrors this tree locally so you can generate membership proofs without a server.

C₀C₁C₂C₃H(C₀,C₁)H(C₂,C₃)RootDepth 20 · 2²⁰ commitments · Poseidon2

Local mirroring

The NoteManager class replays Shielded and Spent events from the contract, rebuilding the local tree leaf by leaf. After every insertion, it recomputes the sibling paths for all owned notes so they always have valid membership proofs.

Zero values

Empty positions in the tree use a pre-computed zeros chain: zeros[0] = 0, zeros[i] = Poseidon2(zeros[i-1], zeros[i-1]). This mirrors the Solidity implementation exactly, ensuring local and on-chain roots always match.

typescript
// Access the local tree via noteManager
const root     = sdk.noteManager.getCurrentRoot();
const notes    = sdk.noteManager.getUnspentNotes(tokenAddress);
const siblings = notes[0].siblings; // 20 sibling hashes for this note