Home > front end >  for loop is not working on array of structs in solidity
for loop is not working on array of structs in solidity

Time:10-17

I am coding a simple voting system where a 'chairperson' is defined...Chairperson will add candidates but the voter are going to register themselves(no role of chairperson in adding of voters, Chairperson is only going to add candidates). Now In code I made an array of voters of type structs and make a function named "vote" which is going to be called only by voter. So, I add a check of that the voter must be in the voterList(array of voter) or else voter must register first.. But when I call the function it always reverting it...even The voters are already registered....(I am going to add code of the contract below)... [NOTE: THE PROBLEM IS IN ONE OF THE MODIFIER I CREATED NAMED "voterRules" IN THE CODE,I USED THIS MODIFIER IN THE VOTE FUNCTION...]

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

contract Ballot{
    //VARIABLES

    //Initialize an address of chairperson of voting system and set it private
    address private chairperson;

   //MODIFIERS

   //To make chairperson as deployer
    modifier isOwner(){
    require(msg.sender == chairperson);
    _;
}

    //To make all the voters register by themselves
    modifier isVoter(address voterAddress_){
    require(voterAddress_ == msg.sender,"The voter must register by itself...");
    _;
}
  //To make rules for vote
  modifier voterRules(){
    require(msg.sender != chairperson,"Chairperson cannot vote!!");
    for(uint m=0;m<voterList.length;m  ){
    // require(msg.sender == voterList[m]._voterAddress,"You must register yourself first...");
    if( msg.sender != voterList[m]._voterAddress){
      revert();
    }
    }
    for(uint k=0;k<candidateList.length;k  ){ 
    require(voterToCandidate[msg.sender] != candidateList[k]._address,"You cannot vote twice...");
    }
    
      _;
  }
  //CONSTRUCTOR

  //constructor to set deployer the chairperson
  constructor(){
  chairperson = msg.sender;
    }

  //STRUCTS

   //Make a struct of candidate and give it properties: Name,Address,No. of votes
  
    struct Candidate{
    // string _name;
    address _address;
    uint256 _noOfVotes;
    }

    //Make a struct of voter and give it properties: Address,IsVoted
    struct Voter{
        address _voterAddress;
        bool _isVoted;
    }
    
    //ARRAYS

   //Make a array of candidates

    Candidate[] public candidateList;
    

     //Make an array of voters
    Voter[] public voterList;
    
    //MAPPINGS

    //Mapping from address of Voter to stuct candidate
    mapping(address=>address) private voterToCandidate;
    
    //FUNCTIONS

   //Make  a function to add candidate in the mapping..
   function addCandidate(address address_) public isOwner{
    for(uint i=0;i<candidateList.length;i  ){
        require(address_ != candidateList[i]._address, "Same Candidate cannot be added twice");
           }

    Candidate memory candidate = Candidate(address_,0);
    candidateList.push(candidate);
    
   }

   //Make a function to make voter to register himself..
   function registerVoter(address voterAddress_) external isVoter(voterAddress_){
    
       for(uint j=0;j<voterList.length;j  ){
       require(voterAddress_ != voterList[j]._voterAddress,"y");
       }
        voterList.push(Voter(voterAddress_,false));
      
       }

   //To make a function for voters to vote their desirable candidate and increase the count votes of the candidates
   function vote(uint256 _candId) public voterRules() {
         voterToCandidate[msg.sender] = candidateList[_candId]._address;
         candidateList[_candId]._noOfVotes  ;
   }


}

CodePudding user response:

I believe you are pretty new to the solidity, here are a couple of things to keep in mind.

  • We have to avoid loops as much as we can, to save gas.
  • Use mappings instead of arrays.
  • mapping can also maps to structs.
  • use indentation for better code readability.
  • Define state variables at the top.

and now to answer your question, I've made a couple of changes in the code that implements your intended logic as per my understanding. I am not explaining what I've done, You can use diffchecker.com to compare the code and think why I did what I did, it will give you a better understanding.

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

contract Ballot {
    struct Candidate {
        // string _name;
        address _address;
        uint256 _noOfVotes;
    }

    address private chairperson;
    Candidate[] public candidateList;
    mapping(address => bool) private isInVoterList;
    mapping(address => address) private voterToCandidate;

    modifier isOwner() {
        require(msg.sender == chairperson);
        _;
    }

    modifier isVoter(address voterAddress_) {
        require(
            voterAddress_ == msg.sender,
            "The voter must register by itself..."
        );
        _;
    }

    modifier voterRules() {
        require(msg.sender != chairperson, "Chairperson cannot vote!!");
        require(isInVoterList[msg.sender], "You must register yourself first");
        for (uint256 k = 0; k < candidateList.length; k  ) {
            require(
                voterToCandidate[msg.sender] != candidateList[k]._address,
                "You cannot vote twice..."
            );
        }

        _;
    }

    constructor() {
        chairperson = msg.sender;
    }

    function addCandidate(address address_) public isOwner {
        for (uint256 i = 0; i < candidateList.length; i  ) {
            require(
                address_ != candidateList[i]._address,
                "Same Candidate cannot be added twice"
            );
        }
        Candidate memory candidate = Candidate(address_, 0);
        candidateList.push(candidate);
    }

    function registerVoter(address voterAddress_)
        external
        isVoter(voterAddress_)
    {
        require(
            isInVoterList[voterAddress_] == false,
            "You are already registerd voter"
        );
        isInVoterList[voterAddress_] = true;
    }

    function vote(uint256 _candId) public voterRules {
        voterToCandidate[msg.sender] = candidateList[_candId]._address;
        candidateList[_candId]._noOfVotes  ;
    }
}

suggesting watch

  1. Mapping by Smart Contract Programmer
  2. Iterable Mapping by Smart Contract Programmer

ps. dun forget to accept my answer.

  • Related