Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AliArshadswl/d8b36c7a4f140adb024e45cd1230d496 to your computer and use it in GitHub Desktop.
Save AliArshadswl/d8b36c7a4f140adb024e45cd1230d496 to your computer and use it in GitHub Desktop.

Smart Contract for Voting with ChainIDE

In this smart contract, we will implement a voting process along with delegation. We'll use Solidity as a programming language, and Metamask for the deployment and testing. All this will be done using Binance IDE.

1. Preliminaries

In this section we will briefly explain the background knowledge to make you better understand the smart contract.

1.1 Tools used in the project

  1. Binance IDE
  2. Metamask (connected to BSC Binance Smart Chain)

1.2 Contract Programming Language

A voting process along with delegation smart contract is written in solidity language as it is an object-oriented, high-level programming language for implementing smart contracts. It was introduced in 2014. Smart contracts are programs that govern the behavior of accounts within the Ethereum state. Solidity was influenced by C++, Python, and JavaScript and is designed to target the Ethereum Virtual Machine (EVM). Now, it is the most commonly used programming language for Blockchain.

1.3 Data types and Definitions

Before moving on, we will briefly explain the basic terms, data types, and definitions used in this smart contract for the better understanding of the audience.
  • Smart Contract- smart contracts are the lines of the code that are stored on Blockchain and execute when predetermined terms and conditions are met. A contract is the fundamental building block of Ethereum applications — all variables and functions belong to a contract, and this will be the starting point of all your projects.
  • All the variables and functions are defined inside the body of contract. The smart contract for the voting has used the data types such as uint, bool, address, byte32, and function, struct, and constructor.
  • uint- The uint data type is an unsigned integer, meaning its value must be non-negative. There's also an int data type for signed integers. In Solidity, uint is actually an alias for uint256, a 256-bit unsigned integer.
  • bool- The possible values are constants true and false. Operators for bool are following ! (logical negation) && (logical conjunction, “and”) || (logical disjunction, “or”) == (equality) != (inequality).
  • byte32- byte32 is a fixed size byte array.
  • struct- Sometimes you need a more complex data type. For this, Solidity provides structs. Structs allow you to create more complicated data types that have multiple properties such as uint, bool, address, string, etc.
  • Array- When you want a collection of something, you can use an array. There are two types of arrays in Solidity: fixed arrays and dynamic arrays: Array with a fixed length of 2 elements: uint[2] fixedArray. A dynamic Array - has no fixed size, can keep growing: uint[] dynamicArray;
  • function- Like other programming languages, solidity also uses function. A function is a block of code which only runs when it is called. You can pass data, known as parameters, into a function. Functions are used to perform certain actions, and they are important for reusing code: Define the code once, and use it many times.
  • address: Holds a 20 byte value (size of an Ethereum address). Address types also have members and serve as a base for all contracts. operators for the address are followings: <=, <, ==, !=, >= and >
  • All solidity source code should start with a "version pragma" — a declaration of the version of the Solidity compiler this code should use. This is to prevent issues with future compiler versions potentially introducing changes that would break your code. For the scope of this smart contract, we'll compile our smart contracts with any compiler version in the range of 0.4.22 (inclusive) to 0.7.0 (exclusive). It looks like this: pragma solidity >=0.4.22 <0.7.0;

2. Practical Implementation of Smart Contract for Voting

In this section, we will implement and discuss in detail, a smart contract for the voting named as Ballot. The figure below shows the functions and structs used in this contract for different purposes such as to gives right to vote, summon winner name etc.

