Intermediate
Gas Optimisation Basics — Hands-on lab
Write cheaper, cleaner code.
Developer Intermediate
4/6 — Gas Optimisation Basics — Hands-on lab
Measured steps Benchmark first. Apply one change at a time and keep the ones that meaningfully help. Add tests/invariants that encode any assumptions (like bounds for unchecked math).
The root problem with conventional currency is all the trust that’s required to make it work.
Documentation Inline comment why an unchecked block is safe or why packing is used. Include before/after gas numbers in PR descriptions for future readers.
Guardrails Avoid unbounded loops over user-controlled arrays; consider batching. Keep CEI and reentrancy guards intact even if they cost a few gas.
function sum(uint256[] memory xs) internal pure returns (uint256 total) {
uint256 len = xs.length;
for (uint256 i; i < len; ) {
total += xs[i];
unchecked { ++i; } // safe because i<len is loop guard
}
}
function transferMany(address[] calldata to, uint256 amount) external {
uint256 len = to.length;
for (uint256 i; i < len; ) {
_transfer(msg.sender, to[i], amount);
unchecked { ++i; }
}
} Steps
- Identify a hot path:(e.g., transfer/loop); record baseline gas with a test or benchmark.
- Apply one change at:A time calldata inputs, cache storage reads in memory, pack small types, cache array length; re-measure.
- Add unchecked only when:You can prove bounds; write tests/invariants to enforce assumptions; document why unchecked is safe.
- Review external calls:Keep CEI/reentrancy guards; ensure batching doesn’t open DoS. Remove unsafe “optimizations.”
- Capture before/after gas numbers;:Remove changes that save little but hurt readability. Commit rationale in code comments/PR notes.