6

Is there a more convenient way to construct the value of data for an eth_call JSON-RPC API call, than the "regular" way of first 4 bytes of web3.sha3 of canonical function signature followed by encoded and padded arguments? I know that the web3 Javascript getData method can be used but, if access via web3 is available, then one could just as well call the function directly, instead of just getting data and using JSON-RPC API. Suppose that only JSON-RPC API access is available in some situation. Is constructing data by hand for a contract function call the only option?

EDIT (6/21/2017): It occurred to me that browser-solidity might display the data for an eth_call or eth_sendTransaction, since it does display compiled contract bytecode and interface. That could have been copy-pasted. However, I checked and do not see the data needed for a function call displayed when I call a function in the right panel.

EDIT #2 (6/21/2017): Maybe my question was not clear as posted above. I will try putting it differently. Say, we have the following Solidity contract (named simple) deployed at some address, e.g. at 0xfbb5fa2ea8c5fc6f492c0795564352f262f49f50

pragma solidity ^0.4.9;

contract owned {
    address owner;
    function owned() {
        owner = msg.sender;
    }
    function getOwner() constant returns(address) {
        return owner;
    }
}

contract simple is owned {
    function twice(int a) constant returns(int) {
        return 2*a;
    }
}

The function twice can be called from Javascript code, using web3.js, as follows:

var simple = eth.contract(<ABI>).at(0xfbb5fa2ea8c5fc6f492c0795564352f262f49f50);
var result = simple.twice(7);

However, to call this function using JSON-RPC, an HTTP post request needs to be sent to the RPC port of a node, with the following body:

{
    "jsonrpc": "2.0",
    "method": "eth_call",
    "params": [
        {
            "from": "0xccf9d7d2f8be1f821cb8d9ec9553ffa92aa8fc4d",
            "to": "0xfbb5fa2ea8c5fc6f492c0795564352f262f49f50",
            "data": "0x6ffa1caa0000000000000000000000000000000000000000000000000000000000000007"
        },
        "latest"
    ],
    "id": 1
}

The value of data element is calculated as first 4 bytes of { the Keccak hash of [ the ASCII encoding of ( a canonical form of the function signature ) ] } followed by the arguments encoded in a particular way, as specified at https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI. NOTE: Added 3 types of brackets to remove ambiguity :-) (This is a very simple function with only 1 int argument but this can quickly get very nasty and error-prone with more complex arguments.

There is a way to easily obtain the appropriate value of data for a function call using a web3.js function, as follows:

var callData = simple.twice.getData(7);

But suppose the function is to be called from a remote machine and also that Javascript is not an option. Is there a convenient way, (i.e. not manually doing so as per the complex rules in the wiki linked above) to compute the correct value of the data element of the JSON-RPC API request?

2
  • Maybe solc could support this functionality, with the function signature and argument values specified in a file in JSON format. Jun 26, 2017 at 19:18
  • I suggested this as an enhancement to solc but any other way to provide this functionality in a locally-run tool is good for me. github.com/ethereum/ethereumj/issues/904 Jun 26, 2017 at 19:52

2 Answers 2

2

I found just the tool that I was looking for - ethabi from Parity.

https://github.com/paritytech/ethabi

0

However, I checked and do not see the data needed for a function call displayed when I call a function in the right panel.

Just remove the constant declaration in your function which just returns data, and do a bogus transaction on it with browser solidity. In the bytecode you'll find the function signature, which you, unfortunately, have to use exactly the way you described. There was indeed a web3 function for reeding storage directly from a contract, as far as i can recount, but that seemed more complicated to me than the oldschool way you described.

5
  • Perhaps you misunderstood my question, maybe the part about what I mean by the term data. I have tried to make it clearer in EDIT #2. Also, I did not find the function signature after removing constant declaration from a function that just returns data and calling it in browser-solidity. Jun 22, 2017 at 0:55
  • "Is there a convenient way to compute the correct value of the data element of the JSON-RPC API request?" What do you exactly mean by "compute" here? You described the way of computing the function signature correctly, and using these algorithms in javascript is the most comfortable way of doing it - of course nothing stops you to try and do that in different languages..?
    – n1cK
    Jun 23, 2017 at 14:22
  • 1
    By "compute", I mean "deduce" or "obtain". Yes, it can be done easily with Javascript but that needs at least some code to be written and to run a node or connect remotely with a node. I thought there would be some tool to generate the data value locally. After all, it just depends on the function signature and argument types and values. None of those requires a connection to a node. Jun 23, 2017 at 19:54
  • Maybe I should try writing such a tool myself. :-) Jun 23, 2017 at 20:20
  • Or maybe solc could support this functionality, with the function signature and argument values specified in a file in JSON format. Jun 26, 2017 at 17:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.