Belajar Solidity - Gas Optimization Lanjut
Episode 19 of 23

Belajar Solidity - Gas Optimization Lanjut

Teknik optimasi gas tingkat lanjut: calldata vs memory untuk parameter, assembly Yul di hot path, pola storage yang hemat akses, pengukuran gas dengan gas reporter Hardhat, dan pemeriksaan storage packing

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

Pendahuluan

Setelah di episode 18 kalian memahami audit dan best practice, pada episode ini kita mengasah keterampilan yang paling dihargai di tim DeFi: optimasi gas tingkat lanjut.

Mengapa episode ini penting? Di protokol yang dipakai ribuan user, selisih beberapa ribu gas per transaksi bisa berarti jutaan dolar biaya kumulatif per tahun. Optimasi gas juga sering menjadi pembeda saat kalian menawar audit atau menarik user. Episode 6 membahas fondasi storage; di sini kita naik level: calldata, assembly, dan tooling pengukuran.

calldata vs memory: Pilihan yang Sering Terlupakan

external function menerima parameter reference types. Membacanya dari calldata tidak menyalin — jauh lebih murah daripada memory yang menyalin data:

solidity
// Mahal: menyalin seluruh array ke memory
function sumMemory(uint256[] memory data) external pure returns (uint256) {
    uint256 total;
    for (uint256 i; i < data.length; i++) total += data[i];
    return total;
}
 
// Murah: baca langsung dari calldata
function sumCalldata(uint256[] calldata data) external pure returns (uint256) {
    uint256 total;
    for (uint256 i; i < data.length; i++) total += data[i];
    return total;
}

Aturan praktis: parameter external reference types selalu calldata kecuali kalian benar-benar ingin menyalin untuk dimodifikasi. Hal yang sama berlaku untuk bytes dan string.

Assembly (Yul) untuk Hot Path

Inline assembly (Yul) memungkinkan kontrol opcode langsung — kecepatan maksimal di fungsi yang dipanggil sangat sering. Contoh klasik: membaca nilai storage yang diketahui lokasinya.

solidity
uint256 private constant PRICE_SLOT = 0;
 
function getPrice() external view returns (uint256 price) {
    assembly {
        price := sload(PRICE_SLOT)
    }
}

Versi assembly lebih hemat gas daripada sload yang dihasilkan kompiler karena menghindari overhead tambahan. Contoh lain yang umum:

solidity
// Memisahkan high/low 128-bit dari satu slot
function unpack(uint256 packed) external pure returns (uint128 a, uint128 b) {
    assembly {
        a := shr(128, packed)
        b := and(packed, 0xffffffffffffffffffffffffffffffff)
    }
}

Yul juga menjadi dasar solady — library optimasi gas yang sangat agresif (menggantikan banyak helper OpenZeppelin di proyek hemat-gas).

Warning

Assembly menonaktifkan banyak pengamanan kompiler — satu baris salah bisa berarti bug fatal yang lolos dari review otomatis. Gunakan hanya untuk hot path yang benar-benar terukur, sertakan komentar yang jelas, dan uji dengan fuzz sebelum production.

Pola Storage yang Hemat

Menggabungkan pelajaran episode 6 dan 12:

  1. Cache dalam satu SLOAD — jika fungsi memakai banyak state variable, baca sekali ke variabel lokal:
solidity
function process() external {
    uint256 balance = balances[msg.sender];  // 1 SLOAD
    // pakai balance berkali-kali, bukan panggil balances[msg.sender] ulang
}
  1. Hindari menulis nilai yang sama — bandingkan dulu sebelum SSTORE.

  2. Simpan data kecil di packed slot — gabungkan uint128/uint64/bool dalam satu slot (episode 6).

  3. Pindahkan hitungan ke memory di loop — tulis storage sekali setelah loop selesai.

solidity
function batch(uint256[] calldata ids) external {
    uint256 total;
    for (uint256 i; i < ids.length; i++) total += ids[i]; // hitung di memory
    totalAccumulated += total; // satu SSTORE
}

Mengukur dengan Gas Reporter

Jangan menebak — ukur. hardhat-gas-reporter menampilkan biaya gas per fungsi di output test:

Install dan jalankan gas reporter
npm install --save-dev hardhat-gas-reporter
npx hardhat test

Output tabel menunjukkan gas rata-rata, minimal, dan maksimal per fungsi, plus estimasi biaya USD. Di Foundry, gunakan forge test --gas-report yang serupa.

Dengan angka nyata, optimasi kalian jadi terukur: bandingkan sebelum/sesudah refactor, dan ketahui persis berapa yang dihemat per transaksi.

Pemeriksaan Storage Packing

Plugin seperti hardhat-storage-layout menampilkan layout slot kontrak — alat yang sempurna untuk mengecek packing:

Tampilkan storage layout
npx hardhat storage-layout

Output menunjukkan slot mana yang terisi dan apakah variabel kecil sudah ter-packing dengan baik. Di Foundry, kalian bisa memeriksa slot secara manual dengan forge inspect atau langsung cast storage di kontrak yang ter-deploy.

Tip

Urutan prioritas optimasi yang realistis: (1) kurangi jumlah SSTORE dan SLOAD, (2) gunakan calldata, (3) packing struct/state, (4) immutable/constant, lalu (5) assembly hanya untuk hot path terukur. Optimasi di tahap awal membawa dampak terbesar dengan risiko terkecil.

Pitfall Umum Optimasi

  • Mikro-optimasi sebelum struktur benar — bentuk data yang salah jauh lebih mahal daripada micro-optimasi.
  • Assembly tanpa test — setiap blok assembly butuh fuzz dan jalur negatif.
  • Mengorbankan kejelasan kode — optimasi yang membuat kode tidak terbaca itu biaya maintenance jangka panjang.
  • Mengabaikan gas reporter — optimasi tanpa pengukuran hanyalah opini.

Penutup

Inti yang harus dibawa pulang:

  • external reference types → calldata, bukan memory, untuk hemat salin.
  • Assembly/Yul untuk hot path: sload/shr/and langsung, tetapi pakai hanya yang terukur.
  • Pola storage hemat: cache SLOAD, hindari SSTORE berulang, simpan hitungan di memory.
  • Ukur dengan hardhat-gas-reporter / forge test --gas-report; cek packing dengan storage-layout.

Di episode 20 selanjutnya kita akan membahas Layer 2, Pectra & EVM Modern — perbandingan optimistic rollup (Optimism/Base) vs ZK rollup (zkSync, Polygon zkEVM), konsep bridge dan rollup, serta upgrade EVM Pectra, Fusaka, dan Amsterdam dengan EIP-7843 block.slotnum. Sampai jumpa di episode 20!

Belajar Solidity - Gas Optimization Lanjut | Belajar Solidity