Ошибка Truffle TestRPC: исключение виртуальной машины при выполнении eth_call: неверный код операции

Я создал проект из Truffle Box. Я создал свой собственный контракт для голосования. На данный момент я хочу иметь возможность голосовать, что, кажется, работает, и возвращать общее количество голосов за всех кандидатов, но я получаю сообщение об ошибке, вот некоторый код.

pragma solidity ^0.4.2;

contract Voting {

mapping (bytes32 => uint8) public votesReceived;

uint8[] public totalVotes;

bytes32[] public candidateList;

function Voting(bytes32[] candidateNames) {
    candidateList = candidateNames;
}

// This function returns the total votes a candidate has received so far
function totalVotesFor(bytes32 candidate) returns (uint8) {
    if (validCandidate(candidate) == false) revert();
    return votesReceived[candidate];
}

//returns totalVotes
function getAllVotes() constant returns (uint8[]) {
    for(uint i = 0; i < candidateList.length; i++) {
        bytes32 candidate = candidateList[i];
        totalVotes[i] = votesReceived[candidate];
    }
    return totalVotes;
}

// This function returns all candidates
function getCandidateList() returns (bytes32[]) {
    return candidateList;
}

// This function increments the vote count for the specified candidate. This
// is equivalent to casting a vote
function voteForCandidate(bytes32 candidate) {
    if (validCandidate(candidate) == false) revert();
    votesReceived[candidate] += 1;
}

function validCandidate(bytes32 candidate) returns (bool) {
    for(uint i = 0; i < candidateList.length; i++) {
        if (candidateList[i] == candidate) {
            return true;
        }
    }
    return false;
}
}

и вот мой код javascript

        const voting = contract(VotingContract)
        voting.setProvider(web3.currentProvider)

        // Declaring this for later so we can chain functions on it.
        var votingInstance;

        // Get current ethereum wallet.
        web3.eth.getCoinbase((error, coinbase) => {
            // Log errors, if any.
            if (error) {
                console.error(error);
            }

            voting.deployed().then(function (instance) {
                votingInstance = instance

                // Attempt to vote.
                votingInstance.voteForCandidate(candidate, {from: coinbase})
                    .then(function (result) {
                        //your vote is cast
                        return votingInstance.getAllVotes()
                    })
                    .then(function(result){
                        console.log(result)
                    })
                    .catch(function (error) {
                        // If error...
                        console.log(error)
                    })
            })
        })

При вызове голосованияInstance.getAllVotes() я получаю эту ошибку

Error: Error: VM Exception while executing eth_call: invalid opcode
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:59368:17
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:69306:5
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:11335:9
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:7895:16
at replenish (/usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:8415:25)
at iterateeCallback (/usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:8405:17)
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:8380:16
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:11332:13
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:69302:9
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:63982:7
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:59368:17
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:69306:5
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:11335:9
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:7895:16
at replenish (/usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:8415:25)
at iterateeCallback (/usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:8405:17)
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:8380:16
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:11332:13
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:69302:9
at /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js:63982:7
at Object.InvalidResponse (http://localhost:3000/static/js/bundle.js:54358:17)
at http://localhost:3000/static/js/bundle.js:43504:37
at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:9899:9
at completeRequest (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:9950:9)
at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:673:16
at replenish (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:1193:25)
at iterateeCallback (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:1183:17)
at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:1158:16
at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:9827:7
at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:9923:18

Нигде не могу найти решение, помогите кто-нибудь!!

Ответы (2)

Проблема здесь в том, что вы пытаетесь изменить переменную состояния totalVotes из постоянной функции ( getAllVotes ).

Константная функция может только читать данные. Если вам нужно выполнить вычисления внутри функции для массива или структуры, вы можете использовать ключевое слово memory. Но вы не можете изменить переменную состояния (переменная, объявленная глобально в смарт-контракте)

//returns totalVotes
function getAllVotes() constant returns (uint8[]) {
    uint8[] memory totalVotes = new uint8[](candidateList.length);

    for(uint i = 0; i < candidateList.length; i++) {
        bytes32 candidate = candidateList[i];
        totalVotes[i] = votesReceived[candidate];
    }
    return totalVotes;
}

Всего несколько вещей. Вы декларируете totalVotesв контрактном хранилище

uint8[] public totalVotes;

Функция getallVotesобъявлена ​​константой, но вы пытаетесь изменитьtotalVotes

//returns totalVotes
function getAllVotes() constant returns (uint8[]) {
    for(uint i = 0; i < candidateList.length; i++) {
        bytes32 candidate = candidateList[i];
        totalVotes[i] = votesReceived[candidate];
    }
    return totalVotes;
}

И из этого ответа https://ethereum.stackexchange.com/a/3590 вы не можете вернуть динамический массив.