Notes for voters, officials, and people deciding whether to host a node. This is not a lending protocol. There is nothing to deposit.
ZK-Voting is a not-for-profit, open-source way for a group to run its own elections and polls. A civic election is one person, one vote, and the choice is designed to stay unpublished. Separately, a host can run an advisory token signal on Ethereum mainnet. That signal is not a civic election: weight comes from an ERC-20 at one finalized block, there is no registration, signing is free, and the choice stays public.
These pages follow the landing page. They explain how a poll differs from a vote, what is public, what is designed to stay private, and how a group hosts its own node. They are not a promise that a deploy satisfies an elections statute.
Markets, liquidations, reserve auctions, incentive programs, and price buckets are not part of ZK-Voting. If a page asks you to deposit or to buy a token, it is not this project.
Short definitions. They match the landing page, and they leave out anything this project does not do.
Definitions are simplified and may not be a complete specification.
Civic election
One person, one vote, with registration and a secret ballot.
Token signal
An advisory poll weighted by an ERC-20 at one finalized Ethereum block. There is no registration, and the choice stays public. It does not use the civic L2.
Poll
A civic contest that publishes per-choice counts on a delayed hourly schedule after a gate. Turnout uses that same hourly schedule.
Vote
A civic contest that keeps choices sealed until the deadline. Turnout is published on a delayed hourly schedule. There are no interim per-choice counts.
Roll
The eligible set for one election. It stores identity commitments, not names, wallet addresses, or document numbers.
Identity commitment
The value written on the roll. It is not a wallet address and not a document number.
Re-vote
The operator decides at creation whether re-voting is allowed, and that setting can't be changed afterward. If it is allowed, the last ballot before the deadline counts. If not, a second ballot is rejected.
Gate
For a poll, choice counts stay hidden until 100 voters have cast their first ballot, or the scheduled end arrives, whichever comes first.
Hourly block
A published slice of a poll's per-choice counts. An hour with fewer than 10 ballots merges forward until a block has at least 10. A published block is designed to stay as first published.
Receipt
Evidence that a ballot was accepted. It is hashes, designed so it doesn't show how you voted.
Guardian
One of the k-of-n parties who can decrypt a vote only as an aggregate at the deadline. The design gives the operator no key share.
Civic L2
A purpose-built sequencer and prover a group runs for its own elections. It settles batches to Ethereum. It is not a general-purpose chain.
Election UUID
The public id of one election, unique within that L2. Ethereum keys a batch by hash of the L2 id and this UUID.
Mock verifier
The stand-in used in tests for a real proof check. With it, rejection of a voter who is not pre-approved is not yet enforced.
What the project is, what it costs, and what it refuses to claim.
What is ZK-Voting?
A not-for-profit, open-source voting system any group can run itself. Zero-knowledge proofs are designed to show that only eligible people voted, each one once, and that the published tally matches the ballots. Tests currently use a mock verifier. Individual choices are designed not to be published.
What are the key features?
Self-hosting, and one person, one vote on a civic election. A separate advisory token signal that is not a secret ballot. Polls with delayed hourly choice counts after a gate, and votes that stay sealed until the deadline. Public registration and disqualification codes. Receipts that are hashes. An AGPL license, no fee for voters, and no product token.
Who is it for?
Any body that needs a roll, a ballot, and a result people can check: cities, counties, unions, cooperatives, boards, schools, clubs, and observers.
What are the fees?
Voters are not charged. There is no deposit, no origination fee, and no interest. A host pays for its own servers. On the civic L2, the operator's minimally funded Ethereum key pays to submit batches. On a token signal, signing a ballot is free. Delegating that token is the transaction that costs gas.
Has it been audited?
Not as a finished system. The code is public under AGPL-3.0-or-later. Tests use a mock verifier, the first proving path is in progress, and the trusted-setup ceremony has not happened. There is no paid bug-bounty program.
What if this website goes down?
This website only explains the project. A group's election runs on the node that group hosts. The software is open source, so someone else can serve the same pages from the repository. A node can also stay on a private network.
Does anyone control every election?
No. Each group runs its own node and owns its roll. Officials on that node create elections, freeze the roll, record disqualifications, and post the tally. Those jobs are not a back door that publishes choices.
A contest with a roll and a ballot. Not a liquidity pool.
What is an election here?
A contest with a roll, a ballot, and a published result. When it is created, the operator chooses a poll or a vote, and whether re-voting is allowed. That setting can't be changed afterward.
Can one node run many elections?
Yes. One civic L2 can hold any number of elections. Anyone can run a civic L2, and there is no limit on how many exist.
How is an election identified?
By an election UUID, unique within that L2. Batches settled to Ethereum are keyed by hash of the L2 id and the election UUID, so two groups do not share a record just by reusing a name.
Can districts be nested?
Yes. A city, county, or district can run elections and referendums with nested districts, measures, and articles. That structure lives on the group's roll. It is not a separate chain.
Joining a roll. Nothing is deposited and nothing is lent.
How does someone join a civic election?
They register with a passkey, a wallet, email, or an ID. The roll stores an identity commitment. Registering for one election does not enroll someone in every contest on the node.
What is stored on the roll?
An identity commitment. Not a name, not a wallet address, and not a document number.
Is registration a deposit?
No. Nothing of value is locked, escrowed, or lent. There is no collateral and no price bucket.
Does a token balance put me on the roll?
Not for a civic election. A token signal is separate: holding the chosen ERC-20 at one finalized block is the credential, there is no sign-up, and the choice stays public.
Marking a choice and proving you were allowed to mark it.
How is a ballot cast?
The voter marks a choice and submits a proof designed to show they are on the frozen roll and not disqualified. Voters are not charged for that submission.
Can I change my vote?
Only if the operator allowed re-voting when the election was created. The operator decides at creation whether re-voting is allowed, and that setting can't be changed afterward. If it is allowed, the last ballot before the deadline counts. If not, a second ballot is rejected.
What does the proof show?
That an eligible person voted, once, in the way that election allows, and that the ballot is well formed. It is designed not to show which option was marked. With the mock verifier in tests, this check is not yet enforced.
What do I get back?
A receipt of hashes, designed so it doesn't show how you voted. Every ballot, including a re-vote, gets one.
A civic contest that can show running choice counts, on a delay, after a gate.
What is a poll?
A civic contest that publishes per-choice counts on a delayed hourly schedule after a gate. Turnout is published on a delayed hourly schedule for both a poll and a vote.
When do choice counts appear?
Once 100 voters have cast their first ballot, or at the scheduled end, whichever comes first. Each hour publishes 30 minutes after it closes.
What if an hour is small?
An hour with fewer than 10 ballots merges forward until a block has at least 10.
Do published hourly blocks change?
No. Published hourly blocks are designed to stay as first published. If re-voting was allowed, replacement ballots show up only in the final tally.
A civic contest whose choices stay sealed until the deadline.
What is a vote?
A civic contest that keeps choices sealed until the deadline. Turnout is published on a delayed hourly schedule. There are no interim per-choice counts.
When can choices be read?
At the deadline, and only as an aggregate. Choices are encrypted to a public key posted on the L2. The matching private key is split among the guardians with Shamir secret sharing, designed so no single party, including the operator, can decrypt early. The design gives the operator no key share.
Why choose a vote instead of a poll?
When a running choice count would add pressure. Nothing a voter is given is designed to prove their choice to someone pressuring them.
Can a vote be ranked choice?
Yes, as an opt-in. Ranked choice is also available in polls. In a sealed vote, guardians then see individual rankings, not identities.
What is visible while a contest is open, and what is posted after the deadline.
What is published while a contest is open?
Turnout is published on a delayed hourly schedule for both kinds. A poll also publishes per-choice counts on that schedule once 100 voters have cast their first ballot, or at the scheduled end, whichever comes first. A vote publishes choices only at the deadline.
What happens at the deadline?
No more ballots are accepted. One final batch goes to Ethereum at the deadline. A challenge window, which must be longer than zero, comes before the final tally.
What is the supplementary batch?
After the grace period, anyone may post a missing final batch and the supplementary batch, before the final tally.
Does the tally carry out the decision?
No. Passing a vote never auto-executes anything. Outcomes are verifiable. Acting on them stays with the people.
How can an outsider check?
Anyone can check that the published totals match the accepted ballots. An independent auditor is designed to be able to rebuild a published result without the operator's private database. Until a real aggregate verifier is in place, the tally is checked by summing ciphertexts on chain.
The choice is the secret. The process is the public part.
What is designed to stay private?
The option on a civic ballot. It is designed never to be a readable field in a transaction or a database. Receipts are hashes, designed so they don't show how you voted.
What is public?
Registrations and disqualification codes are public. Turnout is published on a delayed hourly schedule for both kinds. A poll also publishes per-choice counts on that schedule once 100 voters have cast their first ballot, or at the scheduled end, whichever comes first. The final tally is public too.
Why wait to publish turnout?
So leaving a polling place cannot be matched to a live tick. The delay is the hourly schedule. Counts are not padded.
Is a token signal private?
No. In a token signal the choice stays public. Secret ballots are the civic election.
The group that hosts the node owns the roll. Officers have jobs, not a master key.
Who operates a node?
The group that hosts it. They own the node, the roll, and the record. No vendor account is required to start, and there is no vendor lock-in.
What do officials do?
They create the election and the ballot, freeze the roll, approve registration, record a disqualification with a public reason code, and post the tally after the deadline. A host can also publish its own pages.
Can an officer read how people voted?
That is not the design. A vote's choices are encrypted to the guardian key, and the operator has no key share. A poll publishes aggregates. Officials do not get a private live feed of choices.
Barring someone is a public, coded change. It is not a silent flag.
Why might a registered person be barred?
Registered is not the same as eligible. An official can bar someone for a stated reason code, for example not of age, not resident, a duplicate, or a court order. The code is public so a purge cannot hide.
Where does the evidence go?
Personal evidence stays off the chain. The public record is the reason code and a hash of the evidence, so a later review can match a sealed file to what was posted.
Can a barred person vote anyway?
No. The eligible set is people who are registered and not currently disqualified. The proof is designed to require membership in that set. With the mock verifier in tests, this check is not yet enforced.
Proof that you voted. Not proof of the option you marked.
What is on a receipt?
Hashes that show a ballot was accepted. Enough to look it up, not the option that was marked. If a screen says which option you chose, that is a bug.
How do I check that it counted?
On the node that ran the election, open the receipt page and paste the proof, or use the file the node gave you. The check answers whether that ballot was accepted. It does not show a candidate.
Can someone demand my receipt as proof of my choice?
A receipt is designed so it doesn't show how you voted. It cannot satisfy someone who demands proof of a choice. That refusal is intentional.
There is no project token, no reward for voting, and nothing to deposit.
Is there a ZK-Voting token?
No. There is no product token, no paid tier, and no reward for voting. The license is AGPL-3.0-or-later. The repository is not a way to make money.
Then what is a token signal?
An optional advisory mode on Ethereum mainnet. The host picks an existing ERC-20. Weight comes from that token at one finalized block. Delegated voting power is read there. It is not a secret ballot, it does not use the civic roll, and the result does not execute anything.
Are there incentive programs or liquidity pools?
No. There is nothing to deposit, lend, borrow, liquidate, or auction. Do not send funds to anyone who announces a token sale under this name.
Civic ballots settle to Ethereum. There is no bridge between lending markets, because there are no lending markets.
Where do civic ballots land?
On the group's civic L2, a purpose-built sequencer and prover. Final batches settle to Ethereum so the record outlives any single operator. Day-to-day activity is not a general-purpose chain, and it does not bridge deposits.
Where do token signals land?
On Ethereum mainnet only. That mode needs an Ethereum mainnet RPC. It does not use the civic L2.
Is there one list of official contract addresses?
No single global deployment is published here as a table to copy. Each group pins the contracts its own node uses. The demo node is for trying the software, not for a production election.
Can results be rebuilt if a node disappears?
Settling to Ethereum is what makes that possible. Results are designed to be rebuilt from the L2's data or from the L1 record. An unproven root publishes nothing and can roll back after a timeout.
Many independent civic L2s. One shared record on Ethereum.
What is the large picture?
Anyone can run a civic L2, and there is no limit on how many exist. Each L2 can hold any number of elections. Every L2 settles its vote batches to Ethereum, keyed by hash of the L2 id and the election UUID.
What happens inside one L2?
Voters at the edge vote for free. Only pre-approved voters are accepted. The sequencer batches the votes. The L2 computes the state root and the tally. L1 commits that root hourly and is designed to check a proof of the computation later, in order. Until a real aggregate verifier is in place, the tally is checked by summing ciphertexts on chain.
Where is the diagram?
The home page draws it: a macro view of many L2s, an L2 view of one election team, and the path a poll and a vote take to the final tally. Those figures are the protocol diagram.
What is true on this development line, and what a tally will not start doing later.
What is true today?
You can read this site and try the voting demo. Tests use a mock verifier. The trusted-setup ceremony has not happened. Do not use it for a binding election today.
What is the proving path?
A real proof check is in progress. With the mock verifier in tests, rejection of a voter who is not pre-approved is not yet enforced. Do not describe a local demo as ready for a binding election.
What will a result not do?
It will not auto-execute. The tally is evidence. Acting on it stays with the people. The project will also not add a product token or a fee for voters.
The repository is the starter kit. Fork it, and keep the not-for-profit label.
What is in the repository?
The node, the civic L2, the contracts, and the circuits, together, under AGPL-3.0-or-later. A group is not meant to depend on a vendor's private build. Fork it and keep the not-for-profit label.
What should I read first?
The README at the root of the repository, then the self-hosting guides. Every running node serves those guides at /docs.
What does AGPL ask of a host?
If you run a modified node as a network service, offer the corresponding source to the people who use that service.
Run the node yourself. Do not deploy a pool, a bridge, or a token sale. Those pieces are not in this software.
How do I start a node?
From a checkout, copy the example environment file, then start the stack. The node answers a health check. This website is only the explanation. It is not the node.
# run your own node
cp .env.example .env
docker compose up -d --build
curl -fsS http://127.0.0.1:3000/health
Which platforms?
Docker Compose, Coolify, Dokploy, or CapRover. The node can stay private behind a Tailscale sidecar.
What should I not deploy?
Do not deploy a lending pool, a bridge for deposits, or a token sale. This software does not include them. Pin the contracts for that group's node, and do not treat the demo as a finished ceremony.