2017-08-07 74 views
3

我正在使用testrpc,web3 1.0和solidity構建一個簡單的Dapp,但我總是收到此錯誤,而且我找不到錯在哪裏。請幫忙。虛擬機在處理事務時異常:無法使用

我的JavaScript文件:

const Web3 = require('web3'); 
const fs = require('fs'); 

const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); 

const code = fs.readFileSync('Voting.sol').toString(); 
const solc = require('solc'); 
const compiledCode = solc.compile(code); 

// deploy contract 
const abiDefinition = JSON.parse(compiledCode.contracts[':Voting'].interface); 
const VotingContract = new web3.eth.Contract(abiDefinition); 
const byteCode = compiledCode.contracts[':Voting'].bytecode; 
const deployedContract = VotingContract 
.deploy({data: byteCode, arguments: [['a','b','c']]}) 
.send({ 
    from: '0x386fd5fbe3804f24b35477f06aa78a178ce021bd', 
    gas: 4700000, 
    gasPrice: '2000000000' 
}, function(error, transactionHash) {}) 
.on('error', function(error){}) 
.on('transactionHash', function(transactionHash){}) 
.on('receipt', function(receipt){ 
    console.log(receipt.contractAddress); 
}) 
.then(function(newContractInstance) { 
    newContractInstance.methods.getList().call({from: '0x386fd5fbe3804f24b35477f06aa78a178ce021bd'}).then(console.log); 
}); 

我的合同文件:

pragma solidity ^0.4.11; 
// We have to specify what version of compiler this code will compile with 

contract Voting { 
    /* mapping field below is equivalent to an associative array or hash. 
    The key of the mapping is candidate name stored as type bytes32 and value is 
    an unsigned integer to store the vote count 
    */ 

    mapping (bytes32 => uint8) public votesReceived; 

    /* Solidity doesn't let you pass in an array of strings in the constructor (yet). 
    We will use an array of bytes32 instead to store the list of candidates 
    */ 

    bytes32[] public candidateList; 

    /* This is the constructor which will be called once when you 
    deploy the contract to the blockchain. When we deploy the contract, 
    we will pass an array of candidates who will be contesting in the election 
    */ 
    function Voting(bytes32[] candidateNames) { 
    candidateList = candidateNames; 
    } 

    function getList() returns (bytes32[]) { 
    return candidateList; 
    } 

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

    // This function increments the vote count for the specified candidate. This 
    // is equivalent to casting a vote 
    function voteForCandidate(bytes32 candidate) { 
    require(validCandidate(candidate) == false); 
    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; 
    } 
} 

而且,我用下面的命令啓動testrpc:

testrpc --account =「0xce2ddf7d4509856c2b7256d002c004db6e34eeb19b37cee04f7b493d2b89306d ,2000000000000000000000000000000「

任何幫助,將不勝感激。

回答

5

您不應該使用gas來調用getter方法。請記住,從區塊鏈閱讀是免費的 - 這是寫數據花費金錢(天然氣),因爲寫作必須經過驗證並達成共識。

因此,您的getter方法應該標記爲constant屬性,例如,

function getList() constant returns (bytes32[]) { 
    return candidateList; 
} 

所有的二,你甚至不需要一個getter方法candidateList因爲屬性可以直接訪問,如newContractInstance.candidateList()

第三,您應該使用映射而不是數組,例如mapping(bytes32 => bool) public validCandidates,因爲您的合同只關心候選人是否有效。你真的,真的不想在你的合同中出現循環,因爲你希望你的函數調用具有恆定的天然氣成本。如果你使用循環,你耗盡氣體。

把上述所有的在一起你會得到這樣的合同

pragma solidity ^0.4.11; 
// We have to specify what version of compiler this code will compile with 

contract Voting { 
    /* mapping field below is equivalent to an associative array or hash. 
    The key of the mapping is candidate name stored as type bytes32 and value is 
    an unsigned integer to store the vote count 
    */ 

    mapping (bytes32 => uint8) public votesReceived; 
    mapping (bytes32 => bool) public validCandidates; 

    /* This is the constructor which will be called once when you 
    deploy the contract to the blockchain. When we deploy the contract, 
    we will pass an array of candidates who will be contesting in the election 
    */ 
    function Voting(bytes32[] candidateList) { 
    for (uint i = 0; i < candidateList.length; i++) { 
     validCandidates[candidateList[i]] = true; 
    } 
    } 

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

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

    function isValidCandidate(bytes32 candidate) constant returns (bool) { 
    return validCandidates[candidate]; 
    } 

    modifier onlyForValidCandidate(bytes32 candidate) { 
    require(isValidCandidate(candidate)); 
    _; 
    } 
} 
+0

非常感謝,兄弟! –

+0

我知道這花了我一段時間:D爲什麼構造函數中的循環比另一個函數更好? – Chiptus

+0

在這個特定的合約中,你必須在構造函數中有循環。如果它在另一個函數中,任何人都可以調用它,除非你實現了權限。循環本身並不壞,但您必須瞭解氣體成本 – gaiazov