Ethereum Voting Machine
Tags: blockchain, solidity, hardhat, programming
Published: 2022-10-26 17:14:14



##  Remix-IDE Or Hardhat

* You can use [Remix IDE](https://remix.ethereum.org) if you want to test.

* Create a folder and open VS Code.
```
    npm init
    npm install --dev hardhat
```
* Select * Create javaScript project *

* Then create a new file Voting.sol inside contracts folder
```
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.4;

contract Voting {
    uint totalCandidate;
    uint totalVoter;
    uint totalVoted;
 }
```

* Inside the contract 
```
 // create candidate struct to store candidate name , party name, number of votes
struct Candidate {
        bytes32 candidateName;
        bytes32 partyName;
        uint votes;
 }


 // create voter struct
struct Voter {
        uint candidateVoteId;
        bytes32 votedTo;
        bool voted;
        bool eligible;
}

      mapping(uint => Candidate) public candidates;
   
      mapping(address => Voter) public voters;

```

* Only Owner of the contract or Chief of the Election can verify the Voters to vote. So first make the owner
```
    function VotOwner() public {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    function showOwner() public view returns (address) {
        return owner;
    }
```
* Chief can also add the Candidates
```
 function addCandidate(bytes32 _name, bytes32 _party) public onlyOwner {
        uint i = totalCandidate++;
        candidates[i] = Candidate(_name, _party, 0);
 }
```

* Verify the Voters by passing the address or wallet address of the voter
```
function getRightToVote(address voterID) public {
        // check eligible
        require(!voters[voterID].eligible, "Already Eligible");
        require(!voters[voterID].voted, "The voter already voted");
        voters[voterID].eligible = true;
        totalVoter++;
}
```

* Verified voters can now vote
```
 function toVote(uint candidateID) public {
        Voter storage sender = voters[msg.sender];
        require(sender.eligible, "Not Eligible to Vote");
        require(!sender.voted, "Already Voted");

        sender.voted = true;
        sender.votedTo = candidates[candidateID].partyName;
        candidates[candidateID].votes += 1;
        totalVoted += 1;
 }
```

* Some view functions
```
    function votersLeftTOVote() public view returns (uint) {
        return totalVoter - totalVoted;
    }

    function voterVotedTo() public view returns (bytes32) {
        Voter storage sender = voters[msg.sender];
        return sender.votedTo;
    }

    function getNumOfCandidates() public view returns (uint) {
        return totalCandidate;
    }

    function getNumOfVoters() public view returns (uint) {
        return totalVoter;
    }
```

* Check the Winner
```
    function checkWinner() public view returns (uint wins) {
        uint winCount = 0;
        for (uint i = 0; i <= totalCandidate; i++) {
            if (winCount < candidates[i].votes) {
                winCount = candidates[i].votes;
                wins = i;
            }
        }
    }

    function winnerVotes() public view returns (uint vot) {
        vot = candidates[checkWinner()].votes;
    }

    function winnerName() public view returns (bytes32 name) {
        name = candidates[checkWinner()].candidateName;
    }
```



* open deploy.js inside scripts folder
```
const { ethers } = require("hardhat");
require("dotenv").config({ path: ".env" });

async function main() {
  /*
  A ContractFactory in ethers.js is an abstraction used to deploy new smart contracts,
  so verifyContract here is a factory for instances of our Verify contract.
  */
  const verifyContract = await ethers.getContractFactory("Voting");

  // deploy the contract
  const deployedVerifyContract = await verifyContract.deploy();

  await deployedVerifyContract.deployed();

  // print the address of the deployed contract
  console.log("Verify Contract Address:", deployedVerifyContract.address);

  console.log("Sleeping.....");
  // Wait for etherscan to notice that the contract has been deployed
  await sleep(50000);

  // Verify the contract after deploying
  await hre.run("verify:verify", {
    address: deployedVerifyContract.address,
    constructorArguments: [],
  });
}

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

// Call the main function and catch if there is any error
main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

```

* hardhatconfig.js
```
require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config({ path: ".env" });

const QUICKNODE_HTTP_URL = process.env.QUICKNODE_HTTP_URL;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const POLYGONSCAN_KEY = process.env.POLYGONSCAN_KEY;

module.exports = {
  solidity: "0.8.4",
  networks: {
    mumbai: {
      url: QUICKNODE_HTTP_URL,
      accounts: [PRIVATE_KEY],
    },
  },
  etherscan: {
    apiKey: {
      polygonMumbai: POLYGONSCAN_KEY,
    },
  },
};
```


* Compile and Deploy 
```
npx hardhat compile
npx hardhat run scripts/deploy.js --network mumbai
```
* If everything goes okay you will get the link to Mumbai PolygonScan in the terminal


## Note
* You can modify the contract as you want.
* You can add a timer (Election start -> end).
* [github](https://github.com/sandyabhi/Ethereum-Voting-Machine/tree/main/hardhat-evm)