Hashtag Web3 Logo

Gas Optimization

Techniques for writing smart contracts that minimize gas consumption, reducing transaction costs for users while maintaining functionality and security.

technicalAdvanced
Gas Optimization

Gas optimization is the practice of writing smart contracts that execute using the minimum possible gas, reducing costs for users without compromising functionality or security. On Ethereum and EVM-compatible chains, every operation costs gas—simple operations like addition cost 3 gas, while complex operations like storing data cost thousands. Poorly optimized contracts can cost 2-10x more than necessary, directly impacting user adoption and protocol economics.

Why Gas Optimization Matters

Gas costs significantly impact protocol success:

User Experience: High gas costs deter users. If swapping tokens costs $50 in gas, users won't use your DEX for small trades. Optimized contracts enable broader market participation.

Competitive Advantage: In crowded markets like DEXs or lending protocols, lower gas costs directly translate to competitive advantage. Users gravitate toward cheaper alternatives.

Network Congestion: Inefficient contracts waste limited blockchain capacity. During high network activity, optimized contracts remain usable while inefficient ones become prohibitively expensive.

Protocol Revenue: Lower costs mean higher value capture. A DeFi protocol charging 0.3% fees loses competitive edge if gas costs exceed fees for small transactions.

Sustainability: As Ethereum scales and gas prices potentially decrease, optimization matters less, but today it's critical for usability.

For developers, gas optimization skills command premium salaries and distinguish competent Solidity developers from mediocre ones.

Storage Optimization

Storage operations are the most expensive:

SSTORE (First Set): ~20,000 gas SSTORE (Modify): ~5,000 gas SLOAD: ~2,100 gas

Strategies for minimizing storage costs:

Pack Variables: Solidity stores data in 32-byte (256-bit) slots. Pack multiple smaller variables into single slots:

// Expensive (uses 3 storage slots)
uint256 a;
uint256 b;
uint256 c;

// Optimized (uses 1 storage slot)
uint128 a;
uint128 b; // packed with a
uint256 c; // separate slot

Use Events Over Storage: Events cost ~375-1,500 gas per indexed parameter compared to 20,000 for storage. For data that doesn't need on-chain availability (like historical records), emit events instead of storing.

Mappings vs. Arrays: Mappings are more gas-efficient for random access. Arrays incur costs for length tracking and index bounds checking.

Immutable and Constant: Variables marked immutable or constant don't use storage slots, reading them directly from bytecode. Massive savings for values set once.

Reorder Variables: Group related variables to minimize storage slots used:

// Bad: uses 4 slots
bool flag1;    // slot 1
uint256 num;   // slot 2
bool flag2;    // slot 3
address addr;  // slot 4

// Good: uses 2 slots
uint256 num;   // slot 1
bool flag1;    // slot 2
bool flag2;    // slot 2 (packed)
address addr;  // slot 2 (packed)

Memory vs. Storage vs. Calldata

Understanding data location dramatically impacts gas:

Storage: Persistent blockchain state, most expensive Memory: Temporary execution memory, moderate cost Calldata: Read-only input data, cheapest

Key optimizations:

Use Calldata for Function Parameters: When you don't need to modify input data, use calldata instead of memory:

// Expensive
function process(uint256[] memory data) external {
    // costs gas to copy to memory
}

// Optimized
function process(uint256[] calldata data) external {
    // no copy, direct access
}

Avoid Memory Expansion: Memory costs increase quadratically as you use more. Reuse memory slots when possible.

Return Data Efficiently: Returning large structures from functions costs gas. Consider returning minimal data and letting callers fetch details if needed.

Loop Optimization

Loops can consume massive gas:

Cache Array Length:

// Bad
for (uint i = 0; i < array.length; i++) {
    // repeatedly reads array.length from storage
}

// Good
uint256 length = array.length;
for (uint i = 0; i < length; i++) {
    // reads once
}

Unchecked Math: In controlled loops where overflow is impossible, use unchecked to save gas on overflow checks (Solidity 0.8+):

for (uint i = 0; i < 100; ) {
    // loop body
    unchecked { ++i; } // saves ~40 gas per iteration
}

Break Early: Exit loops as soon as conditions are met rather than completing full iterations unnecessarily.

Limit Iterations: Unbounded loops risk hitting gas limits. Cap maximum iterations or use pagination patterns.

Function Optimization

Multiple techniques optimize function gas consumption:

External vs. Public: External functions are cheaper for external calls because parameters use calldata instead of copying to memory. Use external unless the function needs to be called internally.

View/Pure Functions: Functions that don't modify state marked view or pure cost zero gas when called externally (though they cost gas in transactions calling them).

Short-Circuit Evaluation: Place cheaper conditions first in logical expressions to avoid evaluating expensive conditions when possible:

// Better
if (cheapCheck() && expensiveCheck()) {
    // if cheapCheck fails, expensiveCheck never runs
}

Function Visibility: More restrictive visibility sometimes enables optimizations. Private/internal functions inline when appropriate, saving JUMP operations.

Payable Functions: Adding payable modifier saves ~24 gas by skipping the check whether ether was sent. Use on frequently-called functions where appropriate.

