Smart Contract Event Monitoring in Solidity¶
Events let smart contracts emit logs that are stored on the blockchain and retrieved by external entities. They are the essential tool for monitoring changes to smart contracts, with applications ranging from tracking transactions to updating user interfaces. Developers also use events to store data on-chain that would otherwise be hard to retrieve, which increases data redundancy.
Event Basics¶
Events are defined inside the interface definition or the contract itself and dispatched with the emit keyword. Smaller contracts keep their event definitions in the contract body, where a separate interface definition adds nothing.
1 2 3 4 5 6 7 | |
The Greeting event fires whenever say is called, logging the sender's address and the _message string passed to the function.
More complex systems place events in the interface, alongside the error and function header definitions and other supporting data. That separates the business logic from the rest of the code and improves readability.
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Events carry up to three indexed parameters, denoted by the indexed keyword, and logs are filtered on those parameters. The Ethereum JSON-RPC API standard provides the eth_getLogs method, which returns an array of log objects matching a filter object.
Event Signatures¶
Filtering for Greeting events starts from the event signature, generated as the Keccak-256 hash of the event definition, in this case Greeting(address,string) with the spaces between commas and variable names removed. The result is 0xbd6c018604e259478c316f248542b74f84025ab0e9274fa09d682a3589d115df. In the JSON-RPC naming scheme, events are logs with an array of topics. The first topic is always the event signature, accessible as topic[0], and subsequent topics are the indexed fields. Data that is not indexed is stored as-is and cannot be queried or filtered efficiently, which is why querying all Greetings from a particular address is easy while filtering them by message content is not.
Reference Types
A topic can only hold 32 bytes of data. It is however possible to add a reference type to an event. This can be a Solidity mapping, array, or a struct. In this case, Solidity will take the Keccak-256 hash of the type's value as the topic data.
More information on reference types can be found in the Solidity documentation.
Filtering for Greeting logs where the sender is the address 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa produces the following request:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
In the params object, fromBlock and toBlock specify the range of blocks to search, and address holds the contract emitting the events. topics is an array in which the first item is always the hash of the event signature and the remaining items are the indexed parameters, left-padded to 32 bytes. Here the second item is the address to filter by, in hexadecimal format.
Indexed event parameters admit only exact values. Wildcard searches and partial matching are unsupported, a consequence of how Ethereum nodes store indexed data.
Events Worth Logging¶
Log every significant state change. Accounting-related actions such as deposits and withdrawals are the prime examples, and logging them produces a detailed and reliable record of all financial transactions.
Events are equally useful for monitoring changes to contract settings made by authorized personnel. Where the owner of a smart contract changes system parameters, every change warrants an event, which lets users and third-party infrastructure pick the change up and reflect it on a frontend or a dashboard.
Chingiz's Advice
Chingiz Mardanov, skilled at security audits and smart contract development alike, puts it as follows:
Over the years I came to the conclusion that at the very least what should be logged is the new state of any storage variable that was affected. Additionally, I like to emit the actor that was affected and the actor who triggered the change. The latter is optional.
Third-party Services¶
Ethereum nodes listen for and retrieve logs, and the process is rarely straightforward. Third-party services simplify indexing and analyzing event logs and integrating the results into custom software:
A robust event logging system combined with these services is what makes critical actions and changes on a contract trackable in practice.