Pramesh Bajracharya
Pramesh Bajracharya

Reputation: 2263

Solidity code gives VM exception error when called multiple times

Let's start with my solidity code :

pragma solidity ^0.4.18;

contract Voting {
    address mainAddress;
    bytes32[] candidateNames;
    mapping(bytes32 => uint) candidateVotes;
    mapping(bytes32 => bytes32) candidatesDetails;
    address[] voters;

    function Voting() public {
        mainAddress = msg.sender;
    }

    modifier isMainAddress {
        if (msg.sender == mainAddress) {
            _;
        }
    }

    function getAllCandidates() public view returns (bytes32[]) {
        return candidateNames;
    }

    function setCandidate(bytes32 newCandidate) isMainAddress public {
        candidateNames.push(newCandidate);
    }

    function setVote(bytes32 candidate) public {
        require(validVoters());
        candidateVotes[candidate] = candidateVotes[candidate] + 1;
        voters.push(msg.sender);
    }

    function getVote(bytes32 candidate) public view returns (uint) {
        return candidateVotes[candidate];
    }

    function setDescrption(bytes32 candidateName, bytes32 candidatesDesc) isMainAddress public {
        candidatesDetails[candidateName] = candidatesDesc;
    }

    function getDescription(bytes32 candidateName) public view returns (bytes32){
        return candidatesDetails[candidateName];
    }

    function getCurrentAddress() public view returns (address) {
        return msg.sender;
    }

    function validVoters() public view returns (bool) {
        for(uint i = 0; i < voters.length ; i++){
           if (voters[i] == msg.sender) {
                return false;
           } 
        }
        return true;
    }
}

The functions : Voting(), getAllCandidates(), setCandidate(), getVote(), setDescription(), getDescription(), getCurrentAddress() works fine when called multiple times. So, I guess we can ignore them for now.

The function setVote() runs fine the first time it executes ie. when a person votes for once. The problem arises when the same person tries to vote the second time. It gives the following error :

enter image description here

This might be a beginners mistake but I have been trying to fix this for 2 days straight and now I really need help.

Also,

Thanks.

Upvotes: 0

Views: 417

Answers (1)

user94559
user94559

Reputation: 60153

The function in question:

function setVote(bytes32 candidate) public {
    require(validVoters());
    candidateVotes[candidate] = candidateVotes[candidate] + 1;
    voters.push(msg.sender);
}

Note that validVoters() must return true for this function to succeed. If it returns false, the require will fail and revert the transaction. Also note that at the end of the function, msg.sender is added to the array voters.

Let's take a look at validVoters():

function validVoters() public view returns (bool) {
    for(uint i = 0; i < voters.length ; i++){
       if (voters[i] == msg.sender) {
            return false;
       } 
    }
    return true;
}

This function returns false if msg.sender is in voters, which we know will be the case after the account has voted once.

So the second time through, validVoters() returns false, which causes require(validVoters()) in setVote() to revert the transaction.

Upvotes: 2

Related Questions