Common Patterns

Established patterns for gas efficiency:

Proxy Patterns: Delegate calls to implementation contracts save deployment gas and enable upgradeability, though adding small overhead to execution.

Batch Operations: Processing multiple items in one transaction amortizes fixed costs (21,000 gas base fee) across items.

Merkle Proofs: Instead of storing large datasets on-chain, store a Merkle root and have users provide proofs. Dramatically reduces storage costs for large whitelists or datasets.

Bitmap Techniques: Use bitmaps to store boolean flags compactly. 256 flags fit in one storage slot using bitwise operations.

Minimal Proxy (Clone) Pattern: Deploy lightweight proxy contracts pointing to implementation, saving ~10x deployment costs for creating many similar contracts.

Compiler Optimizations

Solidity compiler offers optimization settings:

Optimizer Runs: Higher values optimize for repeated function calls (common for deployed contracts), lower values optimize for deployment cost. Use 200-1000 for most production contracts.

Via-IR Pipeline: Newer optimization pathway often yields better results. Enable with viaIR: true in compiler settings.

Yul/Assembly: Hand-written assembly gives precise control for critical sections, though at cost of readability and maintainability. Reserve for hot paths where gas savings justify complexity.

Measuring Gas Usage

Proper measurement guides optimization:

Hardhat Gas Reporter: Plugin showing gas costs per function and test case, essential for tracking optimization impact.

Gas Snapshots: Commit gas usage snapshots to catch regressions in CI/CD pipelines.

Profiling Tools: Tools like eth-gas-reporter provide detailed breakdowns of where gas is consumed.

Comparative Testing: Always measure before and after optimization attempts—intuition often misleads.

Real-World Simulation: Test with realistic data sizes and network conditions, not just toy examples.

When to Optimize

Optimization requires tradeoffs:

Premature Optimization: Don't sacrifice readability and maintainability for marginal gas savings in non-critical code.

Hot Paths: Focus on frequently-executed functions—a 100 gas saving on a function called 1000x daily matters more than 500 gas on a function called weekly.

User-Facing Operations: Optimize transactions users directly pay for. Internal operations matter less.

Security First: Never sacrifice security for gas savings. An exploit costs infinitely more than gas fees.

Readability Balance: Extremely optimized code becomes harder to audit. Find balance appropriate for your use case.

Real-World Examples

Protocols that excelled at gas optimization:

Uniswap V3: Extensive optimization using assembly, bitmap techniques, and clever encoding. Swaps cost ~50% less gas than Uniswap V2.

SushiSwap: Minimal changes from Uniswap but added optimizations through library usage and storage packing.

Synthetix: Used extensive assembly for their complex staking and derivatives system, making it viable despite complexity.

OpenZeppelin: Their widely-used contract libraries emphasize gas efficiency alongside security, setting industry standards.

Career Opportunities

Gas optimization expertise is highly valued:

Senior Smart Contract Engineers who master optimization command $180,000-$350,000+ salaries. This skill distinguishes senior engineers from junior ones.

DeFi Protocol Architects design gas-efficient protocols from the ground up. These strategic roles pay $200,000-$400,000+ at leading protocols.

Smart Contract Auditors identifying gas inefficiencies alongside security issues earn $150,000-$350,000+, with optimization audits becoming standard service.

Protocol Optimizers: Some engineers specialize in taking existing contracts and optimizing them, earning consulting rates of $200-500/hour.

EVM Specialists with deep understanding of the Ethereum Virtual Machine's gas mechanics are rare and highly compensated, typically $180,000-$400,000+.

Best Practices

Guidelines for effective optimization:

Profile First: Measure before optimizing. Focus efforts where they matter most.

Test Thoroughly: Optimization introduces bugs. Comprehensive test coverage is essential.

Document Trade-offs: Explain why certain optimizations were chosen and what alternatives were rejected.

Stay Current: Gas costs change with network upgrades. Techniques optimal today might be obsolete tomorrow.

Use Libraries: Don't reinvent wheels. OpenZeppelin and others provide optimized, audited implementations.

Consider Layer 2: Sometimes the best optimization is deploying on a cheaper network.

Future of Gas Optimization

Evolution continues:

EIP-4844 (Proto-Danksharding): Reduces calldata costs for rollups, changing optimization calculus for L2s.

Account Abstraction: May shift where gas optimizations matter as user operations batch differently.

New Opcodes: Ethereum upgrades sometimes add cheaper operations for common patterns.

Compiler Improvements: Solidity compiler constantly improves, automating some manual optimizations.

Layer 2 Adoption: As activity migrates to L2s with lower gas costs, extreme optimization becomes less critical, though still valuable.

Master the EVM

Gas optimization sits at the intersection of compiler technology, protocol economics, and user experience. If you're interested in low-level blockchain engineering, protocol design, or smart contract development, explore blockchain engineering roles at leading protocols. These positions require deep technical expertise and offer exceptional compensation for those who master the craft.

Find Gas Optimization Jobs

Explore positions at companies working with Gas Optimization technology

Browse open roles

Learn More

Read in-depth articles and guides about Web3 careers and technology

Explore the blog