Silent Council
Private NITK voting on Ethereum
Created on 23rd August 2026
•
Silent Council
Private NITK voting on Ethereum
The problem Silent Council solves
Problem
Campus votes today run on Google Forms and WhatsApp. Identity leaks. Counts can be changed.
What Silent Council does
NITK students prove they own an allowed email without putting the email onchain, then vote once per proposal. The tally is public on Base Sepolia.
- Verify with zk.email (or email OTP fallback if the prover is slow).
- Hide identity: the chain stores a nullifier (hash), not the email.
- Vote Yes / No / Abstain. Double votes are rejected onchain.
Production would accept only @nitk.edu.in. This judging demo also allows @gmail.com.
Try it
- Live app: https://silent-council-six.vercel.app
- Code: https://github.com/lakshay196/silent-council
- Contract (Base Sepolia):
0x4838024E8611d4E67fe6B9f6f43559A7e0971130
What we built: voting contract, issuer signatures, APIs, UI.
What we use: zk.email, EAS, RainbowKit.
Challenges we ran into
Issuer key vs address
We first stored a wallet address as ISSUER_PRIVATE_KEY. Signing failed until we used the real 64-character hex key on Vercel.
Unique vs alias URLs
CLI deploys created one-off Vercel URLs that never updated. We always demo https://silent-council-six.vercel.app.
One mock email for every wallet
Early mock verify used the same demo email, so the second wallet hit already_verified without being registered. We switched to a unique mock email per wallet.
Onchain vs database
The UI could show verified from the contract while /api/vote only checked Supabase. Vote now recovers the nullifier from chain if the row is missing.
Honest ZK vs OTP
Live demo uses a fast verify path plus OTP fallback. OTP is not zero-knowledge. We say that in the README and in the pitch.
Tracks Applied (1)