5

I did a smart contract to vote, but I a, having troubles with one of my functions ("results"). Here comes the smart contract:

pragma solidity ^0.5.7;

contract Voting{
    struct Option{
        string name;
        uint256 votes;
    }

    Option[] private options;
    address[] private alreadyVote;

    address private owner = msg.sender;

    constructor() public {}

    function addOption(string memory _name) public{
        require(msg.sender==owner,"Permiso denegado");
        options.push(Option(_name,0));
    }

    function vote(string memory _name) public{
        require(find(msg.sender,alreadyVote)==-1,"Ya ha ejercido su derecho a voto");
        int candidateIndex = findOption(_name);
        require(candidateIndex!=-1,"No se ha encontrado el candidato deseado");

        options[uint(candidateIndex)].votes++;

        alreadyVote.push(msg.sender);
    }

    function findOption(string memory _name) private view returns (int){
        int result = -1;
        for(uint i = 0;i<options.length;i++){
            if(compareStrings(options[i].name,_name))
                result = int(i);
        }
        return result;
    }

    function compareStrings (string memory a, string memory b) private pure returns (bool) {
        return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))) );
    }

    function find(address ad, address[] memory v) private pure returns (int){
        int result = -1;
        for(uint i = 0;i<v.length;i++){
            if(v[i]==ad)
                result = int(i);
        }
        return result;
    }

    function concat(string memory _base, string memory _value) public pure returns (string memory) {
        bytes memory _baseBytes = bytes(_base);
        bytes memory _valueBytes = bytes(_value);

        string memory _tmpValue = new string(_baseBytes.length + _valueBytes.length);
        bytes memory _newValue = bytes(_tmpValue);

        uint i;
        uint j;

        for(i=0; i<_baseBytes.length; i++) {
            _newValue[j++] = _baseBytes[i];
        }

        for(i=0; i<_valueBytes.length; i++) {
            _newValue[j++] = _valueBytes[i];
        }

        return string(_newValue);
    }

    function getResult(string memory _name) public view returns (string memory ,uint){
        require(msg.sender==owner,"Denied");
        int index = findOption(_name);
        string memory error = concat("Didn't found candidate ",_name);
        require(index!=-1,error);

        return (options[uint(index)].name,options[uint(index)].votes);
    }
}

The thing is that when I call the gunction result, second require statement pops. Tgos os how I call it from Web3.py:

tx = contract_instance.functions.getResult("Name").call({'from':acct.address})

I think that this should work, because I am already calling function vote with the same statement, but it perfectly works. This is how I call it:

tx = contract_instance.functions.vote(candidato).buildTransaction({'nonce':w3.eth.getTransactionCount(acc),'gas': 1728712,'gasPrice': w3.toWei('21', 'gwei')})
#Get tx receipt to get contract address
signed_tx = w3.eth.account.signTransaction(tx, key)

I tested it on remix and worked, so I dont really know what could be happening.

TylerH
  • 20,799
  • 66
  • 75
  • 101

2 Answers2

1

Have you call addOption function before getResult?

As you said, you failed on the second require statement, and this would happen if you pass in a name that is not on the candidate list.

StillFantasy
  • 1,677
  • 9
  • 21
1

Solidity codes are 100% right.

Try call() instade of call({'from':acct.address}) e.g.-

address = '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F988'
abi = '[{"inputs":[{"internalType":"add,...'
contract_instance = w3.eth.contract(address=address, abi=abi)

# read state:
contract_instance.functions.storedValue().call()

and make sure you call addOption & vote function before getResult?

aakash4dev
  • 774
  • 4
  • 13