Privacy Developer SDK
The toolkit this site runs on
Membership proof
import * as snarkjs from "snarkjs";
import {
createIdentity, leafOf, MemberTree, scopeOf,
proveEligibility, toBundle, proofCalldata,
} from "@zksium/sdk";
// 1. Member: make an identity, send only the leaf to the gate admin.
const me = createIdentity(); // keep me.secret private
const leaf = leafOf(me);
// 2. Rebuild the gate's tree from its MemberAdded logs (index order)
// and compare tree.root with the contract's currentRoot(gateId).
const tree = new MemberTree(leaves);
const i = tree.indexOf(leaf);
// 3. Prove for a recipient. The scope binds the nullifier to this gate.
const scope = scopeOf(99901, GATE, gateId);
const files = { wasm: "eligibility.wasm", zkey: "eligibility.zkey" };
const p = await proveEligibility(snarkjs, files, me, tree.path(i), scope, recipient);
// 4. Send claimEligibility(gateId, recipient, p.root, p.nullifier, proofCalldata(p.proof))
// from any address, or hand toBundle(p, 99901, GATE, gateId) to a checker.Threshold proof
import { createAttribute, commitmentOf, exportAttribute,
importAttribute, proveThreshold } from "@zksium/sdk";
// Attester: asks the holder for their leaf (never their secret)
const attr = createAttribute(250n, holderLeaf); // value + salt + holder
const c = commitmentOf(attr); // publish: attest(c)
const handout = exportAttribute(attr); // give privately to the holder
// Holder (only the identity behind holderLeaf can prove)
const a = importAttribute(handout);
const p = await proveThreshold(snarkjs, files, a, me, 100n, recipient);
// claimThreshold(gateId, recipient, p.commitment, proofCalldata(p.proof))Check a bundle on Elysium
curl -s https://zksium.xyz/api/verify \
-H 'content-type: application/json' \
--data @zksium-proof.json
# {"valid":true,"block":5527811,"readAt":...}Runs the generated verifier on Elysium's precompiles (eth_call + state override). 30 checks per 10 minutes per network.
Circuits
eligibility.circom · Eligibility(16)
4,326 constraints. Private: secret, 16 path elements, path index. Public: root, scope, recipient; output nullifier = Poseidon(secret, scope). leaf = Poseidon(secret). Up to 65,536 members per gate.
threshold.circom · Threshold()
667 constraints. Private: value, salt, holder secret. Public: commitment = Poseidon(value, salt, Poseidon(holder secret)), threshold, recipient. The attester knows value and salt but not the holder secret, so cannot prove in the holder's place. value and threshold are range-checked to 64 bits.
| File served by this site | What | sha256 |
|---|---|---|
| /circuits/eligibility.wasm | witness generator | 76a0505f2f9038023e912304d8827219e20c6bae616b59870f4f0eb8994b0e4c |
| /circuits/eligibility.zkey | proving key (2.6 MB) | 4f8acedfeb197bef3990fe8aeef49a010ba41e19250de0c10f420b0587170ace |
| /circuits/eligibility.vkey.json | verification key | 1dff35df87dfda715d6773dc274cc37898a262679f4bba8dd9def78d99bc8555 |
| /circuits/threshold.wasm | witness generator | 36fe9664aa0d907edd27750b98d868c1bdab5480f950d1e0d18a9f8e7a54d429 |
| /circuits/threshold.zkey | proving key | c5a15ebb98f7cfbc308cdd5414e196f3e4e1bbe00929c31c78f334e86bf55140 |
| /circuits/threshold.vkey.json | verification key | 23098bfaa05ad122f3bf97c93774bf131ab68e65134dd17bf581865610da6790 |
Contracts
ZksiumProofGate keeps gates, an on-chain Poseidon member tree per eligibility gate (depth 16, last 32 roots accepted), attestations, nullifiers and claims. No owner, no fee, no upgrade, no payable function, no token; it never holds funds. Verifiers are the snarkjs output for the two circuits; the Poseidon hasher is bytecode generated by circomlibjs. Deployed on Elysium on 14 Nov 2026 (gate created at block 6231853). npm run verify-deployment checks all four byte for byte against this build; the three Solidity contracts also have their source verified on the explorer. It is a new contract with no outside security review and a single-contributor setup: try it with nothing of value.
- ZksiumProofGate
- 0x0c0614f14c576065db4e1f19ec560aeebb7cf5d2
- ZksiumEligibilityVerifier
- 0xea29f1477c5d354097ed4b2b515c40e46c9e2b31
- ZksiumThresholdVerifier
- 0xc7785ddf31a20d2ab72e9b868e64bed97032c79e
- PoseidonT3 (circomlibjs)
- 0x1ec77920bc3c559beac5cd393f77499b07ed4ecb
| check* / ClaimRejected code | Meaning |
|---|---|
| 0 | Valid: the contract would record this claim. |
| 1 | No gate with this number. |
| 2 | This proof is for the other kind of gate. |
| 3 | The gate is closed to new claims. |
| 4 | The root is not one of the gate's last 32 roots. |
| 5 | This member already claimed in this gate (nullifier used). |
| 6 | The commitment is not attested by the gate's attester, or the attestation was revoked. |
| 7 | This commitment already claimed in this gate. |
| 8 | This recipient already holds a claim in this gate. |
| 9 | The proof does not verify against these public inputs. |
| 10 | The recipient cannot be the zero address. |
Measured with Foundry: a claim costs about 255,000 to 260,000 gas (Groth16 pairing check included); adding a member costs about 530,000 gas (16 Poseidon hashes on chain); deploying the gate about 2.9 million gas.