4

I went through many questions but I couldn't get my answer.

web3 version -- 0.20.6

According to documentation event parameters that are not indexed, store in data parameters under logs. I want to iterate over blocks and store data from events. How can I decode the data parameter?

I went through this link https://codeburst.io/deep-dive-into-ethereum-logs-a8d2047c7371 but was unable to understand how he decoded that data.

event Record(string location, uint256 temperature);
 
function recordData(string location, uint256 temperature) public {
    emit Record(location, temperature);
}

Input is given: London, 25

data:

"0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000064c6f6e646f6e0000000000000000000000000000000000000000000000000000"

topic: 0xaa39dce7cd051e04c98757533bc6e3eb213cccafa31717ca09ef4dde19f123f5
data parameter under logs

I ran the same parameter transaction in remix and logs don't have any data parameter. In receipt there is input parameter. The input parameter must be the parameter that I passed, am i correct?

input:

"0xbc820aa40000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000064c6f6e646f6e0000000000000000000000000000000000000000000000000000"

enter image description here

Thanks for the help in advance!

2 Answers 2

4

If you want to deal with raw data I'd suggest to use a library like ethereumjs-abi. The rules used to encode/decode are in the solidity abi.

In your case your data split into chunks of 20 bytes/40 hex look like

0000000000000000000000000000000000000000000000000000000000000040
000000000000000000000000000000000000000000000000000000000000001d
0000000000000000000000000000000000000000000000000000000000000006
4c6f6e646f6e0000000000000000000000000000000000000000000000000000

The first parameter location is a string, since strings are of variable length they store an offset instead of the value. So 0x00..040 = 64 is the offset to the location parameter.

The second parameter temperature is uint256, and it fits in 32 bytes so its value is stored directly. Value is then 0x00..001d = 29.

The event doesn't have more parameters and the rest of the data is used by the parameters like location that were not included directly.

The parameter location is at offset 0x40 = 64 and we have this data

0000000000000000000000000000000000000000000000000000000000000006
4c6f6e646f6e0000000000000000000000000000000000000000000000000000

Strings are array of bytes, the first slot is length in this case 0x00..06 = 6 are the length of our string. The rest are the data of our string, the first six bytes are 4c6f6e646f6e. Using web3.toAscii("4c6f6e646f6e") == 'London'.

2
  • Thanks a lot Ismael for the explanation. Now I understood better. Can you please tell which method is used in this link's description to decode data? codeburst.io/deep-dive-into-ethereum-logs-a8d2047c7371 Commented Sep 19, 2018 at 9:45
  • The article has a line values = eth_abi.decode_abi(types, log['data']) that decodes the data from the arguments types.
    – Ismael
    Commented Sep 19, 2018 at 16:30
1

In Remix, you're seeing the event log delimited as described here:

event Record(string location, uint256 temperature);

You see the values provided by index (0,1) and by name (location, temperature). Length is self-explanatory.

You're in a "deep dive" and you're getting pretty raw data pretty "close to the metal". A higher-level abstraction can get you closer to an application-level view of the information. You can use something like Truffle with its "truffle-contract" wrapper.

In that case, the software client (JavaScript) will have inbuilt awareness of how the data is delimited and will unpack it for you.

It would be something like:

var reportLog;
reportLog = myContractInstance.Report({}); // possibility of filters    
reportLog.watch(function(err,res) {
     // you get here when an event is received
     console.log(res.args); // res.args.location, res.args.temperature
}

Hope it helps.

1
  • thanks for the answer. I knew about watch and get function but I was hoping to get the input from "data" parameter. I have tried the below filter but it is giving data from latest block only: reportLog = myContractInstance.Report({fromBlock:1, toBlock:'latest'}); Commented Sep 16, 2018 at 19:47

Your Answer

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

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