web3.eth.call。如何設置“數據”參數?
我通過使用 browser-solidity 來製作字節碼和 web3.eth.sendRawTransaction 來部署我的第一個合約。以下是交易和部署的合約程式碼。
https://ropsten.etherscan.io/tx/0x74426948905cd6e70e8b9d64a660b3c179b7c8a224ca5cd0234842768eb501db
合約程式碼
pragma solidity ^0.4.0; contract Addition { int num = 0; function add(int a){ num += a; } function get() returns(int){ return num; } }
然後,我想通過 web3.eth.call 呼叫這兩個方法。但是,我找不到如何生成“數據”參數的方法。你能給我一些建議嗎?
var Web3 = require('web3'); var web3 = new Web3(new Web3.providers.HttpProvider("http://xxx:xxx")); var result = web3.eth.call({ to: "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a", data: "???" });
https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethcall
我認為需要呼叫gas,但這個例子沒有提到它。在 browser-solidity 上的 JavaScript VM 上,當我執行如下方法時會顯示價格。
Result: "0x" Transaction cost: 41713 gas. Execution cost: 20249 gas.
更新 1
似乎這個頁面描述了它。
然後我想用數字“5”呼叫方法“double”。契約 ABI 文件說您必須獲取 Keccak 雜湊的前 4 個字節。方法簽名是
雙(整數)
這給出了帶有 web3.sha3(“double(int)” 的雜湊:
6740d36c7d42fba12b8eb3b047193c9761224c267d7a2e96dc50949860652317
以“0x”為前綴的前四個字節是:
0x6740d36c
然後文件告訴獲取參數,將其編碼為十六進制並將其填充到 32 個字節。這將是以下,使用數字“5”:
0x0000000000000000000000000000000000000000000000000000000000000000000005
總的來說,編碼後的字元串應該是這樣的:
0x6740d36c00000000000000000000000000000000000000000000000000000000000000000005
如何使用 eth_call JSON-RPC API 呼叫合約方法
更新 2
這沒用。
var Web3 = require('web3'); var web3 = new Web3(new Web3.providers.HttpProvider("http://xxx:xxx")); var result = web3.eth.call({ to: "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a", data: "0x6d4ce63c" // var hash = web3.sha3("get()"); get first 4 byte }); console.log(result); // 0x var result = web3.eth.call({ to: "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a", data: "0x250fc6d90000000000000000000000000000000000000000000000000000000000000001" // var hash = web3.sha3("add(int)"); get first 4 byte and param (1) }); console.log(result); // 0x var result = web3.eth.call({ to: "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a", data: "0x6d4ce63c" // var hash = web3.sha3("get()"); get first 4 byte }); console.log(result); // 0x => I expected 1
更新 3
我從 add(int) 更改為 add(int256) 但仍然無法正常工作。
var result = web3.eth.call({ to: "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a", data: "0x87db03b70000000000000000000000000000000000000000000000000000000000000001" // var hash = web3.sha3("add(int256)"); get first 4 byte and param (1) });
但是 browser-solidity 調試器顯示相同的數據。所以我認為這個數據是正確的。
更新 4
看來我必須在通話前發送交易。我能想像。我會試試。
稱呼。這是一個只讀操作,不會消耗任何乙太幣。
更新 5
雖然我認為找到了答案,但它仍然不起作用。我休息一下。。
(1) sendRawTransaction
var Web3 = require('web3'); var web3 = new Web3(new Web3.providers.HttpProvider("http://xxxx:xxxx")); var Tx = require('ethereumjs-tx'); var privateKey = new Buffer('xxxx', 'hex') var rawTx = { nonce: '0x03', gasPrice: '0x53d9', gasLimit: '0x53d9', to: '0x692a70d2e424a56d2c6c27aa97d1a86395877b3a', data: '0x87db03b70000000000000000000000000000000000000000000000000000000000000001' // add(int256) with param 1 } var tx = new Tx(rawTx); tx.sign(privateKey); var serializedTx = tx.serialize(); console.log('0x' + serializedTx.toString('hex')); // 0xf885038253d98253d994692a70d2e424a56d2c6c27aa97d1a86395877b3a80a487db03b700000000000000000000000000000000000000000000000000000000000000011ba0ec6de7c9c1f31dc95014156479925b2ebd933b715f2bb4450f5d74992d7b3423a016f6a7c6e1885412400a622f82ffa033936c06755896096c7638936c065571c1 web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) { if (!err) { console.log(hash); // 0x26db79c7c3c65992f17f4f62d5d191705933e785dff54db6d27e6f3a92d7117e } else { console.log(err); } });
https://ropsten.etherscan.io/tx/0x26db79c7c3c65992f17f4f62d5d191705933e785dff54db6d27e6f3a92d7117e
(2) 呼叫 get()
var Web3 = require('web3'); var web3 = new Web3(new Web3.providers.HttpProvider("http://xxxx:xxxx")); var result = web3.eth.call({ to: "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a", data: "0x6d4ce63c" }); console.log(result); // 0x => I expected 1
你不需要自己做這一切。您可以改為使用
getData
方法。var contract = web3.eth.contract(contractABI).at(contractAddress); var callData = contract.functionName.getData(functionParameters); var result = web3.eth.call({ to: "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a", data: callData });
web3.eth.call 在節點的 VM 中執行呼叫,但這不是探勘的。這是一種試執行。如果您想將交易發送到區塊鏈,請使用
web3.eth.sendTransaction
.
即使我不得不經歷同樣的過程,直到我發現,以下:
使用有助於做同樣事情的 web3.js 庫。只需使用 NPM(或其他任何地方)下載 web3.js 並獲取任務所需的模組,方法是:
const_ = require('lodash'); const SolidityFunction = require('web3/lib/web3/function');
您可以使用 web3.js 庫和 ABI 來查找函式定義,使用以下程式碼:
var ABI = JSON.parse(<your_ABI>); var functionDef = new SolidityFunction('', _.find(ABI, { name: '<your_function_name>' }), '');
在此之後,您可以呼叫 toPayload 方法,該方法將幫助您將要傳遞給函式的值轉換為 HEX 數據。
var payloadData = functionDef.toPayload([<value_for_var_1>, <value_for_var_2>, <value_for_var_3>, <value_for_var_4>]).data;
payloadData可用作 DATA 屬性的值。例子:
var rawTx = { to: <to_address>, data: payloadData, value: '0x0', from: <from_address>, nonce: nonce,// You need to Get this using web3.eth.getTransactionCount gasLimit: gasLimit, // Get this by web3.eth.estimateGas gasPrice: gasPrice // use, web3.eth.gasPrice }
您可以使用這種方法而忘記要填充多少個零。因為toPayload函式處理一切。您有一個原始交易對象,您可以使用ethereumjs-tx簽署您的交易並使用web3.eth.sendRawTransaction呼叫您的合約函式。
希望這可以幫助。