A decentralized voting system built with Solidity, Hardhat, and Node.js that enables transparent and immutable elections on the blockchain.
- β Add candidates (owner only)
- β Vote (each user votes only once)
- β List all candidates
- β Get election winner
- β Complete RESTful API
- β Web3.js integration
- Solidity ^0.8.19 - Smart contracts
- Hardhat ^2.19.0 - Development framework
- Web3.js ^1.10.0 - Blockchain interface
- Express.js - Backend server
- Node.js - Runtime environment
- Node.js 16+
- npm or yarn
- MetaMask (for Sepolia network testing)
git clone https://github.com/brunofullstack/blockchain-voting-system.git
cd blockchain-voting-systemnpm installCreate a .env file in the project root:
PRIVATE_KEY=your_metamask_private_key
SEPOLIA_URL=https://sepolia.infura.io/v3/your_infura_key
BLOCKCHAIN_URL=http://localhost:8545
PORT=3000blockchain-voting-system/
βββ contracts/
β βββ Voting.sol # Smart contract
βββ scripts/
β βββ deploy.js # Deployment script
βββ artifacts/ # ABI and bytecode (generated)
βββ contract-info.json # Contract info (generated)
βββ hardhat.config.js # Hardhat configuration
βββ server.js # Backend server
βββ .env # Environment variables
βββ package.json
# Compile contracts
npm run compile
# Start local Hardhat network
npm run node
# Deploy contract
npm run deploy
# Start backend server
npm run server
# Run tests
npm run testAdd a new candidate (owner only)
Body:
{
"name": "Candidate Name",
"privateKey": "0x..."
}Get list of all candidates
Response:
[
{
"id": "1",
"name": "Candidate A",
"voteCount": "5"
}
]Cast a vote for a candidate
Body:
{
"candidateId": 1,
"privateKey": "0x..."
}Get the winning candidate
Response:
{
"id": "1",
"name": "Candidate A",
"voteCount": "10"
}npm run nodenpm run deploynpm run serverAdd candidate:
curl -X POST http://localhost:3000/candidates \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "privateKey": "0x..."}'List candidates:
curl http://localhost:3000/candidatesVote:
curl -X POST http://localhost:3000/vote \
-H "Content-Type: application/json" \
-d '{"candidateId": 1, "privateKey": "0x..."}'Get winner:
curl http://localhost:3000/winner- Only contract owner can add candidates
- Each address can vote only once
- Transactions are validated on blockchain
- Votes are immutable and transparent
- Configure your
PRIVATE_KEYandSEPOLIA_URLin.env - Deploy contract:
npx hardhat run scripts/deploy.js --network sepolia- Update
contract-info.jsonwith the new address
function addCandidate(string memory _name) public onlyOwner
function vote(uint256 _candidateId) public
function getCandidates() public view returns (Candidate[] memory)
function getWinner() public view returns (Candidate memory)CandidateAdded(uint256 candidateId, string name)Voted(address voter, uint256 candidateId)
Tests ensure that:
- Only owner can add candidates
- Users can vote only once
- Winner is calculated correctly
- Voting can be opened/closed
- Fork the project
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Bruno Fullstack - brunofullstack@gmail.com
Project Link: https://github.com/brunofullstack/blockchain-voting-system
- OpenZeppelin for base contracts
- Hardhat team for excellent framework
- Ethereum community for the ecosystem