What is an Event Log?
Event logs are a foundational feature of the Ethereum Virtual Machine (EVM) that allow smart contracts to record structured, immutable records of activities and state changes directly on the blockchain. Events are emitted by smart contracts during execution and stored in the transaction receipt’s logs section, separate from contract storage. They provide a gas-efficient way to record information that is important for off-chain monitoring, auditing, and indexing without permanently storing the data in contract state.
Event logs serve as the communication layer between on-chain contracts and off-chain applications. They are the primary mechanism by which external systems — including block explorers, analytics platforms, front-end applications, and indexing services like The Graph — learn about and react to on-chain activities.
How Events Work in Solidity
In Solidity, events are defined using the event keyword and emitted using the emit statement:
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function transfer(address to, uint256 value) external returns (bool) {
require(balances[msg.sender] >= value, "Insufficient balance");
balances[msg.sender] -= value;
balances[to] += value;
emit Transfer(msg.sender, to, value);
return true;
}
Events can have both indexed and non-indexed parameters:
- Indexed parameters (up to 3 per event) are stored as topics in the event log and can be efficiently filtered when querying events. Each topic is a 32-byte keccak256 hash.
- Non-indexed parameters are stored in the event’s data section as ABI-encoded bytes. They are cheaper in terms of topics but cannot be efficiently filtered.
Every event also has an implicit topic containing the event’s signature hash (keccak256 of the event definition), which is always topic0. The three indexed parameters occupy topics 1-3, and all non-indexed parameters are packed into the data section.
Events in Standard Token Contracts
Events are integral to Ethereum’s token standards, and understanding them is essential for anyone working with DeFi or NFTs.
ERC-20 Events
The ERC-20 standard defines two required events:
Transfer(address indexed from, address indexed to, uint256 value): Emitted when tokens are transferred, including minting (from the zero address) and burning (to the zero address). This event is the authoritative record of all token movements and is used by block explorers, portfolio trackers, and DEXs to display transaction history.
Approval(address indexed owner, address indexed spender, uint256 value): Emitted when an owner approves a spender to transfer tokens on their behalf. This event tracks all allowance changes and is critical for DeFi protocols that need to transfer user tokens.
ERC-721 Events
The ERC-721 (NFT) standard extends ERC-20 with an additional event:
Transfer(address indexed from, address indexed to, uint256 indexed tokenId): Note that the third parameter (tokenId) is also indexed, unlike in ERC-20 where the value is not indexed. This allows efficient filtering of all transfers for a specific NFT token ID.
Approval(address indexed owner, address indexed approved, uint256 indexed tokenId): Tracks approval of specific NFT tokens for transfer by approved addresses.
ApprovalForAll(address indexed owner, address indexed operator, bool approved): Tracks blanket operator approvals.
ERC-1155 Events
The ERC-1155 multi-token standard uses a single transfer event:
TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value): Logs transfers of both fungible and non-fungible tokens in a single event type.
TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values): Logs batch transfers, which is one of ERC-1155’s key efficiency features.
The Graph and Event Indexing
The Graph is a decentralized indexing protocol that reads event logs from smart contracts and organizes them into queryable data structures called subgraphs. Without events, off-chain applications would need to maintain their own full nodes or rely on unreliable RPC endpoints to track on-chain state changes.
The Graph works by:
- Indexers (node operators) watch the blockchain for events matching specific contracts and event signatures.
- Mappings (AssemblyScript functions) process each event and update the subgraph’s entity store.
- Applications query the subgraph’s GraphQL API to retrieve structured data about on-chain activities.
For example, a DEX application might use The Graph to query all trades on Uniswap by indexing the Swap event emitted by the Uniswap pool contracts. This is vastly more efficient than maintaining a full Ethereum node and processing every block.
The reliance on events means that contract developers must emit events for any data that off-chain systems need to access. Missing or incomplete events are a common source of bugs in DeFi applications, where front-end interfaces fail to display transactions because the contract didn’t emit the expected event.
Gas Cost of Events
Events are significantly cheaper than storing data in contract storage. Emitting an event costs approximately:
- 375 gas per topic (3 topics maximum for indexed parameters)
- 8 gas per byte for non-indexed data (4 gas for zero bytes, 16 gas for non-zero bytes)
- The implicit topic0 (event signature) costs 375 gas
A typical ERC-20 Transfer event costs approximately 1,500 gas (375 per topic × 4 topics = 1,500), compared to 20,000+ gas for a storage write. This makes events the preferred mechanism for recording data that doesn’t need to be read by other contracts.
However, events cannot be read by other smart contracts — they are only accessible through transaction receipts, which are available off-chain but not from within the EVM. This means that events cannot be used to drive on-chain logic. For data that needs to be accessed by other contracts, storage is necessary.
Common Event Patterns
Emitted vs. Not Emitted
A critical decision in contract design is what to emit as events versus what to store in state. The general principle is:
- Store in state: Data that other contracts need to read (balances, allowances, ownership).
- Emit as events: Data needed for off-chain indexing, auditing, or monitoring (transaction history, parameter changes, admin actions).
Event-Driven Frontends
Modern dApp architectures are often event-driven, meaning the front-end application subscribes to contract events and updates its state accordingly. When a user performs an action on-chain, the front-end waits for the transaction receipt and processes the emitted events to update the UI. This pattern requires comprehensive event emission for every state change that the front-end needs to display.
Audit Events
Governance and administrative actions should always be accompanied by events to provide an immutable audit trail. Events like RoleGranted, RoleRevoked, OwnershipTransferred, Paused, and Unpaused are standard in OpenZeppelin contracts and provide transparency into privileged operations.
Event Log Structure
Each event log entry in a transaction receipt contains:
address: The contract that emitted the event.topics: An array of 0-4 topics (topic0 is always the event signature hash).data: ABI-encoded non-indexed parameters.blockNumber,blockHash,transactionHash,transactionIndex,logIndex,removed: Metadata for locating and identifying the log.
The removed field indicates whether the log has been removed due to a chain reorganization, which is relevant for applications that need to handle chain reorgs (those operating on proof-of-stake Ethereum or other chains where reorgs are possible).
Key Considerations
- Events are the primary mechanism for on-chain to off-chain communication on Ethereum.
- ERC-20 Transfer and Approval events are the backbone of DeFi data infrastructure.
- Events are much cheaper than storage (1,500 gas vs. 20,000+ gas).
- Events cannot be read by other smart contracts — only from transaction receipts off-chain.
- The Graph and similar indexing services depend on comprehensive event emission.
- Always emit events for data that front-end applications, analytics, or governance tools need.
- Use up to 3 indexed parameters for efficient filtering; put larger data in non-indexed params.
Related Terms
- Smart Contract
- The Graph
- ERC-20
- ERC-721
- ERC-1155
- Gas Optimization