Я создал проект из 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
Нигде не могу найти решение, помогите кто-нибудь!!
Проблема здесь в том, что вы пытаетесь изменить переменную состояния 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 вы не можете вернуть динамический массив.