18

I'm new to Ethereum and I'm struggling to understand how logs are stored and can be read using geth and plain JSON-RPC (not web3.js). There's a bit of documentation out there and some posts but I'm looking for a more plain English explanation.

So far I have managed to get the log data using curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],"id":1}'

There's an array of logs in the transaction receipt and inside the array, there's another array called topics and a field data. What do these two fields represent? And what is the relation between logs and logsBloom? And how can I convert these hex values into the original value that was passed into the event?

34

The first topic in the array is the sha3 hash of the hexadecimal representation of the canonical signature of the event. The remaining items in the topics array (there may be up to three) are the hexadecimal values of the indexed parameters to the event. The event's remaining parameters (non-indexed) are stored in the 'data' field of the log.

For example, the ERC20 token Transfer event, which is defined as

Transfer(address indexed _from, address indexed _to, uint256 _value)

has this canonical signature (A canonical signature is the name of event and the data types listed with no spaces):

Transfer(address,address,uint256)

which, when run through sha3, gives:

0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef

This is topic[0]. Topic[1] is the value of _from (padded with zeros to 32 bytes on the left), topic[2] is the value of _to (padded), and the non-indexed _value parameter is carried (in hex) in the log's data field.

This transfer event:

Transfer(0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98,
         0x9e0f70dec65e4a62b5c4df1317f47fd2ef707d6c,
         10235417200000000)

generates this log:

{
  "_from": "0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98",
  "_to": "0x9e0f70dec65e4a62b5c4df1317f47fd2ef707d6c",
  "_value": 10235417200000000,
  "address": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
  "data": "0x00000000000000000000000000000000000000000000000000245d0ec6557c00",
  "logIndex": 0,
  "topics": [
    "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
    "0x000000000000000000000000fbb1b73c4f0bda4f67dca266ce6ef42f520fbb98",
    "0x0000000000000000000000009e0f70dec65e4a62b5c4df1317f47fd2ef707d6c"
  ]
}

The address field is the address of the smart contract that generated the event.

  • 1
    Awesome, thanks! Out of curiosity, what's the benefit of encrypting the hex of the canonical signature with SH3? And what was the reason for including the canonical signature in the same array as the values passed into the event but then putting non indexed values in a separate field? And what happens if there's more than one non indexed value, does the data field become an array? – migu Feb 28 '17 at 19:47
  • 2
    I don't know the benefit of any of it. That would be a question for the author of the Yellow Paper, Gavin Wood. Concerning the data field, it doesn't really become an array because the fields can be different lengths. The subsequent fields simply get padded to 32 bytes and concatenated. A bool would be 32 bytes, an address (20 bytes) is the next 32 bytes. A bytes64 would be 64 bytes, so in that sense it's not an array, just a concatenated and padded list of the non-indexed params. – Thomas Jay Rush Mar 1 '17 at 2:54
  • Thanks. Is there a way to decode the topic[0] to return the canonical signature (in hex or even better as string)? – migu Mar 2 '17 at 11:18
  • 2
    I don't think so. That's why mist and other wallets need the ABI. That info is in the ABI. – Thomas Jay Rush Mar 2 '17 at 18:18
  • 1
    All of the above is in the yellow paper. Everything I said comes from there. – Thomas Jay Rush Mar 15 '18 at 10:36
2

may you know this already but check the API documentation at https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter and subsequents functions to create filter and query logs.

A log is easier to retrieve in this way than to try to decipher the TransactionReceipt.

A log is the result of a contract calling an Event in solidity code (Ethereum EVM). It can keep some parameters indexed (topics) for quicker filtering.

So, first, create a filter with eth_newFilter, and specify the fromBlock, toBlock to the block of your TransactionReceipt. It will return the filter id. Then, use eth_getFilterLogs with the filter id, and it will return an array of logs as documented.

To interpret the data and topics fields in the result you have to have the ABI of the contract to see what event was triggered and what are its parameters

  • Thanks. I'm still trying to understand the data structure. What is a topic? And what does the data and the logsBloom field represent? And how can you decrypt them just by using the JSON-RPC response? – migu Feb 28 '17 at 7:13
  • 1
    Read this to understand bloom filter en.m.wikipedia.org/wiki/Bloom_filter and realize that the logBloom is a precalculated filtering mecanism, not the data of the event itself. – Guenole de Cadoudal Feb 28 '17 at 8:48

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.