TrueCount is a decentralized commit–reveal voting system built for communities that need fairness, transparency, and verifiable results. No moderators. No tampering. Every vote is private until revealed, and then it is permanently auditable on-chain.
One of our teammates experienced a moment in student body government where a candidate's votes were reduced by half because a moderator believed she violated a subjective rule. The issue wasn't just the penalty — it was how easily one person's judgment could undermine trust in the entire process.
TrueCount was born to fix this. By moving voting on-chain, we eliminate human bias and create a system where trust is placed in code, not moderators.
TrueCount/
├── frontend/ # Next.js React frontend application
├── truecount-backend/ # Hardhat blockchain backend
│ ├── contracts/ # Smart contracts (Solidity)
│ ├── scripts/ # Deployment and utility scripts
│ └── artifacts/ # Compiled contract artifacts
└── README.md
- Commit Phase: Voters submit hashed commitments (votes remain hidden)
- Reveal Phase: Voters reveal their vote + salt, verified against commitment
- Privacy: Votes remain secret during the commit phase
- Transparency: All votes are publicly verifiable after reveal
- 🔐 Wallet Integration - Seamless connection with RainbowKit and wagmi
- 📊 Poll Creation - Customizable options with flexible time windows
- 🤝 Commit Phase - Voters submit hashed commitments (votes remain hidden)
- 🔍 Reveal Phase - Voters reveal their vote + salt, verified against commitment
- ✅ Finalize Phase - Results locked on-chain, transparent forever
- 🎨 Enhanced UX - Countdown timers, phase-aware UI, toast notifications, and comprehensive error handling
- Modern, responsive design
- Real-time phase indicators
- Interactive voting interface
- Live results display
- Toast notifications for user feedback
| Category | Technologies |
|---|---|
| Smart Contracts | Solidity, Hardhat, Ignition |
| Frontend | React, TypeScript, wagmi, RainbowKit, viem |
| UI/UX | TailwindCSS, react-hot-toast, react-countdown |
| Development | Hardhat node for local blockchain simulation |
- Node.js (v18 or higher)
- npm or yarn
- MetaMask or compatible wallet
-
Backend Setup (Blockchain)
cd ../truecount-backend npm install npm run compile npm run node # Start local blockchain
Keep this terminal running - it will be your local blockchain!
-
Deploy Smart Contracts
In a new terminal:
npm run deploy # Deploy smart contracts📋 Important: Copy the deployed contract address from the output and add to NEXT_PUBLIC_CONTRACT_ADDRESS in env
-
Launch Frontend
In another terminal:
cd frontend npm install npm run dev🌐 Open http://localhost:3000 and connect your wallet *We recommend using Metamask (Both web application and blockchain are locally hosted)
createPoll(numOptions, commitSecs, revealSecs)- 🎲 Generate random 32-byte salt client-side
- 🔒 Compute
commitment = keccak256(encodePacked(option, salt, voter, pollId)) - 📤 Call
commit(pollId, commitment)
- 📱 Retrieve
{option, salt}from localStorage - 🔓 Call
reveal(pollId, option, salt) - ✅ Smart contract verifies commitment matches
- 🔐 Call
finalize(pollId)to lock results permanently - 📊 Results become immutable and publicly auditable
The core smart contract implementing the commit-reveal voting scheme:
contract SealedVote {
struct Poll {
uint64 commitEnd; // Commit phase end timestamp
uint8 numOptions; // Number of voting options
address creator; // Poll creator
string title; // Poll title
string description; // Poll description
string[] options; // Voting options
mapping(address => bytes32) commitment; // Voter commitments
mapping(address => bool) revealed; // Reveal status
uint32[] tally; // Vote counts per option
}
}createPoll()- Create a new voting pollcommit()- Submit vote commitmentreveal()- Reveal committed votegetTally()- Get current vote countsgetCommitEnd()- Get commit phase end time
- Votes are encrypted using commitment schemes
- No vote information is visible during commit phase
- Salt values prevent vote enumeration
- Cryptographic verification of vote commitments
- Immutable vote storage on blockchain
- Public verification of vote authenticity
- Only poll creators can create polls
- One vote per address per poll
- Time-based phase enforcement
# Deploy contracts
npm run deploy
# Advance blockchain time (for testing)
npm run advance-time
# Check poll status
npm run check-poll <pollId>
# Create demo poll
npm run create-demo
# Start local blockchain
npm run nodedeploy.js- Deploy smart contractsadvance-time.js- Advance blockchain time for testingcheck-poll.js- Check poll status and detailscreate-demo-poll.js- Create a demo student government poll
cd truecount-backend
npm run create-demoThis creates a student government election poll with:
- 4 candidates
- 1-hour commit phase
- 1 committed vote for demonstration
cd truecount-backend
npm run advance-timeAdvances blockchain time to test phase transitions.
- Components: Reusable UI components
- Hooks: Custom React hooks for blockchain interaction
- Pages: Next.js application pages
- Lib: Utility functions and configurations
- Contracts: Solidity smart contracts
- Scripts: Deployment and utility scripts
- Artifacts: Compiled contract bytecode and ABIs
| Scenario | Benefits |
|---|---|
| Student Body Elections | Eliminate moderator bias, ensure fair counting |
| Club Decision Making | Transparent process, tamper-proof results |
| DAO Governance | Decentralized voting with cryptographic guarantees |
| Community Polls | Build trust through verifiable, on-chain results |
- Deploy to Layer 2 networks (Optimism, Arbitrum, Base) for reduced gas costs
- Enhanced salt management with export/backup functionality
- Mobile-responsive design improvements
- Weighted Voting - Token-based or stake-weighted systems
- Quadratic Voting - Prevent vote buying and encourage genuine preferences
- Multi-signature Poll Creation - Require multiple signatures for high-stakes polls
- Zero-Knowledge Proofs - Enhanced privacy without sacrificing verifiability
- Cross-chain Compatibility - Vote on one chain, verify on another
- Governance Framework - Full DAO tooling integration
We welcome contributions! Please see our Contributing Guidelines for details on how to get started.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Live Demo: [Coming Soon]
- Documentation: Wiki
- Issues: Bug Reports & Feature Requests
- Discussions: Community Forum
If you find TrueCount useful, please consider:
- ⭐ Starring this repository
- 🐛 Reporting bugs or suggesting features
- 💡 Contributing code or documentation
- 📢 Sharing with your community
Built with ❤️ by TrueCount for transparent democracy
"Democracy is not just about voting; it's about trust. TrueCount ensures both."