Integration

Onchain events

The pool’s logs are the source of truth for anyone rebuilding shielded state — a wallet, an indexer, a block explorer. Three events carry everything. None of them leak an amount, an asset, or an owner.

The events

EventEmitted whenWhat the chain sees
NoteCommittedA note enters the treeAn opaque commitment hash and its leaf index. Nothing about the note itself.
NoteCipherPaired with every committed noteThe note encrypted to its owner’s view key. Only that key can read it.
NullifiedA note is spentAn unlinkable nullifier. It marks the note spent and ties to no address.

Signatures and topics

The Solidity signature and its keccak256 topic hash, for filtering logs directly:

NoteCommitted(bytes32 indexed commitment, uint32 leafIndex)
topic0  0xacd3e4a7bca8bf97ebe636db52c23601ef31ff83f3054576536dc2dd85c65d12

NoteCipher(uint32 leafIndex, bytes ciphertext)
topic0  0x60afd175ebe031d03117571e6c2be630fbbdfba97b78a8b386661d0a241b03a0

Nullified(bytes32 indexed nullifier)
topic0  0x42e78517ce08fb9519169f7389ca7fb9cb2651093568ccb618ba89e401eae763

Index the pool with viem

Replay from the pool’s deploy block. Every NoteCommitted is a leaf in order; the matching NoteCipher at the same index carries the encrypted note; the Nullified set tells you which leaves are spent.

import { createPublicClient, http, parseAbiItem } from "viem";

const POOL = "0xf9F825f2D6d8509c78baaa587694f74672C32A59";
const DEPLOY_BLOCK = 92522685n;

const client = createPublicClient({
  transport: http("https://46630.rpc.thirdweb.com"),
});

// Every leaf, in order — the commitment tree.
const notes = await client.getLogs({
  address: POOL,
  event: parseAbiItem(
    "event NoteCommitted(bytes32 indexed commitment, uint32 leafIndex)",
  ),
  fromBlock: DEPLOY_BLOCK,
  toBlock: "latest",
});

// Which of them are spent.
const spent = await client.getLogs({
  address: POOL,
  event: parseAbiItem("event Nullified(bytes32 indexed nullifier)"),
  fromBlock: DEPLOY_BLOCK,
  toBlock: "latest",
});

Pull NoteCipher the same way and pair it to a note by leafIndex — that is all a wallet needs to find, decrypt, and spend what is yours. The CLI does exactly this on cowl scan.

Note
Governance emits too: VerifierSwapProposed, VerifierSwapExecuted, and OwnershipTransferred. Watch them to track the timelocked verifier swap on a pool that has not yet renounced ownership.