Playboi.eth
11 min readSep 26, 2023

--

Building a Decentralized Voting Smart Contract with QuickNode RPC.

Prerequisites;

  • What is a Decentralized Voting smart contract.
  • Key features and components of a Decentralized Voting Smart Contract.
  • Use cases of a Decentralized Voting Smart Contract.
  • Writing a Decentralized Voting Smart Contract.
  • Deployment with QuickNode RPC.

WHAT IS A DECENTRALIZED VOTING SMART CONTRACT?

A decentralized voting smart contract is a self-executing digital agreement, written in a programming language like Solidity (used for Ethereum smart contracts), that facilitates the process of conducting secure and transparent voting on a blockchain platform. It operates without the need for a central authority, such as a government or a trusted third party, to oversee or validate the voting process.

Why do we need it?
Current voting systems like ballot box voting or electronic voting suffer from various security threats such as DDoS attacks (Denial of service), polling booth capturing, vote alteration and manipulation, malware attacks, etc, and also require huge amounts of paperwork, human resources, and time. This creates a sense of distrust among existing systems.
Some of the disadvantages are:

  • Long Queues during elections.
  • Security Breaches like data leaks, vote tampering.
  • Lot of paperwork involved, hence less eco-friendly and time-consuming.
  • Difficult for differently-abled voters to reach polling booth.
  • Cost of expenditure on elections is high.

Solution:
Using blockchain, voting process can be made more secure, transparent, immutable, and reliable. How? Let’s take an example.

Suppose you are an eligible voter who goes to polling booth and cast vote using EVM (Electronic Voting Machine). But since it’s a circuitry after all and if someone tampers with microchip, you may never know that did your vote reach to person for whom you voted or was diverted into another candidate’s account?
Since there’s no tracing back of your vote. But, if you use blockchain- it stores everything as a transaction that will be explained soon below; and hence gives you a receipt of your vote (in a form of a transaction ID) and you can use it to ensure that your vote has been counted securely.

KEY FEATURES AND COMPONENTS OF A DECENTRALIZED VOTING SMART CONTRACT.

  1. Transparent and Immutable: All transactions and votes recorded on the blockchain are transparent and cannot be altered or tampered with once recorded, ensuring the integrity of the voting process.
  2. No Central Authority: The smart contract automates the voting process, eliminating the need for a central authority to oversee or administer the election. This reduces the potential for manipulation or fraud.
  3. Voter Authentication: The smart contract may implement mechanisms to verify the eligibility and authenticity of voters. This could involve voter registration and authentication processes.
  4. Anonymous Voting: Voters’ identities are not directly linked to their votes, preserving voter privacy.
  5. Result Tallying: The smart contract is designed to tally the votes and determine the outcome of the election once the voting period is complete.
  6. Secure and Trustless: The decentralized nature of blockchain ensures that the voting process is secure and trustless, meaning participants can have confidence in the integrity of the process without having to trust a single entity.
  7. Option for Public Auditing: Since the details of every transaction are stored on the blockchain, interested parties can independently verify the election results.

Decentralized voting smart contracts are particularly useful in scenarios where trust in a centralized authority may be lacking, or where transparency, security, and immutability are crucial requirements, such as in community governance, corporate decision-making, or public elections.

Other key features include;

  1. Time-Locking: The contract can enforce specific time constraints for the voting process, including opening and closing times. This prevents votes from being cast outside of the designated time frame.
  2. Multi-Candidate Support: The contract can support elections with multiple candidates or options, allowing voters to choose from a list of candidates or proposals.
  3. Weighted Voting: Some systems may implement weighted voting, where certain participants have more voting power based on predefined criteria (e.g., stake, reputation, etc.).
  4. Quorum Requirements: The contract can specify a minimum threshold of participation required for the election results to be considered valid.
  5. Option for Proxy Voting: Proxy voting allows participants to delegate their votes to trusted individuals or entities, enabling a more flexible voting process.
  6. Voter Whitelisting: The contract can maintain a list of authorized voters, ensuring that only eligible participants can cast their votes.
  7. Voter Registration and Authentication: The contract may include a voter registration process to verify the identity and eligibility of participants before allowing them to vote.
  8. Secure Communication: The contract may incorporate encryption or other security measures to protect communication between voters and the contract.
  9. Re-Voting or Changing Votes: Depending on the use case, the contract can allow voters to change their votes before the voting period ends.
  10. Real-time Results: The contract can provide real-time updates on the voting process, allowing participants to track the progress of the election.
  11. Audit Trail: Detailed logs of all voting activities, including timestamps, can be recorded on the blockchain for transparency and auditing purposes.
  12. Voter Feedback and Comments: Participants may be given the option to provide comments or feedback along with their votes.

24. Dispute Resolution Mechanism: In case of disputes or challenges, the contract can include a mechanism for resolving conflicts, potentially involving an arbitrator.

25. Finality of Results: Once the voting period ends, the contract can ensure that the results are immutable and cannot be altered.

