Building our first blockchain project: A blockchain voting contract
Tags: solidity, web3, blockchain, beginners
Published: 2023-09-06 00:08:07

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](https://dev.to/feranmiodugbemi/unlock-the-power-of-solidity-exploring-the-essential-keywords-for-smart-contract-development-1mbf) about solidity keywords.

LFG🚀🚀🚀

## BUILDING OUR SMART CONTRACT
First of all, head over to [remix](https://remix.ethereum.org/). Remix is an online IDE for writing and deploying smart contracts. Create a new file named "`Voting.sol`" inside the contracts directory
![Voting.sol](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6t5wrs9bocundzs0w6at.png)

### The blockchain system
The beginning of a new chapter😌
```solidity
// 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🙌.
```solidity
// 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
```solidity
// 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
```solidity
// 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🙈.
```solidity
// 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😌
![Voting2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ltbu2lr06te7txy05vso.png)
Go ahead and click on that compile button to compile the solidity smart contract on the **solidity compiler page**
![Voting3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rxvij6r5f6mlm9hg97nf.png)
So, [remix](https://remix.ethereum.org/) 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! 😌🚀🔗