Gas Optimization
Gas adalah biaya komputasi di Ethereum. Mengoptimasi gas berarti menulis kode yang lebih murah untuk dieksekusi. Ini sangat penting karena user membayar gas untuk setiap interaksi.
Storage vs Memory vs Calldata
// STORAGE: Paling mahal! 20,000 gas (write baru), 5,000 gas (update)
// Disimpan permanen di blockchain
// MEMORY: Murah. Hanya ada selama function execution.
// Cocok untuk temporary variables.
// CALLDATA: Paling murah untuk input data. Read-only.
// Gunakan untuk function parameters yang tidak perlu diubah.
// BAD — membaca storage berkali-kali
function bad() public {
for (uint i = 0; i < array.length; i++) { // array.length = SLOAD tiap loop
total += array[i]; // SLOAD tiap iterasi
}
}
// GOOD — cache storage ke memory
function good() public {
uint256[] memory arr = array; // 1x SLOAD
uint256 len = arr.length; // Dari memory (murah)
uint256 sum = 0; // Memory variable
for (uint i = 0; i < len; i++) {
sum += arr[i]; // Memory read (murah)
}
total = sum; // 1x SSTORE
}
Variable Packing
// EVM storage menggunakan slot 32 bytes
// Variables yang lebih kecil bisa di-pack ke satu slot
// BAD — 3 storage slots
contract Bad {
uint128 a; // slot 0 (16 bytes, sisa 16 bytes terbuang)
uint256 b; // slot 1 (32 bytes, penuh)
uint128 c; // slot 2 (16 bytes, sisa terbuang)
}
// GOOD — 2 storage slots (pack a dan c bersama)
contract Good {
uint128 a; // slot 0, bytes 0-15
uint128 c; // slot 0, bytes 16-31 (packed!)
uint256 b; // slot 1
}
// Hemat 1 SLOAD/SSTORE = ~2,100 gas per akses
Teknik Optimasi Lainnya
// 1. Gunakan uint256 daripada uint8/uint16 (kecuali packing)
// EVM bekerja dalam 256-bit words. Tipe lebih kecil butuh extra ops.
// 2. Short-circuit conditions
require(cheapCheck && expensiveCheck); // cheapCheck dulu!
// 3. Gunakan custom errors (lebih murah dari string revert)
error InsufficientBalance(uint256 available, uint256 required);
function withdraw(uint256 amount) public {
if (balances[msg.sender] < amount) {
revert InsufficientBalance(balances[msg.sender], amount);
}
}
// vs require(balance >= amount, "Insufficient balance"); // string = mahal
// 4. Gunakan unchecked untuk math yang pasti tidak overflow
function increment() public {
unchecked { counter++; } // Hemat ~80 gas (skip overflow check)
}
// 5. Mapping lebih murah dari array untuk lookup
mapping(address => bool) public whitelist; // O(1)
// vs address[] public whitelist; // O(n) untuk cari
Gas Cost Cheat Sheet
| Operasi | Gas Cost |
|---|---|
| SSTORE (new value) | 20,000 |
| SSTORE (update) | 5,000 |
| SSTORE (set to zero / refund) | -15,000 |
| SLOAD | 2,100 |
| MLOAD / MSTORE | 3 |
| ADD / SUB | 3 |
| MUL / DIV | 5 |
| External call | 2,600+ |
| Deploy contract | 32,000 + (200 × bytecode_length) |
Tools
hardhat-gas-reporter— Gas report per functionforge snapshot— Gas snapshots di Foundry- Etherscan — Lihat gas used per transaction