I deployed my first contract by using browser-solidity to make bytecode and web3.eth.sendRawTransaction
to deploy.
The following is the transaction and the deployed contract code.
https://ropsten.etherscan.io/tx/0x74426948905cd6e70e8b9d64a660b3c179b7c8a224ca5cd0234842768eb501db
contract code
pragma solidity ^0.4.0;
contract Addition {
int num = 0;
function add(int a){
num += a;
}
function get() returns(int){
return num;
}
}
Then, I want to call the two methods by web3.eth.call
. However, I can't find a way how to generate the "data" param. Could you please give me any advices?
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider("http://xxx:xxx"));
const result = web3.eth.call({
to: "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a",
data: "???"
});
https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethcall
I think gas is needed to call but this example does not mention about it. On JavaScript VM on browser-solidity, the prices are showed when I execute the method like below.
Result: "0x"
Transaction cost: 41713 gas.
Execution cost: 20249 gas.
Update 1
Seems this page describes about it.
I then wanted to call the method "double" with the number "5". The Contract ABI documentation says that you have to take the first 4 bytes of the Keccak hash.
The method signature is
double(int)
Which gives the hash with web3.sha3("double(int)":
6740d36c7d42fba12b8eb3b047193c9761224c267d7a2e96dc50949860652317
The first four bytes, prefixed with "0x" are:
0x6740d36c
The documentation then tells to take the parameter, encode it in hex and pad it left to 32 bytes. Which would be the following, using the number "5":
0x0000000000000000000000000000000000000000000000000000000000000005
In total, the encoded string should look like this:
0x6740d36c0000000000000000000000000000000000000000000000000000000000000005
How to call a contract method using the eth_call JSON-RPC API
Update 2
It does not work.
const Web3 = require('web3');
const 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
Updata 3
I changed from add(int) to add(int256) but still does not work.
var result = web3.eth.call({
to: "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a",
data: "0x87db03b70000000000000000000000000000000000000000000000000000000000000001" // var hash = web3.sha3("add(int256)"); get first 4 byte and param (1)
});
However browser-solidity debugger shows the same data. So I think this data is correct.
Update 4
Seems I have to send transaction before call. I can imagine. I will try it.
Call. It is a read-only operation and will not consume any Ether.
What is the difference between a transaction and a call?
Update 5
Although I think found the answer but still it does not work. I'll take a break..
(1) sendRawTransaction
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider("http://xxxx:xxxx"));
const Tx = require('ethereumjs-tx');
const privateKey = new Buffer('xxxx', 'hex')
const rawTx = {
nonce: '0x03',
gasPrice: '0x53d9',
gasLimit: '0x53d9',
to: '0x692a70d2e424a56d2c6c27aa97d1a86395877b3a',
data: '0x87db03b70000000000000000000000000000000000000000000000000000000000000001' // add(int256) with param 1
}
const tx = new Tx(rawTx);
tx.sign(privateKey);
const 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) call get()
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider("http://xxxx:xxxx"));
const result = web3.eth.call({
to: "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a",
data: "0x6d4ce63c"
});
console.log(result); // 0x => I expected 1
Best Answer
You don't need to do this all by yourself. You can instead use
getData
method.web3.eth.call executes the call in VM of the node but this is not mined. This is kind of dry run. If you instead want to send a transaction to blockchain use
web3.eth.sendTransaction
.