Solidity by Example: Events
Blockchain logging and frontend communication with this sample code demonstrating event declarations, indexed parameters for efficient filtering, emit statements for writing logs, and how external applications listen for contract events using Web3.js.
Code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract EventExample {
// Declare an event
event Transfer(address indexed from, address indexed to, uint256 value);
function transfer(address _to, uint256 _amount) public {
// ... transfer logic ...
// Emit the event
emit Transfer(msg.sender, _to, _amount);
}
}
// External consumers (like a JS frontend) can listen for these events:
// contract.on("Transfer", (from, to, value) => { ... })Explanation
Events provide a logging mechanism that allows smart contracts to communicate with external applications like web frontends or backend services. When an event is emitted, its data is stored in the transaction logs on the blockchain, creating a permanent, searchable record. Events are significantly cheaper than storing data in state variables, making them ideal for historical tracking and off-chain indexing. However, smart contracts themselves cannot read events, they're strictly for external consumption.
The indexed keyword enables efficient filtering and searching of event logs. Understanding indexed parameters is crucial for building queryable DApps:
- Up to 3 parameters can be marked as indexed in non-anonymous events
- Indexed values are stored as "topics" in blockchain logs for fast filtering
- Fixed-size types (address, uint, bool) store actual values in topics
- Dynamic types (string, bytes, arrays) store only keccak256 hashes
- Indexing increases gas cost but enables efficient log queries
This allows external applications to quickly query for specific events, such as all Transfer events where the from address is a particular user.
Events are crucial for updating user interfaces in real-time. When a transaction is mined, frontends using Web3.js or Ethers.js can listen for events and immediately update the UI without polling the blockchain. The event structure consists of topics for indexed parameters (enabling fast filtering) and data for non-indexed parameters (cheaper to store but harder to search). The first topic is always the keccak256 hash of the event signature, allowing clients to identify which event was emitted.
Modern DApp architecture relies heavily on events for state synchronization. Services like The Graph use events to build queryable indexes of blockchain data, enabling complex queries that would be impossible or prohibitively expensive to perform on-chain. This pattern of storing minimal state on-chain while emitting comprehensive events has become a best practice for gas-efficient smart contract design.
Code Breakdown
event Transfer(...) defines the log structure with indexed parameters.indexed keyword enables efficient filtering by from and to addresses.emit Transfer(...) writes the log entry to the blockchain.