The function for to give rights to vote is declared as:
 function giveRightToVote(address voter) public {
    require(
        msg.sender == chairperson,
        "Only chairperson can give right to vote."
    );
    require(
        !voters[voter].voted,
        "The voter already voted."
    );
    require(voters[voter].weight == 0);
    voters[voter].weight = 1;
}
2.1 First of all structs with multiple properties are declared for both Voter and Proposal, that are going to be used by functions later.
 1. struct Voter {
    uint weight; // weight is accumulated by delegation
    bool voted;  // if true, that person already voted
    address delegate; // person delegated to
    uint vote;   // index of the voted proposal
}
The 'struct Voter' has four values with different data types and different purpose, 'uint weight' is used to accumulate the weight by the delegation; 'bool voted' is used to check either the voter has already voted or going to vote for the first time; 'address delegate' shows the person delegated to, and 'uint vote'is used as an index of the voted proposal.
2.2 The struct proposal is holds the short personal name and voteCount.
2. struct Proposal {
    // If you can limit the length to a certain number of bytes, 
    // always use one of bytes1 to bytes32 because they are much cheaper
    bytes32 name;   // short name (up to 32 bytes)
    uint voteCount; // number of accumulated votes
}
2.3 Address and array are declared, and address is mapped to the Voter, and a dynamic array has been declared to store the proposal.
3. address public chairperson;

   mapping(address => Voter) public voters;

   Proposal[] public proposals;
2.4 Constructor is a special method which gets invoked whenever an instance of a class is created – that is correct for object-oriented programming languages. However, in Solidity, it's different; Solidity supports declaring constructor inside a smart contract and it is invoked—only once—while deploying it.
4. constructor(bytes32[] memory proposalNames) public {
    chairperson = msg.sender;
    voters[chairperson].weight = 1;

    for (uint i = 0; i < proposalNames.length; i++) {
        // 'Proposal({...})' creates a temporary
        // Proposal object and 'proposals.push(...)'
        // appends it to the end of 'proposals'.
        proposals.push(Proposal({
            name: proposalNames[i],
            voteCount: 0
        }));
    }
}
2.5 Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'.para voter address of voter.
5. function giveRightToVote(address voter) public {
    require(
        msg.sender == chairperson,
        "Only chairperson can give right to vote."
    );
    require(
        !voters[voter].voted,
        "The voter already voted."
    );
    require(voters[voter].weight == 0);
    voters[voter].weight = 1;
}
2.6 Delegate your vote to the voter 'to'. Parameter to address to which vote is delegated.
6. function delegate(address to) public {
    Voter storage sender = voters[msg.sender];
    require(!sender.voted, "You already voted.");
    require(to != msg.sender, "Self-delegation is disallowed.");

    while (voters[to].delegate != address(0)) {
        to = voters[to].delegate;

        // We found a loop in the delegation, not allowed.
        require(to != msg.sender, "Found loop in delegation.");
    }
    sender.voted = true;
    sender.delegate = to;
    Voter storage delegate_ = voters[to];
    if (delegate_.voted) {
        // If the delegate already voted,
        // directly add to the number of votes
        proposals[delegate_.vote].voteCount += sender.weight;
    } else {
        // If the delegate did not vote yet,
        // add to her weight.
        delegate_.weight += sender.weight;
    }
}
2.7 Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'.param proposal index of proposal in the proposals array
7. function vote(uint proposal) public {
    Voter storage sender = voters[msg.sender];
    require(sender.weight != 0, "Has no right to vote");
    require(!sender.voted, "Already voted.");
    sender.voted = true;
    sender.vote = proposal;

    // If 'proposal' is out of the range of the array,
    // this will throw automatically and revert all
    // changes.
    proposals[proposal].voteCount += sender.weight;
}
2.8 Computes the winning proposal taking all previous votes into account.return winningProposal_ index of winning proposal in the proposals array
 8. function winningProposal() public view
        returns (uint winningProposal_)
{
    uint winningVoteCount = 0;
    for (uint p = 0; p < proposals.length; p++) {
        if (proposals[p].voteCount > winningVoteCount) {
            winningVoteCount = proposals[p].voteCount;
            winningProposal_ = p;
        }
    }
}
2.9 Calls winningProposal() function to get the index of the winner contained in the proposals array and then return winnerName_ the name of the winner
9. function winnerName() public view
        returns (bytes32 winnerName_)
{
    winnerName_ = proposals[winningProposal()].name;
}
Once you have written down the code, you can check it for the errors by compiling from the most right side of the panel. If it does not have any error, you can deploy it and practice to write more contracts according to your choice of interest using Binance IDE.

Conclusion

The tutorial on using ChainIDE to develop a smart contract for voting. Students who have questions can leave a message in the comment area. Different platforms bring more possibilities due to different architectures, and hope you can try more , make progress together.
@AliArshadswl
Copy link
Author

WeChat Image_20210120120013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment