Skip to main content

Events and Logs

Smart contracts emit events during execution, which are recorded as logs on the blockchain. This page explains how events work and how to access them.

Overview​

Events provide a way for smart contracts to communicate what happened during execution. They are:

  • Stored on-chain — Permanently recorded in the blockchain.
  • Not accessible to contracts — Only external applications can read logs.
  • Cheaper than storage — Lower gas cost than contract storage.
  • Filterable — Can be queried by topic.

Log Structure​

Each log entry contains:

FieldDescription
addressContract that emitted the event
topicsArray of indexed parameters (max 4)
dataNon-indexed parameters (ABI-encoded)
blockNumberBlock containing the log
transactionHashTransaction that produced the log
logIndexPosition in the block's logs

Example Log Entry​

{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0x4d6",
"blockHash": "0x7d0ac7c12ac...",
"transactionHash": "0xe994022ada...",
"transactionIndex": "0x0",
"address": "0x43d1f9096674b5722d359b6402381816d5b22f28",
"data": "0x0000000000000000000000000000000000000000000000000000000000000007",
"topics": [
"0xd3610b1c54575b7f4f0dc03d210b8ac55624ae007679b7a928a4f25a709331a8",
"0x0000000000000000000000000000000000000000000000000000000000000005"
]
}

Topics​

Topics enable efficient log filtering. A log can have up to 4 topics.

Topic 0: Event Signature​

The first topic is always the event signature hash — a keccak-256 hash of the event name and parameter types:

Event1(uint256 indexed valueA)
→ keccak256("Event1(uint256)")
→ 0x04474795f5b996ff80cb47c148d4c5ccdbe09ef27551820caa9c2f8ed149cce3

Topics 1-3: Indexed Parameters​

Solidity events can have up to 3 indexed parameters, which become additional topics:

event Transfer(
address indexed from, // topic[1]
address indexed to, // topic[2]
uint256 value // in data, not a topic
);
Array Types

For arrays, strings, and bytes, the topic contains the keccak-256 hash of the value, not the value itself. This allows filtering but not value recovery directly from the topic.

Event Parameters​

Indexed vs Non-Indexed​

TypeStored InSearchableSize Limit
IndexedTopicsYes32 bytes (or hash)
Non-indexedDataNoUnlimited

Example Contract​

pragma solidity ^0.8.0;

contract Example {
event ValueSet(
uint256 indexed id, // searchable, topic[1]
address indexed setter, // searchable, topic[2]
uint256 value // not searchable, in data
);

function setValue(uint256 id, uint256 value) public {
emit ValueSet(id, msg.sender, value);
}
}

Topic Filters​

Filter logs by topic patterns using eth_getLogs or filter methods.

Filter Syntax​

{
"topics": [
"0x...", // topic[0] must match
["0x...", "0x..."], // topic[1] must match ANY
null // topic[2] can be anything
]
}

Matching Rules​

FilterMatches
[]All logs
[A]topic[0] = A
[A, B]topic[0] = A AND topic[1] = B
[[A, B]]topic[0] = A OR topic[0] = B
[null, B]Any topic[0], topic[1] = B

Example Filter​

Get all Transfer events to a specific address:

{
"fromBlock": "0x0",
"toBlock": "latest",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
null,
"0x000000000000000000000000YOUR_ADDRESS_HERE"
]
}

Accessing Logs​

Using eth_getLogs​

Query logs directly:

curl -X POST --data '{
"jsonrpc":"2.0",
"method":"eth_getLogs",
"params":[{
"fromBlock": "0x0",
"toBlock": "latest",
"address": "0xContractAddress",
"topics": ["0xEventSignatureHash"]
}],
"id":1
}' http://localhost:8545

Using Filters​

Create a filter and poll for changes:

1. Create filter:

curl -X POST --data '{
"jsonrpc":"2.0",
"method":"eth_newFilter",
"params":[{
"fromBlock": "latest",
"toBlock": "latest",
"topics": []
}],
"id":1
}' http://localhost:8545

Returns: {"result": "0x1"} (filter ID)

2. Poll for changes:

curl -X POST --data '{
"jsonrpc":"2.0",
"method":"eth_getFilterChanges",
"params":["0x1"],
"id":1
}' http://localhost:8545

3. Uninstall when done:

curl -X POST --data '{
"jsonrpc":"2.0",
"method":"eth_uninstallFilter",
"params":["0x1"],
"id":1
}' http://localhost:8545

Using WebSocket Subscriptions​

Subscribe to logs in real-time:

{
"jsonrpc": "2.0",
"method": "eth_subscribe",
"params": ["logs", {
"address": "0xContractAddress",
"topics": ["0xEventSignatureHash"]
}],
"id": 1
}

Use Cases​

Use CaseImplementation
Track token transfersFilter by Transfer event signature
Monitor specific contractFilter by contract address
Follow user activityFilter by indexed address parameter
Build event historyQuery eth_getLogs with block range

Further Reading​