Uniswap v4 hook · on-chain accumulator · zero-knowledge verifier

Set-membership proofs over live order flow.

CROWD commits every swap in its pool to a hash chain, accumulates the traders into a Merkle set on-chain, and verifies zero-knowledge proofs that a message came from a member of that set, without disclosing which member.

tokennot deployed
swaps committed
—
attestation tokens
—
anonymous attestations
—
fig. 1 · anonymity setattempts 000 · success 000

Steer the light to identify the marked member. An observer who sees every swap still cannot.

01 · Disclosure model

What an observer learns

Disclosed public chain state

  • Each swap: tx.origin, direction, both amounts, block number.
  • The sequence number and leaf assigned to that swap.
  • The full member set. It is the anonymity set, so it must be public.
  • An attestation token, if a member chooses to mint one.

Not disclosed zero-knowledge

  • Which member authored an attestation. The verifier learns ∃ leaf ∈ S and nothing about its index.
  • The member's signature. It is a private witness, used in the browser and never transmitted.
  • The member's address, to the attestation contract. msg.sender is not read; submit from an unrelated account.
fig. 2 · indistinguishability game, k = 5guesses 00 · advantage 0.000
INDISTINGUISHABLE

One of these five produced a valid proof. Select the author. The transcript is identical for every candidate.

Limits. Anonymity is bounded by the set size: log₂|S| bits. The proof does not hide your IP address from your RPC provider. Each key yields one stable nullifier, so a member's attestations are linkable to each other, not to the key. Signature malleability and non-deterministic signers can yield additional nullifiers per key.

02 · Commitment scheme

From swap to proof

i

Hook

afterSwap executes for every trade regardless of router. No fee, no gate, no hookData; the swap delta is returned unchanged.

ii

Leaf

leaf = keccak256(n, tx.origin, isBuy, Δcrowd, Δeth, block), emitted in the Joined event with its sequence number n.

iii

Chain

head ← keccak256(head ‖ leaf). Checkpoints every 16 swaps let anyone seal leaves into a depth-32 Merkle root, verified against the chain.

latest commitment

n · origin—
leaf—
head—
iv

Accumulator

Members are enrolled, one leaf per address, into a second Merkle tree hashed with Poseidon, which is efficient inside an arithmetic circuit.

v

Witness

The member signs one fixed message. The circuit checks the ECDSA signature, derives the address, proves its inclusion under the root, and outputs a nullifier.

vi

Verification

A verifier contract checks the proof against (root, nullifier, msgHash) on L1 and records the attestation. No trusted setup.

03 · Set explorer

Member set

One instance per committed swap.

fig. 3 · committed swaps, newest firstpublic by construction

04 · Tools

Verify it yourself

Inclusion proof inspector

Resolve a transaction to its leaf, recompute the preimage hash locally, check the chain link, and export a Merkle proof.

no leaf loaded

Hash-chain audit

Replay every Joined event from genesis in this browser and compare the result with hook.head().

idle

Proof verifier

Paste an exported inclusion proof. The path is folded locally and, when deployed, checked against the on-chain root by eth_call.

idle

Anonymity-set calculator

Entropy an attestation retains against an observer with full chain visibility.

anonymity
—
Pr[correct guess]
—
current |S| on-chain
—

05 · Anonymous attestations

Attest as a member

Publish a message on-chain with a proof that its author holds a key in the member set. The contract stores the nullifier and the text; it never sees the key.

    1 · Witness

    Connect the member key and sign the fixed identity message. The signature is held in memory in this tab only.

    2 · Prove

    Enter the message. The prover runs in WebAssembly in this browser; allow up to a minute.

    3 · Submit

    Switch to an unrelated account and submit. Submitting from the member key would link it to the nullifier.

    06 · Shielded swap router

    Buy without linking the payer

    Deposit a fixed amount of ETH against a secret note. Later, a proof that the note matches some deposit lets the router buy CROWD for any recipient. The router can only spend deposits on CROWD; it has no ETH withdrawal. Ordinary swaps through any other router are unaffected.

    denomination
    —
    deposits
    —
    You pay fixed denomination
    —ETH
    Recipient receives estimate
    —CROWD

    Your note

    Generated in this tab at step 1. It is the only way to spend the deposit, and anyone who has it can spend it. Copy it somewhere safe before you leave the page.

    How it stays unlinked

    1. Deposit from any account. Only a commitment to your note goes on-chain.
    2. Wait for other deposits. The anonymity set is the unspent deposits.
    3. Prove in this browser that your note matches some deposit, bound to the recipient and minimum.
    4. Swap from an account unrelated to the deposit. The hook records that account; the recipient is public.

    Limits. A lost note is a lost deposit. Deposits made before trading is enabled cannot be spent until it is. The set is small at first, and a deposit followed quickly by a swap is easy to correlate. The swap can be sandwiched down to the stated minimum. Unaudited.

    07 · Parameters

    Token and pool

    TokenCrowd Protocol, ticker CROWD, 18 decimals.
    Supply1,000,000,000 CROWD, fixed at construction. No mint path.
    Transfer taxNone. Pool swap fee 0.30%.
    TradingEnabled once by the launcher; irreversible.
    Limits0.5% per transfer and 2% per holder at launch; removable only.
    OwnershipLauncher may enable trading and remove limits. No other privileges.
    Hash chainkeccak256, checkpoint interval 16.
    TreesRoll: keccak256, depth 32. Accumulator: Poseidon over BN254.

    Deployments

    Contracts

    • Addresses are published at deployment.

    Unaudited software. Read the verified source before relying on it.

    Figure model: "Wojak NPC Throw" by Vadim Fedenko, CC BY 4.0, recoloured.

    Entering the set

    1. Hold ETH on Ethereum mainnet.
    2. Swap for CROWD through any Uniswap v4 router. Verify the token address above.
    3. The same transaction commits your leaf. No further action is required.
    4. Inspect the transaction in Tools, or create an attestation.