Solidity
使用 web3 1.0 和 testrpc 正確部署合約(無效操作碼錯誤)
現在本教程沒有使用最新版本的 web3,但我嘗試使用 web3 文件解決這個問題。
這是我走了多遠:
>byteCode = compiledCode.contracts[':Voting'].bytecode >deployedContract = VotingContract.new(['Rama','Nick','Jose'],{data: byteCode, from: web3.eth.accounts[0], gas: 4700000}) >deployedContract.address >contractInstance = VotingContract.at(deployedContract.address)
我成功編譯了字節碼並通過以下方式部署了合約:
> VotingContract.deploy({ data: byteCode, arguments: [[web3.utils.asciiToHex("name1"),web3.utils.asciiToHex("name2"),web3.utils.asciiToHex("name3")]] }).send({ from: acc1, gas: 4700000, gasPrice: '3000000' }).on('confirmation', function(confirmationNumber, receipt){console.log(confirmationNumber + ' ' + receipt) }).then(function(instance) {contractInstance = instance});
現在我應該有一個合約實例,不是嗎?或者這是別的什麼?作者繼續進行以下操作:
>contractInstance = VotingContract.at(deployedContract.address)
我這樣做了:
var contract3 = new web3.eth.Contract(byteCode, contractInstance.options.address, {from: acc1, gasPrice:‘3000000’});
現在,如果我嘗試呼叫此契約上的方法,例如:
contract3.methods.totalVotesFor(web3.utils.toHex(’name1’)).call(acc1).then(function(returned, err) {console.log(returned + ’ ’ + err)});
我收到以下回复:
Promise { _bitField: 0, _fulfillmentHandler0: undefined, _rejectionHandler0: undefined, _promise0: undefined, _receiver0: undefined } > Unhandled rejection Error: Returned error: Error: VM Exception while executing eth_call: invalid opcode at C:\Path\node_modules\ethereumjs-testrpc\build\cli.node.js:59368:17 at C:\Path\node_modules\ethereumjs-testrpc\build\cli.node.js:69306:5 at C:\Path\node_modules\ethereumjs-testrpc\build\cli.node.js:11335:9 at C:\Path\node_modules\ethereumjs-testrpc\build\cli.node.js:7895:16 at replenish (C:\Path\node_modules\ethereumjs-testrpc\build\cli.node.js:8415:25) at iterateeCallback (C:\Path\node_modules\ethereumjs-testrpc\build\cli.node.js:8405:17) at C:\Path\node_modules\ethereumjs-testrpc\build\cli.node.js:8380:16 at C:\Path\node_modules\ethereumjs-testrpc\build\cli.node.js:11332:13 at C:\Path\node_modules\ethereumjs-testrpc\build\cli.node.js:69302:9 at C:\Path\node_modules\ethereumjs-testrpc\build\cli.node.js:63982:7 at Object.ErrorResponse (C:\Path\node_modules\web3-core-helpers\src\errors.js:29:16) at C:\Path\node_modules\web3-core-requestmanager\src\index.js:137:36 at XMLHttpRequest.request.onreadystatechange (C:\Path\node_modules\web3-providers-http\src\index.js:64:13) at XMLHttpRequestEventTarget.dispatchEvent (C:\Path\node_modules\xhr2\lib\xhr2.js:64:18) at XMLHttpRequest._setReadyState (C:\Path\node_modules\xhr2\lib\xhr2.js:354:12)
我可能做錯了什麼?
謝謝你的幫助!
我已經使用這個腳本來部署使用 web3 v1.0-beta24 的合約
const Web3 = require('web3'); const web3 = new Web3('http://127.0.0.1:8545'); const ownerAddress = "0x...."; const contractAbi = [{"constant":false.... }]; const contractCode = "0x606060..."; const MyContract = new web3.eth.Contract(contractAbi); MyContract.deploy({ data: contractCode, }) .send({ from: ownerAddress, gas: 4000000, gasPrice: '30000000000000', }) .then((instance) => { console.log(`Address: ${instance.options.address}`); });
而這個其他腳本發送消息並進行查詢
const Web3 = require('web3'); const web3 = new Web3('http://127.0.0.1:8545'); const ownerAddress = "0x...."; const contractAbi = [{"constant":false.... }]; const contractCode = "0x606060..."; const contractAddress = "0x...."; // <----- previous script output const myContract = new web3.eth.Contract(contractAbi, contractAddress); const options = { from: ownerAddress, gas: 4000000, gasPrice: '30000000000000', }; const message = web3.utils.asciiToHex('hola'); myContract.methods.sendMessage(message) .send(options, (err, hash) => { if (err) { console.log(err); } console.log(`TxHash: ${hash}`); }) .then((result) => { myContract.methods.getMessage().call() .then((result) => { console.log(web3.utils.hexToAscii(result)); }); });
我使用的範例合約非常簡單
pragma solidity ^0.4.18; contract Echo { bytes32 public message; function sendMessage(bytes32 _message) public { message = _message; } function getMessage() view public returns (bytes32) { return message; } }
合約地址在
receipt
或confirmation
事件上返回。這是投票並獲得結果的完整程式碼。const fs = require('fs'); const solc = require('solc'); const Web3 = require('web3'); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545")); async function deploy() { let accounts = await web3.eth.getAccounts(); let code = fs.readFileSync('Voting.sol').toString(); let compiledCode = solc.compile(code); let abi = JSON.parse(compiledCode.contracts[':Voting'].interface); let bytecode = compiledCode.contracts[':Voting'].bytecode; let votingContract = new web3.eth.Contract(abi, {from: accounts[0], gas: 47000, data: bytecode}); let rama = web3.utils.asciiToHex('Rama'); let nick = web3.utils.asciiToHex('Nick'); let jose = web3.utils.asciiToHex('Jose'); let contractInstance = await votingContract.deploy({ arguments: [[rama, nick, jose]] }) .send({ from: accounts[0], gas: 1500000 }, (err, txHash) => { console.log('send:', err, txHash); }) .on('error', (err) => { console.log('error:', err); }) .on('transactionHash', (err) => { console.log('transactionHash:', err); }) .on('receipt', (receipt) => { console.log('receipt:', receipt); votingContract.options.address = receipt.contractAddress; }); console.log('contractInstance.options:', contractInstance.options); let result = await votingContract.methods.totalVotesFor(rama).call({from: accounts[0]}); console.log('result:', result); // 0 let receipt = await votingContract.methods.voteForCandidate(rama).send({from: accounts[0]}); console.log('voteForCandidate receipt:', receipt); result = await votingContract.methods.totalVotesFor(rama).call({from: accounts[0]}); console.log('new result:', result); // 1 } deploy() .then(() => console.log('Success')) .catch(err => console.log('Script failed:', err));