Manual recounts and audit gaps erode trust.
Voters should not have to accept a result without a clear record of how it was produced.
Campus elections need results students can inspect without exposing who voted. This system keeps eligibility off-chain, records sealed ballots on a permissioned Ethereum chain, and publishes final events through a public audit view.
Voters should not have to accept a result without a clear record of how it was produced.
The codebase supports configurable 1 to 4 node Clique/geth deployment
around the ElectionManager contract. Wallets register through
signed eligibility proofs, and no PII is stored on-chain.
IRB exemption approved for the usability/mock-election study. The study focuses on task completion, usability, and perceived trust across the voter, admin, and audit workflow.
The complete one-node laptop deployment covers authentication, wallet registration, commit, reveal, admin finalization, and public audit. A configurable 1 to 4 node deployment path is documented.
The workflow moves through four stages: identity, sealed ballot, reveal and tally, then public audit. Each stage has a clear boundary.
Auth service issues a signed eligibility proof tied to the student's Earlham email. No campus identity ever lands on-chain.
The wallet signs a salted vote hash. The ballot is locked on-chain but unreadable, even to validators, until the reveal phase opens.
After voting closes, voters reveal the salt. The contract verifies each reveal against the stored hash. Clique validators seal blocks.
Admin finalizes the election. The audit view exposes contract events, tallies, and receipt checks without revealing campus identity.
Identity, voter interface, smart contract state, and public audit stay separate. Validators seal blocks; the contract enforces registration, commit, reveal, finalization, and tally reads.
Off-chain only. The auth service binds Earlham email to wallet through a signed eligibility proof. No campus identity crosses the chain boundary.
React DApp + MetaMask. Signs registration, commit, and reveal transactions. Browser-side only.
Configurable 1 to 4 node Clique/geth deployment. ElectionManager
handles register, commit, reveal, and finalize. Validators only seal.
A read-only audit API indexes contract events. Dashboards verify on-chain state without touching the vote pathway.
The implementation combines Solidity, Hardhat, React, MetaMask, Node/JWT services, a read-only audit API, and configurable geth/Clique deployment support.
Mitigations are split between the protocol, the contract, and the deployment: commit-reveal ballots, one-commit-per-address rules, role-gated finalization, Clique consensus, and monitoring.
| Threat | Mitigation | Severity | Status |
|---|---|---|---|
| Double-voting | One-commit-per-address constraint enforced in ElectionManager; on-chain reverts on retry. |
High | ● Implemented |
| Identity spoofing | Signed eligibility proof tied to campus email; expiry; domain restriction; one-time use. | High | ● Implemented |
| Vote coercion / selling | Commit-reveal: the ballot is unreadable on-chain until the voter reveals; no proof-of-vote is exposed during voting. | Medium | ● Protocol-level |
| Premature result disclosure | Reveals only accepted after voting window closes; enforced by contract state machine. | Medium | ● Implemented |
| Reentrancy / overflow | OpenZeppelin patterns; Solidity 0.8 checked arithmetic; focused tests cover role, timing, registration, commit, reveal, and finalization paths. | High | ● Tested locally |
| Rogue validator | Validators in Clique PoA only seal blocks. They do not tally. Tallying is a contract function gated by reveal-phase state. | Medium | ● Consensus |
| Client-side key compromise | MetaMask custody; the DApp never sees raw key material; transaction-level signing only. | Medium | ● Architecture |
| Full STRIDE / formal review | Future review scope. | Planned | ◌ Future work |
The technical report, source repository, final visuals, and demo walkthrough are linked below.