Smart contract for Voting
Tags: blockchain, solidity, web3, smartcontract
Published: 2021-10-14 05:19:48

[jaymakwanacodes.me](https://www.jaymakwanacodes.me/)
To view source code all at once head over to my [Github](https://github.com/jmakwana01/Simple-Bank-Smart-Contract)

Let's understand with the basic, why blockchain and how this smart contract adds value to the existing system

In the Traditional sense there are some concerning problem with voting system,in web2 the interface and backend is connected to a central database which raises the problem of rouge admin,the voting system code is  not public which shows we need to trust that rule are been followed and my vote has been counted

So to come up with a possible change let try Blockchain in the context,
To understand it let start with how blockchain works,in the most basic terms ,blockchain are like link list node connected to nodes creating a network for itself ,okay! so it's solves the the rouge admin issue as it is decentralized no one owns the chain ,let try to use it to next problem the transparency feature blockchain has append only logs that are public so in that case when we deploy our (contract)code for election in blockchain it will be visible in public as it changes the state of the chain,when someone vote the address can be seen who vote(it's still anonymous)

so let dive into the  technical stuff
##Smart contract
Smart contracts are simply programs stored on a blockchain that run when predetermined conditions are met. They typically are used to automate the execution of an agreement so that all participants can be immediately certain of the outcome, without any intermediary's involvement or time loss.
also something that solves a problem as smart contract are immutable the rule of election can't be changed

##Solidity
Solidity is an object-oriented programming language for writing smart contracts. It is used for implementing smart contracts on various blockchain platforms, most notably, Ethereum.
We will be using Solidity to write our smart contract if you are not familiar with it don't sweat just carry on reading 

##Code
```Pragma Solidity ^0.6.6;```

Solidity is a growing language there are frequent updates we are declaring which compiler to use in the line (look at it as something like package-lock.json)

next let create a contract if you are familiar with java or any other object oriented language which uses classes 
same way the keyword contract is used in solidity
```contract PollContract {}```
Struct types are used to represent a record. we need to create a record for poll 
syntax:-struct struct_name {
   type1 type_name_1;
}
here we want to create struct for poll to create a poll we should add following
-id
-question(title for the poll)
-thumbnail(image banner for the poll)
-array of votes(to track the no. of votes recieved)
-array of options(to create voting option for the voter)
###all the code from following line is meant to be added inside contract Pollcontract{}
``` struct Poll {
        uint256 id;
        string question;
        string thumbnail;
        uint64[] votes;
        bytes32[] options;
    }```
Now we have created a struct for poll we declaring we need this parameter for poll let do the same for the voter
-id
-array of votedId(to track whether the user have vote or not )
-voted map (mapping to votedId  array to boll)
```struct Voter {
        address id;
        uint256[] votedIds;
        mapping(uint256 => bool) votedMap;
    }```
now let's define how pool and voter interact
we will create a Poll array and call it polls and set it to private( Can be accessed only by authorized contracts),
next mapping user address to the voter to extract  info about the user,
now we will add event poll created with parameter set to _pollId;
```Poll[] private polls;
    mapping(address => Voter) private voters;

    event PollCreated(uint256 _pollId);```

Now we will add createPoll function to as name suggest create poll we get some parameter as you see in below code 
we will add some require to make sure question isn't empty and have atleast 2 option for every poll

```function createPoll(string memory _question, string memory _thumb, bytes32[] memory  _options) public {
        require(bytes(_question).length > 0, "Empty question");
        require(_options.length > 1, "At least 2 options required")
uint256 pollId = polls.length;
     Poll memory newPoll = Poll({
            id: pollId,
            question: _question,
            thumbnail: _thumb,
            options: _options,
            votes: new uint64[](_options.length)
        });

        polls.push(newPoll);
        emit PollCreated(pollId);
    }```

Now as we have written a function to create a poll we need to write a function to get poll
we use require to check that poll id shouldn't be null
```function getPoll(uint256 _pollId) external view returns(uint256, string memory, string memory, uint64[] memory, bytes32[] memory) {
        require(_pollId < polls.length && _pollId >= 0, "No poll found");
        return (
            polls[_pollId].id,
            polls[_pollId].question,
            polls[_pollId].thumbnail,
            polls[_pollId].votes,
            polls[_pollId].options
        );
    }```

now we can create a poll and get a poll let's  start voting now
create a function to vote ,we will add some required check to find if the poll exsist ,if option exsist and whether you have already vote
the syntax msg.sender get the user address
```function vote(uint256 _pollId, uint64 _vote) external {
        require(_pollId < polls.length, "Poll does not exist");
        require(_vote < polls[_pollId].options.length, "Invalid vote");
        require(voters[msg.sender].votedMap[_pollId] == false, "You already voted");

        polls[_pollId].votes[_vote] +=1 ;

        voters[msg.sender].votedIds.push(_pollId);
        voters[msg.sender].votedMap[_pollId] = true;
    }```

now to get the voter let create a function getVoter to get info about voterId 
```function getVoter(address _id) external view returns(address, uint256[] memory) {
        return (
            voters[_id].id,
            voters[_id].votedIds
        );
    }

    function getTotalPolls() external view returns(uint256) {
        return polls.length;
    }```
Now our Smart contract is completed we can deploy it and check it on our Remix or some testnet as well, we can create front-end with any of the frame work and can connect  it with our smart-contract using web3.js as a middleware