A private DAO where membership is proven with zero-knowledge proofs. Members show the contract that they hold a valid membership credential, using Polygon ID, without revealing who they are. Each real identity can register exactly one wallet, so the DAO is sybil-resistant without collecting anyone's personal data.
Live app: polygon-id-frontend.vercel.app · Frontend: frontend/ · Credential schemas: schemas/
sequenceDiagram
participant I as Credential issuer
participant W as Polygon ID wallet
participant F as DAO frontend
participant C as ShadowDAO contract
I->>W: ProofOfDaoMembership claim
F->>W: proof request (QR code)
W->>C: zero-knowledge proof
C->>C: verify on-chain, register one wallet per identity
Note over C: member can now propose and vote
- Get a credential. A member receives a
ProofOfDaoMembershipclaim from the issuer into their Polygon ID wallet. The owner gets an owner claim the same way. - Prove it. The frontend shows a QR code with a proof request. The wallet generates a zero-knowledge proof that it holds the claim, and submits it to the contract.
- Verify on-chain.
ShadowDAOinherits Polygon ID'sZKPVerifier, and checks the proof with the credential-query validators (signature and Merkle-tree-proof circuits). Only the proof is verified; the contract never sees the credential's contents. - One identity, one wallet. The contract records the identity's public id against the wallet, so the same person can't register a second address. The owner can revoke a membership, or clear an identity so it can re-register with a new wallet.
- Govern. Anyone can donate to the treasury. Verified members create proposals, with a description and the amount they need, and vote once each within a 500-block window. After the deadline, the owner counts the votes, and a passed proposal is paid from the treasury to its proposer.
Two request ids keep the roles apart: MEMBER_REQUEST_ID registers members, and OWNER_REQUEST_ID hands ownership to whoever proves the owner credential.
| 1. Scan the proof request | 2. Approve in the wallet | 3. Verified |
|---|---|---|
![]() |
![]() |
![]() |
| Folder | |
|---|---|
contracts/ |
The DAO contract, Polygon ID's verifier and validators, and iden3 libraries (Hardhat project at the root) |
frontend/ |
The React app: wallet connection, QR proof requests, proposals, voting, treasury, owner console |
schemas/ |
The ProofOfDaoMembership and ProofOfDaoOwnership credential schemas (JSON and JSON-LD) |
scripts/ |
Deployment and verification scripts |
| File | |
|---|---|
contracts/MainContract.sol |
The DAO: treasury, proposals, voting, membership, and the proof hooks (_beforeProofSubmit, _afterProofSubmit) |
contracts/verifiers/ZKPVerifier.sol |
Polygon ID's on-chain proof verifier and request registry |
contracts/validators/ |
Credential atomic query validators for the signature and MTP circuits |
contracts/lib/ |
Poseidon hashing and genesis-state utilities from iden3 |
Solidity · Hardhat · Polygon ID (iden3 circuits, on-chain ZK verification) · Polygon Mumbai · React frontend with wagmi and RainbowKit
npm install
npx hardhat compile
npx hardhat run scripts/deploy.js --network mumbai
cd frontend && npm install && npm start # the app, http://localhost:3000After deploying, set the proof requests on the contract (setZKPRequest) with the validator address and a schema from schemas/.



