Gas Optimization Remediation
Overview
Gas optimization findings flag patterns that waste gas without affecting behavior: reading the same storage slot repeatedly, laying out state variables so they cannot be packed, recomputing loop-invariant values, and using memory where calldata would do. None of these are security bugs, but they raise the cost of every transaction.
Related Detector: Gas Optimization
Recommended Fix
Before (Vulnerable)
uint256 public counter; // slot read repeatedly
function process(uint256[] memory items) external {
for (uint256 i = 0; i < items.length; i++) {
counter += items[i]; // SLOAD + SSTORE every iteration
}
}
After (Fixed)
uint256 public counter;
function process(uint256[] calldata items) external {
uint256 cached = counter; // single SLOAD
uint256 len = items.length; // length hoisted out of the loop
for (uint256 i = 0; i < len; i++) {
cached += items[i];
}
counter = cached; // single SSTORE
}
Caching the storage value in a local variable converts repeated cold/warm storage reads into cheap stack operations and defers the single write until after the loop. Reading the array from calldata avoids copying it into memory, and hoisting items.length removes a per-iteration read.
Alternative Mitigations
- Declare adjacent state variables so they pack into a single 32-byte slot (for example, several
uint64/bool/addressfields grouped together). - Mark read-only reference-type parameters as
calldatarather thanmemory. - Hoist any computation that does not change across iterations out of the loop body.
Common Mistakes
- Caching a storage value, mutating the cache, and forgetting to write it back, which silently changes behavior.
- Reordering state variables for packing after deployment, which shifts storage layout and corrupts an upgradeable contract.
- Micro-optimizing at the expense of readability where the gas saved is negligible.