Gas Optimization: What Actually Matters
The 80/20 of gas optimization. Storage packing, calldata vs memory, the SSTORE rules, custom errors, caching reads, the optimizer settings — with real benchmarks.
35 min · expert · part of Solidity & Smart Contract Development
The Optimization Mindset
Gas optimization is the topic that attracts the most cargo-culting in Solidity. The internet is full of "save 12 gas" micro-optimizations that don't matter, and a smaller number of techniques that genuinely save thousands of gas per call. This lesson focuses on the latter.
The rule of thumb: **storage operations dominate every other cost in a typical contract by 1-2 orders of magnitude.** A function that touches 5 storage slots cleanly will be cheaper than one that touches 3 slots with cache misses, even if the second function has 100 fewer arithmetic operations. Optimize storage first; everything else is downstream.
The second rule: **measure, don't guess.** Foundry's `forge test --gas-report` outputs a per-function gas summary on every test run, and `forge snapshot` writes a baseline file you can diff against in CI to catch regressions. Most "optimizations" are actually no-ops or even regressions in modern Solidity — the compiler is much smarter than it used to be. Always benchmark.
The third rule: **don't optimize what doesn't run often.** A `view` function that gets called once a day from a frontend isn't worth optimizing — the user pays nothing to call it, and the gas savings of refactoring are zero. A function that gets called millions of times (a token transfer, an AMM swap) is worth obsessing over. Profile first, then attack the hot path.
Also in this lesson
- Storage: The 80% of Optimization
- Calldata, Memory, and Arrays
- Custom Errors, External over Public, Modifier vs Internal
- The Solc Optimizer and via_ir
- Anti-patterns: Optimizations That Don't Help (or Hurt)
Key terms
- Storage Packing
- Declaring consecutive small state variables (uint128, uint64, address, bool, etc.) so they share a single 256-bit storage slot. The single biggest gas-optimization lever in most contracts.
- Cold vs Warm SLOAD
- First read of a storage slot in a transaction costs 2,100 gas (cold). Subsequent reads cost 100 gas (warm). Caching repeated reads in a local variable saves ~2,000 gas per redundant read.
- SSTORE Refund
- Writing zero to a previously non-zero slot refunds up to 4,800 gas (capped at 20% of total transaction gas after EIP-3529). Useful for cleanup operations like closing positions.
- optimizer_runs
- Solc setting that tunes the bytecode-size vs. per-call-gas trade-off. Higher values produce more inlining and cheaper calls but larger bytecode. 200 is balanced; AMMs use 1,000,000+; one-shot deployers use 1.
- via_ir
- Solc's newer optimization pipeline (Yul-based intermediate representation). Generally produces cheaper bytecode at the cost of much slower compilation. Used in production builds, often disabled during development.
- Custom Error (re: gas)
- Defined with the `error` keyword (0.8.4+). Saves ~50 gas per revert vs. `require` with a string, plus reduces bytecode size. Strict win.
- unchecked { }
- Solidity block that disables overflow / underflow checks for the contained arithmetic. Saves ~20-30 gas per operation. Use only in code paths where you can prove overflow is impossible (e.g. for-loop counters with known bounds).
Continue this lesson — 5 more sections in the CryptoBipto app.
Open lessonEducational only — not financial advice.