26. Gas Optimization: The contract can be designed to minimize gas costs for participants while still ensuring security and efficiency.

USE CASES OF A DECENTRALIZED VOTING SMART CONTRACT.

  1. Governance in Decentralized Organizations:
  • Decentralized Autonomous Organizations (DAOs) can use smart contracts for decision-making processes, including voting on proposals, budget allocations, and protocol upgrades.

2. Elections in Political Systems:

  • Governments and political organizations can utilize decentralized voting to conduct elections, ensuring transparency, security, and tamper resistance.

3. Corporate Governance:

  • Shareholders of a company can use smart contracts to cast votes on critical matters such as board elections, mergers, and major business decisions.

4. Token Holder Proposals:

  • Projects in the blockchain and cryptocurrency space can implement decentralized voting for token holders to participate in governance decisions, such as protocol upgrades or fund allocations.

5. Community Governance in Cryptocurrencies:

  • Cryptocurrency projects can allow their communities to vote on proposals related to development, marketing, and other strategic initiatives.

6. Decentralized Applications (DApps) Governance:

  • DApp platforms can implement decentralized voting to allow users to influence decisions about the development and direction of the platform.

7. Academic Institutions:

  • Universities or educational institutions can use decentralized voting for student council elections, faculty decisions, or curriculum changes.

8. Non-Profit Organizations:

  • Non-profits can utilize decentralized voting for decision-making processes, allowing members to have a say in matters such as project selection, fundraising strategies, and organizational priorities.

9. Community Fund Allocation:

  • Decentralized communities or ecosystems can allocate funds for initiatives like grants, bounties, or community development projects based on member votes.

10. Proposal Funding in Blockchain Networks:

  • Blockchain networks like Polkadot, Ethereum, or Cardano use decentralized voting for deciding on funding proposals, protocol upgrades, and network improvements.

11. Resource Allocation in Decentralized Finance (DeFi):

  • DeFi protocols can use decentralized voting to determine factors like interest rates, collateral types, and changes to protocol parameters.

12. Consortiums and Partnerships:

  • Member organizations in consortiums or partnerships can use decentralized voting for decision-making related to joint initiatives, investments, or strategic partnerships.

13. Environmental Initiatives:

  • Environmental organizations can employ decentralized voting for deciding on projects or policies related to conservation efforts, renewable energy, and sustainable practices.

14. Content Platforms and Communities:

  • Platforms like social media networks or content sharing sites can implement decentralized voting for users to curate content, select moderators, and influence platform policies.

15. Real Estate Co-ownership:

  • Smart contracts can facilitate co-ownership arrangements for properties, allowing co-owners to vote on decisions regarding maintenance, rental agreements, and property management.

WRITING A DECENTRALIZED VOTING SMART CONTRACT.

Hey, enough of the fundamentals, its time to go technical!

Below is an Voting smart contract code;

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract DecentralizedVoting {

struct Voter {
bool isRegistered;
bool hasVoted;
}

mapping(address => Voter) public voters;
mapping(bytes32 => uint256) public voteCount;

address public admin;
bytes32 public topic;
bool public votingActive;

event VoterRegistered(address voter);
event VoteCasted(address voter, bytes32 choice);
event VotingEnded();

modifier onlyAdmin() {
require(msg.sender == admin, "Only admin can call this function");
_;
}

modifier onlyRegistered() {
require(voters[msg.sender].isRegistered, "Voter is not registered");
_;
}

modifier onlyActive() {
require(votingActive, "Voting is not active");
_;
}

constructor(bytes32 _topic) {
admin = msg.sender;
topic = _topic;
votingActive = true;
}

function registerVoter(address _voter) external onlyAdmin {
require(!voters[_voter].isRegistered, "Voter is already registered");
voters[_voter].isRegistered = true;
emit VoterRegistered(_voter);
}

function startVoting() external onlyAdmin {
require(!votingActive, "Voting is already active");
votingActive = true;
}

function endVoting() external onlyAdmin {
require(votingActive, "Voting is not active");
votingActive = false;
emit VotingEnded();
}

function castVote(bytes32 _choice) external onlyRegistered onlyActive {
require(!voters[msg.sender].hasVoted, "Voter has already voted");
voters[msg.sender].hasVoted = true;
voteCount[_choice]++;
emit VoteCasted(msg.sender, _choice);
}

function getResult(bytes32 _choice) external view returns (uint256) {
require(!votingActive, "Voting is still active");
return voteCount[_choice];
}

function getWinner() external view returns (bytes32) {
require(!votingActive, "Voting is still active");
bytes32 winner;
uint256 maxVotes = 0;

// Iterate through the choices to find the one with the most votes
for (uint256 i = 0; i < 256; i++) {
bytes32 choice = bytes32(i);
if (voteCount[choice] > maxVotes) {
maxVotes = voteCount[choice];
winner = choice;
}
}

return winner;
}
}

