使用简单的 Solidity 合约和脚本的无效操作码错误
Posted
技术标签:
【中文标题】使用简单的 Solidity 合约和脚本的无效操作码错误【英文标题】:invalid opcode error with a simple Solidity contract and script 【发布时间】:2018-09-29 08:33:38 【问题描述】:我是 Solidity 和 web3.js 的新手。我正在关注这里的教程 -
https://medium.com/@mvmurthy/full-stack-hello-world-voting-ethereum-dapp-tutorial-part-1-40d2d0d807c2
构建一个简单的投票 Dapp。 我已经使用 npm 在本地 node_modules 文件夹中安装了 ganache-cli、solc 和 web3 版本 0.20.2。 Solidity 中的 Voting.sol 合约是:
pragma solidity ^0.4.18;
contract Voting
mapping (bytes32 => uint8) public votesReceived;
bytes32[] public candidateList;
function Voting(bytes32[] candidateNames) public
candidateList = candidateNames;
function totalVotesFor(bytes32 candidate) view public returns (uint8)
return votesReceived[candidate];
使用以下名为voting_main.js 的脚本:
Web3 = require('web3')
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))
fs = require('fs')
code = fs.readFileSync('Voting.sol').toString()
solc = require('solc')
compiledCode = solc.compile(code)
abiDefinition = JSON.parse(compiledCode.contracts[':Voting'].interface)
VotingContract = web3.eth.contract(abiDefinition)
byteCode = compiledCode.contracts[':Voting'].bytecode
deployedContract = VotingContract.new(['Rama','Nick','Jose'],data: byteCode, from: web3.eth.accounts[0], gas: 4700000)
contractInstance = VotingContract.at(deployedContract.address)
contractInstance.totalVotesFor.call('Rama')
当我在 localhost:8545 上运行 ganache-cli 然后在另一个终端中运行脚本时,我收到以下错误。
ameya@ameya-HP-ENVY-15-Notebook-PC:~/Fresh_install$ node voting_main.js
/home/ameya/Fresh_install/node_modules/solc/soljson.js:1
(function (exports, require, module, __filename, __dirname) var Module;if(!Module)Module=(typeof Module!=="undefined"?Module:null)||;var moduleOverrides=;for(var key in Module)if(Module.hasOwnProperty(key))moduleOverrides[key]=Module[key]var ENVIRONMENT_IS_WEB=typeof window==="object";var ENVIRONMENT_IS_WORKER=typeof importScripts==="function";var ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE)if(!Module["print"])Module["print"]=function print(x)process["stdout"].write(x+"\n");if(!Module["printErr"])Module["printErr"]=function printErr(x)process["stderr"].write(x+"\n");var nodeFS=require("fs");var nodePath=require("path");Module["read"]=function read(filename,binary)filename=nodePath["normalize"](filename);var ret=nodeFS["readFileSync"](filename);if(!r
Error: VM Exception while processing transaction: invalid opcode
at Object.InvalidResponse (/home/ameya/Fresh_install/node_modules/web3/lib/web3/errors.js:38:16)
at RequestManager.send (/home/ameya/Fresh_install/node_modules/web3/lib/web3/requestmanager.js:61:22)
at Eth.send [as call] (/home/ameya/Fresh_install/node_modules/web3/lib/web3/method.js:145:58)
at SolidityFunction.call (/home/ameya/Fresh_install/node_modules/web3/lib/web3/function.js:135:32)
at Object.<anonymous> (/home/ameya/Fresh_install/voting_main.js:16:32)
at Module._compile (internal/modules/cjs/loader.js:654:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
at Module.load (internal/modules/cjs/loader.js:566:32)
at tryModuleLoad (internal/modules/cjs/loader.js:506:12)
at Function.Module._load (internal/modules/cjs/loader.js:498:3)
这似乎是一个非常简单的例子,它仍然抛出无效的操作码错误。我哪里错了?
【问题讨论】:
@Adams Kipnis 我似乎在这里遇到了类似的问题***.com/questions/55662881/… 【参考方案1】:如果您使用的是.new()
,则无需致电.at()
。当你想与已经部署到区块链的合约进行交互时,你可以使用at()
。
如果您选择部署新合约,则应使用异步版本的方法调用(web3j 1.0 不再支持同步)。你的电话应该是这样的:
VotingContract.new(['Rama','Nick','Jose'],data: byteCode, from: web3.eth.accounts[0], gas: 4700000, (error, deployedContract) =>
if (!error)
if (deployedContract.address)
console.log(deployedContract.totalVotesFor.call('Rama'));
);
请注意,回调被触发了两次。第一次是提交交易(deployedContract.transactionHash
将被设置),第二次是在交易被挖掘之后。
您还可以查看web3js docs 中的示例(为方便起见,粘贴在下面)。
const fs = require("fs");
const solc = require('solc')
let source = fs.readFileSync('nameContract.sol', 'utf8');
let compiledContract = solc.compile(source, 1);
let abi = compiledContract.contracts['nameContract'].interface;
let bytecode = compiledContract.contracts['nameContract'].bytecode;
let gasEstimate = web3.eth.estimateGas(data: bytecode);
let MyContract = web3.eth.contract(JSON.parse(abi));
var myContractReturned = MyContract.new(param1, param2,
from:mySenderAddress,
data:bytecode,
gas:gasEstimate, function(err, myContract)
if(!err)
// NOTE: The callback will fire twice!
// Once the contract has the transactionHash property set and once its deployed on an address.
// e.g. check tx hash on the first call (transaction send)
if(!myContract.address)
console.log(myContract.transactionHash) // The hash of the transaction, which deploys the contract
// check address on the second call (contract deployed)
else
console.log(myContract.address) // the contract address
// Note that the returned "myContractReturned" === "myContract",
// so the returned "myContractReturned" object will also get the address set.
);
【讨论】:
以上是关于使用简单的 Solidity 合约和脚本的无效操作码错误的主要内容,如果未能解决你的问题,请参考以下文章
无法将 Solidity 合约部署到 Rinkeby 网络(无效的 asm.js:stdlib 的无效成员)
在solidity 0.4.6中使用send()函数时合约抛出无效地址