Skip to content
Lattice

IPrivateVoting

Git Source

Title: IPrivateVoting

Author: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80)

External interface for anonymous one-person-one-vote polling. A poll is bound to a Semaphore group (the electorate); a member casts a ballot with a Semaphore proof whose scope is the poll id and whose message is the vote choice. The scope-bound nullifier gives each member exactly one vote per poll while keeping the vote anonymous.

Composes the ISemaphore module: voting reuses that group's membership + the audited verifier for the zero-knowledge check, and keeps its OWN per-poll nullifier set for double-vote protection (so voting nullifiers never collide with general Semaphore signalling). This is 1-person-1-vote, NOT token-weighted: private weighted voting needs a bespoke circuit and is out of scope. The ISemaphore module must be present in the same diamond and its groups created there; proof.scope MUST equal the poll id.

Functions

createPoll

Creates a poll over groupId. Only the group admin may create polls for it.

function createPoll(uint256 groupId, uint32 numChoices, uint64 startTime, uint64 endTime)
        external
        returns (uint256 pollId);

Parameters

NameTypeDescription
groupIduint256The Semaphore group whose members may vote.
numChoicesuint32Number of options (>= 2).
startTimeuint64Unix time voting opens (0 = immediately).
endTimeuint64Unix time voting closes (0 = never).

Returns

NameTypeDescription
pollIduint256The new poll id (1-based); voters must use this as the Semaphore scope.

vote

Casts an anonymous ballot in pollId. proof.scope must equal pollId and proof.message is the chosen option; the nullifier prevents a second ballot.

function vote(uint256 pollId, ISemaphore.SemaphoreProof calldata proof) external;

Parameters

NameTypeDescription
pollIduint256The poll to vote in.
proofISemaphore.SemaphoreProofThe Semaphore proof of membership binding the choice + poll.

pollCount

Returns the number of polls created.

function pollCount() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256

getPoll

Returns the public configuration of pollId.

function getPoll(uint256 pollId) external view returns (PollView memory);

Parameters

NameTypeDescription
pollIduint256

Returns

NameTypeDescription
<none>PollView

getVotes

Returns the vote count for choice in pollId.

function getVotes(uint256 pollId, uint256 choice) external view returns (uint256);

Parameters

NameTypeDescription
pollIduint256
choiceuint256

Returns

NameTypeDescription
<none>uint256

hasVoted

Returns whether nullifier has already voted in pollId.

function hasVoted(uint256 pollId, uint256 nullifier) external view returns (bool);

Parameters

NameTypeDescription
pollIduint256
nullifieruint256

Returns

NameTypeDescription
<none>bool

Events

PollCreated

Emitted when a poll is created.

event PollCreated(
        uint256 indexed pollId,
        uint256 indexed groupId,
        address indexed creator,
        uint32 numChoices,
        uint64 startTime,
        uint64 endTime
    );

Parameters

NameTypeDescription
pollIduint256
groupIduint256
creatoraddress
numChoicesuint32
startTimeuint64
endTimeuint64

VoteCast

Emitted when a ballot is counted. nullifier is the public, scope-bound tag (not linkable to an identity); choice is the counted option.

event VoteCast(uint256 indexed pollId, uint256 indexed choice, uint256 nullifier);

Parameters

NameTypeDescription
pollIduint256
choiceuint256
nullifieruint256

Errors

PrivateVotingPollDoesNotExist

Thrown when the poll id does not exist.

error PrivateVotingPollDoesNotExist();

PrivateVotingNotGroupAdmin

Thrown when the caller is not the admin of the poll's Semaphore group.

error PrivateVotingNotGroupAdmin();

PrivateVotingInvalidNumChoices

Thrown when creating a poll with fewer than two choices.

error PrivateVotingInvalidNumChoices();

PrivateVotingInvalidTimeWindow

Thrown when endTime is set and is not after startTime.

error PrivateVotingInvalidTimeWindow();

PrivateVotingNotOpen

Thrown when voting before startTime.

error PrivateVotingNotOpen();

PrivateVotingClosed

Thrown when voting after endTime.

error PrivateVotingClosed();

PrivateVotingScopeMismatch

Thrown when proof.scope is not the poll id (the ballot is for a different poll).

error PrivateVotingScopeMismatch();

PrivateVotingInvalidChoice

Thrown when proof.message (the choice) is >= numChoices.

error PrivateVotingInvalidChoice();

PrivateVotingInvalidProof

Thrown when the Semaphore membership proof does not verify.

error PrivateVotingInvalidProof();

PrivateVotingAlreadyVoted

Thrown when the proof's nullifier has already voted in this poll.

error PrivateVotingAlreadyVoted();

Structs

PollView

A poll's public configuration (the per-choice tally is read via getVotes).

struct PollView {
        uint256 groupId;
        uint32 numChoices;
        address creator;
        uint64 startTime;
        uint64 endTime;
        uint256 totalVotes;
    }

Properties

NameTypeDescription
groupIduint256The Semaphore group whose members may vote.
numChoicesuint32Number of valid options; votes use 0 .. numChoices-1.
creatoraddressThe group admin who created the poll.
startTimeuint64Unix time voting opens (0 = open immediately).
endTimeuint64Unix time voting closes (0 = never closes).
totalVotesuint256Total ballots cast.