Building our first blockchain project: A blockchain voting contract
feranmiodugbemi
Posted on September 6, 2023
We've all heard about the last election done in Nigeria, how there seem to be claims of tampering with election votes, mistakes in counting votes, and so many other excuses, well, that was my motive for building this project๐๐. So, I thought๐ค "How would it feel like if our Nigerian voting system was blockchain-based", then I decided to build the project.
WHY A BLOCKCHAIN VOTING SYSTEM?
In case you're wondering how a blockchain-based voting system solves the problems in our traditional voting system, Let me answer your curious questions. First of all, the blockchain is trustless and decentralized, so no individual has the power to control or manipulate the votes and secondly I just love the idea๐๐.
WHAT WILL I LEARN FROM THIS PROJECT?
You will gain practical experience on how a smart contract works and how it's deployed. You will also implement the knowledge you gained from my last tutorial about solidity keywords.
LFG๐๐๐
BUILDING OUR SMART CONTRACT
First of all, head over to remix. Remix is an online IDE for writing and deploying smart contracts. Create a new file named "Voting.sol
" inside the contracts directory
The blockchain system
The beginning of a new chapter๐
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract VotingSystem{
//The rest of the code goes in here
}
We are initializing a new contract named VotingSystem
that runs on solidity compiler versions of 0.8.9
and above.
Creating our candidates
We will be using the three musketeers of the 2023 Nigerian election๐๐, Atiku, Obi and Tinubu๐.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract VotingSystem{
struct Candidate{
string name;
uint numberOfVotes;
}
mapping(uint => Candidate) candidates;
constructor(){
candidates[0] = Candidate("Tinubu", 0);
candidates[1] = Candidate("Atiku", 0);
candidates[2] = Candidate("Obi", 0);
}
}
Here, we created a Candidate
struct to hold the name
and numberOfVotes
of each candidate. We are mapping a uint
to our Candidate
to keep track of the number of candidates we have and automatically set their number of votes to be 0
.
Voting logic
Let's solve the problem of double voting and vote manipulation
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract VotingSystem{
struct Candidate{
string name;
uint numberOfVotes;
}
mapping (address => bool) voterVoted;
mapping(address => uint) votesPerVoter;
mapping(uint => Candidate) candidates;
constructor(){
candidates[0] = Candidate("Tinubu", 0);
candidates[1] = Candidate("Atiku", 0);
candidates[2] = Candidate("Obi", 0);
voterVoted[msg.sender] = false;
}
modifier notVoted {
require(!voterVoted[msg.sender] || votesPerVoter[msg.sender] == 0, "You have already voted");
_;
}
}
We created two mappings, voterVoted
is to check if an address has already voted for a candidate before and returns a boolean while votesPerVoter
ensures that an address is given just 1 chance to vote. The modifier
is used for implementing all the logic and will be used in a Vote function.
Vote function
Let's vote for the right candidate
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract VotingSystem{
// The code we've written earlier
function vote(string memory _nameofCandidate) public notVoted returns (string memory) {
bytes32 nameHash = keccak256(abi.encodePacked(_nameofCandidate));
bytes32 tinubuHash = keccak256(abi.encodePacked("Tinubu"));
bytes32 atikuHash = keccak256(abi.encodePacked("Atiku"));
bytes32 obiHash = keccak256(abi.encodePacked("Obi"));
if (nameHash == tinubuHash){
candidates[0].numberOfVotes++;
} else if(nameHash == atikuHash){
candidates[1].numberOfVotes++;
} else if(nameHash == obiHash){
candidates[2].numberOfVotes++;
}else {
revert("Invalid candidate name");
}
voterVoted[msg.sender] = true;
string memory Text = "You have already casted your vote";
votesPerVoter[msg.sender]++;
return Text;
}
}
This is our vote function which is used for casting votes, it takes in the nameOfCandidate
that the address is voting for. Since Solidity cannot compare two strings together so we generated a hash of our Candidate
's name and the _nameofCandidate
using the keccak256 algorithm and compares them, so whichever Candidate
's name matches the _nameofCandidate
their vote count is increased by one else it reverts to Invalid candidate name.
Getting our candidate's votes
After voting, we want to make sure that the right candidate is leading๐.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract VotingSystem{
// Earlier written code
function getVotes() public view returns( Candidate[] memory){
Candidate[] memory candidateList = new Candidate[](3);
candidateList[0] = candidates[0];
candidateList[1] = candidates[1];
candidateList[2] = candidates[2];
return candidateList;
}
}
This function allows anyone to retrieve the vote counts for all Candidates and returns it in an array format.
Deploying our contract
It's time to unleash our project to the world๐
Go ahead and click on that compile button to compile the solidity smart contract on the solidity compiler page
So, remix gives us 15 addresses with 100 fake ETH to test our smart contracts on different Ethereum test networks. Now, we will be deploying our contract to one of those addresses. Click on the Deploy button to deploy our contract. The address after AT is called the contract address, We can use it to interact with our contract using a client library like web3.js, ethers.js, web3.py, etc.
Conclusion
In conclusion, our journey through the development of a blockchain-based voting system has been both informative and entertaining. We embarked on this project with the aim of addressing the challenges and concerns surrounding traditional voting systems, particularly in Nigeria. The issues of vote tampering, counting errors, and other excuses that have plagued past elections served as the catalyst for this endeavor ๐๐.
By creating a blockchain voting system, we have introduced a trustless and decentralized approach, where no single entity can manipulate or control the votes. This not only provides transparency but also safeguards the integrity of the electoral process. And let's not forget, we did it because, well, we just love the idea ๐๐.
Throughout this journey, you've had the opportunity to gain practical experience in working with smart contracts and deploying them. You've also applied the knowledge from our previous tutorial on Solidity keywords, further enhancing your blockchain development skills.
So, as we wrap up this adventure, I hope you've not only enjoyed the journey but also gained valuable insights into building your first blockchain project and deploying it successfully. With your newfound skills, you're well-equipped to explore more exciting possibilities in the world of blockchain technology. Until next time, happy coding! ๐๐๐
Posted on September 6, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.