๐Ÿ”ฌ Event Anatomy: Topics & Data Structure

Understand how events are stored in transaction receipts

โ†
Previous Section
Introduction

๐Ÿ” Anatomy of an Event

Every blockchain event has a specific structure with four main components. Understanding this anatomy is essential for effective event logging and filtering.

๐ŸŽฏ Interactive: Event Component Explorer

Click each component to understand its role:

โœ๏ธ

Event Signature

Topic 0

Keccak256 hash of event declaration

Purpose
Uniquely identifies the event type
Example
Transfer(address,address,uint256)
Technical Details
First 32 bytes of Keccak256 hash

Event Structure Breakdown

โœ๏ธ
Topic 0: Event Signature

The Keccak256 hash of the event's declaration (name + parameter types).

keccak256("Transfer(address,address,uint256)")
๐Ÿท๏ธ
Topics 1-3: Indexed Parameters

Up to 3 indexed parameters for efficient filtering (32 bytes each).

Topic 1: from address
Topic 2: to address
Topic 3: tokenId (if applicable)
๐Ÿ“ฆ
Data: Non-Indexed Parameters

Unlimited non-indexed parameters, ABI-encoded in the data field.

Data: amount (uint256), metadata (string)
๐Ÿงพ
Receipt: Transaction Metadata

Contains block number, transaction hash, log index, and contract address.

blockNumber, transactionHash, logIndex, address

๐ŸŽฏ Interactive: Code Example

Compare event declaration and emission:

๐Ÿ“ Event Declaration

// Declare the event with indexed parameters
event Transfer(
  address indexed from,    // Topic 1: Searchable
  address indexed to,      // Topic 2: Searchable
  uint256 value           // Data: Not searchable
);

event Approval(
  address indexed owner,   // Topic 1
  address indexed spender, // Topic 2
  uint256 value           // Data
);

event OrderCreated(
  uint256 indexed orderId,     // Topic 1
  address indexed buyer,       // Topic 2
  address indexed seller,      // Topic 3 (max 3)
  uint256 amount,             // Data
  string metadata             // Data (unlimited)
);
๐Ÿ’ก Key Points:
  • โ€ข Use indexed for searchable params (max 3)
  • โ€ข Non-indexed params go in data field (unlimited)
  • โ€ข Event name and types form signature hash
  • โ€ข Cost: ~375 gas per indexed topic

Gas Cost Comparison

~375
gas per indexed topic
Very Cheap
~8
gas per byte (data)
Cheap
~20,000
gas per storage slot
Expensive
Events are 50x cheaper than storage for logging historical data

Real Transaction Receipt Example

USDC Transfer Event in Transaction Receipt:

{
  "transactionHash": "0x123...",
  "blockNumber": 12345678,
  "logs": [
    {
      "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      "topics": [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x000000000000000000000000742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
        "0x0000000000000000000000007a250d5630B4cF539739dF2C5dAcb4c659F2488D"
      ],
      "data": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000",
      "logIndex": 5
    }
  ]
}

// Decoded:
// Topic 0: Transfer(address,address,uint256) signature
// Topic 1: from = 0x742d35...
// Topic 2: to = 0x7a250d...
// Data: amount = 1000000000000000000 (1 USDC)

๐Ÿ’ก Quick Reference

When to Use Indexed:

  • โœ“ Addresses you'll filter by (from/to)
  • โœ“ Token IDs, order IDs
  • โœ“ Enum values, status codes
  • โœ— Large data (strings, arrays)

When to Use Data:

  • โœ“ Amounts, quantities
  • โœ“ Strings, metadata
  • โœ“ Arrays, complex types
  • โœ“ Data you won't filter by