Gas Optimization Tricks I Use on Every Solidity Contract
Ten gas optimization patterns I apply to every Solidity contract before mainnet — storage packing, calldata, custom errors, immutable, unchecked, and the ones that actually move the needle.
Why this is worth your time
A user pays for every gas unit your contract consumes. A 30 percent gas reduction is a 30 percent cost reduction for every user, forever. Compounded across millions of transactions, that's serious money.
These ten patterns are what I apply to every Solidity contract before deployment. None of them require advanced knowledge; all of them measurably reduce gas.
1. Pack storage variables
Storage slots are 32 bytes. Multiple smaller variables can share a slot. Solidity packs them automatically if they're declared together and fit.
If you declare uint256 timestamp, address owner, uint96 amount as three separate slots, you use 3 slots. Reorder so address owner (20 bytes) and uint96 amount (12 bytes) sit together — they share one slot. Saves ~22,000 gas per write that would have hit the extra slot.
Apply this once when designing storage layout; the savings persist forever.
2. Use calldata for read-only function parameters
For external functions with array or struct parameters you don't modify, calldata saves significant gas. Compared to memory, ~200 gas per array element on typical calls.
3. Custom errors instead of require strings
Instead of require with an error string (which is stored on chain), define a custom error and revert with it. Saves ~50 gas on revert and more importantly cuts deployment cost.
4. immutable for constructor-set values
Variables set once in the constructor and never changed should be immutable, not regular storage. Saves ~2,000 gas per read.
5. unchecked blocks where overflow is impossible
Solidity 0.8+ checks for overflow on every arithmetic operation. Sometimes you've already validated bounds and the check is redundant. In a loop where i is bounded, wrap the increment in unchecked. Saves ~50 gas per iteration. Add up across a 1000-iteration loop, you save 50K gas.
Use carefully. Only where overflow is provably impossible.
6. Cache storage reads in memory
Every storage read costs ~2,100 gas (cold) or ~100 gas (warm). Don't read the same storage variable twice in one function — read once into a local memory variable, then reuse. Saves ~100 gas per redundant read.
7. Short-circuit operations
When using && or ||, put the cheapest condition first. If it determines the result, the expensive one is never evaluated. Check user is not address zero before checking storage balance.
8. Reduce contract size with library calls
Contract deployment cost scales with bytecode size. If you have rarely-called complex logic, move it to a library. Saves on deployment cost. Marginal effect at runtime, real effect on deploys.
9. Use events instead of storage for historical data
If you only need to read historical data off-chain (analytics, indexers), emit an event instead of storing in contract state. Events cost ~375 gas plus ~8 gas per byte. Storage costs ~20,000 gas per slot. Order-of-magnitude savings.
10. Batch operations
Instead of N separate transactions, accept arrays and batch. For N transfers, batching saves ~21,000 gas per transfer in tx overhead. At N=10, that's 210K gas saved.
Patterns I no longer use
A few tips you'll see in older guides that have been outdated:
Measure, don't guess
The optimizer in Solidity 0.8 is good. Some "optimizations" that mattered in 0.4 don't anymore. Always measure with Hardhat's gasReporter or Foundry's forge snapshot.
Workflow: write the contract naturally, take a gas snapshot of all the tests, apply optimizations one at a time, re-snapshot and compare. You'll discover that some "optimizations" don't help in your specific case. Skip those.
How much can you save in total?
Across these 10 patterns, on a typical staking or AMM contract, I usually shave 20-40 percent off the gas cost of the most-called functions. On a contract with high transaction volume, that's serious user cost saved.
TL;DR
If your contract needs a gas optimization pass before mainnet, contact me. Solidity work is part of my service offering, and gas review is something I do on every contract before deployment.
You might also like
Building Secure Staking Platforms with Solidity & Web3.js
A deep dive into creating production-ready staking contracts with daily reward distribution and security best practices.
Smart Contract Audit Checklist: 25 Things I Check Before Mainnet
A practical 25-point checklist I run through on every Solidity contract before mainnet deployment — covering reentrancy, access control, gas, oracles, upgradeability, and the boring stuff that prevents 80% of incidents.
Building a Token Presale Platform: Smart Contract Plus Next.js Frontend
End-to-end build notes for a production token presale platform — Solidity contract with tiered pricing, Next.js frontend with wallet UX, and the security gotchas that bit me.