I am a newcomer to Solidity and web3.js . I am following the tutorial here -
to build a simple Voting Dapp. I've installed ganache-cli, solc and web3 version 0.20.2 in the local node_modules folder using npm. The Voting.sol contract in Solidity is :
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];
}
}
with the following script called 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')
When I run ganache-cli on localhost:8545 and then run the script in another terminal, I get the following error.
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)
This seems to be a very simple example which is still throwing the invalid opcode error. Where am I going wrong ?
You don't need to call .at()
if you're using .new()
. You use at()
when you want to interact with a contract that has already been deployed to the blockchain.
If you choose to deploy a new contract, you should use the async version of the method call (synchronous is no longer supported in web3j 1.0). Your call should be something like this:
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'));
}
}
});
Note that the callback is fired twice. First time is for the submission of the transaction ( deployedContract.transactionHash
will be set) and the second time after the transaction is mined.
You can also look at the example in the web3js docs (pasted below for convenience).
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.
}
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.