A detailed explanation of the code below:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract DecentralizedVoting {
  • This contract begins with SPDX-License-Identifier to specify the license for the code and the Solidity compiler version pragma. It defines a Solidity smart contract named DecentralizedVoting.
struct Voter {
bool isRegistered;
bool hasVoted;
}
  • Within the contract, there is a struct called Voter. A struct is like a custom data type that allows you to group related data together. In this case, it is used to represent information about each voter. Each voter has two properties:
  • isRegistered: A boolean indicating whether a voter is registered.
  • hasVoted: Another boolean indicating whether a voter has already cast a vote.
mapping(address => Voter) public voters;
mapping(bytes32 => uint256) public voteCount;
  • Two mappings are declared. Mappings are key-value pairs that allow efficient storage and retrieval of data.
  • voters: This maps addresses to Voter structs. It is used to keep track of registered voters and their voting status.
  • voteCount: This maps bytes32 values (representing voting choices) to uint256. It is used to store the count of votes received for each choice.
address public admin;
bytes32 public topic;
bool public votingActive;
  • Three state variables are declared:
  • admin: This is an Ethereum address representing the administrator or organizer of the voting.
  • topic: This is a bytes32 variable representing the topic of the vote. It's a way to label what the vote is about.
  • votingActive: This is a boolean indicating whether the voting is currently active. It will be set to true if the voting process is ongoing.
event VoterRegistered(address voter);
event VoteCasted(address voter, bytes32 choice);
event VotingEnded();
  • Three events are defined to log important contract actions:
  • VoterRegistered: This event is emitted when a voter is successfully registered. It logs the address of the registered voter.
  • VoteCasted: This event is emitted when a voter casts a vote. It logs the address of the voter and the choice they made.
  • VotingEnded: This event is emitted when the voting process is ended by the administrator. It signals that the voting has concluded.
modifier onlyAdmin() {
require(msg.sender == admin, "Only admin can call this function");
_;
}
  • This is a custom modifier named onlyAdmin. Modifiers are used to modify or extend the behavior of functions. The onlyAdmin modifier restricts access to certain functions to the contract administrator (admin) only. If the sender of the transaction is not the admin, the function will revert with the provided error message.
modifier onlyRegistered() {
require(voters[msg.sender].isRegistered, "Voter is not registered");
_;
}
  • Another custom modifier onlyRegistered is defined. This modifier ensures that only registered voters can access certain functions. If the sender is not a registered voter, the function will revert with an error message.
modifier onlyActive() {
require(votingActive, "Voting is not active");
_;
}
  • The onlyActive modifier restricts access to functions to ensure that voting is currently active. If voting is not active, the function will revert with an error message.
constructor(bytes32 _topic) {
admin = msg.sender;
topic = _topic;
votingActive = true;
}
  • The constructor is a special function that is executed only once when the contract is deployed. In this case, it takes a bytes32 parameter _topic. The constructor initializes the contract when it's deployed. It sets the admin to the sender (the deployer of the contract), defines the topic for the vote, and sets the initial state of votingActive to true, indicating that voting is active upon deployment.

Lets write this code in our REMIX IDE.

DEPLOYMENT WITH QUICKNODE RPC.

STEP 1.

Create a new sepolia node on QuickNode. You would have to navigate to the QuickNode Dashboard and click on “Create”.

Then after, make sure you click on the Ethereum chain. Check a screenshoot below;

Click on Sepolia:

Then click on ‘continue’ to proceed. Finally click on ‘create endpoint’ to get your Sepolia url.

STEP 2.

Click on “Add network”. Follow the instructions on how to add the RPC url to your wallet browser.

Click on “Add network manually”.

STEP 3.

Enter a name (any) since your using QuickNode , you can use ‘QKN’ copy/paste your Web3 endpoint (be sure to include the “/” at the end!), enter ChainID and click “Save”.

We are using Sepolia Teastnet, so its advisable to use sepolia chain ID, Which is ‘11155111’.

Finally, you would get the below result.

Perfect! We are almost finished, Now we would be requesting some Eth from Sepolia Testnet so as to be able to deploy our smart contract.

STEP 4.

Now to get gas fees, we are going to be using https://faucet.quicknode.com/drip. Below is the procedure.

Then connect wallet and get some Eth.

After doing this, you would get the result below:

With this, we are ready to deploy our Nft marketplace smart contract.

Deploying smart contract code to sepolia testnet.

Click on ‘confirm’ to finalize transactions.

Conclusion

Congratulations on successfully creating your very own Voting Smart contract on the Ethereum network! .

Subscribe to QuickNode newsletter for more articles and guides on Ethereum. If you have any feedback, feel free to reach out to us via Twitter. You can always chat with us on our Discord community server, featuring some of the coolest developers you’ll ever meet :)

--

--

Playboi.eth

22y/o smart contract engineer. Advocate @graphprotocol, Ambassador @quicknode, Contributor @girscriptsoc . prev @web3_Nados, @blockchain