Topics are values used for indexing events. You cannot search for events without topics. Whenever an event is invoked, a default topic is generated, which is considered the first topic of the event. There can be up to four topics for an event. Topics are always generated in the same order. You can search for an event using one or more of its topics.
The first topic is the signature of the event. The rest of the three topics are the values of indexed parameters. If the index parameter is string, bytes, or array, then the keccak-256 hash of it is the topic instead.
Let's take an example to understand topics. Suppose there is an event of this form:
event ping(string indexed a, int indexed b, uint256 indexed c, string d, int e);
//invocation of event
ping("Random String", 12, 23, "Random String", 45);
Here, these four topics are generated. They are as follows:
- 0xb62a11697c0f56e93f3957c088d492b505b9edd7fb6e7872a93b41cdb2020644: This is the first topic. It is generated using web3.sha3("ping(string,int256,uint256,string,int256)"). Here, you can see that all types are of a canonical form.
- 0x30ee7c926ebaf578d95b278d78bc0cde445887b0638870a26dcab901ba21d3f2: This is the second topic. It is generated using web3.sha3("Random String").
- The third and fourth topics are 0x000000000000000000000000000000000000000000000000000000000000000c and 0x0000000000000000000000000000000000000000000000000000000000000017, respectively, that is, hexadecimal representation of the values . They are calculated using EthJS.Util.bufferToHex(EthJS.Util.setLengthLeft(12, 32)) and EthJS.Util.bufferToHex(EthJS.Util.setLengthLeft(23, 32)), respectively.
Internally, your Ethereum node will build indexes using topics so that you can easily find events based on signatures and indexed values.
Suppose you want to get event calls of the preceding event, where the first argument is Random String and the third argument is either 23 or 78; then, you can find them using web3.eth.getFilter this way:
var filter = web3.eth.filter({
fromBlock: 0,
toBlock: "latest",
address: "0x853cdcb4af7a6995808308b08bb78a74de1ef899",
topics: ["0xb62a11697c0f56e93f3957c088d492b505b9edd7fb6e7872a93b41cdb2020644", "0x30ee7c926ebaf578d95b278d78bc0cde445887b0638870a26dcab901ba21d3f2", null, [EthJS.Util.bufferToHex(EthJS.Util.setLengthLeft(23, 32)), EthJS.Util.bufferToHex(EthJS.Util.setLengthLeft(78, 32))]]
});
filter.get(function(error, result){
if (!error)
console.log(result);
});
So here, we are asking the node to return all events from the blockchain that have been fired by the 0x853cdcb4af7a6995808308b08bb78a74de1ef899 contract address, whose first topic is 0xb62a11697c0f56e93f3957c088d492b505b9edd7fb6e7872a93b41cdb2020644, the second topic is 0x30ee7c926ebaf578d95b278d78bc0cde445887b0638870a26dcab901ba21d3f2, and the third topic is either 0x0000000000000000000000000000000000000000000000000000000000000017 or 0x000000000000000000000000000000000000000000000000000000000000004e.