He creado un proyecto a partir de una caja de trufas. He creado mi propio contrato para votar. En este punto, quiero poder votar, lo que parece estar funcionando, y devolver el total de votos para todos los candidatos, pero recibo un error, aquí hay un código.
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;
}
}
y aquí está mi código 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)
})
})
})
Cuando llamo a voteInstance.getAllVotes() me sale este error
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
No puedo encontrar una solución en ninguna parte, ¡alguien por favor AYUDA!
El problema aquí es que está tratando de cambiar una variable de estado totalVotes de una función constante ( getAllVotes ).
Una función constante solo puede leer datos. Si necesita realizar cálculos dentro de la función en una matriz o estructura, puede usar la palabra clave memory
. Pero no puede cambiar una variable de estado (variable declarada globalmente en el contrato inteligente)
//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;
}
Sólo un par de cosas. Declaras totalVotes
en contrato de almacenamiento
uint8[] public totalVotes;
La función getallVotes
se declara constante pero se intenta modificartotalVotes
//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;
}
Y a partir de esta respuesta https://ethereum.stackexchange.com/a/3590 , no puede devolver una matriz dinámica.