处理事务时VM异常:用完了 [英] VM Exception while processing transaction: out of gas

查看:94
本文介绍了处理事务时VM异常:用完了的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用testrpc,web3 1.0和solidity来构建一个简单的Dapp,但是我总是遇到此错误,并且找不到错误所在.请帮忙.

I am using testrpc, web3 1.0 and solidity to build a simple Dapp, but I'm always getting this error and I can't find what is wrong. Please help.

我的JavaScript文件:

My javascript file:

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:

Also, I'm starting the testrpc using the following command:

testrpc --account ="0xce2ddf7d4509856c2b7256d002c004db6e34eeb19b37cee04f7b493d2b89306d,2000000000000000000000000000000"

testrpc --account="0xce2ddf7d4509856c2b7256d002c004db6e34eeb19b37cee04f7b493d2b89306d, 2000000000000000000000000000000"

任何帮助将不胜感激.

Any help would be appreciated.

推荐答案

您不应该使用gas来调用getter方法.请记住,从区块链进行读取是免费的,因为写入数据会花费大量金钱(天然气),因为必须对写入进行验证并达成共识.

You should not be using gas to call a getter method. Remember that reading from blockchain is free - it is the writing data that costs money (gas), because the writes have to be verified and reach consensus.

因此,您的getter方法应标记为constant属性,例如

So, your getter methods should be marked with constant attribute, e.g.

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

第二,您甚至不需要candidateList的getter,因为可以直接访问该属性,例如newContractInstance.candidateList()

Second of all, you don't even need a getter for candidateList since the property can be accessed directly, e.g. newContractInstance.candidateList()

第三,您应该使用映射而不是数组,例如mapping(bytes32 => bool) public validCandidates,因为您的合同仅关心候选人是否有效.您确实真的不希望合同中有循环,因为您希望函数调用具有不变的耗油量.如果使用循环,则耗尽.

Third, you should use a mapping instead of an array, for example mapping(bytes32 => bool) public validCandidates because your contract only cares if a candidate is valid. You really, really don't want to have loops in your contract because you want your function calls to have constant gas cost. If you use loops, you will run out of gas.

将以上所有内容放在一起,您将获得这样的合同

Putting all of the above together you get a contract like this

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));
    _;
  }
}

这篇关于处理事务时VM异常:用完了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