9

I am facing a strange issue in my solidity smart contract using events. I created the event in 2 ways as below:-

1. event Event1(string assetName, address toAdd);
2. event Event1(string indexed assetName, address indexed toAdd);

Now if I run my smart contract and I have specified approach 1, then the event gets printed in the console logs whereas if I use approach 2, then the event is not printed in the console logs.

Can someone clarify on this?

Note: Not pasting the whole contract code

4
  • Show us the javascript code. Jul 5, 2016 at 11:08
  • var event = contract1.Event1({},'',function(err,result){ console.log('new event::' + JSON.stringify(result)); });
    – Aman C
    Jul 5, 2016 at 11:26
  • Did you redeploy the contract ? and updated the contract1 abi ? after the change ? Jul 5, 2016 at 14:09
  • I recreated the contract at a different address, with indexed event it didn't work and without index, it worked.
    – Aman C
    Jul 7, 2016 at 3:50

3 Answers 3

23

The combination of string and indexed does not work. To understand why, see how event arguments are stored in the blockchain.

All transactions that are executed generate a transaction receipt, which contains a property called logs. You can look up the receipt using eth.getTransactionReceipt("0x...").

In the transaction receipt, all event arguments that are not indexed are included in the data property. This property can hold values of arbitrary length. However, event arguments that are indexed are not stored in the data property, but end up in topics. This allows filters to work.

For fixed size arguments types this is ok. The size of the entries in topics is long enough to hold all fixed types supported by Solidity. However, string can have an arbitrary length. To still be able to store those values in a topic, Solidity creates a hash of the value, which ends up in the topic.

The upside is that filters can still work, since you can just create the hash of the value you're filtering for. The downside is that web3 is unable to decode the value, since that would require performing the hash function in reverse direction.

To solve this problem, you have two options. You can remove indexed from the argument, so it is stored in the data field and no longer hashed to become part of a topic. Or, you change the type of the argument, e.g. into bytes32 or another. Which is appropriate depends on your case.

1
  • 3
    You can always keccak256(your_string_here) (web3.sha3("your_string_here"))
    – Justin
    Oct 2, 2019 at 17:35
4

You can workaround that by creating 2 parameters for the same attribute, one indexed and the other not indexed, like:

event Event1(string indexed indexedAssetName, address indexed toAdd, string assetName);

Then you pass the same value to both, like this:

emit Event1("assetName", address, "assetName");

When searching you use the indexed parameter, when outputting you use the other one.

1
  • As you are referring to assets in your code.

  • As answered below about 256-bit limitation of indexed values

-> You can index maximum of 32 8-bit characters

-> Add unique symbol string to all of your assets, 32 characters each

-> Use this instead of asset name in smart contracts

-> Maintain external asset symbol -> asset name (asset data) registry outside blockchain

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.