Belajar Blockchain Developer - Gas Optimization
Episode 17 of 28

Belajar Blockchain Developer - Gas Optimization

Menghemat biaya di setiap transaksi: pola gas optimization, penggunaan calldata, storage layout yang efisien, immutable dan constant, serta praktik mengoptimasi kontrak sampai gas report turun signifikan

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

Pendahuluan

Setelah di episode 16 kalian membangun lapisan data, pada episode ini kita bicara uang: gas optimization. Di Web2, optimasi berarti server yang lebih cepat; di Web3, setiap operasi on-chain punya harga tetap, dan kalian (atau pengguna kalian) membayarnya. Kontrak yang boros gas bukan sekadar "kurang efisien" — ia kehilangan pengguna karena setiap interaksi terasa mahal.

Episode ini membahas pola-pola yang paling berdampak: storage layout, calldata, immutable, dan teknik yang menurunkan gas report secara nyata.

Mengapa Storage Mahal

Dalam EVM, biaya penyimpanan data di storage jauh lebih mahal daripada komputasi. Operasi SSTORE (menulis storage) memakan puluhan ribu gas, sementara komputasi matematika murah. Karena itu, hampir semua optimasi gas berpusat pada satu pertanyaan: bagaimana meminimalkan akses storage?

Prinsip dasar biaya gas:

Perkiraan biaya gas per operasi
SSTORE (set baru)   → ~20.000 gas
SLOAD  (baca)       → ~100 gas (panas), ~2.100 (dingin)
SSTORE (set 0)      → diskon, tapi jarang dimanfaatkan
Komputasi sederhana → puluhan gas

Satu operasi storage bisa setara dengan ribuan operasi komputasi. Optimasi terbaik sering kali berarti tidak menyentuh storage sama sekali.

Storage Layout: Packing

EVM menyimpan state dalam slot 32 byte. Beberapa variabel kecil dalam satu slot menghemat biaya:

contracts/Packed.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
contract Packed {
    // Buruk: 3 slot terpisah → 3x biaya storage
    uint128 public a1;
    uint128 public b1;
    uint128 public c1;
 
    // Baik: 3 variabel mengisi 1 slot (3 * 16 = 48 byte ≤ 32? tidak!)
    // uint128 * 3 = 48 byte > 32 byte → tetap 2 slot
    uint64 public a2;
    uint64 public b2;
    uint64 public c2;
    uint64 public d2;
}

Aturan praktis packing:

  • uint128 + uint128 → 1 slot (32 byte pas).
  • uint64 x 4 → 1 slot.
  • Urutkan tipe yang sama bersebelahan — kompilator tidak mengatur ulang otomatis.
  • address (20 byte) + uint96 → 1 slot — pola paling umum di token (misal storage balance).

Contoh packing yang benar dan sering dipakai:

contracts/VaultStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
contract VaultStorage {
    // 1 slot: address (20) + uint96 (12) = 32 byte
    struct Position {
        address token;
        uint96 amount;
    }
 
    // Bad: dua field terpisah = 2 slot
    mapping(address => uint256) public badBalances;
 
    // Good: satu struct = 1 slot per mapping entry
    mapping(address => Position) public positions;
}

Setiap slot yang bisa dihemat berarti puluhan ribu gas per transaksi — di volume jutaan transaksi, ini perbedaan jutaan dolar.

Calldata vs Memory vs Storage

Parameter fungsi adalah area optimasi termudah. Mengubah memory menjadi calldata menghilangkan biaya penyalinan ke memory:

contracts/Calldata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
contract Calldata {
    // Buruk: menyalin ke memory, lebih mahal
    function processMemory(string memory _data) external pure {
        // ...
    }
 
    // Baik: baca langsung dari calldata, murah
    function processCalldata(string calldata _data) external pure {
        // ...
    }
}

Aturan: untuk parameter yang hanya dibaca (tidak dimodifikasi, tidak di-assign), gunakan calldata. Untuk data yang akan dimodifikasi, gunakan memory.

Immutable dan Constant

Nilai yang ditentukan sekali di constructor dan tidak pernah berubah sebaiknya disimpan sebagai immutable, bukan variabel storage biasa — immutable disematkan langsung di bytecode kontrak, bukan disimpan di storage:

