05

V1 Mainnet · Public → private

Mask

Masking moves tokens from your public wallet into the pool, as a private note only you can open. It is the one action with no relayer and no proof: tokens leaving your address are public anyway, so your wallet sends it, and the pool builds the note itself.

Sent by

Your wallet

Proof

None — the pool hashes

Gas

Paid by you

Creates

1 private note

Menoid app

picks r, builds npk

encrypts the note

npk + encrypted note

Your wallet

approve (ERC-20)

deposit()

tokens + transaction

NoidPool

computes the commitment

inserts it in the tree

NoteCreated

Your balance

the app finds and

decrypts the note

No relayer here: a mask is public by nature — the chain sees your address send the tokens.

In your browser

  1. 1You choose a token and an amount.
  2. 2The app picks a fresh random r and computes npk = Poseidon(3, userCommitment, r) — the note’s owner, blinded.
  3. 3It encrypts (token, amount, r) to your own viewing key: the encryptedNote.

Your wallet

  1. 4For an ERC-20, approves the pool for the amount (only if the allowance is short).
  2. 5Sends deposit(token, amount, npk, encryptedNote) — or depositNative(npk, encryptedNote) with the coins attached, for MON or ETH.

Inside NoidPool

  1. 6Checks masks aren’t paused, the token is accepted, and 0 < amount ≤ its per-mask cap.
  2. 7Pulls the tokens and checks its balance grew by exactly that amount (tokens that skim a fee on transfer are refused). Native coins are wrapped: MON → WMON, ETH → WETH.
  3. 8Checks npk is non-zero and inside the field, then computes commitment = Poseidon(4, token, amount, npk) itself.
  4. 9Refuses a commitment that already exists, then inserts it as one chunk of 4 leaves (your note and 3 empty ones) and records the new root.
  5. 10Emits NoteCreated(treeId, leafIndex, commitment, encryptedNote) and Deposited(depositor, token, amount, commitment).

Back in your browser

  1. 11The app syncs the new event, decrypts it with your ivk, rebuilds the commitment to confirm it — and your private balance goes up.

Why no proof is needed

A proof exists to show something the chain can’t check by itself. Here it can: the pool sees the token and the amount arrive, and computes the commitment from them. The only thing you supply is npk, which decides who owns the note and can’t add value. A note can never be worth more than what was actually masked.

Monad smart accounts keep 10 MON

On Monad, an account with code — including a MetaMask smart account (EIP-7702) — must keep 10 MON after every transaction it sends. The app knows, and shows how much you can mask.

On-chain, anyone can see

  • Your address masked
  • Which token, how much, and when

Stays private

  • When that note is spent and where its value goes — its nullifier can’t be linked back to it