Hashtag Web3 / Updated
Gas Optimization Techniques for Solidity Developers
A practical guide for Ethereum developers on how to write more gas-efficient smart contracts. Learn techniques to reduce the execution cost of your.
On the Ethereum blockchain, every computational step incurs a financial cost, known as "gas." This cost serves as a vital constraint for smart contract developers. Skilled Solidity developers must write not only secure and functional code but also gas-efficient code. High gas costs can render decentralized applications (dApps) impractical, while optimized contracts can lead to significant savings for users and provide a competitive edge.
This article outlines practical gas optimization techniques that every Ethereum developer should master.
1. Minimize State Changes
State modifications in the Ethereum Virtual Machine (EVM) represent the most expensive operations. Reading data incurs a low cost, while writing or changing data can be costly.
- SSTORE: The
SSTOREopcode, which writes to storage, is the most expensive operation. A singleSSTOREcan cost a significant amount of gas. - Technique: Structure your code to minimize storage writes. Load a state variable into a local memory variable, perform calculations, and write back the result to storage only once.
Example:
// Inefficient: 3 SSTORE operations
function calculateBad() public {
myStateVar += 1; // SSTORE 1
myStateVar *= 2; // SSTORE 2
myStateVar -= 5; // SSTORE 3
}
// Efficient: 1 SSTORE operation
function calculateGood() public {
uint256 local_myStateVar = myStateVar; // SLOAD (cheap)
local_myStateVar += 1;
local_myStateVar *= 2;
local_myStateVar -= 5;
myStateVar = local_myStateVar; // SSTORE (once)
}
2. Use the Right Data Types
The choice of data types in Solidity can significantly influence gas costs due to how the EVM packs data into 256-bit (32-byte) storage slots.
- The Rule: When using multiple
uintvariables in astructor as contiguous state variables, prefer smaller types likeuint128oruint64if the values are within their limits. The EVM can pack these smaller variables into a single 32-byte storage slot, which reduces gas usage.
Example:
// Inefficient: Uses two 32-byte slots
struct BadStruct {
uint256 a; // Slot 1
uint256 b; // Slot 2
}
// Efficient: Uses one 32-byte slot
struct GoodStruct {
uint128 a; // Slot 1 (first 128 bits)
uint128 b; // Slot 1 (last 128 bits)
}
Caution: This optimization applies only to storage variables. For local variables in memory or calldata, using the full uint256 is typically more cost-effective as the EVM efficiently handles 32-byte words.
3. Use calldata for External Function Parameters
For external functions with dynamic data types like string or bytes, prefer using calldata over memory.
- The Difference:
calldatais a read-only, non-persistent area for function arguments. In contrast,memoryis modifiable. - The Optimization: Using
calldataavoids the need for memory allocation and copying, thus saving gas.
// Inefficient
function doSomething(string memory _myString) external { ... }
// Efficient
function doSomething(string calldata _myString) external { ... }
4. Use Custom Errors Instead of require Strings
Custom errors, introduced in Solidity 0.8.4, provide a more gas-efficient method for handling failed require statements.
- The Problem: The
require(condition, "Error string")syntax stores the error string on-chain, which incurs gas costs. - The Solution: Define a custom error and use it in your
requirestatement. This approach avoids storing string data, resulting in considerable gas savings.
Example:
// Inefficient
require(msg.sender == owner, "Caller is not the owner");
// Efficient
error NotOwner();
...
if (msg.sender != owner) {
revert NotOwner();
}
5. Use unchecked for Safe Arithmetic (Solidity 0.8.0+)
With Solidity 0.8.0, arithmetic operations automatically check for overflow and underflow, adding a small gas cost. If you are confident that an operation will not overflow or underflow, you can wrap it in an unchecked block to save gas.
// Example: A for loop where `i` will never overflow
for (uint256 i = 0; i < length; i++) {
unchecked {
// ... operations with i
}
}
Warning: Use this feature cautiously, ensuring that you are certain the arithmetic is safe. An unexpected overflow can create serious security vulnerabilities.
Gas optimization is a complex subject. However, by applying these fundamental techniques, developers can achieve substantial savings. It requires a thorough understanding of how the EVM operates, as well as a focus on both functionality and gas efficiency.

