This question already has an answer here:

I need to update a contract by calling one of their function but I cant use web3.js so I need to send a raw transaction.

example of function to be call on the contract:

test(address buyer, uint256 amount)

my code in javascript:

var rawTx = {
   nonce: 'CX350',
   gasPrice: 'C350',
   gasLimit: '0x09184e72a000',
   to: 'myAddress',
   value: 'CX350',
   data:  .....
}

How I can encode this call and parameters:

test('0xc5622be5861b7200cbace14e28b98c4ab77bd9b4', 10000)

??

marked as duplicate by Ismael, Richard Horrocks, Badr Bellaj Aug 26 '17 at 15:59

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Why can't you use web3.js? You will end up rewriting significant chunks of it if you want to send transactions in javascript. – carver Aug 25 '17 at 16:18
up vote 2 down vote accepted

Well the above approach works, but why not use the web3.js library which helps in doing the same. Just download web3.js using NPM (or anywhere else) and get the modules required for the task, by:

const_ = require('lodash');
const SolidityFunction = require('web3/lib/web3/function');

You can use the web3.js library along with your ABI to find the function definition, using the below code:

var ABI = JSON.parse(<your_ABI>);
var functionDef = new SolidityFunction('', _.find(ABI, { name: '<your_function_name>' }), '');

After this, you can call the method toPayload which will help you converting the values that you want to pass to your function into HEX Data.

var payloadData = functionDef.toPayload([<value_for_var_1>, <value_for_var_2>, <value_for_var_3>, <value_for_var_4>]).data;

payloadData can be used as Value for the DATA property. Example:

var rawTx = {
 to: <to_address>,
 data: payloadData,
 value: '0x0',
 from: <from_address>,
 nonce: nonce,
 gasLimit: gasLimit,
 gasPrice: gasPrice
}

You can use this approach and forget about how many zeros to pad with. As the toPayload function handles everything.

This is fairly straightforward as per the ABI spec

First you need the function selector for test(address,uint256) which is the first four bytes of the keccak-256 hash of that string, namely 0xba14d606.

Then you need the address as a 32-byte word: 0x000000000000000000000000c5622be5861b7200cbace14e28b98c4ab77bd9b4.

Finally you need 10000 as a 32-byte word: 0x0000000000000000000000000000000000000000000000000000000000002710

So the final data string you require is:

0xba14d606000000000000000000000000c5622be5861b7200cbace14e28b98c4ab77bd9b40000000000000000000000000000000000000000000000000000000000002710

And that's it!

  • thanks, it worked :) But now I face another problem: the raw tx works on the Ether Scan ropsten.etherscan.io/pushTx however on web3.js: Error: invalid argument 0: cannot unmarshal non-string as hex data – Ernane Luis Aug 25 '17 at 14:14
  • You probably just need to put the data in single quotation marks, but it's hard to tell exactly on this info. – benjaminion Aug 25 '17 at 14:18
  • My function test(uint256) data: '0xb3f4d2350000000000000000000000000000000000000000000000000000000000003039' ` const txParams = { nonce: nonce, gasPrice: '0x09184e72a000', gasLimit: web3.toHex(47189), to: contractAddress, value: '0x00', data: data, chainId: 3 } ` still getting the error :/ – Ernane Luis Aug 25 '17 at 14:30
  • I think the function signature of test(uint256) is 0x29e99f07, so try that instead of your first four bytes. I.e. 0x29e99f070000000000000000000000000000000000000000000000000‌​000000000003039 – benjaminion Aug 25 '17 at 14:38
  • it works @benjaminion! thanks a lot. – Ernane Luis Aug 25 '17 at 14:39

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