contracts/Immutable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
contract Immutable {
    // Buruk: SLOAD untuk membaca di setiap transaksi
    address public owner;
    uint256 public fee = 100;
 
    // Baik: nilai tertanam di bytecode, tanpa SLOAD
    address public immutable deployer;
    uint256 public constant FEE = 100;
 
    constructor() {
        deployer = msg.sender;
        owner = msg.sender;
    }
 
    function isDeployer() external view returns (bool) {
        // immutable: tidak ada biaya baca storage
        return msg.sender == deployer;
    }
}

constant (nilai ditentukan saat compile) dan immutable (ditentukan saat deploy) menghilangkan biaya SLOAD setiap kali dibaca. Untuk nilai seperti fee, denominator, dan alamat protocol, ini optimasi besar dengan usaha nol.

Tip

Gunakan forge test --gas-report atau plugin hardhat-gas-reporter sejak awal, bukan setelah kontrak selesai. Membaca gas report setiap kali menulis fungsi menanamkan kebiasaan optimasi yang sulit didapat lewat teori.

Pola Optimasi Lain yang Berdampak

Beberapa pola tambahan yang sering muncul di audit:

PolaDampak
unchecked block (Solidity 0.8+)Menghindari cek overflow — hanya jika aman secara matematis
Meminimalkan event dataKurangi non-indexed params
Merkle root untuk allowlistSatu slot, bukan list panjang
Batch operationsGabungkan banyak transfer dalam satu transaksi
Cache SLOAD dalam loopSimpan nilai storage ke variabel lokal sekali

Contoh loop yang meng-cache storage:

contracts/LoopOptimization.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
contract LoopOptimization {
    uint256 public total;
 
    // Buruk: membaca storage di setiap iterasi (N x SLOAD)
    function badLoop(uint256[] calldata _items) external {
        for (uint256 i = 0; i < _items.length; i++) {
            total += _items[i];
        }
    }
 
    // Baik: baca sekali, tulis sekali
    function goodLoop(uint256[] calldata _items) external {
        uint256 cached = total;
        for (uint256 i = 0; i < _items.length; i++) {
            cached += _items[i];
        }
        total = cached;
    }
}

Dengan meng-cache total ke variabel lokal, N kali SLOAD + SSTORE berubah menjadi 1 kali SLOAD + 1 kali SSTORE. Untuk 100 item, ini menghemat ratusan ribu gas.

Warning

Optimasi gas tidak boleh mengorbankan keamanan. unchecked yang menonaktifkan cek overflow hanya aman jika kalian sudah membuktikan nilai tidak mungkin melampaui batas — salah memakai unchecked adalah sumber bug overflow klasik di episode 18. Optimasi setelah fungsi terbukti benar; bukan sebelum.

Praktik: Menurunkan Gas Report

Latihan praktis:

contracts/BeforeAfter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
contract BeforeAfter {
    mapping(address => uint256) public balanceOf;
 
    // SEBELUM optimasi
    function deposit(uint256 _amount) external {
        require(_amount > 0, "zero");
        balanceOf[msg.sender] += _amount;
    }
}
contracts/After.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
contract After {
    // Optimasi: mapping + struct packing
    struct Entry {
        uint128 balance;
        uint128 lastUpdate;
    }
 
    mapping(address => Entry) public entries;
 
    // SESUDAH: satu slot per entry, biaya storage lebih kecil
    function deposit(uint128 _amount) external {
        require(_amount > 0, "zero");
        Entry storage e = entries[msg.sender];
        e.balance += _amount;
        e.lastUpdate = uint128(block.timestamp);
    }
}

Jalankan forge test --gas-report pada kedua versi dan bandingkan angka deployment dan fungsi — kalian akan melihat perbedaan nyata. Itulah angka yang kalian bawa ke review code.

Penutup

Inti yang harus dibawa pulang:

  • Storage adalah biaya dominan: minimalkan akses SSTORE/SLOAD.
  • Packing variabel kecil dalam satu slot menghemat puluhan ribu gas.
  • Pakai calldata untuk parameter read-only, immutable/constant untuk nilai tetap.
  • Cache storage dalam loop; tulis sekali, bukan berulang.
  • Optimasi tidak boleh mengorbankan keamanan — urutkan: benar dulu, cepat kemudian.

Di episode 18 selanjutnya kita masuk ranah paling serius — Smart Contract Security: reentrancy, overflow, front-running, dan pola CEI, dengan praktik security review. Mari lanjut ke episode 18!

Belajar Blockchain Developer - Gas Optimization | Belajar Blockchain Developer