Handling Gas Optimization in Solidity Contracts

Ethereum developers know the pain of gas fees. Every transaction eats into profits, and for large-scale projects, that can mean thousands or even millions of dollars burned away. The worst part? Most of it is unnecessary. Poorly written smart contracts leak gas like a rusty old pipe, and fixing them isn’t just about shaving a few pennies—it’s about keeping your project sustainable.

Gas optimization isn’t just a fancy trick; it’s a necessity. If you’re serious about Solidity development, you need to stop writing wasteful code. Let’s get into the real techniques that make a difference.

Understanding Gas Costs in Solidity

Before cutting down gas fees, you need to know where they come from. Solidity contracts run on the Ethereum Virtual Machine (EVM), which charges gas for every operation. The heavier the operation, the more gas it eats up.

Where Gas Gets Wasted

  • Storage Writes – Writing to the blockchain is expensive. Changing a storage variable costs way more than just reading it.
  • Loops with Too Many Iterations – Every iteration adds more gas usage, especially if it interacts with storage.
  • Unoptimized Data Structures – Picking the wrong data structure can make retrieval slow and costly.
  • Function Calls and Modifiers – External calls and unnecessary modifiers can stack up gas costs.
  • Redundant Code – The more code executed, the higher the gas fees.

Let’s look at how to fix these.

Reducing Storage Costs

Storage is the biggest gas consumer. Ethereum charges hefty fees for writing and modifying storage variables, so the less you touch them, the better.

Use Memory Instead of Storage

Whenever possible, use memory instead of storage. Storage variables persist on-chain, while memory variables exist only during function execution.

Bad Practice:

function inefficientFunction() public {
    uint[] storage numbers = someStorageArray;  
    numbers[0] = 5;  
}

Optimized Code:

function optimizedFunction() public {
    uint[] memory numbers = someStorageArray;  
    numbers[0] = 5;  
}

By using memory, you avoid unnecessary storage writes.

Pack Storage Variables

Ethereum stores data in 32-byte slots. If you have multiple small variables, Solidity will store each in a separate slot unless you manually pack them.

Expensive Storage Usage:

uint256 a;
uint256 b;
uint256 c;

Optimized Storage Packing:

uint128 a;
uint128 b;
uint256 c;

Here, a and b can share a single 32-byte slot. This tiny change saves gas every time you access or modify these variables.

Minimize State Changes

Instead of updating storage variables multiple times inside a function, do all calculations first, then write to storage once.

Inefficient Code:

function updateValues() public {
    someStorageVariable += 1;  
    anotherStorageVariable = someStorageVariable * 2;  
}

Optimized Code:

function updateValues() public {
    uint temp = someStorageVariable + 1;  
    anotherStorageVariable = temp * 2;  
    someStorageVariable = temp;  
}

Fewer storage writes mean lower gas fees.

Optimizing Function Calls

Every function call adds overhead, and external calls are even worse. The fewer calls, the better.

Use view and pure Functions

Functions that don’t modify storage should always be marked view or pure. This saves gas when called internally.

function getSum(uint a, uint b) public pure returns (uint) {
    return a + b;
}

Since this function doesn’t modify storage, marking it pure reduces gas costs.

Avoid External Contract Calls When Possible

Calling another contract is costly because it requires additional computations. Sometimes, you can store the needed data inside your own contract instead.

Bad Practice:

function getBalance() public returns (uint) {
    return externalContract.getBalance(msg.sender);
}

Optimized Approach:
Store the balance within your contract when needed, rather than calling an external one each time.

Controlling Loops

Loops are necessary, but they can be expensive if not handled properly.

Minimize Loop Iterations

If you’re looping through an array stored in contract storage, each iteration costs gas. Instead, copy it to memory first.

Expensive Loop:

function processArray() public {
    for (uint i = 0; i < storageArray.length; i++) {
        doSomething(storageArray[i]);
    }
}

Optimized Loop:

function processArray() public {
    uint[] memory tempArray = storageArray;
    for (uint i = 0; i < tempArray.length; i++) {
        doSomething(tempArray[i]);
    }
}

Now, each iteration reads from memory instead of storage, cutting gas costs.

Use unchecked for Safe Arithmetic

Solidity automatically checks for integer overflows and underflows, but if you know a variable will never overflow, you can save gas by disabling these checks.

Default Safe Math (More Gas):

uint sum = a + b;

Optimized Math Using unchecked (Less Gas):

unchecked {
    uint sum = a + b;
}

This can save a few thousand gas units over multiple operations.

Managing Smart Contract Size

Ethereum charges more gas for larger contracts. If your contract is bloated, gas fees increase.

Remove Redundant Code

Unused variables, unnecessary imports, and excessive event emissions add size. Trim them down to keep contracts lean.

Use Libraries

Instead of repeating code, move reusable functions into libraries. Libraries store logic off-chain, reducing deployment costs.

Before (Bloated Code in Contract):

contract MathContract {
    function add(uint a, uint b) public pure returns (uint) {
        return a + b;
    }
}

After (Optimized with Library):

library MathLib {
    function add(uint a, uint b) internal pure returns (uint) {
        return a + b;
    }
}

Contracts that use libraries can keep their bytecode smaller and cheaper to deploy.

Gas-Saving Tricks Developers Overlook

Some gas optimizations are well-known, but others slip under the radar. Here are a few hidden gems:

  • Events Instead of Storage for Logs – Storing logs as events instead of variables can cut costs drastically.
  • Shorter Function and Variable Names – Solidity compiles to bytecode, and shorter names reduce contract size.
  • Bitwise Operations Instead of Math – Some operations (like division by powers of two) are cheaper with bitwise shifts.

Final Thoughts

Gas fees aren’t going anywhere. They’re a constant challenge in Ethereum development, but the difference between a poorly optimized contract and a well-structured one can be the difference between a viable project and one that bleeds money.

Optimization isn’t just about saving a few cents—it’s about keeping your smart contract competitive. A few tweaks can mean thousands saved in transaction fees over time. Solidity gives you the tools, but it’s up to you to use them right.

Leave a Reply

Your email address will not be published. Required fields are marked *