UPP — Universal Private PoolConcepts

Notes and Account Model

UPP uses a UTXO-style note model instead of account balances — encrypted UTXOs that prove ownership without revealing contents.

Notes and Account Model

Notes, Not Balances

UPP uses notes (like Bitcoin UTXOs) instead of account balances:

Ethereum:  Address → Balance (1000 tokens)
UPP:       Note A (500 UPD) + Note B (300 UPD) + Note C (200 UPD) = 1000 UPD

Transactions consume existing notes and create new ones. Notes are never modified — only created and nullified.

Note Structure

interface Note {
  amount: bigint       // Token amount
  blinding: bigint     // Random value (ensures hiding — prevents commitment duplication)
  origin: Address      // Original depositor (for ASP compliance)
  sender: Address      // Who sent this specific note
  token: Address       // ERC20 contract address
}

Origin vs Sender:

  • origin — who first deposited. Preserved through all transfers. Used for ASP compliance. Only changes via merge.
  • sender — who sent this specific note. Changes each transfer.

Commitments

Notes are stored on-chain as Poseidon hashes (never the note itself):

commitment = Poseidon(amount, blinding, origin, token)

Properties:

  • Hiding: Cannot recover note contents from commitment
  • Binding: Cannot create two notes with the same commitment (blinding prevents this)
  • Token-locked: Token is bound in the commitment — no transmutation attacks

Nullifiers

Prevent double-spending:

nullifier = Poseidon(commitment, spendingKey, leafIndex)

When a note is spent:

  1. The circuit computes the nullifier privately
  2. The nullifier is published on-chain (not the note contents)
  3. The contract records it as spent
  4. The same note can never be spent again

Because the nullifier depends on spendingKey, only the note owner can produce it.

Merkle Tree

All commitments are stored in a LeanIMT (Lean Incremental Merkle Tree):

PropertyValue
Depth32 levels
Hash functionPoseidon
Capacity~4.3 billion notes
On-chainCommitment appended at each shield/transfer

ZK proofs include a Merkle membership proof — proving a commitment exists in the tree without revealing which one.

Note Lifecycle

Transfer Example

Alice sends 600 of her 1000 UPD note to Bob:

The original 1000 UPD note is nullified. Two new notes are created. Origin remains Alice in both.

Merge Example

Bob merges two received notes:

After merge, origin becomes Bob — Bob vouches for the funds (bona fide purchaser).

Merge Changes Origin

Merge is the only operation that changes a note's origin. The merger takes on compliance responsibility for the combined funds.

On this page