A secure and transparent electoral voting system built with Solidity and Foundry for Ethereum-based blockchains.
- Candidate Registration: Admin can register candidates with name and party affiliation
- Voter Registration: Admin can register eligible voters
- Secure Voting: Registered voters can cast one vote for their preferred candidate
- Voting Lifecycle: Start and end voting periods with admin controls
- Results & Winner: Query election results and determine the winner
- Event Logging: All major actions emit events for transparency
- Comprehensive Testing: Full test suite with unit and fuzz tests
electoral-system/
├── src/
│ └── ElectoralSystem.sol # Main contract
├── test/
│ └── ElectoralSystem.t.sol # Comprehensive test suite
├── script/
│ ├── Deploy.s.sol # Deployment script
│ ├── SetupElection.s.sol # Setup candidates and voters
│ ├── StartVoting.s.sol # Start voting period
│ ├── CastVote.s.sol # Cast a vote
│ └── EndVotingAndResults.s.sol # End voting and show results
├── foundry.toml # Foundry configuration
└── README.md # This file
## Test Coverage
Coverage was measured using `forge coverage`.
Note:
- Deployment and interaction scripts under `/script` are excluded from evaluation
- Core contract logic under `/src` has ~99% line and statement coverage
- Foundry installed
- An Ethereum wallet with some ETH for gas fees (for deployment)
- Clone the repository:
git clone <your-repo-url>
cd electoral-system- Install dependencies:
forge install- Build the project:
forge buildRun all tests:
forge testRun tests with verbosity:
forge test -vvvRun specific test:
forge test --match-test test_Vote -vvvRun with gas report:
forge test --gas-reportRun coverage:
forge coverage- Start a local Ethereum node:
anvil- In a new terminal, deploy the contract:
forge script script/Deploy.s.sol:DeployElectoralSystem --rpc-url http://localhost:8545 --broadcast --private-key <YOUR_PRIVATE_KEY>- Set up environment variables in
.env:
PRIVATE_KEY=your_private_key_here
SEPOLIA_RPC_URL=your_sepolia_rpc_url
ETHERSCAN_API_KEY=your_etherscan_api_key- Load environment variables:
source .env- Deploy to Sepolia:
forge script script/Deploy.s.sol:DeployElectoralSystem --rpc-url $SEPOLIA_RPC_URL --broadcast --verifyAfter deployment, set the ELECTORAL_ADDRESS environment variable:
export ELECTORAL_ADDRESS=<deployed_contract_address>Run the setup script to register candidates and voters:
forge script script/SetupElection.s.sol:SetupElection --rpc-url http://localhost:8545 --broadcastforge script script/StartVoting.s.sol:StartVoting --rpc-url http://localhost:8545 --broadcastSet the candidate ID and voter's private key:
export CANDIDATE_ID=1
forge script script/CastVote.s.sol:CastVote --rpc-url http://localhost:8545 --broadcast --private-key <VOTER_PRIVATE_KEY>forge script script/EndVotingAndResults.s.sol:EndVotingAndResults --rpc-url http://localhost:8545 --broadcastregisterCandidate(string name, string party)- Register a new candidateregisterVoter(address voter)- Register a voterstartVoting()- Start the voting periodendVoting()- End the voting period
vote(uint256 candidateId)- Cast a vote for a candidate
getCandidate(uint256 candidateId)- Get candidate detailsgetVoter(address voter)- Get voter detailsgetWinner()- Get the winning candidate (only after voting ends)getAllCandidates()- Get all candidatesgetResults()- Get complete election results
event CandidateRegistered(uint256 indexed candidateId, string name, string party);
event VoterRegistered(address indexed voter);
event VoteCast(address indexed voter, uint256 indexed candidateId);
event VotingStarted();
event VotingEnded();
event WinnerDeclared(uint256 indexed candidateId, string name, uint256 voteCount);- Only the admin (contract deployer) can register candidates and voters
- Voters must be registered before voting starts
- Each voter can only vote once
- Voting is only allowed during the active voting period
- Results can only be queried after voting ends
The contract uses efficient data structures and includes:
- Indexed events for efficient filtering
- Minimal storage updates
- Efficient loops in view functions
The test suite includes:
- Constructor tests
- Candidate registration tests
- Voter registration tests
- Voting lifecycle tests
- Vote casting tests
- Results and winner calculation tests
- Access control tests
- Fuzz tests for edge cases
Potential improvements for future versions:
- Multi-admin support with role-based access control
- Time-based automatic voting period management
- Weighted voting systems
- Anonymous voting with zero-knowledge proofs
- Integration with identity verification systems
- Vote delegation features
- Multi-round elections
MIT License
Contributions are welcome! Please feel free to submit a Pull Request.
For issues, questions, or contributions, please open an issue in the GitHub repository..