Belajar Solidity - Events & Logging
Episode 8 of 23

Belajar Solidity - Events & Logging

Memahami events di Solidity: mendeklarasikan dan memancarkan event, peran indexed topics dalam pencarian log, membaca event dengan ethers.js dan abi.decode, serta strategi pengindeksan event di DApp menggunakan The Graph

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 7 kalian menguasai inheritance dan interface, pada episode ini kita membahas cara kontrak berbicara ke luar: events dan logging.

Mengapa episode ini penting? Karena kontrak tidak bisa menampilkan UI, mengirim notifikasi, atau menyimpan riwayat tanpa membayar storage. Events adalah satu-satunya saluran komunikasi dari kontrak ke dunia luar — dan juga salah satu alat paling hemat gas untuk menyimpan riwayat transaksi. Frontend, indexer, dan analitik on-chain semuanya dibangun di atas event.

Apa itu Event?

Event adalah log yang disimpan di blockchain ketika fungsi memancarkannya (dengan emit). Berbeda dengan storage, event tidak bisa dibaca oleh kontrak lain dan tidak memengaruhi state — tetapi bisa dibaca oleh siapa pun dari luar chain, dan jauh lebih murah daripada menyimpan data di storage.

solidity
event Transfer(address indexed from, address indexed to, uint256 amount);
event Deposit(address indexed user, uint256 amount);

Aturan penting:

  • Event bisa di-emit kapan saja dalam fungsi.
  • Event hanya mencatat; ia tidak mengembalikan nilai ke pemanggil.
  • Semua data event bisa di-log, tapi hanya 3 parameter yang bisa indexed.

Indexed Topics

Parameter yang ditandai indexed menjadi topic — bagian log yang diindeks dan bisa dicari. Maksimal 3 topic per event (topic 0 adalah signature event-nya).

solidity
event Transfer(address indexed from, address indexed to, uint256 amount);

Dengan from dan to sebagai topic, frontend bisa memfilter semua Transfer dari satu alamat tanpa memindai seluruh log — ini kunci efisiensi aplikasi berbasis event.

Tipe dataPerilaku
indexed (max 3)Menjadi topic, bisa difilter cepat
Non-indexedDi-encode dalam data log, tidak bisa difilter

Perhatikan: tipe reference seperti string dan bytes yang indexed disimpan sebagai hash keccak256-nya, bukan nilainya — gunakan hanya jika memang perlu filter.

Emit dalam Praktik

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.36;
 
contract Vault {
    event Deposit(address indexed user, uint256 amount, uint256 balance);
 
    mapping(address => uint256) public balances;
 
    function deposit() external payable {
        balances[msg.sender] += msg.value;
        emit Deposit(msg.sender, msg.value, balances[msg.sender]);
    }
}

Perhatikan urutan checks-effects-interactions yang akan kita dalami di episode 15: state diubah dulu, baru event di-emit. Karena event tidak bisa revert bersama transaksi, emit setelah state aman.

Membaca Event

Di frontend (ethers.js), event bisa dibaca dengan dua cara: query log lama atau subscribe ke event baru.

Baca event Deposit dengan ethers.js
const contract = new ethers.Contract(address, abi, signer);
 
// 1. Query log lama (sejak block X)
const filter = contract.filters.Deposit(userAddress);
const logs = await contract.queryFilter(filter, 0, "latest");
 
// 2. Subscribe ke event baru
contract.on("Deposit", (user, amount, balance) => {
  console.log(`${user} deposit ${ethers.formatEther(amount)} ETH`);
});

contract.filters.Deposit(userAddress) memfilter hanya event milik alamat tertentu — ini memanfaatkan indexed topic di atas. Data non-indexed (amount, balance) di-decode otomatis oleh ethers.js dari ABI.

Untuk penguraian manual (misalnya di backend tanpa ethers), abi.decode bekerja pada data log:

solidity
// Di kontrak, memanggil log kontrak lain
bytes memory data = log.data;
(uint256 amount, uint256 balance) = abi.decode(data, (uint256, uint256));

Tip

Ethers.js dan viem sudah menangani decode event dari ABI secara otomatis — kalian jarang butuh abi.decode manual kecuali membangun indexer sendiri. Yang penting dipahami adalah struktur: topics untuk filter, data untuk nilai.

Event-Driven UI dan Indexing dengan The Graph

Satu DApp nyata biasanya menggabungkan keduanya:

  • UI real-time: subscribe ke event baru dengan contract.on untuk update halaman tanpa refresh.
  • Riwayat historis: queryFilter untuk mengambil log lama.

Untuk skala besar, memindai log langsung tidak cukup. Di sinilah The Graph masuk: subgraph mendengarkan event kontrak, memprosesnya, dan menyimpan data terstruktur di database yang bisa di-query cepat.

Query subgraph di GraphQL
query {
  deposits(first: 5, orderBy: amount, orderDirection: desc) {
    user
    amount
    balance
  }
}

Pola pengembangan indexer umum: mapping subgraph menangkap event Deposit, menyimpan user, amount, balance, lalu menyediakannya via GraphQL. Ini cara standar DApp DeFi menyajikan riwayat — kita kembali ke The Graph di episode 13.

Warning

Event tidak bisa diandalkan sebagai penyimpanan bisnis yang "tunggal": ia tidak bisa dibaca kontrak lain dan bisa (secara teknis) di-spam. Untuk state yang harus dibaca on-chain, tetap gunakan storage; simpan riwayat di event.

Penutup

Inti yang harus dibawa pulang:

  • Event adalah log murah yang menjadi satu-satunya saluran keluar kontrak ke dunia.
  • Maksimal 3 parameter indexed (topic) yang bisa difilter; sisanya tersimpan di data.
  • Frontend memakai contract.on (realtime) dan queryFilter (histori).
  • Untuk skala besar, indeks event dengan subgraph The Graph.

Di episode 9 selanjutnya kita akan membahas toolchain: Foundry & Hardhat — perbedaan kedua framework, forge init/build/test, forge script untuk deploy, cast untuk interaksi RPC, dan ekosistem plugin Hardhat dengan hardhat-toolbox. Sampai jumpa di episode 9!