Gas Golfing Techniques You Must Know in Solidity

When a Solidity smart contract is compiled, it transforms into EVM bytecode, composed of numerous opcodes. Each opcode represents a fundamental operation that the Ethereum Virtual Machine (EVM) can perform, such as arithmetic calculations, data storage, or control flow changes. These opcodes are executed sequentially to perform the functions defined in the smart contract. For example, an ADD opcode performs an addition operation, while an SSTORE opcode stores data in the contract's storage.

Each opcode in the EVM has a predefined gas cost associated with it, reflecting the computational resources required to execute that particular operation. Simpler operations like ADD or MUL have lower gas costs, while more complex or resource-intensive operations like SSTORE (storing data in contract storage) incur significantly higher gas fees.

Gas golfing in Solidity refers to the practice of optimizing smart contract codes to reduce gas consumption.

It is difficult to overstate the significance of these optimizations, as a small percentage decrement in the gas of a piece of code could translate to millions of dollars saved over the contract's lifetime, especially for frequently executed contracts. Gas golfing involves using various techniques and best practices to make smart contracts more efficient

Below are some of the common Gas optimization techniques.

1. Mappings instead of arrays: Using mappings instead of arrays can save gas because mappings have constant time complexity (O(1)) for lookups, insertions, and deletions, whereas arrays can have linear time complexity (O(n)) for certain operations. Mappings do not store the data sequentially in storage, which avoids the overhead associated with arrays, especially dynamic ones, where operations may involve shifting elements. This is because mappings offer constant time complexity (O(1)) for both reading and writing operations, whereas arrays may require linear time complexity (O(n)) for certain operations, such as searching for an element.

Of course at the end of the day it ultimately depends on the use-case.

2. Fixed-sized Arrays over Dynamic: Fixed-sized arrays are generally more gas-efficient than dynamic arrays because their size is known at compile time, and they do not require additional operations to manage their length. Dynamic arrays, on the other hand, require extra storage to keep track of their size and additional operations to handle resizing

3. Storage Optimization: Storage optimization involves reducing the number of storage operations in your contract. Storage operations (SSTORE and SLOAD opcodes) are among the most expensive operations in the EVM. Optimizing storage access and usage can lead to substantial gas savings.

4. Constant and Immutable Variable: Using constant and immutable variables can lead to significant gas savings. These types of variables are used for values that do not change after they are set. Constant variables are set at compile time and cannot be changed; they are stored directly in the bytecode and do not occupy storage slots, resulting in lower gas costs for read operations. Immutable variables are set at deployment time and cannot be changed thereafter. They are particularly useful for values that are determined at deployment time but remain unchanged.

Below is an example of how to use constant and immutable variables in a Solidity contract: