โ†
Previous Module
Transaction Debugging

๐Ÿ› ๏ธ Code Optimization: Loops & Memory

Learn gas-efficient patterns for common operations

Write efficient smart contracts that save money

๐Ÿš€ Code-Level Optimizations

Beyond storage, code structure matters. Loop optimization is criticalโ€”caching array.length saves 2,100 gas per iteration; using ++i instead of i++ saves 5 gas (no temp variable); wrapping in unchecked saves 100+ gas (skip overflow checks). Short-circuiting leverages && and ||โ€”put cheap checks first (local vars) before expensive ones (storage reads). Unchecked math (Solidity 0.8+) removes automatic overflow checks when you've manually verified safety. Function modifiers copy code into each functionโ€”if a modifier reads storage, inline it or cache the value. These micro-optimizations compound: a 100-iteration loop with all techniques applied saves 30,000+ gas.

๐ŸŽฎ Interactive: Before & After Comparison

Select an optimization technique to see inefficient vs optimized code side-by-side with gas savings explained.

๐Ÿ”„

Loop Optimization

30-50% savings

Cache length, use ++i instead of i++, avoid storage in loops

โŒ Inefficient Code
// โŒ BAD: Expensive loop
for (uint i = 0; i < array.length; i++) {
  total += array[i];
  // SLOAD on length each iteration
  // i++ creates temporary variable
}
โœ… Optimized Code
// โœ… GOOD: Optimized loop
uint len = array.length;  // Cache
uint _total = total;      // Cache storage
for (uint i; i < len; ) {
  _total += array[i];
  unchecked { ++i; }      // Cheaper increment
}
total = _total;
๐Ÿ’ก Why This Works

Caching array.length saves SLOAD per iteration (2,100 gas each). ++i is 5 gas cheaper than i++ (no temp variable). Unchecked saves overflow check (Solidity 0.8+).

๐Ÿ”ง Advanced Loop Techniques

Reverse Iteration: for (uint i = len; i > 0; ) { unchecked { --i; } } saves gas vs forward (comparison to 0 is cheaper than to variable).
Do-While over While: Do-while executes once before checking condition (saves 1 comparison gas if guaranteed to run at least once).
Unroll Small Loops: If loop runs 2-3 times, manually unroll: x += a[0]; x += a[1]; x += a[2]; vs loop. Saves loop overhead.
Break Early: Use break or return as soon as condition met. Don't iterate remaining elements unnecessarily.

โšก Short-Circuit Cheat Sheet

โœ… Optimal Ordering
1. Constants/literals - Zero gas
2. Function parameters - Already in memory
3. Local variables - Memory reads (3 gas)
4. Storage reads - SLOAD (2,100 gas)
5. External calls - CALL (700+ gas)
Example: require(amount > 0 && balance[msg.sender] >= amount && isWhitelisted(msg.sender))
Cheap โ†’ Medium โ†’ Expensive. Most failures caught early.

๐Ÿ”ข When to Use Unchecked

โœ… Safe Cases
  • โ€ข Loop counters (bounded by known length)
  • โ€ข Decrement after require check
  • โ€ข Increment where max is type limit
  • โ€ข Array index iteration (length is bound)
โŒ Unsafe Cases
  • โ€ข User-provided arithmetic
  • โ€ข Token amounts (transfers, balances)
  • โ€ข Reward calculations
  • โ€ข Price conversions

๐Ÿ’ก Quick Wins

  • โ€ข
    Use != 0 instead of > 0: Costs 6 less gas (no GT opcode).
  • โ€ข
    Use bytes32 over string: Fixed-size types are cheaper. Convert strings to bytes32 when possible.
  • โ€ข
    Use calldata for read-only arrays: Cheaper than memory for function parameters (no copy).
  • โ€ข
    Use private over public: Public creates automatic getter (costs deployment gas).