13

I have an ABI and the input value of the transaction and want to know what function has been called on a contract and with what arguments (one or multiple of different types), preferably using geth, JSON-RPC and some pseudo code that I can then translate into Ruby.

There are a couple of similar questions on SO but none of them really answered the question in a way that's understandable to someone new to Ethereum.

As an example, I use the MetaCoin contract generated by Truffle. I call the method getBalance('0xfd46f749f9d916122fe958d7f8d5ad033b187472') and get the input 0xf8b2cb4f000000000000000000000000fd46f749f9d916122fe958d7f8d5ad033b187472.

truffle(development)> web3.eth.getTransaction('0x5d7a91c9f068d723ac52480c0ef61b9bf3f7b52dc726046e0b47f1beaa2f44ff')
{ hash: '0x5d7a91c9f068d723ac52480c0ef61b9bf3f7b52dc726046e0b47f1beaa2f44ff',
  nonce: 5,
  blockHash: '0xd150b520eb69a621a7218722c0de5b270c9abc499a90a81ca96340e274599c28',
  blockNumber: 6,
  transactionIndex: 0,
  from: '0xfd46f749f9d916122fe958d7f8d5ad033b187472',
  to: '0x8dec2f9cccbe718c7c51e9154f223eb226bb7942',
  value: { [String: '0'] s: 1, e: 0, c: [ 0 ] },
  gas: 4712388,
  gasPrice: { [String: '100000000000'] s: 1, e: 11, c: [ 100000000000 ] },
  input: '0xf8b2cb4f000000000000000000000000fd46f749f9d916122fe958d7f8d5ad033b187472' }

The ABI is as follows:

[
    {
      "constant": false,
      "inputs": [
        {
          "name": "addr",
          "type": "address"
        }
      ],
      "name": "getBalanceInEth",
      "outputs": [
        {
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "name": "receiver",
          "type": "address"
        },
        {
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "sendCoin",
      "outputs": [
        {
          "name": "sufficient",
          "type": "bool"
        }
      ],
      "payable": false,
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "name": "addr",
          "type": "address"
        }
      ],
      "name": "getBalance",
      "outputs": [
        {
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "type": "function"
    },
    {
      "inputs": [],
      "payable": false,
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "name": "_from",
          "type": "address"
        },
        {
          "indexed": true,
          "name": "_to",
          "type": "address"
        },
        {
          "indexed": false,
          "name": "_value",
          "type": "uint256"
        }
      ],
      "name": "Transfer",
      "type": "event"
    }
  ]

How can I decode any input to know what method was called and what arguments were passed in?

Update

I've added all data of the block with the input field at the very bottom in the logs.

{"number"=>"0x09",
 "hash"=>"0xf543eba0c80d49beea1f934c0f0ad9f0babe272a8318312545d43e6b612e4006",
 "parentHash"=>
  "0xde7a61e8dd84b5e080da8e16430951f7f138347c77ed263d0093e367c9d30775",
 "nonce"=>"0x0",
 "sha3Uncles"=>
  "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
 "logsBloom"=>
  "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
 "transactionsRoot"=>
  "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
 "stateRoot"=>
  "0x269cfa04ca1fe73202f788397ece62c520c64d5da7225ba2af2d673a2e9892f2",
 "receiptRoot"=>
  "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
 "miner"=>"0x0000000000000000000000000000000000000000",
 "difficulty"=>"0x0",
 "totalDifficulty"=>"0x0",
 "extraData"=>"0x0",
 "size"=>"0x03e8",
 "gasLimit"=>"0x47e7c4",
 "gasUsed"=>"0x5a3e",
 "timestamp"=>"0x58c83fda",
 "transactions"=>
  [{"hash"=>
     "0xce1eaf03dd1dfa5898243711ebcc1dc5c6357701f5a6c19f0b1f84130cb651fa",
    "nonce"=>"0x08",
    "blockHash"=>
     "0xf543eba0c80d49beea1f934c0f0ad9f0babe272a8318312545d43e6b612e4006",
    "blockNumber"=>"0x09",
    "transactionIndex"=>"0x0",
    "from"=>"0xfd46f749f9d916122fe958d7f8d5ad033b187472",
    "to"=>"0x8dec2f9cccbe718c7c51e9154f223eb226bb7942",
    "value"=>"0x0",
    "gas"=>"0x47e7c4",
    "gasPrice"=>"0x174876e800",
    "input"=>
     "0xf8b2cb4f000000000000000000000000fd46f749f9d916122fe958d7f8d5ad033b187472"}],
 "uncles"=>[]}
  • 1
    When you say "input" do you mean output? Because your example seems to indicate you want to parse output. – Samuel Hawksby-Robinson Mar 14 '17 at 16:12
  • 1
    @SamuelHawksby-Robinson I've added more details to the bottom of the question to clarify. – migu Mar 14 '17 at 19:14
