🏠 Home
Beginner
01 — Introduction to Solidity 02 — Setting Up Your Environment 03 — Your First Smart Contract 04 — Data Types & Variables 05 — Functions & Visibility 06 — Control Flow 07 — Arrays & Mappings 08 — Structs & Enums
Intermediate
09 — Events & Logging 10 — Modifiers 11 — Inheritance 12 — Interfaces & Abstract Contracts 13 — Error Handling 14 — Ether & Wei 15 — Payable Functions 16 — msg.sender & msg.value 17 — Storage vs Memory vs Stack
Advanced
18 — Gas Optimization 19 — ERC-20 Tokens 20 — ERC-721 NFT Standard 21 — Contract Security 22 — Reentrancy Attacks 23 — Oracles & Chainlink 24 — Upgradeable Contracts 25 — Deploying to Mainnet
SolidityMaster / Lesson 09
Lesson 09 of 25

Events & Logging

Emit events, index parameters, and listen for contract activity off-chain.

Intermediate

Why Events?

Events are the EVM's logging mechanism. They are stored in transaction receipts (not contract storage), making them cheap to emit. Off-chain applications (dApps, indexers, bots) use events to track what happened on-chain without expensive storage reads. Key uses: activity feeds, balance snapshots, dApp state sync, analytics.

Declaring and Emitting Events

Declare events at the contract level, then emit them inside functions.
Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract EventDemo {
    event Transfer(
        address indexed from,
        address indexed to,
        uint256         amount
    );

    event Deposit(address indexed user, uint256 amount);

    mapping(address => uint256) public balances;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
        emit Deposit(msg.sender, msg.value);
    }

    function transfer(address to, uint256 amount) public {
        require(balances[msg.sender] >= amount, "Insufficient balance");
        balances[msg.sender] -= amount;
        balances[to]         += amount;
        emit Transfer(msg.sender, to, amount);
    }
}

Indexed Parameters

Up to 3 parameters can be marked indexed. Indexed parameters are stored as topics and can be efficiently filtered in off-chain queries. Non-indexed parameters are encoded in the event data and cannot be filtered.
Solidity
// Good: index fields you'll commonly filter by
event Approval(
    address indexed owner,    // filter by owner ✓
    address indexed spender,  // filter by spender ✓
    uint256 value             // not indexed — data only
);

// Off-chain filter example (ethers.js):
// contract.filters.Approval(myAddress, null)
// → returns all approvals FROM myAddress

Listening to Events (Front-end)

Use ethers.js or web3.js to listen for events in your dApp.
Solidity
// ethers.js v6 example
const contract = new ethers.Contract(address, abi, provider);

// Listen in real-time
contract.on("Transfer", (from, to, amount, event) => {
  console.log(`${from} → ${to}: ${ethers.formatEther(amount)} ETH`);
});

// Query historical events
const filter = contract.filters.Transfer(null, myAddress);
const events = await contract.queryFilter(filter, 0, "latest");
events.forEach(e => console.log(e.args));