Ok, so I'm trying to call a contract method using the methods provided by the Ethereum JSON RPC interface. The JSON RPC is running on an Ubuntu machine. Unfortunately, I can't really get a result back from the test contract I created.
The first thing I did was start Go Ethereum on the Testnet with:
geth --rpc --testnet
I then open another console and open the JS console with
geth attach
I then compiled my contract using Browser Solidity, where my code is:
contract test { function double(int a) returns(int) { return 2*a; } }
Which gives me the following byte code:
606060405260728060106000396000f360606040526000357c0100000000000000000000000000000000000000000000000000000000900480636ffa1caa146037576035565b005b604b60048080359060200190919050506061565b6040518082815260200191505060405180910390f35b6000816002029050606d565b91905056
Then I created the contract with:
curl localhost:8545 -X POST --data '{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{"from": "0x8aff0a12f3e8d55cc718d36f84e002c335df2f4a", "data": "606060405260728060106000396000f360606040526000357c0100000000000000000000000000000000000000000000000000000000900480636ffa1caa146037576035565b005b604b60048080359060200190919050506061565b6040518082815260200191505060405180910390f35b6000816002029050606d565b91905056"}],"id":1}
Which gives me back the transaction hash, which I use to get the contract address:
curl localhost:8545 -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x8290c22bd9b4d61bc57222698799edd7bbc8df5214be44e239a95f679249c59c"],"id":1}'
Which gives me back the following:
{"id":1,"jsonrpc":"2.0","result":{"transactionHash":"0x8290c22bd9b4d61bc57222698799edd7bbc8df5214be44e239a95f679249c59c","transactionIndex":"0x0","blockNumber":"0xd32da","blockHash":"0xf13f185f0eb1e4797885400e3b371c972eedebcf3eef27815a45b649283ec669","cumulativeGasUsed":"0x14293","gasUsed":"0x14293","contractAddress":"0x5c7687810ce3eae6cda44d0e6c896245cd4f97c6","logs":[]}}
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
So, using this to call the method:
curl localhost:8545 -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"from": "0x8aff0a12f3e8d55cc718d36f84e002c335df2f4a", "to": "0x5c7687810ce3eae6cda44d0e6c896245cd4f97c6", "data": "0x6740d36c0000000000000000000000000000000000000000000000000000000000000005"}, "latest"],"id":1}'
Which gives me this result:
{"id":1,"jsonrpc":"2.0","result":"0x"}
Am I doing something wrong here or forgetting an important step?
Also, are there any way to access already-existing methods within the Go Ethereum library that would free me from having to implement for example methods that to the padding myself?
Thank your very much in advance!
Best Answer
Summary
Your original contract code would not work correctly until I added a
constant
to the function definition to indicate that this function does not modify the blockchain.I had to use the method signature of
double(int256)
instead ofdouble(int)
to get theeth_call
JSON-RPC to work.The Details
Run Your
geth
InstanceYou can use the Testnet blockchain that is synchronised with other peers over the Internet, or you can use a private Dev blockchain that is only available on your computer and faster to develop with. The
--rpc
parameter will allow you to usecurl
to communicate with yourgeth
instance.Testnet Blockchain
You will need to create an account and mine some coins as you need the coins to insert your code into the blockchain or to send transactions to the blockchain:
Your
geth
instance will have to synchronise your Testnet blockchain with other peers on the Internet. This may take and hour or more. Once synchronised, your mining operation will commence and you should mine some coins in 10 or 20 minutes. Startgeth
with the mining parameters:To check if you have coins, run the command:
If you want to exit from
geth
, press Control-D.If you want to, you can now run your
geth
instance without the mining parameters as anothergeth
instance somewhere on the Internet will mine your transactions. Use the following command to remove the mining option, or just use the previousgeth
command:Dev Blockchain
You will need to create an account and mine some coins:
Start
geth
with the--miner
and--minerthreads
parameters as yourgeth
instance will need to mine your private blockchain:Flatten Your Code And Assign To A Variable
I had to modify your code to get it to run correctly by adding the word
constant
to your function definition as this function does not modify the blockchain when it is run.In your example, your code will normally be formatted for easy reading:
You can use a service like Line Break Removal Tool to strip out your line breaks, or see How to load Solidity source file into geth for some alternatives.
Your flattened code will look like the example you posted:
You will need to assign your code to a string variable:
Note that
//
comments will cause some problems when your code if flattened as all text after the//
comment will be treated as a comment. Use/* ... */
instead if you need to add comments to your code.Compile Your Code
In your
geth
instance, type in your flattened code with the assignment to the variable. Don't worry about theundefined
result as this is a normal response fromgeth
:Compile your code:
If you want to see the binary form of your code:
You will need the Application Binary Interface (ABI) signature for your contract if you want to access run your function outside this
geth
session:Note: This is the second hint as to why your JSON RPC call did not work - the method signature has
int256
for thea
parameter instead ofint
.Insert Your Code Into The Blockchain
Run the following commands to insert your code into the blockchain:
Wait up to a few minutes and you will see the following output:
You should save the address if you want to run this contract from outside your
geth
session.Use Your Contract Within The Same
geth
SessionBefore adding the
constant
to thedouble
function, I was getting the following results:Note: This is the first hint as to why your JSON RPC call failed.
To use your contract within your
geth
session, AFTER addingconstant
to thedouble
function:Use Your Contract Using
curl
And JSON-RPCAnd now we get to the tricky part.
Your function
double(int)
is reallydouble(int256)
. From Solidity - Types:In
geth
, we run the following command to find the signature of thedouble(...)
function:And take the first 4 bytest to create the
data
parameterAnd using the address from the "Contract mined! parameter", we build the following
curl
command:And run this command from the command line:
The result of
0x0000...000a
is the value10
.Update Oct 18 2016
As documented in RPC error "invalid or missing value for params" when calling contract constant void functions, you may have to add a block parameter to the
params
list. Your command with the block parameter will be:You may also have to leave out the
from
parameter.References:
eth_call
Your Other Question
Could you please ask this in another question as this answer is already too long.