8

You can refer to a packaged developed by Consensys https://github.com/ConsenSys/abi-decoder

  • 2
    Awesome. This works very well and returns the name of the method (getBalance), the name of each argument passed in (receiver) and the value passed in (0xfd46f749f9d916122fe958d7f8d5ad033b187472) for each argument. It doesn't return the type of the argument though? – migu Mar 15 '17 at 10:21
  • 2
    Yeah. It does not return the type of arguments – Luan Do The Mar 16 '17 at 8:01
  • 1
    I opened an issue, one friendly maintainer of the repo already added it – migu Mar 16 '17 at 10:12
  • 1
    Cool. Quick work – Luan Do The Mar 17 '17 at 8:39
4

Ah ok, I understand what you are asking. You can do this web3.toAscii(transactionID.input) to get a human readable format.

See web3.toAscii https://github.com/ethereum/wiki/wiki/JavaScript-API#web3toascii

So with your code it would be:

transaction = web3.eth.getTransaction('0x5d7a91c9f068d723ac52480c0ef61b9bf3f7b52dc726046e0b47f1beaa2f44ff')
input = web3.toAscii(transaction.input)
console.log(input)
  • 4
    This gives me 'ø²ËO\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000ýF÷IùÙ\u0016\u0012/éX×øÕ­\u0003;\u0018tr'. I'm not familiar with Ascii and I don't know how I could derive from this string that the method getBalance(address) was called with the argument 0xfd46f749f9d916122fe958d7f8d5ad033b187472. – migu Mar 14 '17 at 22:00
  • 1
    @Samuel Hawksby-Robinson I used your command for my Tx hash (0x37361fd8eb5f78c7558ccfaa338c1935ecbc3d486f7a63c5b3e1b245779bc90e) However i receive these errors : "TypeError: web3.toAscii is not a function" and also "ReferenceError: input is not defined" Thanks – Questioner May 7 '18 at 13:59
1

You can use the tool ethereum-input-data-decoder for decoding transaction input data given the ABI.

Example:

const InputDataDecoder = require('ethereum-input-data-decoder');
const decoder = new InputDataDecoder(`${__dirname}/abi.json`);

const data = `0x67043cae0000000000000000000000005a9dac9315fdd1c3d13ef8af7fdfeb522db08f020000000000000000000000000000000000000000000000000000000058a20230000000000000000000000000000000000000000000000000000000000040293400000000000000000000000000000000000000000000000000000000000000a0f3df64775a2dfb6bc9e09dced96d0816ff5055bf95da13ce5b6c3f53b97071c800000000000000000000000000000000000000000000000000000000000000034254430000000000000000000000000000000000000000000000000000000000`;

const result = decoder.decodeData(data);

console.log(result);

{
  "name": "registerOffChainDonation",
  "types": [
    "address",
    "uint256",
    "uint256",
    "string",
    "bytes32"
    ],
    "inputs": [
      <BN: 5a9dac9315fdd1c3d13ef8af7fdfeb522db08f02>,
      <BN: 58a20230>,
      <BN: 402934>,
      "BTC",
      <Buffer f3 df ... 71 c8>
    ]
}
1

On new web3.js 1.0 you must use: web3.utils.toAscii(transaction.input).

Some times you should do a let input = transaction.input.replace(/^0x/, ``); to remove these useless characters from string start.

See docs.

1

You can now use the web3.eth.abi.decodeLog function (web3 1.0).

Example from the documentation:

web3.eth.abi.decodeLog([{
    type: 'string',
    name: 'myString'
},{
    type: 'uint256',
    name: 'myNumber',
    indexed: true
},{
    type: 'uint8',
    name: 'mySmallNumber',
    indexed: true
}],
'0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000748656c6c6f252100000000000000000000000000000000000000000000000000',
['0x000000000000000000000000000000000000000000000000000000000000f310', '0x0000000000000000000000000000000000000000000000000000000000000010']);
> Result {
    '0': 'Hello%!',
    '1': '62224',
    '2': '16',
    myString: 'Hello%!',
    myNumber: '62224',
    mySmallNumber: '16'
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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